diff --git a/README.md b/README.md index c6f69d8..67e5280 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ recommended and required. This installation method requires Arduino IDE version 1.6.11 or greater. * Open the Arduino IDE. * Open the **File > Preferences** menu item. -* Enter the following URL in **Additional Boards Manager URLs**: `https://j54n1n.github.io/arduinorobot/package_j54n1n_arduinorobot_index.json` +* Enter the following URL in **Additional Boards Manager URLs**: `https://rainerum-robotics-arduino.github.io/arduinorobot/package_j54n1n_arduinorobot_index.json` * Open the **Tools > Board > Boards Manager...** menu item. * Wait for the platform indexes to finish downloading. * Scroll down until you see the **Arduino Robot Boards** entry and click on it. diff --git a/avr/boards.txt b/avr/boards.txt index ca7409e..d03d168 100644 --- a/avr/boards.txt +++ b/avr/boards.txt @@ -29,48 +29,47 @@ arduinorobot.bootloader.lock_bits=0x2F arduinorobot.build.mcu=atmega32u4 arduinorobot.build.f_cpu=16000000L arduinorobot.build.core=arduino:arduino +# Default board will be overridden by the cpu menu +arduinorobot.build.board=AVR_ROBOT_CONTROL +arduinorobot.build.vid=0x2341 arduinorobot.build.extra_flags={build.usb_flags} ## Arduino Robot Control Board ## ------------------------------------------------- arduinorobot.menu.cpu.controlboard=Control Board -arduinorobot.menu.cpu.controlboard.vid.0=0x2341 -arduinorobot.menu.cpu.controlboard.pid.0=0x0038 -arduinorobot.menu.cpu.controlboard.vid.1=0x2341 -arduinorobot.menu.cpu.controlboard.pid.1=0x8038 -arduinorobot.menu.cpu.controlboard.vid.2=0x2A03 -arduinorobot.menu.cpu.controlboard.pid.2=0x0038 -arduinorobot.menu.cpu.controlboard.vid.3=0x2A03 -arduinorobot.menu.cpu.controlboard.pid.3=0x8038 - arduinorobot.menu.cpu.controlboard.bootloader.file=caterina-Arduino_Robot/Caterina-Robot-Control.hex -arduinorobot.menu.cpu.controlboard.build.vid=0x2341 +arduinorobot.menu.cpu.controlboard.build.vid.0=0x2341 +arduinorobot.menu.cpu.controlboard.build.pid.0=0x0038 +arduinorobot.menu.cpu.controlboard.build.vid.1=0x2341 +arduinorobot.menu.cpu.controlboard.build.pid.1=0x8038 +arduinorobot.menu.cpu.controlboard.build.vid.2=0x2A03 +arduinorobot.menu.cpu.controlboard.build.pid.2=0x0038 +arduinorobot.menu.cpu.controlboard.build.vid.3=0x2A03 +arduinorobot.menu.cpu.controlboard.build.pid.3=0x8038 arduinorobot.menu.cpu.controlboard.build.pid=0x8038 arduinorobot.menu.cpu.controlboard.build.usb_product="Robot Control" arduinorobot.menu.cpu.controlboard.build.board=AVR_ROBOT_CONTROL -arduinorobot.menu.cpu.controlboard.build.variant=arduino:robot_control +arduinorobot.menu.cpu.controlboard.build.variant=robot_control ## Arduino Robot Motor Board ## ------------------------------------------------- arduinorobot.menu.cpu.motorboard=Motor Board -arduinorobot.menu.cpu.motorboard.vid.0=0x2341 -arduinorobot.menu.cpu.motorboard.pid.0=0x0039 -arduinorobot.menu.cpu.motorboard.vid.1=0x2341 -arduinorobot.menu.cpu.motorboard.pid.1=0x8039 -arduinorobot.menu.cpu.motorboard.vid.2=0x2A03 -arduinorobot.menu.cpu.motorboard.pid.2=0x0039 -arduinorobot.menu.cpu.motorboard.vid.3=0x2A03 -arduinorobot.menu.cpu.motorboard.pid.3=0x8039 - arduinorobot.menu.cpu.motorboard.bootloader.file=caterina-Arduino_Robot/Caterina-Robot-Motor.hex -arduinorobot.menu.cpu.motorboard.build.vid=0x2341 +arduinorobot.menu.cpu.motorboard.build.vid.0=0x2341 +arduinorobot.menu.cpu.motorboard.build.pid.0=0x0039 +arduinorobot.menu.cpu.motorboard.build.vid.1=0x2341 +arduinorobot.menu.cpu.motorboard.build.pid.1=0x8039 +arduinorobot.menu.cpu.motorboard.build.vid.2=0x2A03 +arduinorobot.menu.cpu.motorboard.build.pid.2=0x0039 +arduinorobot.menu.cpu.motorboard.build.vid.3=0x2A03 +arduinorobot.menu.cpu.motorboard.build.pid.3=0x8039 arduinorobot.menu.cpu.motorboard.build.pid=0x8039 arduinorobot.menu.cpu.motorboard.build.usb_product="Robot Motor" arduinorobot.menu.cpu.motorboard.build.board=AVR_ROBOT_MOTOR -arduinorobot.menu.cpu.motorboard.build.variant=arduino:robot_motor +arduinorobot.menu.cpu.motorboard.build.variant=robot_motor ############################################################## \ No newline at end of file diff --git a/avr/libraries/AnalogMultiplexer/LICENSE.md b/avr/libraries/AnalogMultiplexer/LICENSE.md new file mode 100644 index 0000000..0b11359 --- /dev/null +++ b/avr/libraries/AnalogMultiplexer/LICENSE.md @@ -0,0 +1,23 @@ +Library for the CMOS 40xx analog multiplexer series. + +The MIT License (MIT) + +Copyright (c) 2017 Julian Sanin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/avr/libraries/AnalogMultiplexer/README.md b/avr/libraries/AnalogMultiplexer/README.md new file mode 100644 index 0000000..c4e4cbc --- /dev/null +++ b/avr/libraries/AnalogMultiplexer/README.md @@ -0,0 +1,33 @@ +# CMOS 40xx Analog Multiplexer Series Library +A library to interface with analog multiplexers. Supports 4051, 4052, 4053, and +4067 series multiplexers. + +## How to use +``` +#include + +enum { + PIN_EN = 2, // The enable pin of the multiplexer or NOT_A_PIN. + PIN_S0 = 3, // Channel selector pin 0. + PIN_S1 = 4, // Channel selector pin 1. + PIN_S2 = 5, // Channel selector pin 2. + PIN_IO = A0 // Use here a pin that can work in analog & digital modes. +}; + +AMxx4051 mux{ PIN_EN, PIN_S0, PIN_S1, PIN_S2 }; // 8:1 Multiplexer. + +void setup() { + Serial.begin(9600); + while (!Serial); +} + +void loop() { + mux.pinMode(PIN_IO, INPUT); // PIN_IO will be used to read from the mux. + mux.enable(); // Enable multiplexer. + for (int channel = 0; channel < 8; channel++) { + int value = mux.analogRead(channel); // Do analog read. + Serial.println(value); + } + Serial.println(); +} +``` diff --git a/avr/libraries/AnalogMultiplexer/examples/AnalogMultiplexerExample/AnalogMultiplexerExample.ino b/avr/libraries/AnalogMultiplexer/examples/AnalogMultiplexerExample/AnalogMultiplexerExample.ino new file mode 100644 index 0000000..3973cfb --- /dev/null +++ b/avr/libraries/AnalogMultiplexer/examples/AnalogMultiplexerExample/AnalogMultiplexerExample.ino @@ -0,0 +1,48 @@ +#include + +// Selected Arduino pins. +enum { + PIN_EN = 2, // The enable pin of the multiplexer or NOT_A_PIN. + PIN_S0 = 3, // Channel selector pin 0. + PIN_S1 = 4, // Channel selector pin 1. + PIN_S2 = 5, // Channel selector pin 2. + PIN_S3 = 6, // Channel selector pin 3. + PIN_IO = A0 // Use here a pin that can work in analog & digital modes. +}; + +AMxx4067 mux{ PIN_EN, PIN_S0, PIN_S1, PIN_S2, PIN_S3 }; // 16:1 Multiplexer. +// Other possible types are: +//AMxx4051 mux{ PIN_EN, PIN_S0, PIN_S1, PIN_S2 }; // 8:1 Multiplexer. +//AMxx4052 mux{ PIN_EN, PIN_S0, PIN_S1 }; // Dual 4:1 Multiplexer. +//AMxx4053 mux{ PIN_EN, PIN_S0 }; // Triple 2:1 Multiplexer. + +void setup() { + Serial.begin(9600); + while (!Serial); + + mux.pinMode(PIN_IO, INPUT); // PIN_IO will be used to read from the mux. + mux.enable(); // Enable multiplexer. + for (int channel = 0; channel < 16; channel++) { + int value = mux.analogRead(channel); // Do analog read. + Serial.println(value); + } + Serial.println(); + + mux.pinMode(PIN_IO, INPUT_PULLUP); // Enable weak pull up resistor. + for (int channel = 0; channel < 16; channel++) { + int value = mux.digitalRead(channel); // Do digital read. + Serial.println(value); + } + Serial.println(); + + mux.pinMode(PIN_IO, OUTPUT); // Switch to write mode. + for (int channel = 0; channel < 16; channel++) { + int value = channel % 2; + mux.digitalWrite(channel, value); // Do digital write (multiplexed). + Serial.println(value); + } + Serial.println(); + mux.disable(); // Switch off multiplexer. +} + +void loop() { } diff --git a/avr/libraries/AnalogMultiplexer/keywords.txt b/avr/libraries/AnalogMultiplexer/keywords.txt new file mode 100644 index 0000000..d19998a --- /dev/null +++ b/avr/libraries/AnalogMultiplexer/keywords.txt @@ -0,0 +1,26 @@ +####################################### +# Syntax Coloring Map for +# AnalogMultiplexer +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +AnalogMultiplexer KEYWORD1 +AMxx40xx KEYWORD1 +AMxx4051 KEYWORD1 +AMxx4052 KEYWORD1 +AMxx4053 KEYWORD1 +AMxx4067 KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +enable KEYWORD2 +disable KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### \ No newline at end of file diff --git a/avr/libraries/AnalogMultiplexer/library.properties b/avr/libraries/AnalogMultiplexer/library.properties new file mode 100644 index 0000000..4e30139 --- /dev/null +++ b/avr/libraries/AnalogMultiplexer/library.properties @@ -0,0 +1,9 @@ +name=AnalogMultiplexer +version=1.0.1 +author=Julian Sanin +maintainer=Julian Sanin +sentence=A library to interface with analog multiplexers. +paragraph=Supports 4051, 4052, 4053, and 4067 series multiplexers. +category=Uncategorized +url=https://github.com/j54n1n/arduinorobot +architectures=avr diff --git a/avr/libraries/AnalogMultiplexer/src/AnalogMultiplexer.cpp b/avr/libraries/AnalogMultiplexer/src/AnalogMultiplexer.cpp new file mode 100644 index 0000000..780d73e --- /dev/null +++ b/avr/libraries/AnalogMultiplexer/src/AnalogMultiplexer.cpp @@ -0,0 +1,76 @@ +/* + * Library for the CMOS 40xx analog multiplexer series. + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Julian Sanin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "AnalogMultiplexer.h" + +AnalogMultiplexer::AnalogMultiplexer(uint8_t pinEnable) { + _pinEnable = pinEnable; + _pinCommon = NOT_A_PIN; + if (NOT_A_PIN != _pinEnable) { + /*Arduino*/::pinMode(_pinEnable, OUTPUT); + } +} + +void AnalogMultiplexer::enable() { + if (NOT_A_PIN != _pinEnable) { + /*Arduino*/::digitalWrite(_pinEnable, LOW); + } +} + +void AnalogMultiplexer::disable() { + if (NOT_A_PIN != _pinEnable) { + /*Arduino*/::digitalWrite(_pinEnable, HIGH); + } +} + +void AnalogMultiplexer::pinMode(uint8_t pinCommon, uint8_t mode) { + if (NOT_A_PIN != digitalPinToPort(pinCommon)) { + _pinCommon = pinCommon; + /*Arduino*/::pinMode(_pinCommon, mode); + } else { + _pinCommon = NOT_A_PIN; + } +} + +void AnalogMultiplexer::digitalWrite(uint8_t channel, uint8_t value) { + if ((NOT_A_PIN != _pinCommon) && (NOT_A_PIN != selectChannel(channel))) { + /*Arduino*/::digitalWrite(_pinCommon, value); + } +} + +int AnalogMultiplexer::digitalRead(uint8_t channel) { + if ((NOT_A_PIN != _pinCommon) && (NOT_A_PIN != selectChannel(channel))) { + return /*Arduino*/::digitalRead(_pinCommon); + } + return LOW; +} + +int AnalogMultiplexer::analogRead(uint8_t channel) { + if ((NOT_A_PIN != _pinCommon) && (NOT_A_PIN != selectChannel(channel))) { + return /*Arduino*/::analogRead(_pinCommon); + } + return 0; +} diff --git a/avr/libraries/AnalogMultiplexer/src/AnalogMultiplexer.h b/avr/libraries/AnalogMultiplexer/src/AnalogMultiplexer.h new file mode 100644 index 0000000..469b62a --- /dev/null +++ b/avr/libraries/AnalogMultiplexer/src/AnalogMultiplexer.h @@ -0,0 +1,167 @@ +/* + * Library for the CMOS 40xx analog multiplexer series. + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Julian Sanin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef ANALOG_MULTIPLEXER_H +#define ANALOG_MULTIPLEXER_H + +#include + +/// CMOS Logic Analog Multiplexer and Demultiplexer. +class AnalogMultiplexer { + + /// Channel enable. + uint8_t _pinEnable; + + /// Channel common input or output. + uint8_t _pinCommon; + +protected: + /// + /// Select channel (from 0 to MAX) to be connected to common pin. + /// + virtual uint8_t selectChannel(uint8_t channel) = 0; + +public: + explicit AnalogMultiplexer(uint8_t pinEnable); + + /// Enables the analog multiplexer channels. + void enable(); + + /// Disables the analog multiplexer channels. + void disable(); + + /// + /// Configures the specified common channel pin to behave either as an input + /// or an output. + /// + /// + /// The pin number of whose mode you wish to set. The selected pin will be + /// used for , + /// , and + /// . + /// + /// + /// , , or + /// . + /// + void pinMode(uint8_t pinCommon, uint8_t mode); + + /// + /// Write a or a value to a specified + /// common channel pin. + /// + /// + /// + /// The channel number. + /// + /// + /// or . + /// + void digitalWrite(uint8_t channel, uint8_t value); + + /// + /// Reads the value from a specified common channel pin, either + /// or . + /// + /// + /// The channel number of the multiplexer pin you want to read. + /// + /// + /// or . + /// + int digitalRead(uint8_t channel); + + /// + /// Reads the value from the specified common channel pin. + /// + /// + /// The channel number of the multiplexer pin you want to read. + /// + /// + /// 0 to 1023. + /// + int analogRead(uint8_t channel); +}; + +/// +/// Generic class for all types of analog mulitplexer with selector pins. +/// +template +class AMxx40xx : public AnalogMultiplexer { + + enum { MAX_SELECTORS = sizeof...(Args) }; + + /// 2^n selectors for each channel. + uint8_t _pinSelectors[MAX_SELECTORS]; + + /// + /// See . + /// + uint8_t selectChannel(uint8_t channel) { + if ((1 << MAX_SELECTORS) > channel) { + for (uint8_t i = 0; i < MAX_SELECTORS; i++) { + const uint8_t pinSelector = _pinSelectors[i]; + /*Arduino*/::digitalWrite(pinSelector, bitRead(channel, i)); + } + return channel + 1; + } + return NOT_A_PIN; + } + +public: + /// + /// Setup an analog multiplexer with given enable pin and selector pins. + /// + AMxx40xx(uint8_t pinEnable, Args... pinSelector) + : AnalogMultiplexer(pinEnable), _pinSelectors{pinSelector...} { + for (uint8_t i = 0; i < MAX_SELECTORS; i++) { + /*Arduino*/::pinMode(_pinSelectors[i], OUTPUT); + } + } +}; + +/// +/// 4051 Series Single 8:1 Analog Multiplexer. +/// +using AMxx4051 = AMxx40xx; + +/// +/// 4052 Series Dual 4:1 Analog Multiplexer. +/// +using AMxx4052 = AMxx40xx; + +/// +/// 4053 Series Triple 2:1 Analog Multiplexer. Assuming all 3 selectors are tied +/// together. +/// +using AMxx4053 = AMxx40xx; + +/// +/// 4067 Series Single 16:1 Analog Multiplexer. +/// +using AMxx4067 = AMxx40xx; + +#endif //ANALOG_MULTIPLEXER diff --git a/avr/libraries/IntegerEasyTransfer/README.txt b/avr/libraries/IntegerEasyTransfer/README.txt new file mode 100644 index 0000000..7ff0463 --- /dev/null +++ b/avr/libraries/IntegerEasyTransfer/README.txt @@ -0,0 +1,97 @@ +/******************************************************************************* +* IntegerEasyTransfer 1.1.1 library modified by Julian Sanin, sourced from: +* +* EasyTransfer Arduino Library v2.1 +* details and example sketch: +* http://www.billporter.info/easytransfer-arduino-library/ +* +* Brought to you by: +* Bill Porter +* www.billporter.info +* +* Major props to Mathieu Alorent (kumy) for +* I2C version and the pretty pictures. +* +* +* Lib version history +* 1.0 Created +* 1.1 Fixed dumb Copy-paste error in header file +* Added a keyword file +* 1.5 Forked lib into Software and Hardware Serial branches, I don't know a +* better way added passing in of Serial port of different types +* 1.6 Fixed bug where it wasn't clearing out the buffers if the CheckSum +* failed, I'm good at dumb mistakes +* 1.7 Fixed a bug where the receive function could block for too long and +* never process data correctly +* Organized the examples to be Arduino IDE compatible +* 1.8 +* Now Arduino 1.0 compatible! +* 1.81 +* Made it more cross compatible. Man, They really made us work for this +* one. +* 2.0 +* Combined SoftEasyTransfer with the other two to make everything one +* repo +* Added EasyTransferVirtualWire library for use with Virtual Wire and +* cheap radios. +* 2.0.1 +* VirtualWire version tested by garth@netram, bugs fixed. +* 2.1 +* Changes RX parsing buffer to dynamic allocation to conserve RAM. +* 1.0.0 +* Imported EasyTransfer library as IntegerEasyTransfer. +* Backported ArduinoRobot modifications and restarted version numbering. +* The library supports a maximum of 20 uint8_t or 10 int16_t values. +* Mixed uint8_t and int16_t are allowed but care should be taken that the +* values do not overflow the data buffer. +* 1.1.0 +* Added new classes to support two way communications and extended +* messages and software reset. +* 1.1.1 +* Added overloaded write method to TwoWayIntegerEasyTransfer. +* Initalized RX packet variables to zero. +* +* +* Limits of the Library +* You can change the Serial port, +* but the Struct size must not pass 255 bytes +* VirtualWire Version Struct can'e be bigger then 26 bytes +* +* The protcol is as follows: +* Header(0x06,0x85),SizeofPayload,Payload,Checksum +* +* +* This program is free software: you can redistribute it and/or modify it under +* the terms of the GNU General Public License as published by the Free Software +* Foundation, either version 3 of the License, or(at your option) any later +* version. +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* +* This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 +* Unported License. To view a copy of this license, visit +* http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to Creative +* Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. +*******************************************************************************/ + + +********************To Install************************************* + +To install, unzip and place 'EasyTransfer' folder into your 'C:\Users\{user name}\Documents\Arduino\libraries' folder or '{Arduino IDE path}\hardware\libraries" or {Arduino IDE path}\libraries" directory. + +Restart the Arduino IDE, look for the Library under "Sketch" -> "Import Library". You can also try the examples by finding them +under "File" -> "Examples" -> "EasyTransfer". + +All uses of the library are in the example sketchs. + + +******************************************************************* + + +Library now has two versions, one for regular hardware Serial, one for use with the NewSoftSerial library +making any Arduino pin capable of transfering data back and forth easily. + +See the examples to find out how to use the library. \ No newline at end of file diff --git a/avr/libraries/IntegerEasyTransfer/examples/IntegerEasyTransfer_Interop_Example/IntegerEasyTransfer_Interop_Example.ino b/avr/libraries/IntegerEasyTransfer/examples/IntegerEasyTransfer_Interop_Example/IntegerEasyTransfer_Interop_Example.ino new file mode 100644 index 0000000..8517c01 --- /dev/null +++ b/avr/libraries/IntegerEasyTransfer/examples/IntegerEasyTransfer_Interop_Example/IntegerEasyTransfer_Interop_Example.ino @@ -0,0 +1,67 @@ +#include +#include + +// New custom feature. +struct MyFeature : public IntegerEasyTransferFeature { + + enum { + MY_COMMAND = 0x0F, + // Add further commands if needed. + }; + + uint8_t data = 0x00; + + bool handleMessage(uint8_t command, IntegerEasyTransfer & request) { + // Filter commands that you are interested in. + switch(command) { + case MY_COMMAND: + data = request.readByte(); + return true; + default: + // Got a message that is not handled by this feature. + return false; + } + } + + void reset() { + data = 0x00; + } + + void sendNewData() { + // Extended feature messages uses following format for sending data: + TwoWayIntegerEasyTransfer.writeByte( + TwoWayIntegerEasyTransfer.MESSAGE_FEATURE + ); + TwoWayIntegerEasyTransfer.writeByte(MY_COMMAND); + TwoWayIntegerEasyTransfer.writeByte(++data); + TwoWayIntegerEasyTransfer.sendData(); + } +}; + +// Instance of the feature. +MyFeature myFeature; + +// Create a instance of the feature manager. +IntegerEasyTransferFeatureManager featureManager; + +void setup() { + // Begin communication channel. + Serial.begin(9600); + TwoWayIntegerEasyTransfer.begin(&Serial); + // Attach callbacks and add features. + TwoWayIntegerEasyTransfer.attach([]() { doSystemReset(); }); + featureManager.addFeature(myFeature); + // Perform software reset manually. + doSystemReset(); +} + +void loop() { + // Keep message pumping up and running. + if (TwoWayIntegerEasyTransfer.hasReceivedData()) { + TwoWayIntegerEasyTransfer.processInput(); + } +} + +void doSystemReset() { + featureManager.reset(); +} \ No newline at end of file diff --git a/avr/libraries/IntegerEasyTransfer/examples/IntegerEasyTransfer_RX_Example/IntegerEasyTransfer_RX_Example.ino b/avr/libraries/IntegerEasyTransfer/examples/IntegerEasyTransfer_RX_Example/IntegerEasyTransfer_RX_Example.ino new file mode 100644 index 0000000..b89777d --- /dev/null +++ b/avr/libraries/IntegerEasyTransfer/examples/IntegerEasyTransfer_RX_Example/IntegerEasyTransfer_RX_Example.ino @@ -0,0 +1,45 @@ +#include + +//create object +IntegerEasyTransfer ET; + +struct RECEIVE_DATA_STRUCTURE { + //put your variable definitions here for the data you want to receive + //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO + int16_t blinks; + int16_t pause; +}; + +//give a name to the group of data +RECEIVE_DATA_STRUCTURE mydata; + +void setup() { + Serial.begin(9600); + //start the library, pass in the name of the serial port. Can be Serial, + //Serial1, Serial2, etc. + ET.begin(&Serial); + + pinMode(13, OUTPUT); + +} + +void loop() { + //check and see if a data packet has come in. + if (ET.receiveData()) { + //this is how you access the variables. + //[name of the group].[variable name] + mydata.blinks = ET.readInt(); + mydata.pause = ET.readInt(); + //since we have data, we will blink it out. + for (int i = mydata.blinks; i > 0; i--) { + digitalWrite(13, HIGH); + delay(mydata.pause * 100); + digitalWrite(13, LOW); + delay(mydata.pause * 100); + } + } + + //you should make this delay shorter then your transmit delay or else + //messages could be lost + delay(250); +} diff --git a/avr/libraries/IntegerEasyTransfer/examples/IntegerEasyTransfer_TX_Example/IntegerEasyTransfer_TX_Example.ino b/avr/libraries/IntegerEasyTransfer/examples/IntegerEasyTransfer_TX_Example/IntegerEasyTransfer_TX_Example.ino new file mode 100644 index 0000000..ae7e84c --- /dev/null +++ b/avr/libraries/IntegerEasyTransfer/examples/IntegerEasyTransfer_TX_Example/IntegerEasyTransfer_TX_Example.ino @@ -0,0 +1,46 @@ +#include + +//create object +IntegerEasyTransfer ET; + +struct SEND_DATA_STRUCTURE { + //put your variable definitions here for the data you want to send + //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO + int16_t blinks; + int16_t pause; +}; + +//give a name to the group of data +SEND_DATA_STRUCTURE mydata; + +void setup() { + Serial.begin(9600); + //start the library, pass in the name of the serial port. Can be Serial, + //Serial1, Serial2, etc. + ET.begin(&Serial); + + pinMode(13, OUTPUT); + + randomSeed(analogRead(0)); + +} + +void loop() { + //this is how you access the variables. [name of the group].[variable name] + mydata.blinks = random(5); + mydata.pause = random(5); + //send the data + ET.writeInt(mydata.blinks); + ET.writeInt(mydata.pause); + ET.sendData(); + + //Just for fun, we will blink it out too + for (int i = mydata.blinks; i > 0; i--) { + digitalWrite(13, HIGH); + delay(mydata.pause * 100); + digitalWrite(13, LOW); + delay(mydata.pause * 100); + } + + delay(5000); +} diff --git a/avr/libraries/IntegerEasyTransfer/extras/I2C_Wiring.png b/avr/libraries/IntegerEasyTransfer/extras/I2C_Wiring.png new file mode 100644 index 0000000..4c15cd7 Binary files /dev/null and b/avr/libraries/IntegerEasyTransfer/extras/I2C_Wiring.png differ diff --git a/avr/libraries/IntegerEasyTransfer/extras/UARTS_Wiring.png b/avr/libraries/IntegerEasyTransfer/extras/UARTS_Wiring.png new file mode 100644 index 0000000..48ba613 Binary files /dev/null and b/avr/libraries/IntegerEasyTransfer/extras/UARTS_Wiring.png differ diff --git a/avr/libraries/IntegerEasyTransfer/keywords.txt b/avr/libraries/IntegerEasyTransfer/keywords.txt new file mode 100644 index 0000000..19105db --- /dev/null +++ b/avr/libraries/IntegerEasyTransfer/keywords.txt @@ -0,0 +1,43 @@ +####################################### +# Syntax Coloring Map +# IntegerEasyTransfer +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +IntegerEasyTransfer KEYWORD1 +IntegerEasyTransferFeature KEYWORD1 +IntegerEasyTransferFeatureManager KEYWORD1 +TwoWayIntegerEasyTransfer KEYWORD1 +DefaultMessageCallbackFunction KEYWORD1 +FeatureMessageCallbackFunction KEYWORD1 +SystemResetCallbackFunction KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +sendData KEYWORD2 +receiveData KEYWORD2 +writeByte KEYWORD2 +writeInt KEYWORD2 +write KEYWORD2 +readByte KEYWORD2 +readInt KEYWORD2 +sendSystemReset KEYWORD2 +hasReceivedData KEYWORD2 +processInput KEYWORD2 +attach KEYWORD2 +addFeature KEYWORD2 +handleMessage KEYWORD2 +reset KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +MESSAGE_FEATURE LITERAL1 +MESSAGE_SYSTEM_RESET LITERAL1 \ No newline at end of file diff --git a/avr/libraries/IntegerEasyTransfer/library.properties b/avr/libraries/IntegerEasyTransfer/library.properties new file mode 100644 index 0000000..6e134d0 --- /dev/null +++ b/avr/libraries/IntegerEasyTransfer/library.properties @@ -0,0 +1,9 @@ +name=IntegerEasyTransfer +version=1.1.1 +author=Bill Porter , Julian Sanin +maintainer=Julian Sanin +sentence=A library to interface Arduino boards. +paragraph=Supports Arduino Robot Control & Motor Board. +category=Uncategorized +url=https://github.com/j54n1n/arduinorobot +architectures=avr diff --git a/avr/libraries/IntegerEasyTransfer/src/IntegerEasyTransfer.cpp b/avr/libraries/IntegerEasyTransfer/src/IntegerEasyTransfer.cpp new file mode 100644 index 0000000..67758e8 --- /dev/null +++ b/avr/libraries/IntegerEasyTransfer/src/IntegerEasyTransfer.cpp @@ -0,0 +1,208 @@ +/******************************************************************************* +* IntegerEasyTransfer 1.1.1 library modified by Julian Sanin, sourced from: +* +* EasyTransfer Arduino Library v2.1 +* details and example sketch: +* http://www.billporter.info/easytransfer-arduino-library/ +* +* Brought to you by: +* Bill Porter +* www.billporter.info +* +* Major props to Mathieu Alorent (kumy) for +* I2C version and the pretty pictures. +* +* +* Lib version history +* 1.0 Created +* 1.1 Fixed dumb Copy-paste error in header file +* Added a keyword file +* 1.5 Forked lib into Software and Hardware Serial branches, I don't know a +* better way added passing in of Serial port of different types +* 1.6 Fixed bug where it wasn't clearing out the buffers if the CheckSum +* failed, I'm good at dumb mistakes +* 1.7 Fixed a bug where the receive function could block for too long and +* never process data correctly +* Organized the examples to be Arduino IDE compatible +* 1.8 +* Now Arduino 1.0 compatible! +* 1.81 +* Made it more cross compatible. Man, They really made us work for this +* one. +* 2.0 +* Combined SoftEasyTransfer with the other two to make everything one +* repo +* Added EasyTransferVirtualWire library for use with Virtual Wire and +* cheap radios. +* 2.0.1 +* VirtualWire version tested by garth@netram, bugs fixed. +* 2.1 +* Changes RX parsing buffer to dynamic allocation to conserve RAM. +* 1.0.0 +* Imported EasyTransfer library as IntegerEasyTransfer. +* Backported ArduinoRobot modifications and restarted version numbering. +* The library supports a maximum of 20 uint8_t or 10 int16_t values. +* Mixed uint8_t and int16_t are allowed but care should be taken that the +* values do not overflow the data buffer. +* 1.1.0 +* Added new classes to support two way communications and extended +* messages and software reset. +* 1.1.1 +* Added overloaded write method to TwoWayIntegerEasyTransfer. +* Initalized RX packet variables to zero. +* +* +* Limits of the Library +* You can change the Serial port, +* but the Struct size must not pass 255 bytes +* VirtualWire Version Struct can'e be bigger then 26 bytes +* +* The protcol is as follows: +* Header(0x06,0x85),SizeofPayload,Payload,Checksum +* +* +* This program is free software: you can redistribute it and/or modify it under +* the terms of the GNU General Public License as published by the Free Software +* Foundation, either version 3 of the License, or(at your option) any later +* version. +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* +* This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 +* Unported License. To view a copy of this license, visit +* http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to Creative +* Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. +*******************************************************************************/ +#include "IntegerEasyTransfer.h" + +void IntegerEasyTransfer::begin(Stream *theStream) { + _rx_len = 0; + _rx_array_inx = 0; + _stream = theStream; + + _resetData(); +} + +//Sends out data in binary, with header, length info and checksum +void IntegerEasyTransfer::sendData() { + uint8_t CS = _size; + _stream->write(0x06); + _stream->write(0x85); + _stream->write(_size); + for (int i = 0; i<_size; i++) { + CS ^= *(_data + i); + _stream->write(*(_data + i)); + } + _stream->write(CS); + + _resetData(); +} + +bool IntegerEasyTransfer::receiveData() { + + //start off by looking for the header bytes. If they were already found in a + //previous call, skip it. + if (_rx_len == 0) { + //this size check may be redundant due to the size check below, but for + //now I'll leave it the way it is. + if (_stream->available() >= 3) { + //this will block until a 0x06 is found or buffer size becomes less + //then 3. + while (_stream->read() != 0x06) { + //This will trash any preamble junk in the serial buffer + //but we need to make sure there is enough in the buffer to + //process while we trash the rest if the buffer becomes too + //empty, we will escape and try again on the next call + if (_stream->available() < 3) + return false; + } + if (_stream->read() == 0x85) { + _rx_len = _stream->read(); + + _resetData(); + } + } + } + + //we get here if we already found the header bytes, the struct size matched + //what we know, and now we are byte aligned. + if (_rx_len != 0) { + while (_stream->available() && _rx_array_inx <= _rx_len) { + _data[_rx_array_inx++] = _stream->read(); + } + + if (_rx_len == (_rx_array_inx - 1)) { + //seem to have got whole message + //last uint8_t is CS + _calc_CS = _rx_len; + for (int i = 0; i<_rx_len; i++) { + _calc_CS ^= _data[i]; + } + + if (_calc_CS == _data[_rx_array_inx - 1]) {//CS good + + _size = _rx_len; + + _rx_len = 0; + _rx_array_inx = 0; + return true; + } + + else { + + _resetData(); + + //failed checksum, need to clear this out anyway + _rx_len = 0; + _rx_array_inx = 0; + return false; + } + + } + } + + return false; +} + +void IntegerEasyTransfer::writeByte(uint8_t data) { + if (_position < MAX_DATA_SIZE) { + _data[_position++] = data; + _size++; + } +} + +void IntegerEasyTransfer::writeInt(int16_t data) { + if (_position < (MAX_DATA_SIZE - 1)) { + _data[_position++] = (data >> 8); + _data[_position++] = data; + _size += 2; + } +} + +uint8_t IntegerEasyTransfer::readByte() { + if (_position >= _size) { + return 0; + } + return _data[_position++]; +} + +int16_t IntegerEasyTransfer::readInt() { + if ((_position + 1) >= _size) { + return 0; + } + int16_t data_1 = (_data[_position++] << 8); + int16_t data_2 = _data[_position++]; + int16_t data = data_1 | data_2; + return data; +} + +void IntegerEasyTransfer::_resetData() { + for (uint8_t i = 0; i < MAX_DATA_SIZE; i++) { + _data[i] = 0; + } + _size = 0; + _position = 0; +} diff --git a/avr/libraries/IntegerEasyTransfer/src/IntegerEasyTransfer.h b/avr/libraries/IntegerEasyTransfer/src/IntegerEasyTransfer.h new file mode 100644 index 0000000..5f76e9e --- /dev/null +++ b/avr/libraries/IntegerEasyTransfer/src/IntegerEasyTransfer.h @@ -0,0 +1,160 @@ +/******************************************************************************* +* IntegerEasyTransfer 1.1.1 library modified by Julian Sanin, sourced from: +* +* EasyTransfer Arduino Library v2.1 +* details and example sketch: +* http://www.billporter.info/easytransfer-arduino-library/ +* +* Brought to you by: +* Bill Porter +* www.billporter.info +* +* Major props to Mathieu Alorent (kumy) for +* I2C version and the pretty pictures. +* +* +* Lib version history +* 1.0 Created +* 1.1 Fixed dumb Copy-paste error in header file +* Added a keyword file +* 1.5 Forked lib into Software and Hardware Serial branches, I don't know a +* better way added passing in of Serial port of different types +* 1.6 Fixed bug where it wasn't clearing out the buffers if the CheckSum +* failed, I'm good at dumb mistakes +* 1.7 Fixed a bug where the receive function could block for too long and +* never process data correctly +* Organized the examples to be Arduino IDE compatible +* 1.8 +* Now Arduino 1.0 compatible! +* 1.81 +* Made it more cross compatible. Man, They really made us work for this +* one. +* 2.0 +* Combined SoftEasyTransfer with the other two to make everything one +* repo +* Added EasyTransferVirtualWire library for use with Virtual Wire and +* cheap radios. +* 2.0.1 +* VirtualWire version tested by garth@netram, bugs fixed. +* 2.1 +* Changes RX parsing buffer to dynamic allocation to conserve RAM. +* 1.0.0 +* Imported EasyTransfer library as IntegerEasyTransfer. +* Backported ArduinoRobot modifications and restarted version numbering. +* The library supports a maximum of 20 uint8_t or 10 int16_t values. +* Mixed uint8_t and int16_t are allowed but care should be taken that the +* values do not overflow the data buffer. +* 1.1.0 +* Added new classes to support two way communications and extended +* messages and software reset. +* 1.1.1 +* Added overloaded write method to TwoWayIntegerEasyTransfer. +* Initalized RX packet variables to zero. +* +* +* Limits of the Library +* You can change the Serial port, +* but the Struct size must not pass 255 bytes +* VirtualWire Version Struct can'e be bigger then 26 bytes +* +* The protcol is as follows: +* Header(0x06,0x85),SizeofPayload,Payload,Checksum +* +* +* This program is free software: you can redistribute it and/or modify it under +* the terms of the GNU General Public License as published by the Free Software +* Foundation, either version 3 of the License, or(at your option) any later +* version. +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* +* This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 +* Unported License. To view a copy of this license, visit +* http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to Creative +* Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. +*******************************************************************************/ +#ifndef INTEGER_EASY_TRANSFER_H +#define INTEGER_EASY_TRANSFER_H + +#include +#include + +class IntegerEasyTransfer { + + enum { MAX_DATA_SIZE = 20 }; + +public: + /// + /// Start protocol with given transport stream. + /// + /// + /// The reference to the transport stream implementation. + /// + void begin(Stream *theStream); + + /// + /// Sends out data in binary, with header, length info and checksum. + /// + void sendData(); + + /// + /// Check if data has been received from the transport stream. + /// + /// + /// true if data has been received otherwise false. + /// + bool receiveData(); + + /// + /// Adds a byte to the protocol buffer. See also: + /// + /// + /// + /// The byte to be inserted to the buffer. + /// + void writeByte(uint8_t data); + + /// + /// Adds a integer to the protocol buffer. See also: + /// + /// + /// + /// The integer to be inserted to the buffer. + /// + void writeInt(int16_t data); + + /// + /// Retrives a byte from the protocol buffer. See also: + /// + /// + /// + /// The byte from the buffer otherwise 0 if an error occurred. + /// + uint8_t readByte(); + + /// + /// Retrives a integer from the protocol buffer. See also: + /// + /// + /// + /// The integer from the buffer otherwise 0 if an error occurred. + /// + int16_t readInt(); + +private: + void _resetData(); + + uint8_t _data[MAX_DATA_SIZE]; //data storage, for both read and send + uint8_t _position; + + Stream *_stream; + uint8_t _size; //size of data in bytes both for read and send + uint8_t _rx_array_inx; //index for RX parsing buffer + uint8_t _rx_len; //RX packet length according to the packet + uint8_t _calc_CS; //calculated Chacksum +}; + +#endif diff --git a/avr/libraries/IntegerEasyTransfer/src/IntegerEasyTransferFeature.h b/avr/libraries/IntegerEasyTransfer/src/IntegerEasyTransferFeature.h new file mode 100644 index 0000000..a4bbb11 --- /dev/null +++ b/avr/libraries/IntegerEasyTransfer/src/IntegerEasyTransferFeature.h @@ -0,0 +1,63 @@ +/* + * Library for configurable and easy transfers. + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Julian Sanin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef INTEGER_EASY_TRANSFER_FEATURE_H +#define INTEGER_EASY_TRANSFER_FEATURE_H + +#include + +class IntegerEasyTransfer; + +class IntegerEasyTransferFeature { + + // Link to next feature item, used by FeatureManager. + IntegerEasyTransferFeature * _nextFeature = nullptr; + friend class IntegerEasyTransferFeatureManager; + +public: + /// + /// Handle the incoming request message. + /// + /// + /// The first command byte of the incoming request message. + /// + /// + /// Further data messages of the incoming request. + /// + /// + /// True if the message has been handled otherwise false. + /// + virtual bool handleMessage( + uint8_t command, IntegerEasyTransfer & request + ) = 0; + + /// + /// System reset command. + /// + virtual void reset() = 0; +}; + +#endif // INTEGER_EASY_TRANSFER_FEATURE_H diff --git a/avr/libraries/IntegerEasyTransfer/src/IntegerEasyTransferFeatureManager.cpp b/avr/libraries/IntegerEasyTransfer/src/IntegerEasyTransferFeatureManager.cpp new file mode 100644 index 0000000..9fd1ec3 --- /dev/null +++ b/avr/libraries/IntegerEasyTransfer/src/IntegerEasyTransferFeatureManager.cpp @@ -0,0 +1,81 @@ +/* + * Library for configurable and easy transfers. + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Julian Sanin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "IntegerEasyTransferFeatureManager.h" +#include "TwoWayIntegerEasyTransfer.h" + +static IntegerEasyTransferFeatureManager * _featureManager = nullptr; + +IntegerEasyTransferFeatureManager::IntegerEasyTransferFeatureManager() + : _features{ nullptr } { + _featureManager = this; + // Handle extended messages on connected features. + TwoWayIntegerEasyTransfer.attach( + [](IntegerEasyTransfer & request) { + if (_featureManager != nullptr) { + uint8_t extendedCommand = request.readByte(); + if (!_featureManager->handleMessage(extendedCommand, request)) { + // TODO: Report unhandled message. + } + } + }); +} + +bool IntegerEasyTransferFeatureManager::handleMessage( + uint8_t command, IntegerEasyTransfer & request +) { + IntegerEasyTransferFeature * selectedFeature = _features; + while (selectedFeature != nullptr) { + if (selectedFeature->handleMessage(command, request)) { + return true; + } + selectedFeature = selectedFeature->_nextFeature; + } + return false; +} + +void IntegerEasyTransferFeatureManager::reset() { + IntegerEasyTransferFeature * selectedFeature = _features; + while (selectedFeature != nullptr) { + selectedFeature->reset(); + selectedFeature = selectedFeature->_nextFeature; + } +} + +void IntegerEasyTransferFeatureManager::addFeature( + IntegerEasyTransferFeature & feature) { + if (_features != nullptr) { + IntegerEasyTransferFeature * selectedFeature = _features; + while (selectedFeature->_nextFeature != nullptr) { + selectedFeature = selectedFeature->_nextFeature; + } + selectedFeature->_nextFeature = &feature; + selectedFeature->_nextFeature = nullptr; + } else { + _features = &feature; + _features->_nextFeature = nullptr; + } +} diff --git a/avr/libraries/IntegerEasyTransfer/src/IntegerEasyTransferFeatureManager.h b/avr/libraries/IntegerEasyTransfer/src/IntegerEasyTransferFeatureManager.h new file mode 100644 index 0000000..e96584f --- /dev/null +++ b/avr/libraries/IntegerEasyTransfer/src/IntegerEasyTransferFeatureManager.h @@ -0,0 +1,53 @@ +/* + * Library for configurable and easy transfers. + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Julian Sanin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef INTEGER_EASY_TRANSFER_FEATURE_MANAGER_H +#define INTEGER_EASY_TRANSFER_FEATURE_MANAGER_H + +#include "IntegerEasyTransferFeature.h" + +class IntegerEasyTransferFeatureManager : public IntegerEasyTransferFeature { + + // List of managed features. + IntegerEasyTransferFeature * _features; + +public: + IntegerEasyTransferFeatureManager(); + + bool handleMessage(uint8_t command, IntegerEasyTransfer & request); + void reset(); + + /// + /// Adds the feature to the manager. See also: + /// + /// + /// + /// The feature to be added. + /// + void addFeature(IntegerEasyTransferFeature & feature); +}; + +#endif // INTEGER_EASY_TRANSFER_FEATURE_MANAGER_H diff --git a/avr/libraries/IntegerEasyTransfer/src/TwoWayIntegerEasyTransfer.cpp b/avr/libraries/IntegerEasyTransfer/src/TwoWayIntegerEasyTransfer.cpp new file mode 100644 index 0000000..f2324d0 --- /dev/null +++ b/avr/libraries/IntegerEasyTransfer/src/TwoWayIntegerEasyTransfer.cpp @@ -0,0 +1,107 @@ +/* + * Library for configurable and easy transfers. + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Julian Sanin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "TwoWayIntegerEasyTransfer.h" + +void CTwoWayIntegerEasyTransfer::begin(Stream * stream) { + _request.begin(stream); + _response.begin(stream); +} + +void CTwoWayIntegerEasyTransfer::sendSystemReset(void) { + // Message format: [SYSTEM_RESET] + writeByte(TwoWayIntegerEasyTransfer.MESSAGE_SYSTEM_RESET); + sendData(); +} + +void CTwoWayIntegerEasyTransfer::sendData() { + _response.sendData(); +} + +void CTwoWayIntegerEasyTransfer::writeByte(uint8_t data) { + _response.writeByte(data); +} + +void CTwoWayIntegerEasyTransfer::write(uint8_t data) { + writeByte(data); +} + +void CTwoWayIntegerEasyTransfer::writeInt(int16_t data) { + _response.writeInt(data); +} + +void CTwoWayIntegerEasyTransfer::write(int16_t data) { + writeInt(data); +} + +bool CTwoWayIntegerEasyTransfer::hasReceivedData(void) { + return _request.receiveData(); +} + +void CTwoWayIntegerEasyTransfer::processInput(void) { + uint8_t command = _request.readByte(); + switch (command) { + case MESSAGE_SYSTEM_RESET: + // Extended system reset callback (0xFF). + if (_systemResetCallbackFunction != nullptr) { + _systemResetCallbackFunction(); + } + break; + case MESSAGE_FEATURE: + // Extended feature message callback (0xF0). + if (_featureMessageCallbackFunction != nullptr) { + _featureMessageCallbackFunction(_request); + } + break; + default: + // Default message callback for commands less than 0xF0. + if (_defaultMessageCallbackFunction != nullptr) { + _defaultMessageCallbackFunction(command, _request); + } + break; + } +} + +void CTwoWayIntegerEasyTransfer::attach( + DefaultMessageCallbackFunction defaultMessageCallbackFunction +) { + _defaultMessageCallbackFunction = defaultMessageCallbackFunction; +} + +void CTwoWayIntegerEasyTransfer::attach( + FeatureMessageCallbackFunction featureMessageCallbackFunction +) { + _featureMessageCallbackFunction = featureMessageCallbackFunction; +} + +void CTwoWayIntegerEasyTransfer::attach( + SystemResetCallbackFunction systemResetCallbackFunction +) { + _systemResetCallbackFunction = systemResetCallbackFunction; +} + +// Make one instance for the user to use. +CTwoWayIntegerEasyTransfer TwoWayIntegerEasyTransfer; diff --git a/avr/libraries/IntegerEasyTransfer/src/TwoWayIntegerEasyTransfer.h b/avr/libraries/IntegerEasyTransfer/src/TwoWayIntegerEasyTransfer.h new file mode 100644 index 0000000..312da7f --- /dev/null +++ b/avr/libraries/IntegerEasyTransfer/src/TwoWayIntegerEasyTransfer.h @@ -0,0 +1,150 @@ +/* + * Library for configurable and easy transfers. + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Julian Sanin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef TWO_WAY_INTEGER_EASY_TRANSFER_H +#define TWO_WAY_INTEGER_EASY_TRANSFER_H + +#include +#include "IntegerEasyTransfer.h" + +class CTwoWayIntegerEasyTransfer { + + using DefaultMessageCallbackFunction = + void(*)(uint8_t command, IntegerEasyTransfer & request); + using FeatureMessageCallbackFunction = + void(*)(IntegerEasyTransfer & request); + using SystemResetCallbackFunction = void(*)(void); + + DefaultMessageCallbackFunction _defaultMessageCallbackFunction = nullptr; + FeatureMessageCallbackFunction _featureMessageCallbackFunction = nullptr; + SystemResetCallbackFunction _systemResetCallbackFunction = nullptr; + + IntegerEasyTransfer _request; + IntegerEasyTransfer _response; + +public: + enum { + /// Extended message for a feature request. + MESSAGE_FEATURE = 0xF0, + /// Extended message for software reset. + MESSAGE_SYSTEM_RESET = 0xF1 + }; + + /// + /// Start protocol with given transport stream. + /// + /// + /// The reference to the transport stream implementation. + /// + void begin(Stream * stream); + + /// Broadcasts a extended system reset message. + void sendSystemReset(void); + + /// + /// Sends out data in binary, with header, length info and checksum. + /// For extended feature messages send in following format: + /// { [MESSAGE_FEATURE]:byte, [EXTENDED_COMMAND]:byte, [PAYLOAD]:byte|int } + /// For default messages omit the MESSAGE_FEATURE prefix. + /// + void sendData(void); + + /// + /// Adds a byte to the protocol buffer. See also: + /// + /// + /// + /// The byte to be inserted to the buffer. + /// + void writeByte(uint8_t data); + + /// + /// Adds a byte to the protocol buffer. See also: + /// + /// + /// + /// The byte to be inserted to the buffer. + /// + void write(uint8_t data); + + /// + /// Adds a integer to the protocol buffer. See also: + /// + /// + /// + /// The integer to be inserted to the buffer. + /// + void writeInt(int16_t data); + + /// + /// Adds a integer to the protocol buffer. See also: + /// + /// + /// + /// The integer to be inserted to the buffer. + /// + void write(int16_t data); + + /// Check wether messages have been received. + /// + /// True if a messages has been recieved otherwise false. + /// + bool hasReceivedData(void); + + /// Process messages after data has been received. + void processInput(void); + + /// + /// Connects callback function to listen for default messages. + /// + /// + /// The default message callback function of type + /// void(*)(uint8_t command, IntegerEasyTransfer & request) or nullptr. + /// + void attach(DefaultMessageCallbackFunction defaultMessageCallbackFunction); + + /// + /// Connects callback function to listen for extended feature messages. + /// + /// + /// The feature message callback function of type + /// void(*)(IntegerEasyTransfer & request) or a nullptr. + /// + void attach(FeatureMessageCallbackFunction featureMessageCallbackFunction); + + /// + /// Connects callback function to listen for system reset messages. + /// + /// + /// The system reset callback function of type void(*)(void) or a nullptr. + /// + void attach(SystemResetCallbackFunction systemResetCallbackFunction); +}; + +extern CTwoWayIntegerEasyTransfer TwoWayIntegerEasyTransfer; + +#endif + diff --git a/avr/libraries/IntegerEasyTransfer/tests/IntegerEasyTransfer/IntegerEasyTransfer.ino b/avr/libraries/IntegerEasyTransfer/tests/IntegerEasyTransfer/IntegerEasyTransfer.ino new file mode 100644 index 0000000..673529e --- /dev/null +++ b/avr/libraries/IntegerEasyTransfer/tests/IntegerEasyTransfer/IntegerEasyTransfer.ino @@ -0,0 +1,125 @@ +/* + * Unit test for IntegerEasyTransfer library. + * Run this test after adding changes to the library. To run this sketch start + * by downloading and installing the ArduinoUnit library into your sketchbook + * and then open the test example sketches of this library. + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Julian Sanin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +void setup() { + Serial.begin(9600); + while (!Serial); + Test::out = &Serial; +} + +void loop() { + Test::run(); +} + +const uint8_t DATA_TRASH{ 0x55 }; +const uint8_t HEADER1{ 0x06 }; +const uint8_t HEADER0{ 0x85 }; +const uint8_t DATA_SIZE{ 3 }; +const uint8_t DATA_BYTE{ 0x01 }; +const uint8_t DATA_INT1{ 0x02 }; +const uint8_t DATA_INT0{ 0x03 }; +const int16_t DATA_INT{ (DATA_INT1 << 8) | (DATA_INT0) }; +const uint8_t CRC{ DATA_SIZE ^ DATA_BYTE ^ DATA_INT1 ^ DATA_INT0 }; + +const char partialData[]{ + DATA_TRASH, + static_cast(HEADER1), static_cast(HEADER0), + 0 +}; + +const char fullData[]{ + static_cast(HEADER1), static_cast(HEADER0), + DATA_SIZE, DATA_BYTE, DATA_INT1, DATA_INT0, CRC, + 0 +}; + +test(IntegerEasyTransfer_receiveData) { + bool hasReceivedData; + FakeStreamBuffer fakeStreamBuffer; + IntegerEasyTransfer integerEasyTransfer; + + integerEasyTransfer.begin(&fakeStreamBuffer); + + fakeStreamBuffer.nextBytes(partialData); + hasReceivedData = integerEasyTransfer.receiveData(); + assertFalse(hasReceivedData); + fakeStreamBuffer.reset(); + + fakeStreamBuffer.nextBytes(fullData); + hasReceivedData = integerEasyTransfer.receiveData(); + assertTrue(hasReceivedData); + fakeStreamBuffer.reset(); + + assertEqual(integerEasyTransfer.readByte(), DATA_BYTE); + assertEqual(integerEasyTransfer.readInt(), DATA_INT); +} + +test(IntegerEasyTransfer_sendData) { + FakeStream fakeStream; + IntegerEasyTransfer integerEasyTransfer; + + integerEasyTransfer.begin(&fakeStream); + integerEasyTransfer.writeByte(DATA_BYTE); + integerEasyTransfer.writeInt(DATA_INT); + integerEasyTransfer.sendData(); + + assertEqual(fakeStream.bytesWritten(), fullData); +} + +const uint8_t DATA_BYTE_MIN{ 0 }; +const uint8_t DATA_BYTE_MAX{ 255 }; +const int16_t DATA_INT_MIN{ -32768 }; +const int16_t DATA_INT_MAX{ 32767 }; + +test(IntegerEasyTransfer_writeByte) { + FakeStream fakeStream; + IntegerEasyTransfer integerEasyTransfer; + + integerEasyTransfer.begin(&fakeStream); + integerEasyTransfer.writeByte(DATA_BYTE_MIN); + integerEasyTransfer.writeByte(DATA_BYTE_MAX); + + const char * expected{ "" }; + assertEqual(fakeStream.bytesWritten(), expected); +} + +test(IntegerEasyTransfer_writeInt) { + FakeStream fakeStream; + IntegerEasyTransfer integerEasyTransfer; + + integerEasyTransfer.begin(&fakeStream); + integerEasyTransfer.writeInt(DATA_INT_MIN); + integerEasyTransfer.writeInt(DATA_INT_MAX); + + const char * expected{ "" }; + assertEqual(fakeStream.bytesWritten(), expected); +} diff --git a/avr/libraries/IntegerEasyTransfer/tests/README.md b/avr/libraries/IntegerEasyTransfer/tests/README.md new file mode 100644 index 0000000..c816c64 --- /dev/null +++ b/avr/libraries/IntegerEasyTransfer/tests/README.md @@ -0,0 +1,14 @@ +# Unit Testing IntegerEasyTransfer library + +Tests tests are written using the +[ArduinoUnit library version 2.2.0](https://github.com/mmurdoch/arduinounit). + +Follow the instructions in the ArduinoUnit readme to install the library. + +Compile and upload the test sketch as you would any other sketch. Then open the +Serial Monitor to view the test results. + +If you make changes to the IntegerEasyTransfer library, run the tests in /tests/ +to ensure that your changes have not produced any unexpected errors. + +You should also perform manual tests against actual hardware. diff --git a/avr/libraries/IntegerEasyTransfer/tests/TwoWayIntegerEasyTransfer/TwoWayIntegerEasyTransfer.ino b/avr/libraries/IntegerEasyTransfer/tests/TwoWayIntegerEasyTransfer/TwoWayIntegerEasyTransfer.ino new file mode 100644 index 0000000..0f48487 --- /dev/null +++ b/avr/libraries/IntegerEasyTransfer/tests/TwoWayIntegerEasyTransfer/TwoWayIntegerEasyTransfer.ino @@ -0,0 +1,176 @@ +/* + * Unit test for IntegerEasyTransfer library. + * Run this test after adding changes to the library. To run this sketch start + * by downloading and installing the ArduinoUnit library into your sketchbook + * and then open the test example sketches of this library. + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Julian Sanin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +void setup() { + Serial.begin(9600); + while (!Serial); + Test::out = &Serial; +} + +void loop() { + Test::run(); +} + +const uint8_t HEADER1{ 0x06 }; +const uint8_t HEADER0{ 0x85 }; +const uint8_t DATA_SIZE{ 3 }; +const uint8_t DATA_BYTE{ 0x01 }; +const uint8_t DATA_INT1{ 0x02 }; +const uint8_t DATA_INT0{ 0x03 }; +const int16_t DATA_INT{ (DATA_INT1 << 8) | (DATA_INT0) }; +const uint8_t CRC{ DATA_SIZE ^ DATA_BYTE ^ DATA_INT1 ^ DATA_INT0 }; + +const char fullData[]{ + static_cast(HEADER1), static_cast(HEADER0), + DATA_SIZE, DATA_BYTE, DATA_INT1, DATA_INT0, CRC, + 0 +}; + +test(TwoWayIntegerEasyTransfer_attachDefaultMessageCallback) { + static uint8_t receivedDataCmd; + static int16_t receivedDataArg; + FakeStreamBuffer fakeStreamBuffer; + + receivedDataCmd = 0x00; + receivedDataArg = 0x0000; + fakeStreamBuffer.nextBytes(fullData); + + TwoWayIntegerEasyTransfer.begin(&fakeStreamBuffer); + TwoWayIntegerEasyTransfer.attach( + [](uint8_t command, IntegerEasyTransfer & request) { + receivedDataCmd = command; + receivedDataArg = request.readInt(); + }); + + assertTrue(TwoWayIntegerEasyTransfer.hasReceivedData()); + + TwoWayIntegerEasyTransfer.processInput(); + fakeStreamBuffer.reset(); + + assertEqual(receivedDataCmd, DATA_BYTE); + assertEqual(receivedDataArg, DATA_INT); +} + +const uint8_t EXT_SIZE{ 2 }; +const uint8_t EXT_MSG{ TwoWayIntegerEasyTransfer.MESSAGE_FEATURE }; +const uint8_t CRC_EXT{ EXT_SIZE ^ EXT_MSG ^ DATA_BYTE }; + +const char extendedMessage[]{ + static_cast(HEADER1), static_cast(HEADER0), EXT_SIZE, + static_cast(EXT_MSG), DATA_BYTE, static_cast(CRC_EXT), + 0 +}; + +test(TwoWayIntegerEasyTransfer_attachExtendedMessageCallback) { + static uint8_t receivedDataArg; + FakeStreamBuffer fakeStreamBuffer; + + receivedDataArg = 0x0000; + fakeStreamBuffer.nextBytes(extendedMessage); + + TwoWayIntegerEasyTransfer.begin(&fakeStreamBuffer); + TwoWayIntegerEasyTransfer.attach([](IntegerEasyTransfer & request) { + receivedDataArg = request.readByte(); + }); + + assertTrue(TwoWayIntegerEasyTransfer.hasReceivedData()); + + TwoWayIntegerEasyTransfer.processInput(); + fakeStreamBuffer.reset(); + + assertEqual(receivedDataArg, DATA_BYTE); +} + +const uint8_t EXT_SYS_RESET_SIZE{ 1 }; +const uint8_t EXT_SYS_RESET_MSG{ + TwoWayIntegerEasyTransfer.MESSAGE_SYSTEM_RESET +}; +const uint8_t CRC_EXT_SYS_RESET{ EXT_SYS_RESET_SIZE ^ EXT_SYS_RESET_MSG }; + +const char extendedSysResetMessage[]{ + static_cast(HEADER1), static_cast(HEADER0), EXT_SYS_RESET_SIZE, + static_cast(EXT_SYS_RESET_MSG), static_cast(CRC_EXT_SYS_RESET), + 0 +}; + +test(TwoWayIntegerEasyTransfer_attachSystemResetCallback) { + static bool hasReceivedSystemReset; + FakeStreamBuffer fakeStreamBuffer; + + hasReceivedSystemReset = false; + fakeStreamBuffer.nextBytes(extendedSysResetMessage); + + TwoWayIntegerEasyTransfer.begin(&fakeStreamBuffer); + TwoWayIntegerEasyTransfer.attach([]() { + hasReceivedSystemReset = true; + }); + + assertTrue(TwoWayIntegerEasyTransfer.hasReceivedData()); + TwoWayIntegerEasyTransfer.processInput(); + assertTrue(hasReceivedSystemReset); + + fakeStreamBuffer.reset(); +} + +test(TwoWayIntegerEasyTransfer_sendDefaultMessage) { + FakeStream fakeStream; + + TwoWayIntegerEasyTransfer.begin(&fakeStream); + + TwoWayIntegerEasyTransfer.write(DATA_BYTE); + TwoWayIntegerEasyTransfer.write(DATA_INT); + TwoWayIntegerEasyTransfer.sendData(); + + assertEqual(fakeStream.bytesWritten(), fullData); +} + +test(TwoWayIntegerEasyTransfer_sendExtendedMessage) { + FakeStream fakeStream; + + TwoWayIntegerEasyTransfer.begin(&fakeStream); + + TwoWayIntegerEasyTransfer.write(EXT_MSG); + TwoWayIntegerEasyTransfer.write(DATA_BYTE); + TwoWayIntegerEasyTransfer.sendData(); + + assertEqual(fakeStream.bytesWritten(), extendedMessage); +} + +test(TwoWayIntegerEasyTransfer_sendSystemResetMessage) { + FakeStream fakeStream; + + TwoWayIntegerEasyTransfer.begin(&fakeStream); + TwoWayIntegerEasyTransfer.sendSystemReset(); + + assertEqual(fakeStream.bytesWritten(), extendedSysResetMessage); +} diff --git a/avr/libraries/LottieLemon/README.md b/avr/libraries/LottieLemon/README.md new file mode 100644 index 0000000..b766357 --- /dev/null +++ b/avr/libraries/LottieLemon/README.md @@ -0,0 +1,28 @@ +# Arduino Robot Library (codename 'Lottie Lemon') + +The Robot has a number of built in sensors and actuators. The library is +designed to easily access the robot's functionality. + +For more information about this library please visit: +* https://www.arduino.cc/en/Main/Robot +* https://www.arduino.cc/en/Reference/RobotLibrary +* https://github.com/j54n1n/arduinorobot + +## License +``` +Copyright (c) Arduino LLC. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +``` \ No newline at end of file diff --git a/avr/libraries/LottieLemon/examples/Robot_Motor_Battery_Test/Robot_Motor_Battery_Test.ino b/avr/libraries/LottieLemon/examples/Robot_Motor_Battery_Test/Robot_Motor_Battery_Test.ino new file mode 100644 index 0000000..39610e6 --- /dev/null +++ b/avr/libraries/LottieLemon/examples/Robot_Motor_Battery_Test/Robot_Motor_Battery_Test.ino @@ -0,0 +1,59 @@ +/* Motor Core with battery stats readout. + + This code for the Arduino Robot's motor board + is the stock firmware with added code printing + the battery status. + +*/ + +#include +#include +#include + +enum { + SW_RX = SDA, + SW_TX = SCL +}; + +SoftwareSerial swSerial{ SW_RX, SW_TX }; + +LottieLemon::MotorBoard motorBoard; + +void setup() { + // start serial communication + swSerial.begin(19200); + // initialize the libraries + Serial1.begin(9600); + TwoWayIntegerEasyTransfer.begin(&Serial1); + TwoWayIntegerEasyTransfer.attach([]() { doSystemReset(); }); + doSystemReset(); +} + +void loop() { + if (TwoWayIntegerEasyTransfer.hasReceivedData()) { + TwoWayIntegerEasyTransfer.processInput(); + } + motorBoard.run(); + + measureBattery(); +} + +void doSystemReset() { + motorBoard.reset(); +} + +void measureBattery() { + static String bar; // string for storing the information + static unsigned long tStart = millis(); + unsigned long tStop = millis(); + if ((tStop - tStart) > 100) { + bar = String(""); // empty the string + // read the sensors and add them to the string + bar = bar + "Vbat=" + motorBoard.getBatteryTerminalVolts() + 'V' + + "\tIcharge=" + motorBoard.getBatteryChargeMilliamps() + "mA" + + "\tIdischarge=" + motorBoard.getBatteryDischargeMilliamps() + "mA"; + + swSerial.println(bar); + tStart = tStop; + } +} diff --git a/avr/libraries/LottieLemon/examples/Robot_Motor_Core/Robot_Motor_Core.ino b/avr/libraries/LottieLemon/examples/Robot_Motor_Core/Robot_Motor_Core.ino new file mode 100644 index 0000000..5f6e29b --- /dev/null +++ b/avr/libraries/LottieLemon/examples/Robot_Motor_Core/Robot_Motor_Core.ino @@ -0,0 +1,31 @@ +/* Motor Core + + This code for the Arduino Robot's motor board + is the stock firmware. program the motor board with + this sketch whenever you want to return the motor + board to its default state. + +*/ + +#include +#include + +LottieLemon::MotorBoard motorBoard; + +void setup() { + Serial1.begin(9600); + TwoWayIntegerEasyTransfer.begin(&Serial1); + TwoWayIntegerEasyTransfer.attach([]() { doSystemReset(); }); + doSystemReset(); +} + +void loop() { + if (TwoWayIntegerEasyTransfer.hasReceivedData()) { + TwoWayIntegerEasyTransfer.processInput(); + } + motorBoard.run(); +} + +void doSystemReset() { + motorBoard.reset(); +} diff --git a/avr/libraries/LottieLemon/examples/Robot_Motor_IR_Array_Test/Robot_Motor_IR_Array_Test.ino b/avr/libraries/LottieLemon/examples/Robot_Motor_IR_Array_Test/Robot_Motor_IR_Array_Test.ino new file mode 100644 index 0000000..9d1353b --- /dev/null +++ b/avr/libraries/LottieLemon/examples/Robot_Motor_IR_Array_Test/Robot_Motor_IR_Array_Test.ino @@ -0,0 +1,32 @@ +/* Motor Board IR Array Test + +This example of the Arduno robot's motor board returns the +values read fron the 5 infrared sendors on the bottom of +the robot. + +*/ + +#include + +LottieLemon::MotorBoard motorBoard; +String bar; // string for storing the information + +void setup() { + // start serial communication + Serial.begin(9600); + // initialize the library + motorBoard.begin(); +} + +void loop() { + bar = String(""); // empty the string + // read the sensors and add them to the string + bar = bar + motorBoard.IRread(1) + + '\t' + motorBoard.IRread(2) + + '\t' + motorBoard.IRread(3) + + '\t' + motorBoard.IRread(4) + + '\t' + motorBoard.IRread(5); + // print out the values + Serial.println(bar); + delay(100); +} diff --git a/avr/libraries/LottieLemon/keywords.txt b/avr/libraries/LottieLemon/keywords.txt new file mode 100644 index 0000000..da16417 --- /dev/null +++ b/avr/libraries/LottieLemon/keywords.txt @@ -0,0 +1,30 @@ +####################################### +# Syntax Coloring Map for +# LottieLemon +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +LottieLemon KEYWORD1 +MotorBoard KEYWORD1 +LineFollow KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +run KEYWORD2 +motorsWrite KEYWORD2 +IRread KEYWORD2 +calibIRs KEYWORD2 +runLineFollow KEYWORD2 +config KEYWORD2 +motorsWritePct KEYWORD2 +motorsStop KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### \ No newline at end of file diff --git a/avr/libraries/LottieLemon/library.properties b/avr/libraries/LottieLemon/library.properties new file mode 100644 index 0000000..12c320b --- /dev/null +++ b/avr/libraries/LottieLemon/library.properties @@ -0,0 +1,9 @@ +name=LottieLemon +version=1.0.0 +author=Arduino , Julian Sanin +maintainer=Julian Sanin +sentence=Enables access to the Arduino Robot boards. For Arduino Robot only. +paragraph=Supports Arduino Robot Control and Motor Board. +category=Device Control +url=https://github.com/j54n1n/arduinorobot +architectures=avr diff --git a/avr/libraries/LottieLemon/src/LottieLemon.h b/avr/libraries/LottieLemon/src/LottieLemon.h new file mode 100644 index 0000000..10594d0 --- /dev/null +++ b/avr/libraries/LottieLemon/src/LottieLemon.h @@ -0,0 +1,141 @@ +/* + Copyright (c) 2012 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef LOTTIE_LEMON_H +#define LOTTIE_LEMON_H + +#include + +namespace LottieLemon { + + /* + A message structure will be: + switch mode (2): + byte COMMAND_SWITCH_MODE, byte mode + run (5): + byte COMMAND_RUN, int speedL, int speedR + analogWrite (3): + byte COMMAND_ANALOG_WRITE, byte codename, byte value; + digitalWrite (3): + byte COMMAND_DIGITAL_WRITE, byte codename, byte value; + analogRead (2): + byte COMMAND_ANALOG_READ, byte codename; + analogRead _return_ (4): + byte COMMAND_ANALOG_READ_RE, byte codename, int value; + digitalRead (2): + byte COMMAND_DIGITAL_READ, byte codename; + digitalRead _return_ (4): + byte COMMAND_DIGITAL_READ_RE, byte codename, int value; + read IR (1): + byte COMMAND_READ_IR; + read IR _return_ (9): + byte COMMAND_READ_IR_RE, int valueA, int valueB, int valueC, int valueD; + + + */ + + //Command code + enum Command { + COMMAND_SWITCH_MODE = 0, + COMMAND_RUN = 10, + COMMAND_MOTORS_STOP = 11, + COMMAND_ANALOG_WRITE = 20, + COMMAND_DIGITAL_WRITE = 30, + COMMAND_ANALOG_READ = 40, + COMMAND_ANALOG_READ_RE = 41, + COMMAND_DIGITAL_READ = 50, + COMMAND_DIGITAL_READ_RE = 51, + COMMAND_READ_IR = 60, + COMMAND_READ_IR_RE = 61, + COMMAND_ACTION_DONE = 70, + COMMAND_READ_TRIM = 80, + COMMAND_READ_TRIM_RE = 81, + COMMAND_PAUSE_MODE = 90, + COMMAND_LINE_FOLLOW_CONFIG = 100, + COMMAND_PIN_MODE = 110 + }; + + //motor board modes + enum Mode { + MODE_SIMPLE = 0, + MODE_LINE_FOLLOW = 1, + MODE_ADJUST_MOTOR = 2, + MODE_IR_CONTROL = 3 + }; + + //bottom TKs, just for communication purpose + enum BottomMicrocontrollerPin { + B_TK1 = 201, + B_TK2 = 202, + B_TK3 = 203, + B_TK4 = 204, + BOT_D7 = B_TK3, + BOT_D8 = B_TK4, + BOT_D9 = B_TK2, + BOT_D10 = B_TK1 + }; + +#ifdef ARDUINO_AVR_ROBOT_CONTROL + //top TKs + enum TopMultiplexerPin { + T_TK0 = 100, + T_TK1 = 101, + T_TK2 = 102, + T_TK3 = 103, + T_TK4 = 104, + T_TK5 = 105, + T_TK6 = 106, + T_TK7 = 107, + TOP_M0 = T_TK0, + TOP_M1 = T_TK1, + TOP_M2 = T_TK2, + TOP_M3 = T_TK3, + TOP_M4 = T_TK4, + TOP_M5 = T_TK5, + TOP_M6 = T_TK6, + TOP_M7 = T_TK7 + }; + + //top TKDs + enum TopMicrocontrollerPin { + T_TKD0 = TKD0, + T_TKD1 = TKD1, + T_TKD2 = TKD2, + T_TKD3 = TKD3, + T_TKD4 = TKD4, // Shared with MUXA + T_TKD5 = TKD5, // Shared with MUXC + T_LED1 = LED1, + TOP_D0 = T_TKD0, + TOP_D1 = T_TKD1, + TOP_D2 = T_TKD2, + TOP_D3 = T_TKD3, + TOP_D4 = T_TKD4, // Shared with MUXA + TOP_D5 = T_TKD5, // Shared with MUXC + TOP_LED1 = T_LED1 + }; +#endif // ARDUINO_AVR_ROBOT_CONTROL +} + +#ifdef ARDUINO_AVR_ROBOT_MOTOR +#include "utility/LottieLemonMotorBoard.h" +#endif +#ifdef ARDUINO_AVR_ROBOT_CONTROL +#include "utility/LottieLemonControlBoard.h" +#endif + +#endif // LOTTIE_LEMON_H diff --git a/avr/libraries/LottieLemon/src/utility/LottieLemonControlBoard.cpp b/avr/libraries/LottieLemon/src/utility/LottieLemonControlBoard.cpp new file mode 100644 index 0000000..323d32d --- /dev/null +++ b/avr/libraries/LottieLemon/src/utility/LottieLemonControlBoard.cpp @@ -0,0 +1,214 @@ +/* + Copyright (c) 2012 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include "../LottieLemon.h" + +#ifdef ARDUINO_AVR_ROBOT_CONTROL + +using namespace LottieLemon; + +static void processRequest() { + if (TwoWayIntegerEasyTransfer.hasReceivedData()) { + TwoWayIntegerEasyTransfer.processInput(); + } +} + +template +static void sendData(const Tail & tail) { + TwoWayIntegerEasyTransfer.write(tail); + TwoWayIntegerEasyTransfer.sendData(); +} + +template +static void requestData(const Tail & tail) { + sendData(tail); + processRequest(); +} + +template +static void sendData(const Head & head, const Body & ... body) { + TwoWayIntegerEasyTransfer.write(head); + sendData(body...); +} + +template +static void requestData(const Head & head, const Body & ... body) { + TwoWayIntegerEasyTransfer.write(head); + requestData(body...); +} + +ControlBoard::ControlBoard() + : _multiplexer{ NOT_A_PIN, MUXA, MUXB, MUXC, MUXD } { + _multiplexer.pinMode(MUX_IN, INPUT); +} + +void ControlBoard::setMode(uint8_t mode) { + sendData(static_cast(COMMAND_SWITCH_MODE), mode); +} + +void ControlBoard::pauseMode(bool isPaused) { + sendData( + static_cast(COMMAND_PAUSE_MODE), + static_cast(isPaused) + ); +} + +bool ControlBoard::isActionDone(void) { + static bool actionValue; + TwoWayIntegerEasyTransfer.attach( + [](uint8_t command, IntegerEasyTransfer &) { + if (command == COMMAND_ACTION_DONE) + actionValue = true; + else + actionValue = false; + }); + processRequest(); + return actionValue; +} + +void ControlBoard::lineFollowConfig( + uint8_t kP, uint8_t kD, + uint8_t robotSpeedPercentage, uint8_t intergrationTimeMillis) { + sendData(static_cast(COMMAND_LINE_FOLLOW_CONFIG), + kP, kD, robotSpeedPercentage, intergrationTimeMillis); +} + +void ControlBoard::motorsWrite(int speedLeft, int speedRight) { + sendData(static_cast(COMMAND_RUN), speedLeft, speedRight); +} + +void ControlBoard::motorsStop(void) { + sendData(static_cast(COMMAND_MOTORS_STOP)); +} + +void ControlBoard::pinMode(TopMicrocontrollerPin pin, uint8_t value) { + /*Arduino*/::pinMode(pin, value); +} + +void ControlBoard::pinMode(BottomMicrocontrollerPin pin, uint8_t value) { + sendData( + static_cast(COMMAND_PIN_MODE), + static_cast(pin), value + ); +} + +bool ControlBoard::digitalRead(TopMicrocontrollerPin pin) { + return /*Arduino*/::digitalRead(pin); +} + +bool ControlBoard::digitalRead(TopMultiplexerPin pin) { + int channel = pin - T_TK0; + return _multiplexer.digitalRead(channel); +} + +bool ControlBoard::digitalRead(BottomMicrocontrollerPin pin) { + static uint8_t pinCode; + static uint8_t pinValue; + pinCode = static_cast(pin); + TwoWayIntegerEasyTransfer.attach( + [](uint8_t command, IntegerEasyTransfer & request) { + if ((command == COMMAND_DIGITAL_READ_RE) && + (request.readByte() == pinCode)) + pinValue = request.readByte(); + else + pinValue = 0; + }); + requestData(static_cast(COMMAND_DIGITAL_READ), pinCode); + return (pinValue != 0); +} + +void ControlBoard::digitalWrite(TopMicrocontrollerPin pin, uint8_t value) { + /*Arduino*/::digitalWrite(pin, value); +} + +void ControlBoard::digitalWrite(BottomMicrocontrollerPin pin, uint8_t value) { + sendData( + static_cast(COMMAND_DIGITAL_WRITE), + static_cast(pin), value + ); +} + +int ControlBoard::analogRead(TopMicrocontrollerPin pin) { + return /*Arduino*/::analogRead(pin); +} + +int ControlBoard::analogRead(TopMultiplexerPin pin) { + int channel = pin - T_TK0; + return _multiplexer.analogRead(channel); +} + +int ControlBoard::analogRead(BottomMicrocontrollerPin pin) { + static uint8_t pinCode; + static int pinValue; + pinCode = static_cast(pin); + TwoWayIntegerEasyTransfer.attach( + [](uint8_t command, IntegerEasyTransfer & request) { + if ((command == COMMAND_ANALOG_READ_RE) && + (request.readByte() == pinCode)) + pinValue = request.readInt(); + else + pinValue = 0; + }); + requestData(static_cast(COMMAND_ANALOG_READ), pinCode); + return pinValue; +} + +void ControlBoard::analogWrite(TopMicrocontrollerPin pin, uint8_t value) { + if (pin == T_TKD4) + /*Arduino*/::analogWrite(pin, value); +} + +uint8_t ControlBoard::updateIR(uint16_t * ir, uint8_t size) { + static const uint8_t MAX_IR_DATA = 5; + static uint16_t irValues[MAX_IR_DATA]; + static uint8_t maxItems; + maxItems = min(MAX_IR_DATA, size); + TwoWayIntegerEasyTransfer.attach( + [](uint8_t command, IntegerEasyTransfer & request) { + for (uint16_t i = 0; i < MAX_IR_DATA; i++) { + if (command == COMMAND_READ_IR_RE) + irValues[i] = request.readInt(); + else + irValues[i] = 0; + } + }); + requestData(static_cast(COMMAND_READ_IR)); + memcpy(ir, irValues, maxItems * sizeof(uint16_t)); + return maxItems; +} + +int LottieLemon::ControlBoard::trimRead() { + static int trimmerValue; + TwoWayIntegerEasyTransfer.attach( + [](uint8_t command, IntegerEasyTransfer & request) { + if (command == COMMAND_READ_TRIM_RE) + trimmerValue = request.readInt(); + else + trimmerValue = 0; + }); + requestData(static_cast(COMMAND_READ_TRIM)); + return trimmerValue; +} + +int ControlBoard::knobRead() { + return /*Arduino*/::analogRead(POT); +} + +#endif // ARDUINO_AVR_ROBOT_CONTROL diff --git a/avr/libraries/LottieLemon/src/utility/LottieLemonControlBoard.h b/avr/libraries/LottieLemon/src/utility/LottieLemonControlBoard.h new file mode 100644 index 0000000..4864ced --- /dev/null +++ b/avr/libraries/LottieLemon/src/utility/LottieLemonControlBoard.h @@ -0,0 +1,63 @@ +/* + Copyright (c) 2012 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef LOTTIE_LEMON_CONTROL_BOARD_H +#define LOTTIE_LEMON_CONTROL_BOARD_H + +#include +#include + +namespace LottieLemon { + + class ControlBoard { + + AMxx4067 _multiplexer; + + public: + ControlBoard(); + void setMode(uint8_t mode); + void pauseMode(bool isPaused); + bool isActionDone(void); + void lineFollowConfig( + uint8_t kP, uint8_t kD, + uint8_t robotSpeedPercentage, uint8_t intergrationTimeMillis + ); + + void motorsWrite(int speedLeft, int speedRight); + void motorsStop(void); + + void pinMode(TopMicrocontrollerPin pin, uint8_t value); + void pinMode(BottomMicrocontrollerPin pin, uint8_t value); + bool digitalRead(TopMicrocontrollerPin pin); + bool digitalRead(TopMultiplexerPin pin); + bool digitalRead(BottomMicrocontrollerPin pin); + void digitalWrite(TopMicrocontrollerPin pin, uint8_t value); + void digitalWrite(BottomMicrocontrollerPin pin, uint8_t value); + int analogRead(TopMicrocontrollerPin pin); + int analogRead(TopMultiplexerPin pin); + int analogRead(BottomMicrocontrollerPin pin); + void analogWrite(TopMicrocontrollerPin pin, uint8_t value); + + uint8_t updateIR(uint16_t * /*[out]*/ ir, uint8_t size); + int trimRead(void); + + int knobRead(void); + }; +} + +#endif // LOTTIE_LEMON_CONTROL_BOARD_H diff --git a/avr/libraries/LottieLemon/src/utility/LottieLemonLineFollow.cpp b/avr/libraries/LottieLemon/src/utility/LottieLemonLineFollow.cpp new file mode 100644 index 0000000..bbabe7c --- /dev/null +++ b/avr/libraries/LottieLemon/src/utility/LottieLemonLineFollow.cpp @@ -0,0 +1,94 @@ +/* + Copyright (c) 2012 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include "LottieLemonLineFollow.h" +using namespace LottieLemon; + +LineFollow::LineFollow() { + config(11, 5, 50, 10); +} + +void LineFollow::config(uint8_t KP, uint8_t KD, + uint8_t robotSpeedPct, uint8_t integrationTimeMillis) { + config(KP, 0, KD, robotSpeedPct, integrationTimeMillis); +} + +void LineFollow::config(uint8_t KP, uint8_t KI, uint8_t KD, + uint8_t robotSpeedPct, uint8_t integrationTimeMillis) { + _KP = KP; + _KI = KI; + _KD = KD; + _robotSpeedPct = robotSpeedPct; + _integrationTimeMillis = integrationTimeMillis; +} + +void LineFollow::calibIRs() { + // So only init once. + static bool isInited = false; + if (isInited) { + return; + } + delay(1000); + doCalibration(30, 500); + doCalibration(-30, 800); + doCalibration(30, 500); + delay(1000); + isInited = true; +} + +void LineFollow::runLineFollow() { + enum { STOP_LINE_VALUE = 1500 }; + uint32_t weight = 0; + uint16_t sum = 0; + for (int i = 0; i < 5; i++) { + _sensors[i] = _IRread(i); + weight += _sensors[i] * (i + 1); + sum += _sensors[i]; + } + if (sum > STOP_LINE_VALUE) { + if ((millis() - _tStartMillis) <= _integrationTimeMillis) { + return; + } + _tStartMillis = millis(); + int16_t error = 100 * weight / sum - 300; + _integral = _integral + error; + _derivative = error - _lastError; + _lastError = error; + // Calculate the adjustment with PID control. + int16_t change = _KP * error + _KI * _integral + _KD * _derivative; + change = change / 10; + // Change motor speed. + int16_t leftSpeed = constrain((_robotSpeedPct + change), -100, 100); + int16_t rightSpeed = constrain((_robotSpeedPct - change), -100, 100); + motorsWritePct(leftSpeed, rightSpeed); + } else { + // The robot discovered a perpendicular black line. Stop motors. + motorsStop(); + // Stop the execution of the control board program. + reportActionDone(); + } +} + +void LineFollow::doCalibration(int speedPct, unsigned int time) { + motorsWritePct(speedPct, -speedPct); + unsigned long beginTime = millis(); + while ((millis() - beginTime) < time); + _tStartMillis = millis(); + motorsStop(); +} diff --git a/avr/libraries/LottieLemon/src/utility/LottieLemonLineFollow.h b/avr/libraries/LottieLemon/src/utility/LottieLemonLineFollow.h new file mode 100644 index 0000000..5485e5c --- /dev/null +++ b/avr/libraries/LottieLemon/src/utility/LottieLemonLineFollow.h @@ -0,0 +1,63 @@ +/* + Copyright (c) 2012 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef LOTTIE_LEMON_LINE_FOLLOW_H +#define LOTTIE_LEMON_LINE_FOLLOW_H + +#include + +namespace LottieLemon { + + class LineFollow { + public: + LineFollow(); + + void runLineFollow(); + void config(uint8_t KP, uint8_t KD, + uint8_t robotSpeedPct, uint8_t integrationTimeMillis + ); + void config(uint8_t KP, uint8_t KI, uint8_t KD, + uint8_t robotSpeedPct, uint8_t integrationTimeMillis + ); + //These are all pure virtual functions, pure VF needs pure specifier "=0" + //virtual void motorsWrite(int speedL, int speedR)=0; + virtual void motorsWritePct(int speedLpct, int speedRpct) = 0; + virtual void motorsStop() = 0; + protected: + virtual int _IRread(uint8_t num) = 0; + virtual void reportActionDone() = 0; + void calibIRs(); + + private: + void doCalibration(int speedPct, unsigned int time); + + uint8_t _KP; + uint8_t _KI; + uint8_t _KD; + uint8_t _robotSpeedPct; + uint8_t _integrationTimeMillis; + unsigned long _tStartMillis; + + uint16_t _sensors[5]; + int16_t _integral = 0; + int16_t _derivative = 0; + int16_t _lastError = 0; + }; +} + +#endif // LOTTIE_LEMON_LINE_FOLLOW_H diff --git a/avr/libraries/LottieLemon/src/utility/LottieLemonMotorBoard.cpp b/avr/libraries/LottieLemon/src/utility/LottieLemonMotorBoard.cpp new file mode 100644 index 0000000..0f3401f --- /dev/null +++ b/avr/libraries/LottieLemon/src/utility/LottieLemonMotorBoard.cpp @@ -0,0 +1,346 @@ +/* + Copyright (c) 2012 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include "../LottieLemon.h" + +#ifdef ARDUINO_AVR_ROBOT_MOTOR + +using namespace LottieLemon; + +static MotorBoard * _motorBoard = nullptr; + +MotorBoard::MotorBoard() : _multiplexer{ MUXI, MUXA, MUXB, MUXC } { + _motorBoard = this; + TwoWayIntegerEasyTransfer.attach( + [](uint8_t command, IntegerEasyTransfer & request) { + if (_motorBoard != nullptr) { + if (!_motorBoard->handleMessage(command, request)) { + // TODO: Report unhandled command. + } + } + }); +} +/*void RobotMotorBoard::beginIRReceiver(){ +IRrecv::enableIRIn(); +}*/ +void MotorBoard::begin() { + //init MUX + _multiplexer.pinMode(MUX_IN, INPUT); + _multiplexer.enable(); + + isPaused = false; +} + +void MotorBoard::run() { + if (isPaused)return;//skip process if the mode is paused + + if (mode == MODE_SIMPLE) { + //Serial.println("s"); + //do nothing? Simple mode is just about getting commands + } + else if (mode == MODE_LINE_FOLLOW) { + //do line following stuff here. + LineFollow::runLineFollow(); + } + else if (mode == MODE_ADJUST_MOTOR) { + //Serial.println('a'); + //motorAdjustment=analogRead(POT); + //setSpeed(255,255); + //delay(100); + } +} +void MotorBoard::pauseMode(bool onOff) { + if (onOff) { + isPaused = true; + } + else { + isPaused = false; + } + stopCurrentActions(); + +} +bool MotorBoard::handleMessage(uint8_t command, IntegerEasyTransfer & request) { + uint8_t modeName; + uint8_t codename; + int value; + int speedL; + int speedR; + uint8_t kP; + uint8_t kD; + uint8_t robotSpeedPct; + uint8_t integrationTimeMillis; + //Serial.println("data received"); + //Serial.println(command); + switch (command) { + case COMMAND_SWITCH_MODE: + modeName = request.readByte(); + setMode(modeName); + break; + case COMMAND_RUN: + if (mode == MODE_LINE_FOLLOW) + break;//in follow line mode, the motor does not follow commands + speedL = request.readInt(); + speedR = request.readInt(); + motorsWrite(speedL, speedR); + break; + case COMMAND_MOTORS_STOP: + motorsStop(); + break; + case COMMAND_PIN_MODE: + codename = request.readByte(); + modeName = request.readByte(); + _pinMode(codename, modeName); + case COMMAND_ANALOG_WRITE: + codename = request.readByte(); + value = request.readInt(); + _analogWrite(codename, value); + break; + case COMMAND_DIGITAL_WRITE: + codename = request.readByte(); + value = request.readByte(); + _digitalWrite(codename, value); + break; + case COMMAND_ANALOG_READ: + codename = request.readByte(); + _analogRead(codename); + break; + case COMMAND_DIGITAL_READ: + codename = request.readByte(); + _digitalRead(codename); + break; + case COMMAND_READ_IR: + _readIR(); + break; + case COMMAND_READ_TRIM: + _readTrim(); + break; + case COMMAND_PAUSE_MODE: + pauseMode(request.readByte());//onOff state + break; + case COMMAND_LINE_FOLLOW_CONFIG: + kP = request.readByte(); + kD = request.readByte(); + robotSpeedPct = request.readByte(); + integrationTimeMillis = request.readByte(); + LineFollow::config(kP, kD, robotSpeedPct, integrationTimeMillis); + break; + default: + return false; + } + return true; +} +uint8_t MotorBoard::parseCodename(uint8_t codename) { + switch (codename) { + case B_TK1: + return TK1; + case B_TK2: + return TK2; + case B_TK3: + return TK3; + case B_TK4: + return TK4; + default: + return 0; + } +} +uint8_t MotorBoard::codenameToAPin(uint8_t codename) { + switch (codename) { + case B_TK1: + return A0; + case B_TK2: + return A1; + case B_TK3: + return A6; + case B_TK4: + return A11; + default: + return 0; + } +} + +void MotorBoard::setMode(uint8_t mode) { + if (mode == MODE_LINE_FOLLOW) { + LineFollow::calibIRs(); + } + /*if(mode==SET_MOTOR_ADJUSTMENT){ + save_motor_adjustment_to_EEPROM(); + } + */ + /*if(mode==MODE_IR_CONTROL){ + beginIRReceiver(); + }*/ + this->mode = mode; + //stopCurrentActions();//If line following, this should stop the motors +} + +void MotorBoard::stopCurrentActions() { + motorsStop(); + //motorsWrite(0,0); +} + +void MotorBoard::motorsWrite(int speedL, int speedR) { + /*Serial.print(speedL); + Serial.print(" "); + Serial.println(speedR);*/ + //motor adjustment, using percentage + _refreshMotorAdjustment(); + + if (motorAdjustment<0) { + speedR *= (1 + motorAdjustment); + } + else { + speedL *= (1 - motorAdjustment); + } + + if (speedR>0) { + analogWrite(IN_A1, speedR); + analogWrite(IN_A2, 0); + } + else { + analogWrite(IN_A1, 0); + analogWrite(IN_A2, -speedR); + } + + if (speedL>0) { + analogWrite(IN_B1, speedL); + analogWrite(IN_B2, 0); + } + else { + analogWrite(IN_B1, 0); + analogWrite(IN_B2, -speedL); + } +} +void MotorBoard::motorsWritePct(int speedLpct, int speedRpct) { + //speedLpct, speedRpct ranges from -100 to 100 + motorsWrite(speedLpct*2.55, speedRpct*2.55); +} +void MotorBoard::motorsStop() { + analogWrite(IN_A1, 255); + analogWrite(IN_A2, 255); + + analogWrite(IN_B1, 255); + analogWrite(IN_B2, 255); +} + + +/* + * + * + * Input and Output ports + * + * + */ +void MotorBoard::_pinMode(uint8_t codename, uint8_t value) { + uint8_t pin = parseCodename(codename); + if (pin == 0) { return; } // Not valid codename. + pinMode(pin, value); +} +void MotorBoard::_digitalWrite(uint8_t codename, uint8_t value) { + uint8_t pin = parseCodename(codename); + if (pin == 0) { return; } // Not valid codename. + digitalWrite(pin, value); +} +void MotorBoard::_analogWrite(uint8_t, int) { + //There's no PWM available on motor board +} +void MotorBoard::_digitalRead(uint8_t codename) { + uint8_t pin = parseCodename(codename); + if (pin == 0) { return; } // Not valid codename. + bool value = digitalRead(pin); + TwoWayIntegerEasyTransfer.writeByte(COMMAND_DIGITAL_READ_RE); + TwoWayIntegerEasyTransfer.writeByte(codename); + TwoWayIntegerEasyTransfer.writeByte(value); + TwoWayIntegerEasyTransfer.sendData(); +} +void MotorBoard::_analogRead(uint8_t codename) { + uint8_t pin = codenameToAPin(codename); + if (pin == 0) { return; } // Not valid codename. + int value = analogRead(pin); + TwoWayIntegerEasyTransfer.writeByte(COMMAND_ANALOG_READ_RE); + TwoWayIntegerEasyTransfer.writeByte(codename); + TwoWayIntegerEasyTransfer.writeInt(value); + TwoWayIntegerEasyTransfer.sendData(); +} +int MotorBoard::IRread(uint8_t num) { + return _IRread(num - 1); //To make consistant with the pins labeled on the board +} + +int MotorBoard::_IRread(uint8_t num) { + if (num < 5) { + return _multiplexer.analogRead(num); + } + return 0; +} + + +void MotorBoard::_readIR() { + int value; + TwoWayIntegerEasyTransfer.writeByte(COMMAND_READ_IR_RE); + for (int i = 0; i<5; i++) { + value = _IRread(i); + TwoWayIntegerEasyTransfer.writeInt(value); + } + TwoWayIntegerEasyTransfer.sendData(); +} + +void MotorBoard::_readTrim() { + int value = analogRead(TRIM); + TwoWayIntegerEasyTransfer.writeByte(COMMAND_READ_TRIM_RE); + TwoWayIntegerEasyTransfer.writeInt(value); + TwoWayIntegerEasyTransfer.sendData(); +} + +void MotorBoard::_refreshMotorAdjustment() { + motorAdjustment = map(analogRead(TRIM), 0, 1023, -30, 30) / 100.0; +} + +void MotorBoard::reportActionDone() { + setMode(MODE_SIMPLE); + TwoWayIntegerEasyTransfer.writeByte(COMMAND_ACTION_DONE); + TwoWayIntegerEasyTransfer.sendData(); +} + +void MotorBoard::reset() { + begin(); + stopCurrentActions(); +} + +float MotorBoard::getBatteryTerminalVolts() { + // Read battery voltage on multiplexer channel 5. + int adcValue = _multiplexer.analogRead(5); + float adcVoltage = (5.0f / 1023.0f) * adcValue; + return 2.0f * adcVoltage; // Compensate for voltage divider. +} + +float MotorBoard::getBatteryChargeMilliamps() { + // Read battery charge current on multiplexer channel 6. + int adcValue = _multiplexer.analogRead(6); + float adcVoltage = (5.0f / 1023.0f) * adcValue; + return adcVoltage / 0.00075f; // Compensate sense resistor and gain. +} + +float MotorBoard::getBatteryDischargeMilliamps() { + // Read battery discharge current on multiplexer channel 7. + int adcValue = _multiplexer.analogRead(7); + float adcVoltage = (5.0f / 1023.0f) * adcValue; + return adcVoltage / 0.00075f; // Compensate sense resistor and gain. +} + +#endif // ARDUINO_AVR_ROBOT_MOTOR diff --git a/avr/libraries/LottieLemon/src/utility/LottieLemonMotorBoard.h b/avr/libraries/LottieLemon/src/utility/LottieLemonMotorBoard.h new file mode 100644 index 0000000..194803f --- /dev/null +++ b/avr/libraries/LottieLemon/src/utility/LottieLemonMotorBoard.h @@ -0,0 +1,82 @@ +/* + Copyright (c) 2012 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef LOTTIE_LEMON_MOTOR_BOARD_H +#define LOTTIE_LEMON_MOTOR_BOARD_H + +#include +#include +#include "LottieLemonLineFollow.h" +//#include "IRremote.h" + +namespace LottieLemon { + + class MotorBoard : public LineFollow, public IntegerEasyTransferFeature { + public: + MotorBoard(); + void begin(); + + void run(); + + int IRread(uint8_t num); + + float getBatteryTerminalVolts(); + float getBatteryChargeMilliamps(); + float getBatteryDischargeMilliamps(); + + void setMode(uint8_t mode); + void pauseMode(bool onOff); + + void motorsWrite(int speedL, int speedR); + void motorsWritePct(int speedLpct, int speedRpct);//write motor values in percentage + void motorsStop(); + + bool handleMessage(uint8_t command, IntegerEasyTransfer & request); + void reset(); + + private: + float motorAdjustment;//-1.0 ~ 1.0, whether left is lowered or right is lowered + + //convert codename to actual pins + uint8_t parseCodename(uint8_t codename); + uint8_t codenameToAPin(uint8_t codename); + + void stopCurrentActions(); + //void sendCommand(byte command,byte codename,int value); + + void _pinMode(uint8_t codename, uint8_t value); + void _analogWrite(uint8_t codename, int value); + void _digitalWrite(uint8_t codename, uint8_t value); + void _analogRead(uint8_t codename); + void _digitalRead(uint8_t codename); + int _IRread(uint8_t num); + void _readIR(); + void _readTrim(); + + void _refreshMotorAdjustment(); + + AMxx4051 _multiplexer; + uint8_t mode; + uint8_t isPaused; + + //Line Following + void reportActionDone(); + }; +} + +#endif // LOTTIE_LEMON_MOTOR_BOARD_H diff --git a/avr/platform.txt b/avr/platform.txt index ad5c394..30dbd5f 100644 --- a/avr/platform.txt +++ b/avr/platform.txt @@ -5,7 +5,7 @@ # - https://github.com/arduino/Arduino/wiki/Arduino-Hardware-Cores-migration-guide-from-1.0-to-1.6 name=Arduino Robot Boards -version=1.0.0 +version=1.0.4 # AVR compile variables # --------------------- diff --git a/avr/variants/robot_control/pins_arduino.h b/avr/variants/robot_control/pins_arduino.h new file mode 100644 index 0000000..4039fa6 --- /dev/null +++ b/avr/variants/robot_control/pins_arduino.h @@ -0,0 +1,331 @@ +/* + pins_arduino.h - Pin definition functions for Arduino Robot Control Board + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2913 D. Cuartielles, X. Yang (Arduino Verkstad) + Copyright (c) 2012 D. Cuartielles, N. de la Riva, I. Gallego, E. Gallego + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define ARDUINO_MODEL_USB_PID 0x0038 + +#define TX_RX_LED_INIT DDRD |= (1<<5), DDRB |= (1<<0) +#define TXLED0 PORTD |= (1<<5) +#define TXLED1 PORTD &= ~(1<<5) +#define RXLED0 PORTB |= (1<<0) +#define RXLED1 PORTB &= ~(1<<0) + +#define D0 TKD0 +#define D1 TKD1 +#define D2 TKD2 +#define D3 TKD3 +#define D4 TKD4 +#define D5 TKD5 + +#define PIN_SERIAL_RX (0) +#define PIN_SERIAL_TX (1) + +static const uint8_t RX = PIN_SERIAL_RX; +static const uint8_t TX = PIN_SERIAL_TX; + +#define PIN_WIRE_SDA (2) +#define PIN_WIRE_SCL (3) + +static const uint8_t SDA = PIN_WIRE_SDA; +static const uint8_t SCL = PIN_WIRE_SCL; + +// Map SPI port to 'new' pins D14..D17 +#define PIN_SPI_SS (17) +#define PIN_SPI_MOSI (16) +#define PIN_SPI_MISO (14) +#define PIN_SPI_SCK (15) + +static const uint8_t SS = PIN_SPI_SS; +static const uint8_t MOSI = PIN_SPI_MOSI; +static const uint8_t MISO = PIN_SPI_MISO; +static const uint8_t SCK = PIN_SPI_SCK; + +// Mapping of analog pins as digital I/O +// A6-A11 share with digital pins +#define PIN_A0 (18) +#define PIN_A1 (19) +#define PIN_A2 (20) +#define PIN_A3 (21) +#define PIN_A4 (22) +#define PIN_A5 (23) +#define PIN_A6 (24) +#define PIN_A7 (25) +#define PIN_A8 (26) +#define PIN_A9 (27) +#define PIN_A10 (28) +#define PIN_A11 (29) + +static const uint8_t A0 = PIN_A0; +static const uint8_t A1 = PIN_A1; +static const uint8_t A2 = PIN_A2; +static const uint8_t A3 = PIN_A3; +static const uint8_t A4 = PIN_A4; +static const uint8_t A5 = PIN_A5; +static const uint8_t A6 = PIN_A6; // D4 +static const uint8_t A7 = PIN_A7; // D6 +static const uint8_t A8 = PIN_A8; // D8 +static const uint8_t A9 = PIN_A9; // D9 +static const uint8_t A10 = PIN_A10; // D10 +static const uint8_t A11 = PIN_A11; // D12 + +// Specific Mapping for the Control Board +static const uint8_t KEY = 18; // AD0 +static const uint8_t MUX_IN = 24; // ADC8 - A6 +static const uint8_t MUXA = 6; // D5 - TKD4 +static const uint8_t MUXB = 11; // D11 +static const uint8_t MUXC = 12; // D12 - TKD5 +static const uint8_t MUXD = 13; // D13 +static const uint8_t BUZZ = 5; // D5 +static const uint8_t POT = 23; // AD5 +static const uint8_t DC_LCD = 10; // D10 +static const uint8_t LCD_CS = 9; // D9 +static const uint8_t RST_LCD = 7; // D6 +static const uint8_t CARD_CS = 8; // D8 +static const uint8_t TKD0 = 19; // ADC6 - A1 +static const uint8_t TKD1 = 20; // ADC5 - A2 +static const uint8_t TKD2 = 21; // ADC4 - A3 +static const uint8_t TKD3 = 22; // ADC1 - A4 +static const uint8_t TKD4 = 6; // D5 - MUXA +static const uint8_t TKD5 = 12; // D12 - MUXC +static const uint8_t LED1 = 17; // D17 - RX_Led + +#define digitalPinToPCICR(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCICR) : ((uint8_t *)0)) +#define digitalPinToPCICRbit(p) 0 +#define digitalPinToPCMSK(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCMSK0) : ((uint8_t *)0)) +#define digitalPinToPCMSKbit(p) ( ((p) >= 8 && (p) <= 11) ? (p) - 4 : ((p) == 14 ? 3 : ((p) == 15 ? 1 : ((p) == 16 ? 2 : ((p) == 17 ? 0 : (p - A8 + 4)))))) + +// __AVR_ATmega32U4__ has an unusual mapping of pins to channels +extern const uint8_t PROGMEM analog_pin_to_channel_PGM[]; +#define analogPinToChannel(P) ( pgm_read_byte( analog_pin_to_channel_PGM + (P) ) ) + +#define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT))))) + +#ifdef ARDUINO_MAIN + +// On the Arduino board, digital pins are also used +// for the analog output (software PWM). Analog input +// pins are a separate set. + +// ARDUINO LEONARDO / ARDUINO ROBOT CONTROL / ATMEGA 32U4 / FUNCTION / REGISTER +// +// D0 RX PD2 RX RXD1/INT2 +// D1 TX PD3 TX TXD1/INT3 +// D2 SDA PD1 SDA SDA/INT1 +// D3# SCL PD0 PWM8/SCL OC0B/SCL/INT0 +// D4 MUX_IN A6 PD4 ADC8 +// D5# BUZZ PC6 ??? OC3A/#OC4A +// D6# MUXA/TKD4 A7 PD7 FastPWM #OC4D/ADC10 +// D7 RST_LCD PE6 INT6/AIN0 +// +// D8 CARD_CS A8 PB4 ADC11/PCINT4 +// D9# LCD_CS A9 PB5 PWM16 OC1A/#OC4B/ADC12/PCINT5 +// D10# DC_LCD A10 PB6 PWM16 OC1B/0c4B/ADC13/PCINT6 +// D11# MUXB PB7 PWM8/16 0C0A/OC1C/#RTS/PCINT7 +// D12 MUXC/TKD5 A11 PD6 T1/#OC4D/ADC9 +// D13# MUXD PC7 PWM10 CLK0/OC4A +// +// A0 KEY D18 PF7 ADC7 +// A1 TKD0 D19 PF6 ADC6 +// A2 TKD1 D20 PF5 ADC5 +// A3 TKD2 D21 PF4 ADC4 +// A4 TKD3 D22 PF1 ADC1 +// A5 POT D23 PF0 ADC0 +// +// MISO MISO D14 PB3 MISO,PCINT3 +// SCK SCK D15 PB1 SCK,PCINT1 +// MOSI MOSI D16 PB2 MOSI,PCINT2 +// SS RX_LED D17 PB0 RXLED,SS/PCINT0 +// +// TXLED TX_LED PD5 +// HWB PE2 HWB + +// these arrays map port names (e.g. port B) to the +// appropriate addresses for various functions (e.g. reading +// and writing) +const uint16_t PROGMEM port_to_mode_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &DDRB, + (uint16_t) &DDRC, + (uint16_t) &DDRD, + (uint16_t) &DDRE, + (uint16_t) &DDRF, +}; + +const uint16_t PROGMEM port_to_output_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &PORTB, + (uint16_t) &PORTC, + (uint16_t) &PORTD, + (uint16_t) &PORTE, + (uint16_t) &PORTF, +}; + +const uint16_t PROGMEM port_to_input_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &PINB, + (uint16_t) &PINC, + (uint16_t) &PIND, + (uint16_t) &PINE, + (uint16_t) &PINF, +}; + +const uint8_t PROGMEM digital_pin_to_port_PGM[30] = { + PD, // D0 - PD2 + PD, // D1 - PD3 + PD, // D2 - PD1 + PD, // D3 - PD0 + PD, // D4 - PD4 + PC, // D5 - PC6 + PD, // D6 - PD7 + PE, // D7 - PE6 + + PB, // D8 - PB4 + PB, // D9 - PB5 + PB, // D10 - PB6 + PB, // D11 - PB7 + PD, // D12 - PD6 + PC, // D13 - PC7 + + PB, // D14 - MISO - PB3 + PB, // D15 - SCK - PB1 + PB, // D16 - MOSI - PB2 + PB, // D17 - SS - PB0 + + PF, // D18 - A0 - PF7 + PF, // D19 - A1 - PF6 + PF, // D20 - A2 - PF5 + PF, // D21 - A3 - PF4 + PF, // D22 - A4 - PF1 + PF, // D23 - A5 - PF0 + + PD, // D24 / D4 - A6 - PD4 + PD, // D25 / D6 - A7 - PD7 + PB, // D26 / D8 - A8 - PB4 + PB, // D27 / D9 - A9 - PB5 + PB, // D28 / D10 - A10 - PB6 + PD, // D29 / D12 - A11 - PD6 +}; + +const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[30] = { + _BV(2), // D0 - PD2 + _BV(3), // D1 - PD3 + _BV(1), // D2 - PD1 + _BV(0), // D3 - PD0 + _BV(4), // D4 - PD4 + _BV(6), // D5 - PC6 + _BV(7), // D6 - PD7 + _BV(6), // D7 - PE6 + + _BV(4), // D8 - PB4 + _BV(5), // D9 - PB5 + _BV(6), // D10 - PB6 + _BV(7), // D11 - PB7 + _BV(6), // D12 - PD6 + _BV(7), // D13 - PC7 + + _BV(3), // D14 - MISO - PB3 + _BV(1), // D15 - SCK - PB1 + _BV(2), // D16 - MOSI - PB2 + _BV(0), // D17 - SS - PB0 + + _BV(7), // D18 - A0 - PF7 + _BV(6), // D19 - A1 - PF6 + _BV(5), // D20 - A2 - PF5 + _BV(4), // D21 - A3 - PF4 + _BV(1), // D22 - A4 - PF1 + _BV(0), // D23 - A5 - PF0 + + _BV(4), // D24 / D4 - A6 - PD4 + _BV(7), // D25 / D6 - A7 - PD7 + _BV(4), // D26 / D8 - A8 - PB4 + _BV(5), // D27 / D9 - A9 - PB5 + _BV(6), // D28 / D10 - A10 - PB6 + _BV(6), // D29 / D12 - A11 - PD6 +}; + +const uint8_t PROGMEM digital_pin_to_timer_PGM[18] = { + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + TIMER0B, /* 3 */ + NOT_ON_TIMER, + TIMER3A, /* 5 */ + TIMER4D, /* 6 */ + NOT_ON_TIMER, + + NOT_ON_TIMER, + TIMER1A, /* 9 */ + TIMER1B, /* 10 */ + TIMER0A, /* 11 */ + + NOT_ON_TIMER, + TIMER4A, /* 13 */ + + NOT_ON_TIMER, + NOT_ON_TIMER, +}; + +const uint8_t PROGMEM analog_pin_to_channel_PGM[12] = { + 7, // A0 PF7 ADC7 + 6, // A1 PF6 ADC6 + 5, // A2 PF5 ADC5 + 4, // A3 PF4 ADC4 + 1, // A4 PF1 ADC1 + 0, // A5 PF0 ADC0 + 8, // A6 D4 PD4 ADC8 + 10, // A7 D6 PD7 ADC10 + 11, // A8 D8 PB4 ADC11 + 12, // A9 D9 PB5 ADC12 + 13, // A10 D10 PB6 ADC13 + 9 // A11 D12 PD6 ADC9 +}; + +#endif /* ARDUINO_MAIN */ + +// These serial port names are intended to allow libraries and architecture-neutral +// sketches to automatically default to the correct port name for a particular type +// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, +// the first hardware serial port whose RX/TX pins are not dedicated to another use. +// +// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor +// +// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial +// +// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library +// +// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. +// +// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX +// pins are NOT connected to anything by default. +#define SERIAL_PORT_MONITOR Serial +#define SERIAL_PORT_USBVIRTUAL Serial +#define SERIAL_PORT_HARDWARE Serial1 + +#endif /* Pins_Arduino_h */ diff --git a/avr/variants/robot_motor/pins_arduino.h b/avr/variants/robot_motor/pins_arduino.h new file mode 100644 index 0000000..2ed77e7 --- /dev/null +++ b/avr/variants/robot_motor/pins_arduino.h @@ -0,0 +1,326 @@ +/* + pins_arduino.h - Pin definition functions for Arduino Robot Control Board + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2913 D. Cuartielles, X. Yang (Arduino Verkstad) + Copyright (c) 2012 D. Cuartielles, N. de la Riva, I. Gallego, E. Gallego + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define ARDUINO_MODEL_USB_PID 0x0039 + +#define TX_RX_LED_INIT DDRD |= (1<<5), DDRB |= (1<<0) +#define TXLED0 PORTD |= (1<<5) +#define TXLED1 PORTD &= ~(1<<5) +#define RXLED0 PORTB |= (1<<0) +#define RXLED1 PORTB &= ~(1<<0) + +#define D10 TK1 +#define D9 TK2 +#define D8 TK4 +#define D7 TK3 + +#define PIN_SERIAL_RX (0) +#define PIN_SERIAL_TX (1) + +static const uint8_t RX = PIN_SERIAL_RX; +static const uint8_t TX = PIN_SERIAL_TX; + +#define PIN_WIRE_SDA (2) +#define PIN_WIRE_SCL (3) + +static const uint8_t SDA = PIN_WIRE_SDA; +static const uint8_t SCL = PIN_WIRE_SCL; + +// Map SPI port to 'new' pins D14..D17 +#define PIN_SPI_SS (17) +#define PIN_SPI_MOSI (16) +#define PIN_SPI_MISO (14) +#define PIN_SPI_SCK (15) + +static const uint8_t SS = PIN_SPI_SS; +static const uint8_t MOSI = PIN_SPI_MOSI; +static const uint8_t MISO = PIN_SPI_MISO; +static const uint8_t SCK = PIN_SPI_SCK; + +// Mapping of analog pins as digital I/O +// A6-A11 share with digital pins +#define PIN_A0 (18) +#define PIN_A1 (19) +#define PIN_A2 (20) +#define PIN_A3 (21) +#define PIN_A4 (22) +#define PIN_A5 (23) +#define PIN_A6 (24) +#define PIN_A7 (25) +#define PIN_A8 (26) +#define PIN_A9 (27) +#define PIN_A10 (28) +#define PIN_A11 (29) + +static const uint8_t A0 = PIN_A0; +static const uint8_t A1 = PIN_A1; +static const uint8_t A2 = PIN_A2; +static const uint8_t A3 = PIN_A3; +static const uint8_t A4 = PIN_A4; +static const uint8_t A5 = PIN_A5; +static const uint8_t A6 = PIN_A6; // D4 +static const uint8_t A7 = PIN_A7; // D6 +static const uint8_t A8 = PIN_A8; // D8 +static const uint8_t A9 = PIN_A9; // D9 +static const uint8_t A10 = PIN_A10; // D10 +static const uint8_t A11 = PIN_A11; // D12 + +// Specific Mapping for the Motor Board +static const uint8_t MUX_IN = 20; // A2 +static const uint8_t MUXA = 7; // D7 +static const uint8_t MUXB = 8; // D8 +static const uint8_t MUXC = 11; // D11 +static const uint8_t MUXI = 13; // D13 +static const uint8_t TRIM = 21; // A3 +static const uint8_t SENSE_A = 22; // A4 +static const uint8_t SENSE_B = 23; // A5 +static const uint8_t IN_A1 = 6; // D6 - A7 +static const uint8_t IN_A2 = 5; // D5 +static const uint8_t IN_B1 = 10; // D10 +static const uint8_t IN_B2 = 9; // D9 +static const uint8_t TK1 = 18; // A0 +static const uint8_t TK2 = 19; // A1 +static const uint8_t TK3 = 4; // A6 +static const uint8_t TK4 = 12; // A11 + +#define digitalPinToPCICR(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCICR) : ((uint8_t *)0)) +#define digitalPinToPCICRbit(p) 0 +#define digitalPinToPCMSK(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCMSK0) : ((uint8_t *)0)) +#define digitalPinToPCMSKbit(p) ( ((p) >= 8 && (p) <= 11) ? (p) - 4 : ((p) == 14 ? 3 : ((p) == 15 ? 1 : ((p) == 16 ? 2 : ((p) == 17 ? 0 : (p - A8 + 4)))))) + +// __AVR_ATmega32U4__ has an unusual mapping of pins to channels +extern const uint8_t PROGMEM analog_pin_to_channel_PGM[]; +#define analogPinToChannel(P) ( pgm_read_byte( analog_pin_to_channel_PGM + (P) ) ) + +#define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT))))) + +#ifdef ARDUINO_MAIN + +// On the Arduino board, digital pins are also used +// for the analog output (software PWM). Analog input +// pins are a separate set. + +// ARDUINO LEONARDO / ARDUINO ROBOT CONTROL / ATMEGA 32U4 / FUNCTION / REGISTER +// +// D0 RX PD2 RX RXD1/INT2 +// D1 TX PD3 TX TXD1/INT3 +// D2 SDA PD1 SDA SDA/INT1 +// D3# SCL PD0 PWM8/SCL OC0B/SCL/INT0 +// D4 TK3 A6 PD4 ADC8 +// D5# INA2 PC6 ??? OC3A/#OC4A +// D6# INA1 A7 PD7 FastPWM #OC4D/ADC10 +// D7 MUXA PE6 INT6/AIN0 +// +// D8 MUXB A8 PB4 ADC11/PCINT4 +// D9# INB2 A9 PB5 PWM16 OC1A/#OC4B/ADC12/PCINT5 +// D10# INB1 A10 PB6 PWM16 OC1B/0c4B/ADC13/PCINT6 +// D11# MUXC PB7 PWM8/16 0C0A/OC1C/#RTS/PCINT7 +// D12 TK4 A11 PD6 T1/#OC4D/ADC9 +// D13# MUXI PC7 PWM10 CLK0/OC4A +// +// A0 TK1 D18 PF7 ADC7 +// A1 TK2 D19 PF6 ADC6 +// A2 MUX_IN D20 PF5 ADC5 +// A3 TRIM D21 PF4 ADC4 +// A4 SENSE_A D22 PF1 ADC1 +// A5 SENSE_B D23 PF0 ADC0 +// +// MISO MISO D14 PB3 MISO,PCINT3 +// SCK SCK D15 PB1 SCK,PCINT1 +// MOSI MOSI D16 PB2 MOSI,PCINT2 +// SS RX_LED D17 PB0 RXLED,SS/PCINT0 +// +// TXLED TX_LED PD5 +// HWB PE2 HWB + +// these arrays map port names (e.g. port B) to the +// appropriate addresses for various functions (e.g. reading +// and writing) +const uint16_t PROGMEM port_to_mode_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &DDRB, + (uint16_t) &DDRC, + (uint16_t) &DDRD, + (uint16_t) &DDRE, + (uint16_t) &DDRF, +}; + +const uint16_t PROGMEM port_to_output_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &PORTB, + (uint16_t) &PORTC, + (uint16_t) &PORTD, + (uint16_t) &PORTE, + (uint16_t) &PORTF, +}; + +const uint16_t PROGMEM port_to_input_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &PINB, + (uint16_t) &PINC, + (uint16_t) &PIND, + (uint16_t) &PINE, + (uint16_t) &PINF, +}; + +const uint8_t PROGMEM digital_pin_to_port_PGM[30] = { + PD, // D0 - PD2 + PD, // D1 - PD3 + PD, // D2 - PD1 + PD, // D3 - PD0 + PD, // D4 - PD4 + PC, // D5 - PC6 + PD, // D6 - PD7 + PE, // D7 - PE6 + + PB, // D8 - PB4 + PB, // D9 - PB5 + PB, // D10 - PB6 + PB, // D11 - PB7 + PD, // D12 - PD6 + PC, // D13 - PC7 + + PB, // D14 - MISO - PB3 + PB, // D15 - SCK - PB1 + PB, // D16 - MOSI - PB2 + PB, // D17 - SS - PB0 + + PF, // D18 - A0 - PF7 + PF, // D19 - A1 - PF6 + PF, // D20 - A2 - PF5 + PF, // D21 - A3 - PF4 + PF, // D22 - A4 - PF1 + PF, // D23 - A5 - PF0 + + PD, // D24 / D4 - A6 - PD4 + PD, // D25 / D6 - A7 - PD7 + PB, // D26 / D8 - A8 - PB4 + PB, // D27 / D9 - A9 - PB5 + PB, // D28 / D10 - A10 - PB6 + PD, // D29 / D12 - A11 - PD6 +}; + +const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[30] = { + _BV(2), // D0 - PD2 + _BV(3), // D1 - PD3 + _BV(1), // D2 - PD1 + _BV(0), // D3 - PD0 + _BV(4), // D4 - PD4 + _BV(6), // D5 - PC6 + _BV(7), // D6 - PD7 + _BV(6), // D7 - PE6 + + _BV(4), // D8 - PB4 + _BV(5), // D9 - PB5 + _BV(6), // D10 - PB6 + _BV(7), // D11 - PB7 + _BV(6), // D12 - PD6 + _BV(7), // D13 - PC7 + + _BV(3), // D14 - MISO - PB3 + _BV(1), // D15 - SCK - PB1 + _BV(2), // D16 - MOSI - PB2 + _BV(0), // D17 - SS - PB0 + + _BV(7), // D18 - A0 - PF7 + _BV(6), // D19 - A1 - PF6 + _BV(5), // D20 - A2 - PF5 + _BV(4), // D21 - A3 - PF4 + _BV(1), // D22 - A4 - PF1 + _BV(0), // D23 - A5 - PF0 + + _BV(4), // D24 / D4 - A6 - PD4 + _BV(7), // D25 / D6 - A7 - PD7 + _BV(4), // D26 / D8 - A8 - PB4 + _BV(5), // D27 / D9 - A9 - PB5 + _BV(6), // D28 / D10 - A10 - PB6 + _BV(6), // D29 / D12 - A11 - PD6 +}; + +const uint8_t PROGMEM digital_pin_to_timer_PGM[18] = { + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + TIMER0B, /* 3 */ + NOT_ON_TIMER, + TIMER3A, /* 5 */ + TIMER4D, /* 6 */ + NOT_ON_TIMER, + + NOT_ON_TIMER, + TIMER1A, /* 9 */ + TIMER1B, /* 10 */ + TIMER0A, /* 11 */ + + NOT_ON_TIMER, + TIMER4A, /* 13 */ + + NOT_ON_TIMER, + NOT_ON_TIMER, +}; + +const uint8_t PROGMEM analog_pin_to_channel_PGM[12] = { + 7, // A0 PF7 ADC7 + 6, // A1 PF6 ADC6 + 5, // A2 PF5 ADC5 + 4, // A3 PF4 ADC4 + 1, // A4 PF1 ADC1 + 0, // A5 PF0 ADC0 + 8, // A6 D4 PD4 ADC8 + 10, // A7 D6 PD7 ADC10 + 11, // A8 D8 PB4 ADC11 + 12, // A9 D9 PB5 ADC12 + 13, // A10 D10 PB6 ADC13 + 9 // A11 D12 PD6 ADC9 +}; + +#endif /* ARDUINO_MAIN */ + +// These serial port names are intended to allow libraries and architecture-neutral +// sketches to automatically default to the correct port name for a particular type +// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, +// the first hardware serial port whose RX/TX pins are not dedicated to another use. +// +// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor +// +// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial +// +// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library +// +// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. +// +// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX +// pins are NOT connected to anything by default. +#define SERIAL_PORT_MONITOR Serial +#define SERIAL_PORT_USBVIRTUAL Serial +#define SERIAL_PORT_HARDWARE Serial1 + +#endif /* Pins_Arduino_h */