├── files ├── out.txt └── sender_test.txt ├── requirements.txt ├── firmware ├── lib │ ├── Arduino-GPIO │ │ ├── _gitignore │ │ ├── examples │ │ │ ├── Blink │ │ │ │ └── Blink.ino │ │ │ ├── ATtiny │ │ │ │ ├── Blink │ │ │ │ │ └── Blink.ino │ │ │ │ ├── Pulse │ │ │ │ │ └── Pulse.ino │ │ │ │ ├── Button │ │ │ │ │ └── Button.ino │ │ │ │ ├── ShiftInOut │ │ │ │ │ └── ShiftInOut.ino │ │ │ │ ├── ShiftOut │ │ │ │ │ └── ShiftOut.ino │ │ │ │ ├── ShiftIn │ │ │ │ │ └── ShiftIn.ino │ │ │ │ └── Benchmark │ │ │ │ │ └── Benchmark.ino │ │ │ ├── Button │ │ │ │ └── Button.ino │ │ │ ├── SoftwareSerial │ │ │ │ └── SoftwareSerial.ino │ │ │ ├── Pulse │ │ │ │ └── Pulse.ino │ │ │ ├── ShiftInOut │ │ │ │ └── ShiftInOut.ino │ │ │ ├── ShiftOut │ │ │ │ └── ShiftOut.ino │ │ │ ├── ShiftIn │ │ │ │ └── ShiftIn.ino │ │ │ └── Benchmark │ │ │ │ └── Benchmark.ino │ │ ├── library.properties │ │ ├── src │ │ │ ├── GPIO.h │ │ │ ├── bswap.h │ │ │ ├── bcd.h │ │ │ ├── assert.h │ │ │ ├── iovec.h │ │ │ ├── SRPO.h │ │ │ ├── SRPI.h │ │ │ ├── Keypad.h │ │ │ ├── benchmark.h │ │ │ ├── Button.h │ │ │ ├── SRPIO.h │ │ │ ├── Software │ │ │ │ └── Serial.h │ │ │ └── Hardware │ │ │ │ ├── AVR │ │ │ │ ├── GPIO.h │ │ │ │ └── Board.h │ │ │ │ └── SAM │ │ │ │ ├── GPIO.h │ │ │ │ └── Board.h │ │ ├── mainpage.dox │ │ └── README.md │ └── DueTimer │ │ ├── _gitignore │ │ ├── library.json │ │ ├── keywords.txt │ │ ├── library.properties │ │ ├── examples │ │ ├── SimpleTimer │ │ │ └── SimpleTimer.pde │ │ ├── MultipleTimers │ │ │ └── MultipleTimers.pde │ │ └── AvaliableTimer │ │ │ └── AvaliableTimer.pde │ │ ├── LICENSE.txt │ │ ├── DueTimer.h │ │ ├── README.md │ │ ├── TimerCounter.md │ │ └── DueTimer.cpp ├── driver_receive │ └── driver_receive.ino ├── driver_send │ └── driver_send.ino └── bidirectional │ └── bidirectional.ino ├── hardware └── README.MD ├── lib ├── fsm.py ├── state.py ├── main.py ├── serial_connect.py ├── my_states.py ├── LiFiGUI.py ├── Receiver.py └── Sender.py ├── .gitignore └── README.MD /files/out.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyserial 2 | -------------------------------------------------------------------------------- /files/sender_test.txt: -------------------------------------------------------------------------------- 1 | Sender test 2 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/_gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | doc 3 | -------------------------------------------------------------------------------- /firmware/lib/DueTimer/_gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | 15 | .DS_Store 16 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/examples/Blink/Blink.ino: -------------------------------------------------------------------------------- 1 | #include "GPIO.h" 2 | 3 | GPIO led; 4 | 5 | void setup() 6 | { 7 | led.output(); 8 | } 9 | 10 | void loop() 11 | { 12 | led = HIGH; 13 | delay(1000); 14 | led = LOW; 15 | delay(1000); 16 | } 17 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/examples/ATtiny/Blink/Blink.ino: -------------------------------------------------------------------------------- 1 | #include "GPIO.h" 2 | 3 | GPIO led; 4 | 5 | void setup() 6 | { 7 | led.output(); 8 | } 9 | 10 | void loop() 11 | { 12 | led = HIGH; 13 | delay(1000); 14 | led = LOW; 15 | delay(1000); 16 | } 17 | -------------------------------------------------------------------------------- /firmware/lib/DueTimer/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DueTimer", 3 | "keywords": "timer", 4 | "description": "Timer Library fully implemented for Arduino DUE", 5 | "repository": 6 | { 7 | "type": "git", 8 | "url": "https://github.com/ivanseidel/DueTimer.git" 9 | }, 10 | "frameworks": "arduino", 11 | "platforms": "atmelsam" 12 | } 13 | -------------------------------------------------------------------------------- /hardware/README.MD: -------------------------------------------------------------------------------- 1 | ## Things To Note 2 | - LM311N Part Is To Be Replaced With LT1016 3 | - They share the same footprint, pinout used is for the LT1016 4 | 5 | R1 -> 36 Ω 6 | 7 | R2 -> 160 kΩ 8 | 9 | R3 -> 22 kΩ 10 | 11 | R4 -> Feedback Resistor (variable value for optimization) 12 | 13 | C1 -> 1 μF 14 | 15 | C2 -> .047 μF 16 | 17 | C3 -> Feedback Capacitor (variable value for optimization) 18 | 19 | C4 -> 1 pF 20 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/examples/Button/Button.ino: -------------------------------------------------------------------------------- 1 | #include "GPIO.h" 2 | #include "Button.h" 3 | 4 | Button button; 5 | 6 | void setup() 7 | { 8 | Serial.begin(57600); 9 | while (!Serial); 10 | } 11 | 12 | void loop() 13 | { 14 | if (button.ischanged()) { 15 | Serial.print(button.timestamp()); 16 | Serial.print(':'); 17 | Serial.println(button ? F("released") : F("pushed")); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/examples/SoftwareSerial/SoftwareSerial.ino: -------------------------------------------------------------------------------- 1 | #include "GPIO.h" 2 | #include "Software/Serial.h" 3 | 4 | Software::Serial outs; 5 | 6 | void setup() 7 | { 8 | // outs.begin(9600); 9 | outs.begin(57600); 10 | // outs.begin(114200); 11 | // outs.begin(230400); 12 | // outs.begin(250000); 13 | } 14 | 15 | void loop() 16 | { 17 | outs.println(millis()); 18 | delay(10); 19 | } 20 | -------------------------------------------------------------------------------- /firmware/lib/DueTimer/keywords.txt: -------------------------------------------------------------------------------- 1 | DueTimer KEYWORD2 2 | start KEYWORD2 3 | stop KEYWORD2 4 | attachInterrupt KEYWORD2 5 | detachInterrupt KEYWORD2 6 | setPeriod KEYWORD2 7 | setFrequency KEYWORD2 8 | getFrequency KEYWORD2 9 | getPeriod KEYWORD2 10 | 11 | Timer KEYWORD1 12 | Timer0 KEYWORD1 13 | Timer1 KEYWORD1 14 | Timer2 KEYWORD1 15 | Timer3 KEYWORD1 16 | Timer4 KEYWORD1 17 | Timer5 KEYWORD1 18 | Timer6 KEYWORD1 19 | Timer7 KEYWORD1 20 | 21 | -------------------------------------------------------------------------------- /firmware/lib/DueTimer/library.properties: -------------------------------------------------------------------------------- 1 | name=DueTimer 2 | version=1.4.7 3 | author=Ivan Seidel 4 | maintainer=Ivan Seidel 5 | sentence=Timer Library fully implemented for Arduino DUE 6 | paragraph=There are 9 Timer objects already instantiated for you: Timer0, Timer1, Timer2, Timer3, Timer4, Timer5, Timer6, Timer7 and Timer8. 7 | category=Timing 8 | url=https://github.com/ivanseidel/DueTimer 9 | architectures=sam 10 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/examples/Pulse/Pulse.ino: -------------------------------------------------------------------------------- 1 | #include "GPIO.h" 2 | 3 | GPIO led; 4 | 5 | void setup() 6 | { 7 | led.output(); 8 | } 9 | 10 | void loop() 11 | { 12 | // Pulse width 1..10 us, not interrupted 13 | for (int width = 1; width < 11; width++) 14 | led.pulse(width); 15 | 16 | // Delay 10 us but observe with logic analyzer variation 10,15 us 17 | // as timer interrupts will occur here 18 | delayMicroseconds(10); 19 | } 20 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/examples/ATtiny/Pulse/Pulse.ino: -------------------------------------------------------------------------------- 1 | #include "GPIO.h" 2 | 3 | GPIO led; 4 | 5 | void setup() 6 | { 7 | led.output(); 8 | } 9 | 10 | void loop() 11 | { 12 | // Pulse width 1..10 us, not interrupted 13 | for (int width = 1; width < 11; width++) 14 | led.pulse(width); 15 | 16 | // Delay 10 us but observe with logic analyzer variation 10,15 us 17 | // as timer interrupts will occur here 18 | delayMicroseconds(10); 19 | } 20 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/examples/ATtiny/Button/Button.ino: -------------------------------------------------------------------------------- 1 | #include "GPIO.h" 2 | #include "Button.h" 3 | 4 | #include "Software/Serial.h" 5 | Software::Serial Serial; 6 | Button button; 7 | 8 | void setup() 9 | { 10 | Serial.begin(57600); 11 | while (!Serial); 12 | } 13 | 14 | void loop() 15 | { 16 | if (button.ischanged()) { 17 | Serial.print(button.timestamp()); 18 | Serial.print(':'); 19 | Serial.println(button ? F("released") : F("pushed")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /firmware/lib/DueTimer/examples/SimpleTimer/SimpleTimer.pde: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int myLed = 13; 4 | 5 | bool ledOn = false; 6 | void myHandler(){ 7 | ledOn = !ledOn; 8 | 9 | digitalWrite(myLed, ledOn); // Led on, off, on, off... 10 | } 11 | 12 | void setup(){ 13 | pinMode(myLed, OUTPUT); 14 | 15 | Timer3.attachInterrupt(myHandler); 16 | Timer3.start(50000); // Calls every 50ms 17 | } 18 | 19 | void loop(){ 20 | 21 | while(1){ 22 | // I'm stuck in here! help me... 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/examples/ShiftInOut/ShiftInOut.ino: -------------------------------------------------------------------------------- 1 | #include "GPIO.h" 2 | #include "SRPIO.h" 3 | #include "benchmark.h" 4 | 5 | SRPIO srpio; 6 | 7 | void setup() 8 | { 9 | Serial.begin(57600); 10 | while (!Serial); 11 | BENCHMARK_BASELINE(1000); 12 | } 13 | 14 | void loop() 15 | { 16 | uint8_t value = 0; 17 | 18 | BENCHMARK("1. SRPIO input operator", 1000) { 19 | srpio >> value; 20 | } 21 | 22 | value = 0xa5; 23 | BENCHMARK("2. SRPIO output operator", 1000) { 24 | srpio << value; 25 | } 26 | 27 | Serial.println(); 28 | delay(2000); 29 | } 30 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/examples/ATtiny/ShiftInOut/ShiftInOut.ino: -------------------------------------------------------------------------------- 1 | #include "GPIO.h" 2 | #include "SRPIO.h" 3 | #include "benchmark.h" 4 | 5 | #include "Software/Serial.h" 6 | Software::Serial Serial; 7 | SRPIO srpio; 8 | 9 | void setup() 10 | { 11 | Serial.begin(57600); 12 | while (!Serial); 13 | BENCHMARK_BASELINE(1000); 14 | } 15 | 16 | void loop() 17 | { 18 | uint8_t value = 0; 19 | 20 | BENCHMARK("1. SRPIO input operator", 1000) { 21 | srpio >> value; 22 | } 23 | 24 | value = 0xa5; 25 | BENCHMARK("2. SRPIO output operator", 1000) { 26 | srpio << value; 27 | } 28 | 29 | Serial.println(); 30 | delay(2000); 31 | } 32 | -------------------------------------------------------------------------------- /firmware/lib/DueTimer/examples/MultipleTimers/MultipleTimers.pde: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void firstHandler(){ 4 | Serial.println("[- ] First Handler!"); 5 | } 6 | 7 | void secondHandler(){ 8 | Serial.println("[ - ] Second Handler!"); 9 | } 10 | 11 | void thirdHandler(){ 12 | Serial.println("[ -] Third Handler!"); 13 | } 14 | 15 | void setup(){ 16 | Serial.begin(9600); 17 | 18 | Timer3.attachInterrupt(firstHandler).start(500000); // Every 500ms 19 | Timer4.attachInterrupt(secondHandler).setFrequency(1).start(); 20 | Timer5.attachInterrupt(thirdHandler).setFrequency(10); 21 | } 22 | 23 | void loop(){ 24 | delay(2000); 25 | Timer5.start(); 26 | 27 | delay(2000); 28 | Timer5.stop(); 29 | } -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/examples/ShiftOut/ShiftOut.ino: -------------------------------------------------------------------------------- 1 | #include "GPIO.h" 2 | #include "SRPO.h" 3 | #include "benchmark.h" 4 | 5 | SRPO srpo; 6 | #define DATA_PIN 12 7 | #define CLOCK_PIN 13 8 | 9 | void setup() 10 | { 11 | Serial.begin(57600); 12 | while (!Serial); 13 | pinMode(DATA_PIN, OUTPUT); 14 | pinMode(CLOCK_PIN, OUTPUT); 15 | BENCHMARK_BASELINE(1000); 16 | } 17 | 18 | void loop() 19 | { 20 | uint8_t value = 0xa5; 21 | 22 | BENCHMARK("1. Arduino core shiftOut", 1000) { 23 | shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, value); 24 | } 25 | 26 | BENCHMARK("2. SRPO output operator", 1000) { 27 | srpo << value; 28 | } 29 | 30 | Serial.println(); 31 | delay(2000); 32 | } 33 | -------------------------------------------------------------------------------- /lib/fsm.py: -------------------------------------------------------------------------------- 1 | """ 2 | fsm.py 3 | 4 | This file contains our state machine class (FSM) and gives access to states 5 | and state transitions. 6 | """ 7 | 8 | from my_states import Receiver, Sender 9 | 10 | 11 | class FSM: 12 | """ 13 | A simple state machine to cycle through 14 | our states. 15 | """ 16 | def __init__(self): 17 | """ Initialize The Components. """ 18 | # Start With A Default State 19 | self.state = Receiver() 20 | 21 | def on_event(self, event): 22 | """ 23 | Incoming events are delegated to the given states which then 24 | handle the event. The result is then assigned as the new state. 25 | """ 26 | # The Next State Is The Result Of on_event 27 | self.state = self.state.on_event(event) 28 | -------------------------------------------------------------------------------- /lib/state.py: -------------------------------------------------------------------------------- 1 | """ 2 | state.py 3 | 4 | This file is a base template for my_states.py 5 | """ 6 | 7 | class State: 8 | """ 9 | Defining our state object to provide utility functions 10 | for our individual states within our FSM. 11 | """ 12 | 13 | def __init__(self): 14 | print("Processing current state: %s" % str(self)) 15 | 16 | def on_event(self, event): 17 | """ 18 | Handle events that are delegated to the specific State. 19 | """ 20 | pass 21 | 22 | def __repr__(self): 23 | """ 24 | Leverages the __str__ method to describe the State. 25 | """ 26 | return self.__str__() 27 | 28 | def __str__(self): 29 | """ 30 | Returns the name of the current State. 31 | """ 32 | return self.__class__.__name__ 33 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/examples/ShiftIn/ShiftIn.ino: -------------------------------------------------------------------------------- 1 | #include "GPIO.h" 2 | #include "SRPI.h" 3 | #include "benchmark.h" 4 | 5 | SRPI srpi; 6 | #define DATA_PIN 12 7 | #define CLOCK_PIN 13 8 | 9 | void setup() 10 | { 11 | Serial.begin(57600); 12 | while (!Serial); 13 | 14 | // Set pin mode 15 | pinMode(DATA_PIN, INPUT); 16 | pinMode(CLOCK_PIN, OUTPUT); 17 | 18 | // Set benchmark baseline 19 | BENCHMARK_BASELINE(1000); 20 | } 21 | 22 | void loop() 23 | { 24 | uint8_t value; 25 | 26 | BENCHMARK("1. Arduino core shiftIn", 1000) { 27 | value = shiftIn(DATA_PIN, CLOCK_PIN, LSBFIRST); 28 | } 29 | 30 | BENCHMARK("2. SRPI input operator", 1000) { 31 | srpi >> value; 32 | } 33 | 34 | Serial.println(); 35 | delay(2000); 36 | } 37 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/examples/ATtiny/ShiftOut/ShiftOut.ino: -------------------------------------------------------------------------------- 1 | #include "GPIO.h" 2 | #include "SRPO.h" 3 | #include "benchmark.h" 4 | 5 | #include "Software/Serial.h" 6 | Software::Serial Serial; 7 | SRPO srpo; 8 | #define DATA_PIN 0 9 | #define CLOCK_PIN 1 10 | 11 | void setup() 12 | { 13 | Serial.begin(57600); 14 | while (!Serial); 15 | BENCHMARK_BASELINE(1000); 16 | pinMode(DATA_PIN, OUTPUT); 17 | pinMode(CLOCK_PIN, OUTPUT); 18 | } 19 | 20 | void loop() 21 | { 22 | uint8_t value = 0xa5; 23 | 24 | BENCHMARK("1. Arduino core shiftOut", 1000) { 25 | shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, value); 26 | } 27 | 28 | BENCHMARK("2. SRPO output operator", 1000) { 29 | srpo << value; 30 | } 31 | 32 | Serial.println(); 33 | delay(2000); 34 | } 35 | -------------------------------------------------------------------------------- /lib/main.py: -------------------------------------------------------------------------------- 1 | """ 2 | main.py 3 | 4 | This file is the main file for the LiFi driver. It imports all the files associated with 5 | our driver and gives appropriate access to each object. 6 | """ 7 | 8 | from fsm import FSM 9 | from LiFiGUI import SerialGUI 10 | from Sender import Sender_Driver 11 | from Receiver import Receiver_Driver 12 | 13 | class Main: 14 | def __init__(self): 15 | # Create a State Machine object 16 | self.__my_fsm = FSM() 17 | 18 | # Create a Sender and Receiver Driver object 19 | self.__sd = Sender_Driver(self.__my_fsm) 20 | self.__rd = Receiver_Driver(self.__my_fsm) 21 | 22 | # Create a GUI object 23 | self.__my_gui = SerialGUI(self.__my_fsm, self.__sd, self.__rd) 24 | self.__my_gui.window.mainloop() 25 | 26 | 27 | main = Main() 28 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/examples/ATtiny/ShiftIn/ShiftIn.ino: -------------------------------------------------------------------------------- 1 | #include "GPIO.h" 2 | #include "SRPI.h" 3 | #include "benchmark.h" 4 | 5 | #include "Software/Serial.h" 6 | Software::Serial Serial; 7 | SRPI srpi; 8 | #define DATA_PIN 1 9 | #define CLOCK_PIN 2 10 | 11 | void setup() 12 | { 13 | Serial.begin(57600); 14 | while (!Serial); 15 | 16 | // Set pin mode 17 | pinMode(DATA_PIN, INPUT); 18 | pinMode(CLOCK_PIN, OUTPUT); 19 | 20 | // Set benchmark baseline 21 | BENCHMARK_BASELINE(1000); 22 | } 23 | 24 | void loop() 25 | { 26 | uint8_t value; 27 | 28 | BENCHMARK("1. Arduino core shiftIn", 1000) { 29 | value = shiftIn(DATA_PIN, CLOCK_PIN, LSBFIRST); 30 | } 31 | 32 | BENCHMARK("2. SRPI input operator", 1000) { 33 | srpi >> value; 34 | } 35 | 36 | Serial.println(); 37 | delay(2000); 38 | } 39 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/library.properties: -------------------------------------------------------------------------------- 1 | name=Arduino-GPIO 2 | version=1.11 3 | author=Mikael Patel 4 | maintainer=Mikael Patel 5 | sentence=General Purpose Input/Output (GPIO) library for Arduino. 6 | paragraph=The GPIO library has been developed to allow high performance digital pin access. Most access functions are compiled to a single instruction and execute in 1-2 clock cycles. The library functions are more than 10 times faster than the Arduino digital pin functions. In some cases as much as 100 times faster. Additional support classes are available for Debounced Digital and Analog Pin, Shift Register Parallel Input/Output and Software Serial. These also demonstrate how the GPIO template class may be used to construct additional libraries. 7 | category=Communication 8 | url=https://github.com/mikaelpatel/Arduino-GPIO 9 | architectures=avr,sam 10 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/src/GPIO.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file GPIO.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2017, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef GPIO_H 20 | #define GPIO_H 21 | #if defined(AVR) 22 | #include "Hardware/AVR/GPIO.h" 23 | #elif defined(SAM) 24 | #include "Hardware/SAM/GPIO.h" 25 | #endif 26 | #endif 27 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/src/bswap.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file bswap.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2017, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * @section References 19 | * Byte swap functions, https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html 20 | */ 21 | 22 | #ifndef BSWAP_H 23 | #define BSWAP_H 24 | 25 | #define bswap16(x) __builtin_bswap16(x) 26 | #define bswap32(x) __builtin_bswap32(x) 27 | #define bswap64(x) __builtin_bswap64(x) 28 | #define bswap(x) bswap16(x) 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /firmware/lib/DueTimer/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Ivan Seidel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /firmware/driver_receive/driver_receive.ino: -------------------------------------------------------------------------------- 1 | #include "DueTimer.h" 2 | #include "GPIO.h" 3 | 4 | #define LENGTH 64 // we can change arduino hardware limit 5 | 6 | GPIO pin7in; 7 | volatile int handler_running = 0; 8 | char binaryNum[LENGTH][8]; 9 | 10 | volatile int i; 11 | volatile int j; 12 | 13 | DueTimer myTimer = DueTimer(0); 14 | 15 | void setup() { 16 | // put your setup code here, to run once: 17 | myTimer.attachInterrupt(handler).setPeriod(10); 18 | pin7in.input(); 19 | 20 | Serial.begin(115200); 21 | while (!Serial); 22 | } 23 | 24 | void loop() { 25 | // put your main code here, to run repeatedly: 26 | char strArray[64]; 27 | 28 | while(pin7in); 29 | 30 | i = 0; 31 | j = 0; 32 | myTimer.start(); 33 | handler_running = 1; 34 | 35 | while(handler_running) delay(1); 36 | 37 | for(int k = 0; k < 64; k++) { 38 | strArray[k] = convertToChar(binaryNum[k]); 39 | } 40 | 41 | for(int k = 0; k < 64; k++) { 42 | Serial.print(strArray[k]); 43 | } 44 | } 45 | 46 | void handler() { 47 | binaryNum[i][j] = pin7in; 48 | if(j<7) { 49 | j++; 50 | } else if (i<63){ 51 | j=0; 52 | i++; 53 | } else { 54 | pin7in = 1; 55 | myTimer.stop(); 56 | handler_running = 0; 57 | } 58 | } 59 | 60 | char convertToChar(char* binaryChar) 61 | { 62 | int multiplier = 0; 63 | int temp; 64 | int sum = 0; 65 | for(temp = 7; temp>=0; temp--) 66 | sum += (binaryChar[temp]*(1 << multiplier++)); 67 | return sum; 68 | } 69 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/src/bcd.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file bcd.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2017, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef BCD_H 20 | #define BCD_H 21 | 22 | /** 23 | * Binary-Coded Decimal (BCD) to integer conversion handling. 24 | */ 25 | struct bcd_t { 26 | /** 27 | * Default constructor. 28 | */ 29 | bcd_t() : m_value(0) {} 30 | 31 | /** 32 | * Construct bcd value from given value; 0..99 to 0x00..0x99. 33 | * @param[in] value as integer. 34 | */ 35 | bcd_t(uint8_t value) 36 | { 37 | uint8_t high = 0; 38 | uint8_t low = value; 39 | while (low > 9) { 40 | high += 0x10; 41 | low -= 10; 42 | } 43 | m_value = high + low; 44 | } 45 | 46 | /** 47 | * Convert bcd value to integer; 0x00..0x99 to 0..99. 48 | * @return integer. 49 | */ 50 | operator uint8_t() 51 | { 52 | uint8_t high = (m_value & 0xf0); 53 | uint8_t low = (m_value & 0x0f); 54 | return ((high >> 1) + (high >> 3) + low); 55 | } 56 | 57 | private: 58 | uint8_t m_value; 59 | } __attribute__((packed)); 60 | 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/mainpage.dox: -------------------------------------------------------------------------------- 1 | /** @mainpage Arduino-GPIO 2 | 3 | The Arduino GPIO library has been developed to allow high performance 4 | digital pin access. Most access functions are compiled to a single 5 | instruction and execute in 1-2 clock cycles. The library functions are 6 | more than 10 times faster than the Arduino digital pin functions. In 7 | some cases as much as 100 times faster. 8 | 9 | Additional support classes are available for Debounced Digital 10 | (Button) and Analog Pin (Keypad), Shift Register Parallel Input and 11 | Output (SRPI, SRPO and SRPIO), and Serial (Software::Serial). These 12 | also demonstrate how the GPIO template class may be used to construct 13 | additional classes and libraries. 14 | 15 | This library supports boards based on SAM3X8E, ATmega168, ATmega328P, 16 | ATmega32U4, ATmega1280, ATmega2560, ATtinyX4 and ATtinyX5. 17 | 18 | Version: 1.11 19 | */ 20 | 21 | /** @page License 22 | 23 | Copyright (C) 2017, Mikael Patel 24 | 25 | This library is free software; you can redistribute it and/or 26 | modify it under the terms of the GNU Lesser General Public 27 | License as published by the Free Software Foundation; either 28 | version 2.1 of the License, or (at your option) any later version. 29 | 30 | This library is distributed in the hope that it will be useful, 31 | but WITHOUT ANY WARRANTY; without even the implied warranty of 32 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 33 | Lesser General Public License for more details. 34 | 35 | You should have received a copy of the GNU Lesser General 36 | Public License along with this library; if not, write to the 37 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 38 | Boston, MA 02111-1307 USA 39 | */ 40 | -------------------------------------------------------------------------------- /firmware/lib/DueTimer/examples/AvaliableTimer/AvaliableTimer.pde: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void playVideogame(){ 4 | Serial.println("[- ] I'm playing Videogame!"); 5 | } 6 | 7 | void drinkWater(){ 8 | Serial.println("[ - ] I'm driking water!"); 9 | } 10 | 11 | void makeSushi(){ 12 | Serial.println("[ - ] Slicing Salmon..."); 13 | } 14 | 15 | void singOnShower(){ 16 | Serial.println("[ - ] Hello World! Hello world!"); 17 | } 18 | 19 | void studyMath(){ 20 | int x = random(1, 40), y = random(1,40); 21 | Serial.print("[ - ] "); 22 | Serial.print(x); Serial.print(" x "); Serial.print(y); Serial.print(" = "); 23 | Serial.println(x*y); 24 | } 25 | 26 | void watchStarTrek(){ 27 | Serial.println("[ - ] Long live and prosper \\\\//_"); 28 | } 29 | 30 | void eatSushi(){ 31 | Serial.println("[ - ] ..."); 32 | } 33 | 34 | void readTextMessage(){ 35 | Serial.println("[ - ] [Unlock ---->>]"); 36 | } 37 | 38 | void goToSleep(){ 39 | Serial.println("[ -] zzzzzz"); 40 | } 41 | 42 | void setup(){ 43 | Serial.begin(9600); 44 | 45 | Timer.getAvailable().attachInterrupt(playVideogame).start(); delay(50); 46 | Timer.getAvailable().attachInterrupt(drinkWater).start(); delay(50); 47 | Timer.getAvailable().attachInterrupt(makeSushi).start(); delay(50); 48 | Timer.getAvailable().attachInterrupt(singOnShower).start(); delay(50); 49 | Timer.getAvailable().attachInterrupt(studyMath).start(); delay(50); 50 | Timer.getAvailable().attachInterrupt(watchStarTrek).start(); delay(50); 51 | Timer.getAvailable().attachInterrupt(eatSushi).start(); delay(50); 52 | Timer.getAvailable().attachInterrupt(readTextMessage).start(); delay(50); 53 | Timer.getAvailable().attachInterrupt(goToSleep).start(); delay(50); 54 | } 55 | 56 | void loop(){ 57 | while(1){ 58 | // ... 59 | } 60 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | # OS generated files # 107 | ###################### 108 | .DS_Store 109 | .DS_Store? 110 | -------------------------------------------------------------------------------- /firmware/driver_send/driver_send.ino: -------------------------------------------------------------------------------- 1 | #include "DueTimer.h" 2 | #include "GPIO.h" 3 | 4 | #define LENGTH 64 // we can change arduino hardware limit 5 | 6 | GPIO pin4out; 7 | enum sender_state {INIT, SENDING} state = INIT; 8 | volatile int handler_running = 0; 9 | volatile char binaryNum[LENGTH][8]; 10 | DueTimer myTimer = DueTimer(0); 11 | 12 | void setup() { 13 | // put your setup code here, to run once: 14 | myTimer.attachInterrupt(handler).setPeriod(10); 15 | pin4out.output(); 16 | 17 | Serial.begin(115200); 18 | while (!Serial); 19 | 20 | pin4out = 1; 21 | } 22 | 23 | void loop() { 24 | // put your main code here, to run repeatedly: 25 | // digitalWrite(4,state); 26 | //pin4out = state; 27 | char strArray[64]; 28 | 29 | while(!Serial.available()); 30 | 31 | while(Serial.available()){ 32 | delay(50); 33 | 34 | for(int i = 0; i<64; i++){ 35 | strArray[i] = Serial.read(); 36 | } 37 | } 38 | 39 | printbincharpad(strArray); 40 | myTimer.start(); 41 | handler_running = 1; 42 | 43 | while(handler_running) delay(1); 44 | } 45 | 46 | void handler() { 47 | static int i; 48 | static int j; 49 | switch (state) { 50 | case INIT: 51 | pin4out = 0; 52 | i = 0; 53 | j = 0; 54 | state = SENDING; 55 | break; 56 | case SENDING: 57 | pin4out = binaryNum[i][j]; 58 | if(j<7) { 59 | j++; 60 | } else if (i<63){ 61 | j=0; 62 | i++; 63 | } else { 64 | pin4out = 1; 65 | myTimer.stop(); 66 | state = INIT; 67 | handler_running = 0; 68 | } 69 | break; 70 | } 71 | } 72 | 73 | void printbincharpad(char * c) 74 | { 75 | for(int i = 0; i <= LENGTH; i++){ 76 | for (int j = 7; j >= 0; --j) 77 | { 78 | binaryNum[i][7-j] = (c[i] & (1 << j)) ? 1 : 0; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/src/assert.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file assert.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2017, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef ASSERT_H 20 | #define ASSERT_H 21 | 22 | /** 23 | * Trace support macro. Used in the form: 24 | * @code 25 | * TRACE(expr) 26 | * @endcode 27 | * Prints message with expression, executes and prints value. 28 | * @param[in] expr expression to execute and print. 29 | */ 30 | #if defined(NDEBUG) 31 | #define TRACE(expr) expr 32 | #else 33 | #define TRACE(expr) \ 34 | do { \ 35 | Serial.print(F(#expr "=")); \ 36 | Serial.println(expr); \ 37 | Serial.flush(); \ 38 | } while (0) 39 | #endif 40 | 41 | /** 42 | * Assert support macro. Used in the form: 43 | * @code 44 | * ASSERT(expr) 45 | * @endcode 46 | * Checks that the expression is true, otherwise prints line number, 47 | * and assert message with expression, and stops execution. 48 | * @param[in] expr expression to execute and check. 49 | */ 50 | #if defined(NDEBUG) 51 | #define ASSERT(expr) expr 52 | #else 53 | #define ASSERT(expr) \ 54 | do { \ 55 | if (!(expr)) { \ 56 | Serial.print(__LINE__); \ 57 | Serial.println(F(":assert:" #expr)); \ 58 | Serial.flush(); \ 59 | exit(0); \ 60 | } \ 61 | } while (0) 62 | #endif 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/examples/ATtiny/Benchmark/Benchmark.ino: -------------------------------------------------------------------------------- 1 | #include "GPIO.h" 2 | #include "benchmark.h" 3 | 4 | #include "Software/Serial.h" 5 | Software::Serial Serial; 6 | GPIO led; 7 | GPIO button; 8 | #define LED_PIN 1 9 | #define BUTTON_PIN 2 10 | 11 | void setup() 12 | { 13 | Serial.begin(57600); 14 | while (!Serial); 15 | 16 | // Set pin mode; Arduino style 17 | pinMode(LED_PIN, OUTPUT); 18 | pinMode(BUTTON_PIN, INPUT_PULLUP); 19 | 20 | // Set pin mode; GPIO style 21 | led.output(); 22 | button.input().pullup(); 23 | 24 | // Calculate baseline 25 | BENCHMARK_BASELINE(1000); 26 | } 27 | 28 | void loop() 29 | { 30 | BENCHMARK("1.1 Arduino core digitalRead", 1000) { 31 | bool state = digitalRead(BUTTON_PIN); 32 | (void) state; 33 | } 34 | 35 | BENCHMARK("1.2 Arduino core digitalWrite(HIGH)", 1000) { 36 | digitalWrite(LED_PIN, HIGH); 37 | } 38 | 39 | BENCHMARK("1.3 Arduino core digitalWrite(LOW)", 1000) { 40 | digitalWrite(LED_PIN, LOW); 41 | } 42 | 43 | BENCHMARK("1.4 Arduino core toggle; digitalRead-digitalWrite", 1000) { 44 | digitalWrite(LED_PIN, !digitalRead(LED_PIN)); 45 | } 46 | 47 | BENCHMARK("1.5 Arduino core toggle; digitalWrite", 1000) { 48 | digitalWrite(LED_PIN, HIGH); 49 | digitalWrite(LED_PIN, LOW); 50 | } 51 | 52 | BENCHMARK("2.1 GPIO pin value operator", 1000) { 53 | bool state = button; 54 | (void) state; 55 | } 56 | 57 | BENCHMARK("2.2 GPIO high member function", 1000) { 58 | led.high(); 59 | } 60 | 61 | BENCHMARK("2.3 GPIO low member function", 1000) { 62 | led.low(); 63 | } 64 | 65 | BENCHMARK("2.4 GPIO assignment HIGH", 1000) { 66 | led = HIGH; 67 | } 68 | 69 | BENCHMARK("2.5 GPIO assignment LOW", 1000) { 70 | led = LOW; 71 | } 72 | 73 | BENCHMARK("2.6 GPIO toggle; value and assignment operator", 1000) { 74 | led = !led; 75 | } 76 | 77 | BENCHMARK("2.7 GPIO toggle; high and low member functions", 1000) { 78 | led.high(); 79 | led.low(); 80 | } 81 | 82 | BENCHMARK("2.8 GPIO toggle; assignment operator, HIGH/LOW", 1000) { 83 | led = HIGH; 84 | led = LOW; 85 | } 86 | 87 | BENCHMARK("2.9 GPIO toggle member function", 1000) { 88 | led.toggle(); 89 | } 90 | 91 | Serial.println(); 92 | delay(2000); 93 | } 94 | -------------------------------------------------------------------------------- /lib/serial_connect.py: -------------------------------------------------------------------------------- 1 | """ 2 | serial_connect.py 3 | 4 | This file contains the functions for connecting to a serial device. It also has a function for 5 | finding and automatically connecting to Arduino devices. 6 | """ 7 | 8 | import time 9 | import warnings 10 | import platform 11 | from serial.tools import list_ports 12 | 13 | 14 | # Get Serial Port Associated With Arduino and connects to it 15 | def getArduinoPort(): 16 | 17 | arduino_ports = [ 18 | p.device 19 | for p in list_ports.comports() 20 | if 'Arduino' in p.description 21 | ] 22 | 23 | if not arduino_ports: 24 | raise IOError("No Arduino Found") 25 | if len(arduino_ports) > 1: 26 | warnings.warn('Multiple Arduinos Found - Using First One') 27 | 28 | return arduino_ports[0] 29 | 30 | 31 | # Setup Serial Port To Connect To Specified COM Port At Specified Baud Rate 32 | def connectToSerial(self): 33 | sys_name = platform.system() 34 | if self.inComPort.get() == "": 35 | self.comPort = getArduinoPort() 36 | self.baudRate = 14400 37 | else: 38 | if sys_name == "Windows": 39 | self.comPort = "COM" + self.inComPort.get() 40 | self.baudRate = self.inBaudRate.get() 41 | else: 42 | self.comPort = "/dev/" + self.inComPort.get() 43 | self.baudRate = self.inBaudRate.get() 44 | 45 | self.serialPort.port = self.comPort 46 | self.serialPort.baudrate = self.baudRate 47 | self.serialPort.setRTS(False) 48 | self.serialPort.setDTR(False) 49 | self.serialPort.open() 50 | if self.serialPort.is_open: 51 | self.serialPort.reset_output_buffer() 52 | self.serialPort.flush() 53 | self.serialPort.reset_input_buffer() 54 | self.connectButton["text"] = "Connected: Port " + str(self.comPort) + " at " + str(self.baudRate) 55 | self.connectButton.config(state="disabled") 56 | self.disconnectButton["text"] = "Disconnect" 57 | self.disconnectButton.config(state="normal") 58 | self.sd.serialPort = self.serialPort 59 | self.rd.serialPort = self.serialPort 60 | 61 | return self.serialPort 62 | 63 | 64 | # Disconnect Serial Port If One Is Open 65 | def disconnectFromSerial(self): 66 | self.serialPort.close() 67 | if not self.serialPort.is_open: 68 | self.disconnectButton["text"] = "Disconnected" 69 | self.disconnectButton.config(state="disabled") 70 | self.connectButton["text"] = "Connect" 71 | self.connectButton.config(state="normal") 72 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/src/iovec.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file iovec.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2017, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef IOVEC_H 20 | #define IOVEC_H 21 | 22 | /** 23 | * Buffer structure for scatter/gather. 24 | */ 25 | struct iovec_t { 26 | void* buf; //!< Buffer pointer. 27 | size_t size; //!< Size of buffer in bytes. 28 | }; 29 | 30 | /** 31 | * Return total size of null terminated io buffer vector. 32 | * @param[in] vec io vector pointer 33 | * @return size. 34 | */ 35 | inline size_t iovec_size(const iovec_t* vec) __attribute__((always_inline)); 36 | inline size_t iovec_size(const iovec_t* vec) 37 | { 38 | size_t len = 0; 39 | for (const iovec_t* vp = vec; vp->buf != NULL; vp++) 40 | len += vp->size; 41 | return (len); 42 | } 43 | 44 | /** 45 | * Set next io-vector buffer. Used in to form: 46 | * @code 47 | * iovec_t vec[N]; 48 | * iovec_t* vp = vec; 49 | * iovec_arg(vp, buf, size); 50 | * .. 51 | * iovec_end(vp); 52 | * @endcode 53 | * @param[in,out] vp io vector pointer 54 | * @param[in] buf buffer. 55 | * @param[in] size number of bytes. 56 | */ 57 | inline void iovec_arg(iovec_t* &vp, const void* buf, size_t size) 58 | __attribute__((always_inline)); 59 | inline void iovec_arg(iovec_t* &vp, const void* buf, size_t size) 60 | { 61 | vp->buf = (void*) buf; 62 | vp->size = size; 63 | vp++; 64 | } 65 | 66 | /** 67 | * Mark end of io-vector buffer at given index. Used in the form: 68 | * @code 69 | * iovec_t vec[N]; 70 | * iovec_t* vp = vec; 71 | * iovec_arg(vp, buf, size); 72 | * .. 73 | * iovec_end(vp); 74 | * @endcode 75 | * @param[in,out] vp io vector. 76 | */ 77 | inline void iovec_end(iovec_t* &vp) __attribute__((always_inline)); 78 | inline void iovec_end(iovec_t* &vp) 79 | { 80 | vp->buf = 0; 81 | vp->size = 0; 82 | } 83 | #endif 84 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/src/SRPO.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SRPO.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2017, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef SRPO_H 20 | #define SRPO_H 21 | 22 | #include "GPIO.h" 23 | 24 | /** 25 | * Shift Register Parallel Output (SRPO) template class using GPIO. 26 | * @param[in] BITORDER LSBFIRST or MSBFIRST. 27 | * @param[in] DATA_PIN board pin for data output signal. 28 | * @param[in] CLOCK_PIN board pin for clock output signal. 29 | */ 30 | template 31 | class SRPO { 32 | public: 33 | /** 34 | * Construct Shift Register Parallel Output (SRPO) instance with 35 | * given template parameters. Initiate GPIO pins for data and clock 36 | * to output mode. 37 | */ 38 | SRPO() 39 | { 40 | m_data.output(); 41 | m_clock.output(); 42 | } 43 | 44 | /** 45 | * Serialize given value according to the template bit order 46 | * parameter. Generate a positive clock pulse for each bit transfer. 47 | * @param[in] value to data output signal. 48 | */ 49 | void write(uint8_t value) 50 | { 51 | if (BITORDER == LSBFIRST) { 52 | uint8_t mask = 1; 53 | do { 54 | m_data = value & mask; 55 | m_clock.toggle(); 56 | mask <<= 1; 57 | m_clock.toggle(); 58 | } while (mask); 59 | } 60 | else { 61 | uint8_t mask = 0x80; 62 | do { 63 | m_data = value & mask; 64 | m_clock.toggle(); 65 | mask >>= 1; 66 | m_clock.toggle(); 67 | } while (mask); 68 | } 69 | } 70 | 71 | /** 72 | * Serial output operator. Shorthand for write(). 73 | * @param[in] value to data output signal. 74 | */ 75 | void operator<<(uint8_t value) 76 | { 77 | write(value); 78 | } 79 | 80 | protected: 81 | GPIO m_data; 82 | GPIO m_clock; 83 | }; 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/src/SRPI.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SRPI.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2017, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef SRPI_H 20 | #define SRPI_H 21 | 22 | #include "GPIO.h" 23 | 24 | /** 25 | * Shift Register Parallel Input (SRPI) template class using GPIO. 26 | * @param[in] BITORDER LSBFIRST or MSBFIRST. 27 | * @param[in] DATA_PIN board pin for data input signal. 28 | * @param[in] CLOCK_PIN board pin for clock output signal. 29 | */ 30 | template 31 | class SRPI { 32 | public: 33 | /** 34 | * Construct Shift Register Parallel Input (SRPI) instance with given 35 | * template parameters. Initiate GPIO pins for data to input mode 36 | * and clock to output mode. 37 | */ 38 | SRPI() 39 | { 40 | m_data.input(); 41 | m_clock.output(); 42 | } 43 | 44 | /** 45 | * Return deserialized value according to the template bit order 46 | * parameter. Generates a positive clock pulse for each bit 47 | * transfer. 48 | * @return read byte. 49 | */ 50 | uint8_t read() 51 | { 52 | uint8_t res = 0; 53 | if (BITORDER == LSBFIRST) { 54 | uint8_t mask = 1; 55 | do { 56 | m_clock.toggle(); 57 | res |= (m_data ? mask : 0); 58 | m_clock.toggle(); 59 | mask <<= 1; 60 | } while (mask); 61 | } 62 | else { 63 | uint8_t mask = 0x80; 64 | do { 65 | m_clock.toggle(); 66 | res |= (m_data ? mask : 0); 67 | m_clock.toggle(); 68 | mask >>= 1; 69 | } while (mask); 70 | } 71 | return (res); 72 | } 73 | 74 | /** 75 | * Serial input operator. Shorthand for read(). 76 | * @param[out] value from data input signal. 77 | */ 78 | void operator>>(uint8_t& value) 79 | { 80 | value = read(); 81 | } 82 | 83 | protected: 84 | GPIO m_data; 85 | GPIO m_clock; 86 | }; 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/src/Keypad.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Keypad.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2017, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef KEYPAD_H 20 | #define KEYPAD_H 21 | 22 | /** 23 | * Resistor ladder keypad read and debounce template class. 24 | * @param[in] PIN analog pin. 25 | * @param[in] DEBOUNCE time limit (default 50 ms). 26 | */ 27 | template 28 | class Keypad { 29 | public: 30 | /** 31 | * Construct keypad with given template parameters. 32 | */ 33 | Keypad(const uint16_t* map = NULL) : 34 | m_timestamp(0), 35 | m_key(0), 36 | m_map(map) 37 | { 38 | } 39 | 40 | /** 41 | * Check if it is time to sample the keypad and check for 42 | * key pressed/release. 43 | * @return true(1) if a change was detected, otherwise false(0). 44 | */ 45 | bool ischanged() 46 | { 47 | // Check if debounce time limit has elapsed 48 | if (millis() - m_timestamp < DEBOUNCE) return (false); 49 | m_timestamp = millis(); 50 | 51 | // Read the analog pin and map 52 | uint16_t value = analogRead(PIN); 53 | uint8_t key = 0; 54 | if (m_map == NULL) return (false); 55 | while (value < (uint16_t) pgm_read_word(&m_map[key])) key++; 56 | if (key == m_key) return (false); 57 | m_key = key; 58 | return (true); 59 | } 60 | 61 | /** 62 | * Return latest key. 63 | * @return key number. 64 | */ 65 | uint8_t key() 66 | __attribute__((always_inline)) 67 | { 68 | return (m_key); 69 | } 70 | 71 | /** 72 | * Return debounce timestamp. 73 | * @return timestamp. 74 | */ 75 | uint16_t timestamp() 76 | __attribute__((always_inline)) 77 | { 78 | return (m_timestamp); 79 | } 80 | 81 | protected: 82 | /** Timestamp for latest pin read. */ 83 | uint16_t m_timestamp; 84 | 85 | /** Latest debounced key. */ 86 | uint8_t m_key; 87 | 88 | /** Key map; program memory with values in descent order. */ 89 | const uint16_t* m_map; 90 | }; 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /lib/my_states.py: -------------------------------------------------------------------------------- 1 | """ 2 | my_states.py 3 | 4 | This file contains the definitions and transitions for ever state in our state machine. 5 | """ 6 | 7 | import serial 8 | from state import State 9 | from Sender import Sender_Driver 10 | 11 | 12 | # Start Of Our States 13 | class Receiver(State): 14 | """ 15 | The state indicating that the driver/arduino is 16 | going to receive data. 17 | """ 18 | def on_event(self, event): 19 | if event == 'send': 20 | return Sender() 21 | elif event == '': 22 | return Meta_Parser() 23 | 24 | return self 25 | 26 | 27 | class Meta_Parser(State): 28 | """ 29 | The state indicating that we are parsing the 30 | meta packet. 31 | """ 32 | def on_event(self, event): 33 | if event == '': 34 | return Receive_Data() 35 | 36 | return self 37 | 38 | 39 | class Receive_Data(State): 40 | """ 41 | The state indicating that we are currently 42 | receiving data. 43 | """ 44 | def on_event(self, event): 45 | if event == 'timeout': 46 | return Receiver() 47 | elif event == 'finish': 48 | return Receiver() 49 | elif event == 'resend': 50 | return Receive_Data() 51 | elif event == '': 52 | return Receive_Data() 53 | 54 | return self 55 | 56 | 57 | class Sender(State): 58 | """ 59 | The state indicating that the driver/arduino is 60 | going to send data. 61 | """ 62 | def on_event(self, event): 63 | if event == '': 64 | return Create_Meta() 65 | 66 | return self 67 | 68 | 69 | class Create_Meta(State): 70 | """ 71 | The state indicating that we are creating the 72 | meta data packet. 73 | """ 74 | 75 | def on_event(self, event): 76 | if event == '': 77 | return Send_Data() 78 | 79 | return self 80 | 81 | 82 | class Send_Data(State): 83 | """ 84 | The state indicating that we are currently 85 | receiving data. 86 | """ 87 | def on_event(self, event): 88 | if event == '': 89 | return Wait() 90 | 91 | return self 92 | 93 | 94 | class Wait(State): 95 | """ 96 | The state indicating that we are currently 97 | waiting on a command. 98 | """ 99 | def on_event(self, event): 100 | if event == 'timeout': 101 | return Receiver() 102 | elif event == 'finish': 103 | return Receiver() 104 | elif event == 'resend': 105 | return Send_Data() 106 | elif event == '': 107 | return Wait() 108 | 109 | return self 110 | 111 | # End Of Our States 112 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/src/benchmark.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file benchmark.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2017, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef BENCHMARK_H 20 | #define BENCHMARK_H 21 | 22 | /** Benchmark timestamp variables. */ 23 | static uint32_t _start, _baseline = 0; 24 | static uint32_t _benchmark; 25 | 26 | /** Benchmark support function. */ 27 | inline void noop() __attribute__((always_inline)); 28 | inline void noop() { __asm__ __volatile__("nop"); } 29 | 30 | /** 31 | * Calculate and set benchmark baseline. Should be called in setup(). 32 | * @param[in] scale number of block executions. 33 | */ 34 | #define BENCHMARK_BASELINE(scale) \ 35 | Serial.flush(); \ 36 | _start = micros(); \ 37 | for (int _i = 1; _i; _i--, _baseline = micros() - _start - _baseline) \ 38 | for (int _j = scale; _j; _j--, noop()) 39 | 40 | /** 41 | * Benchmark support macro. Use in the form: 42 | * @code 43 | * BENCHMARK("description") statement 44 | * @endcode 45 | * Prints description message and time to execute the statement in 46 | * micro-seconds. The maximum resolution depends on micros() and is 47 | * typically 4 us (F_CPU is 16 MHz). Message strings are stored in 48 | * program memory. 49 | * @param[in] msg description of the benchmark. 50 | * @param[in] scale number of block executions. 51 | */ 52 | #define BENCHMARK(msg,scale) \ 53 | Serial.print(F(msg ": ")); \ 54 | Serial.flush(); \ 55 | _start = micros(); \ 56 | for (int _i = 1; _i; _i--, _benchmark = micros() - _start - _baseline,\ 57 | Serial.println(_benchmark / (float) scale, 3)) \ 58 | for (int _j = scale; _j; _j--, noop()) 59 | 60 | /** 61 | * Execution time measurement support macro. Use in the form: 62 | * @code 63 | * MEASURE(expr) 64 | * @endcode 65 | * Executes given expression and prints time to execute micro- 66 | * seconds. The maximum resolution depends on micros() and is 67 | * typically 4 us (F_CPU is 16 MHz). 68 | * @param[in] expr expression to execute and measure. 69 | */ 70 | #define MEASURE(expr) BENCHMARK(#expr,1) expr 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/README.md: -------------------------------------------------------------------------------- 1 | # Arduino-GPIO 2 | The Arduino GPIO library has been developed to allow high performance 3 | digital pin access. Most access functions are compiled to a single 4 | instruction and execute in 1-2 clock cycles. The library functions are 5 | more than 10 times faster than the Arduino digital pin functions. In 6 | some cases as much as 100 times faster. 7 | 8 | Additional support classes are available for Debounced Digital and 9 | Analog Pin, Shift Register Input/Output, and Software Serial. These 10 | also demonstrate how the GPIO template class may be used to construct 11 | additional libraries. 12 | 13 | This library supports boards based on ATtinyX4, ATtinyX5, ATmega168, 14 | ATmega328P, ATmega32U4, ATmega1280, ATmega2560 and SAM3X8E. 15 | 16 | Version: 1.11 17 | 18 | ## Classes 19 | 20 | * [AVR Board Configuration, BOARD](./src/Hardware/AVR/Board.h) 21 | * [AVR General Purpose Input/Output, GPIO](./src/Hardware/AVR/GPIO.h) 22 | * [SAM Board Configuration, BOARD](./src/Hardware/SAM/Board.h) 23 | * [SAM General Purpose Input/Output, GPIO](./src/Hardware/SAM/GPIO.h) 24 | * [Debounced Digital Pin, Button](./src/Button.h) 25 | * [Debounced Analog Pin, Keypad](./src/Keypad.h) 26 | * [Shift Register Parallel Input, SRPI](./src/SRPI.h) 27 | * [Shift Register Parallel Input/Output, SRPIO](./src/SRPIO.h) 28 | * [Shift Register Parallel Output, SRPO](./src/SRPO.h) 29 | * [Software Serial, Software::Serial](./src/Software/Serial.h) 30 | 31 | ## Example Sketches 32 | 33 | * [Benchmark](./examples/Benchmark) 34 | * [Blink](./examples/Blink) 35 | * [Button](./examples/Button) 36 | * [Pulse](./examples/Pulse) 37 | * [ShiftIn](./examples/ShiftIn) 38 | * [ShiftInOut](./examples/ShiftInOut) 39 | * [ShiftOut](./examples/ShiftOut) 40 | * [SoftwareSerial](./examples/SoftwareSerial) 41 | 42 | Benchmarks for [ATtiny](./examples/ATtiny). 43 | 44 | ## Benchmarks 45 | 46 | Wiring | us | GPIO | us | Xn (Due/Uno/Mega) 47 | ------ |---------------|------|----|-------------- 48 | digitalRead | 1.23/3.75/6.4 | var = pin | 0.0625/0.071 | 17/60/99 49 | digitalWrite | 2.30/4.25/7.2 | pin = val | 0.125/0.048 | 48/34/56 50 | shiftIn | 46/87/151 | srpi >> var | 4.8/4.6/4.6 | 9.6/19/32 51 | shiftOut | 53/104/161 | srpo << val | 5.7/7.9/7.9 | 9.3/13/20 52 | 53 | ## Usage 54 | 55 | * [Arduino-DHT](https://github.com/mikaelpatel/Arduino-DHT) 56 | * [Arduino-LCD](https://github.com/mikaelpatel/Arduino-LCD) 57 | * [Arduino-OWI](https://github.com/mikaelpatel/Arduino-OWI) 58 | * [Arduino-RTC](https://github.com/mikaelpatel/Arduino-RTC) 59 | * [Arduino-SPI](https://github.com/mikaelpatel/Arduino-SPI) 60 | * [Arduino-TWI](https://github.com/mikaelpatel/Arduino-TWI) 61 | * [Arduino-Storage](https://github.com/mikaelpatel/Arduino-Storage) 62 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/src/Button.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Button.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2017, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef BUTTON_H 20 | #define BUTTON_H 21 | 22 | #include "GPIO.h" 23 | 24 | /** 25 | * Debounced Input Pin template class using GPIO. The internal pullup 26 | * resistor is used. The button/switch should be connected to ground. 27 | * @param[in] PIN board pin for input signal. 28 | * @param[in] DEBOUNCE time limit (Default 50 ms). 29 | */ 30 | template 31 | class Button { 32 | public: 33 | /** 34 | * Construct debounced input pin instance with given template 35 | * parameters. Initiate GPIO pins input mode with pullup resistor. 36 | */ 37 | Button() : 38 | m_timestamp(0), 39 | m_state(true) 40 | { 41 | m_pin.input().pullup(); 42 | } 43 | 44 | /** 45 | * Return true(1) if a button state change was detected, otherwise 46 | * false(0). Rising or falling edge is determined by reading the 47 | * debounced pin state. 48 | * @return bool. 49 | */ 50 | bool ischanged() 51 | { 52 | // Check if debounce time limit has elapsed 53 | if (millis() - m_timestamp < DEBOUNCE) return (false); 54 | m_timestamp = millis(); 55 | 56 | // Check for the pin state has changed 57 | bool state = m_pin; 58 | if (state == m_state) return (false); 59 | m_state = state; 60 | return (true); 61 | } 62 | 63 | /** 64 | * Return debounced pin state. 65 | * @return state. 66 | */ 67 | bool read() 68 | { 69 | return (m_state); 70 | } 71 | 72 | /** 73 | * Return debounced pin state. Shorthand for read(). 74 | * @return bool. 75 | */ 76 | operator bool() 77 | __attribute__((always_inline)) 78 | { 79 | return (read()); 80 | } 81 | 82 | /** 83 | * Return debounce timestamp. 84 | * @return timestamp. 85 | */ 86 | uint16_t timestamp() 87 | { 88 | return (m_timestamp); 89 | } 90 | 91 | protected: 92 | /** Button pin. */ 93 | GPIO m_pin; 94 | 95 | /** Timestamp for latest pin read. */ 96 | uint16_t m_timestamp; 97 | 98 | /** Latest pin read; debounced pin state. */ 99 | bool m_state; 100 | }; 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /firmware/lib/DueTimer/DueTimer.h: -------------------------------------------------------------------------------- 1 | /* 2 | DueTimer.h - DueTimer header file, definition of methods and attributes... 3 | For instructions, go to https://github.com/ivanseidel/DueTimer 4 | 5 | Created by Ivan Seidel Gomes, March, 2013. 6 | Modified by Philipp Klaus, June 2013. 7 | Released into the public domain. 8 | */ 9 | 10 | #ifdef __arm__ 11 | 12 | #ifndef DueTimer_h 13 | #define DueTimer_h 14 | 15 | #include "Arduino.h" 16 | 17 | #include 18 | 19 | /* 20 | This fixes compatibility for Arduono Servo Library. 21 | Uncomment to make it compatible. 22 | 23 | Note that: 24 | + Timers: 0,2,3,4,5 WILL NOT WORK, and will 25 | neither be accessible by Timer0,... 26 | */ 27 | // #define USING_SERVO_LIB true 28 | 29 | #ifdef USING_SERVO_LIB 30 | #warning "HEY! You have set flag USING_SERVO_LIB. Timer0, 2,3,4 and 5 are not available" 31 | #endif 32 | 33 | 34 | #define NUM_TIMERS 9 35 | 36 | class DueTimer 37 | { 38 | protected: 39 | 40 | // Represents the timer id (index for the array of Timer structs) 41 | const unsigned short timer; 42 | 43 | // Stores the object timer frequency 44 | // (allows to access current timer period and frequency): 45 | static double _frequency[NUM_TIMERS]; 46 | 47 | // Picks the best clock to lower the error 48 | static uint8_t bestClock(double frequency, uint32_t& retRC); 49 | 50 | // Make Interrupt handlers friends, so they can use callbacks 51 | friend void TC0_Handler(void); 52 | friend void TC1_Handler(void); 53 | friend void TC2_Handler(void); 54 | friend void TC3_Handler(void); 55 | friend void TC4_Handler(void); 56 | friend void TC5_Handler(void); 57 | friend void TC6_Handler(void); 58 | friend void TC7_Handler(void); 59 | friend void TC8_Handler(void); 60 | 61 | static void (*callbacks[NUM_TIMERS])(); 62 | 63 | struct Timer 64 | { 65 | Tc *tc; 66 | uint32_t channel; 67 | IRQn_Type irq; 68 | }; 69 | 70 | // Store timer configuration (static, as it's fixed for every object) 71 | static const Timer Timers[NUM_TIMERS]; 72 | 73 | public: 74 | 75 | static DueTimer getAvailable(void); 76 | 77 | DueTimer(unsigned short _timer); 78 | DueTimer& attachInterrupt(void (*isr)()); 79 | DueTimer& detachInterrupt(void); 80 | DueTimer& start(long microseconds = -1); 81 | DueTimer& stop(void); 82 | DueTimer& setFrequency(double frequency); 83 | DueTimer& setPeriod(unsigned long microseconds); 84 | 85 | double getFrequency(void) const; 86 | long getPeriod(void) const; 87 | }; 88 | 89 | // Just to call Timer.getAvailable instead of Timer::getAvailable() : 90 | extern DueTimer Timer; 91 | 92 | extern DueTimer Timer1; 93 | // Fix for compatibility with Servo library 94 | #ifndef USING_SERVO_LIB 95 | extern DueTimer Timer0; 96 | extern DueTimer Timer2; 97 | extern DueTimer Timer3; 98 | extern DueTimer Timer4; 99 | extern DueTimer Timer5; 100 | #endif 101 | extern DueTimer Timer6; 102 | extern DueTimer Timer7; 103 | extern DueTimer Timer8; 104 | 105 | #endif 106 | 107 | #else 108 | #error Oops! Trying to include DueTimer on another device? 109 | #endif 110 | -------------------------------------------------------------------------------- /firmware/bidirectional/bidirectional.ino: -------------------------------------------------------------------------------- 1 | #include "DueTimer.h" 2 | #include "GPIO.h" 3 | 4 | #define LENGTH 64 // we can change arduino hardware limit 5 | 6 | GPIO pin4out; 7 | GPIO pin7in; 8 | volatile int i; 9 | volatile int j; 10 | enum sender_state {INIT, SENDING, RECEIVING} state; 11 | volatile int handler_running = 0; 12 | volatile char sendBinaryNum[LENGTH][8]; 13 | char receiveBinaryNum[LENGTH][8]; 14 | DueTimer myTimer = DueTimer(0); 15 | 16 | void setup() { 17 | // put your setup code here, to run once: 18 | //myTimer.attachInterrupt(handler).setPeriod(125); 19 | pin7in.input(); 20 | pin4out.output(); 21 | pinMode(DAC0, OUTPUT); 22 | analogWrite(DAC0, 24); 23 | 24 | Serial.begin(14400); 25 | Serial1.begin(14400); 26 | while (!Serial); 27 | 28 | pin4out = 1; 29 | while (!pin7in); 30 | while (Serial.available()) Serial.read(); 31 | //Serial.print("Setup Complete"); 32 | } 33 | 34 | void loop() { 35 | 36 | if(Serial.available()) { 37 | 38 | Serial1.write(Serial.read()); 39 | 40 | } 41 | 42 | else if(Serial1.available()) { 43 | 44 | Serial.write(Serial1.read()); 45 | 46 | } 47 | 48 | } 49 | 50 | /* void loop() { 51 | char strArray[64]; 52 | 53 | while(pin7in){ 54 | if(Serial.available()){ 55 | 56 | delay(10); 57 | 58 | for(int i = 0; i<64; i++){ 59 | strArray[i] = Serial.read(); 60 | } 61 | 62 | printbincharpad(strArray); 63 | myTimer.start(); 64 | handler_running = 1; 65 | state = INIT; 66 | 67 | while(handler_running) delay(1); 68 | 69 | } 70 | } 71 | 72 | i = 0; 73 | j = 0; 74 | //for (int i = 0; i < 4000; i++); 75 | myTimer.start(); 76 | handler_running = 1; 77 | state = RECEIVING; 78 | 79 | 80 | 81 | while(handler_running) delay(1); 82 | 83 | for(int k = 0; k < 64; k++) { 84 | strArray[k] = convertToChar(receiveBinaryNum[k]); 85 | } 86 | 87 | for(int k = 0; k < 64; k++) { 88 | Serial.print(strArray[k]); 89 | } 90 | 91 | } 92 | 93 | void handler() { 94 | switch (state) { 95 | case INIT: 96 | pin4out = 0; 97 | i = 0; 98 | j = 0; 99 | state = SENDING; 100 | break; 101 | case SENDING: 102 | pin4out = sendBinaryNum[i][j]; 103 | if(j<7) { 104 | j++; 105 | } else if (i<63){ 106 | j=0; 107 | i++; 108 | } else { 109 | pin4out = 1; 110 | myTimer.stop(); 111 | state = INIT; 112 | handler_running = 0; 113 | } 114 | break; 115 | case RECEIVING: 116 | receiveBinaryNum[i][j] = pin7in; 117 | if(j<7) { 118 | j++; 119 | } 120 | else if (i<63){ 121 | j=0; 122 | i++; 123 | } 124 | else { 125 | myTimer.stop(); 126 | handler_running = 0; 127 | state = INIT; 128 | } 129 | break; 130 | } 131 | } 132 | 133 | 134 | 135 | char convertToChar(char* binaryChar) { 136 | int multiplier = 0; 137 | int temp; 138 | int sum = 0; 139 | for(temp = 7; temp>=0; temp--) 140 | sum += (binaryChar[temp]*(1 << multiplier++)); 141 | return sum; 142 | } 143 | 144 | void printbincharpad(char * c) { 145 | for(int i = 0; i <= LENGTH; i++){ 146 | for (int j = 7; j >= 0; --j) 147 | { 148 | sendBinaryNum[i][7-j] = (c[i] & (1 << j)) ? '1' : '0'; 149 | } 150 | } 151 | }*/ 152 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/src/SRPIO.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SRPIO.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2017, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef SRPIO_H 20 | #define SRPIO_H 21 | 22 | #include "GPIO.h" 23 | 24 | /** 25 | * Shift Register Parallel Input Output (SRPIO) template class using GPIO. 26 | * @param[in] BITORDER LSBFIRST or MSBFIRST. 27 | * @param[in] DATA_PIN board pin for data input/output signal. 28 | * @param[in] CLOCK_PIN board pin for clock output signal. 29 | */ 30 | template 31 | class SRPIO { 32 | public: 33 | /** 34 | * Construct Shift Register Parallel Input Output (SRPIO) instance 35 | * with given template parameters. Initiate GPIO pins for data to 36 | * open drain mode (external pullup resistor) and clock to output 37 | * mode. 38 | */ 39 | SRPIO() 40 | { 41 | m_data.open_drain(); 42 | m_clock.output(); 43 | } 44 | 45 | /** 46 | * Serialize given value according to the template bit order 47 | * parameter. Generate a positive clock pulse for each bit transfer. 48 | * @param[in] value to data output signal. 49 | */ 50 | void write(uint8_t value) 51 | { 52 | if (BITORDER == LSBFIRST) { 53 | uint8_t mask = 1; 54 | do { 55 | if (value & mask) m_data.input(); else m_data.output(); 56 | m_clock.toggle(); 57 | mask <<= 1; 58 | m_clock.toggle(); 59 | } while (mask); 60 | } 61 | else { 62 | uint8_t mask = 0x80; 63 | do { 64 | if (value & mask) m_data.input(); else m_data.output(); 65 | m_clock.toggle(); 66 | mask >>= 1; 67 | m_clock.toggle(); 68 | } while (mask); 69 | } 70 | m_data.input(); 71 | } 72 | 73 | /** 74 | * Serial output operator. Shorthand for write(). 75 | * @param[in] value to data output signal. 76 | */ 77 | void operator<<(uint8_t value) 78 | { 79 | write(value); 80 | } 81 | 82 | /** 83 | * Return deserialized value according to the template bit order 84 | * parameter. Generates a positive clock pulse for each bit 85 | * transfer. 86 | * @return byte read from data input signal. 87 | */ 88 | uint8_t read() 89 | { 90 | uint8_t res = 0; 91 | if (BITORDER == LSBFIRST) { 92 | uint8_t mask = 1; 93 | do { 94 | m_clock.toggle(); 95 | res |= (m_data ? mask : 0); 96 | m_clock.toggle(); 97 | mask <<= 1; 98 | } while (mask); 99 | } 100 | else { 101 | uint8_t mask = 0x80; 102 | do { 103 | m_clock.toggle(); 104 | res |= (m_data ? mask : 0); 105 | m_clock.toggle(); 106 | mask >>= 1; 107 | } while (mask); 108 | } 109 | return (res); 110 | } 111 | 112 | /** 113 | * Serial input operator. Shorthand for read(). 114 | * @param[out] value from data input signal. 115 | */ 116 | void operator>>(uint8_t& value) 117 | { 118 | value = read(); 119 | } 120 | 121 | protected: 122 | GPIO m_data; 123 | GPIO m_clock; 124 | }; 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/src/Software/Serial.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Software/Serial.h 3 | * @version 1.0 4 | * 5 | * @section License 6 | * Copyright (C) 2017, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef SOFTWARE_SERIAL_H 20 | #define SOFTWARE_SERIAL_H 21 | 22 | #include "GPIO.h" 23 | 24 | /** 25 | * Output only Software Serial template class using GPIO. 26 | * May be used with baudrates up to 250.000 bps. 27 | * @param[in] TX_PIN board pin for transmit signal. 28 | */ 29 | namespace Software { 30 | template 31 | class Serial : public ::Stream { 32 | public: 33 | /** 34 | * Construct Output only Software Serial instance with 35 | * given template parameters. Initiate GPIO transmit pin 36 | * to output mode and set default baudrate (57600 bps). 37 | */ 38 | Serial() : 39 | m_count(((F_CPU / 57600) / 4) - 4) 40 | { 41 | m_tx.output(); 42 | m_tx.high(); 43 | } 44 | 45 | /** 46 | * Start the Output only Software Serial with the given 47 | * baudrate. 48 | * @param[in] baudrate in bits per second. 49 | */ 50 | void begin(uint32_t baudrate) 51 | { 52 | #if defined(AVR) 53 | m_count = ((F_CPU / baudrate) / 4) - 4; 54 | #elif defined(SAM) 55 | m_count = 1000000 / baudrate; 56 | #endif 57 | } 58 | 59 | /** 60 | * Check if Serial is ready (see Arduino/HardwareSerial). 61 | * @return true(1); 62 | */ 63 | operator bool() 64 | { 65 | return (true); 66 | } 67 | 68 | /** 69 | * @override{Stream} 70 | * Write given byte to serial output with one start and stop 71 | * bit. Interrupts are disabled during the transmission. Returns 72 | * number of bytes transmitted(1). 73 | * @param[in] byte to transmit. 74 | * @return number of bytes transmitted(1). 75 | */ 76 | virtual size_t write(uint8_t byte) 77 | { 78 | uint16_t data = ((0xff00 | byte) << 1); 79 | uint8_t bits = 10; 80 | noInterrupts(); 81 | do { 82 | m_tx = data & 0x01; 83 | #if defined(AVR) 84 | _delay_loop_2(m_count); 85 | #elif defined(SAM) 86 | delayMicroseconds(m_count); 87 | #endif 88 | data >>= 1; 89 | } while (--bits); 90 | interrupts(); 91 | return (1); 92 | } 93 | 94 | /** 95 | * @override{Stream} 96 | * Returns always zero(0) as this stream is output only. 97 | * @return zero(0). 98 | */ 99 | virtual int available() 100 | { 101 | return (0); 102 | } 103 | 104 | /** 105 | * @override{Stream} 106 | * Returns always error code(-1) as this stream is output only. 107 | * @return error code(-1); 108 | */ 109 | virtual int peek() 110 | { 111 | return (-1); 112 | } 113 | 114 | /** 115 | * @override{Stream} 116 | * Returns always error code(-1) as this stream is output only. 117 | * @return error code(-1); 118 | */ 119 | virtual int read() 120 | { 121 | return (-1); 122 | } 123 | 124 | /** 125 | * @override{Stream} 126 | * Output only stream. 127 | */ 128 | virtual void flush() 129 | { 130 | } 131 | 132 | protected: 133 | /** Asynchronous Serial Output pin. */ 134 | GPIO m_tx; 135 | 136 | /** Bit delay counter for given baudrate. */ 137 | uint16_t m_count; 138 | }; 139 | }; 140 | #endif 141 | -------------------------------------------------------------------------------- /firmware/lib/DueTimer/README.md: -------------------------------------------------------------------------------- 1 | # DueTimer 2 | 3 | Timer Library to work with Arduino DUE 4 | 5 | ## Installation 6 | 7 | 1. [Download](https://github.com/ivanseidel/DueTimer/releases) the Latest release from GitHub. 8 | 2. Unzip and modify the Folder name to "DueTimer" (Remove the '-version') 9 | 3. Paste the modified folder on your Library folder (On your `Libraries` folder inside Sketchbooks or Arduino software). 10 | 4. Re-open Arduino Software 11 | 12 | ## Getting Started 13 | 14 | To call a function `handler` every `1000` microseconds: 15 | 16 | ```c++ 17 | Timer3.attachInterrupt(handler).start(1000); 18 | // or: 19 | Timer3.attachInterrupt(handler).setPeriod(1000).start(); 20 | // or, to select whichever available timer: 21 | Timer.getAvailable().attachInterrupt(handler).start(1000); 22 | ``` 23 | 24 | To call a function `handler` `10` times a second: 25 | 26 | ```c++ 27 | Timer3.attachInterrupt(handler).setFrequency(10).start(); 28 | ``` 29 | 30 | In case you need to stop a timer, just do like this: 31 | 32 | ```c++ 33 | Timer3.stop(); 34 | ``` 35 | 36 | And to continue running: 37 | 38 | ```c++ 39 | Timer3.start(); 40 | ``` 41 | 42 | There are `9` Timer objects already instantiated for you: 43 | `Timer0`, `Timer1`, `Timer2`, `Timer3`, `Timer4`, `Timer5`, `Timer6`, `Timer7` and `Timer8`. 44 | 45 | ### TIPs and Warnings 46 | 47 | ```c++ 48 | Timer4.attachInterrupt(handler).setFrequency(10).start(); 49 | // Is the same as: 50 | Timer4.attachInterrupt(handler); 51 | Timer4.setFrequency(10); 52 | Timer4.start(); 53 | 54 | // To create a custom timer, refer to: 55 | DueTimer myTimer = DueTimer(0); // Creates a Timer 0 object. 56 | DueTimer myTimer = DueTimer(3); // Creates a Timer 3 object. 57 | DueTimer myTimer = DueTimer(t); // Creates a Timer t object. 58 | // Note: Maximum t allowed is 8, as there is only 9 timers [0..8]; 59 | 60 | Timer1.attachInterrupt(handler1).start(10); 61 | Timer1.attachInterrupt(handler2).start(10); 62 | DueTimer myTimer = DueTimer(1); 63 | myTimer.attachInterrupt(handler3).start(20); 64 | // Will run only handle3, on Timer 1 (You are just overriding the callback) 65 | 66 | Timer.getAvailable().attachInterrupt(callback1).start(10); 67 | // Start timer on first available timer 68 | DueTimer::getAvailable().attachInterrupt(callback2).start(10); 69 | // Start timer on second available timer 70 | // And so on... 71 | ``` 72 | 73 | ### Compatibility with Servo.h 74 | 75 | Because Servo Library uses the same callbacks of DueTimer, we provides a custom solution for working with both of them. However, Timers 0,2,3,4 and 5 will not Work anymore. 76 | 77 | You will need uncommend the line in `DueTimer.h` in `DueTimer` folder inside the `Libraries` folder. Uncomment the following line in `DueTimer.h`: 78 | 79 | ``` 80 | #define USING_SERVO_LIB true 81 | ``` 82 | 83 | ## Library Reference 84 | 85 | ### You should know: 86 | 87 | - `getAvailable()` - Get the first available Timer. 88 | 89 | - `attachInterrupt(void (*isr)())` - Attach a interrupt (callback function) for the timer of the object. 90 | 91 | - `detachInterrupt()` - Detach current callback of timer. 92 | 93 | - `start(long microseconds = -1)` - Start the timer with an optional period parameter. 94 | 95 | - `stop()` - Stop the timer 96 | 97 | - `setFrequency(long frequency)` - Set the timer frequency 98 | 99 | - `long getFrequency()` - Get the timer frequency 100 | 101 | - `setPeriod(long microseconds)` - Set the timer period (in microseconds) 102 | 103 | - `long getPeriod()` - Get the timer period (in microseconds) 104 | 105 | ### You don't need to know: 106 | 107 | - `unsigned short timer` - Stores the object timer id (to access Timers struct array). 108 | 109 | - `DueTimer(unsigned short _timer)` - Instantiate a new DueTimer object for Timer _timer (NOTE: All objects are already instantiated!). 110 | 111 | - `static const Timer Timers[]` - Stores all timers information 112 | 113 | - `static void (*callbacks[])()` - Stores all callbacks for all timers 114 | 115 | 116 | ### Hardware Information 117 | 118 | More information on the Timer Counter module of the µC on the Arduino Due 119 | can be found in the documentation file [TimerCounter](TimerCounter.md). -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/examples/Benchmark/Benchmark.ino: -------------------------------------------------------------------------------- 1 | #include "GPIO.h" 2 | #include "benchmark.h" 3 | 4 | GPIO button; 5 | GPIO led; 6 | #define BUTTON_PIN 12 7 | #define LED_PIN 13 8 | 9 | void setup() 10 | { 11 | Serial.begin(57600); 12 | while (!Serial); 13 | 14 | // Set pin mode; Arduino style 15 | pinMode(LED_PIN, OUTPUT); 16 | pinMode(BUTTON_PIN, INPUT_PULLUP); 17 | 18 | // Set pin mode; GPIO style 19 | led.output(); 20 | button.input().pullup(); 21 | 22 | // Calculate baseline 23 | BENCHMARK_BASELINE(1000); 24 | } 25 | 26 | void loop() 27 | { 28 | BENCHMARK("1.1 Arduino core digitalRead", 1000) { 29 | bool state = digitalRead(BUTTON_PIN); 30 | (void) state; 31 | } 32 | 33 | BENCHMARK("1.2 Arduino core digitalWrite(HIGH)", 1000) { 34 | digitalWrite(LED_PIN, HIGH); 35 | } 36 | 37 | BENCHMARK("1.3 Arduino core digitalWrite(LOW)", 1000) { 38 | digitalWrite(LED_PIN, LOW); 39 | } 40 | 41 | BENCHMARK("1.4 Arduino core toggle; digitalRead-digitalWrite", 1000) { 42 | digitalWrite(LED_PIN, !digitalRead(LED_PIN)); 43 | } 44 | 45 | BENCHMARK("1.5 Arduino core toggle; digitalWrite", 1000) { 46 | digitalWrite(LED_PIN, HIGH); 47 | digitalWrite(LED_PIN, LOW); 48 | } 49 | 50 | BENCHMARK("2.1 GPIO pin value operator", 1000) { 51 | bool state = button; 52 | (void) state; 53 | } 54 | 55 | BENCHMARK("2.2 GPIO high member function", 1000) { 56 | led.high(); 57 | } 58 | 59 | BENCHMARK("2.3 GPIO low member function", 1000) { 60 | led.low(); 61 | } 62 | 63 | BENCHMARK("2.4 GPIO assignment HIGH", 1000) { 64 | led = HIGH; 65 | } 66 | 67 | BENCHMARK("2.5 GPIO assignment LOW", 1000) { 68 | led = LOW; 69 | } 70 | 71 | BENCHMARK("2.6 GPIO toggle; value and assignment operator", 1000) { 72 | led = !led; 73 | } 74 | 75 | BENCHMARK("2.7 GPIO toggle; high and low member functions", 1000) { 76 | led.high(); 77 | led.low(); 78 | } 79 | 80 | BENCHMARK("2.8 GPIO toggle; assignment operator, HIGH/LOW", 1000) { 81 | led = HIGH; 82 | led = LOW; 83 | } 84 | 85 | BENCHMARK("2.9 GPIO toggle member function", 1000) { 86 | led.toggle(); 87 | } 88 | 89 | #ifdef PORTH 90 | 91 | // GPIO atomic access of io ports with higher address. These 92 | // benchmarks are for Arduino Mega pins that use ports above address 93 | // 0x40 (PORTH, PORTJ, PINK and PINL). See Hardware/AVR/Board.h. 94 | 95 | #define DIN_PIN 6 96 | #define DOUT_PIN 7 97 | GPIO din; 98 | GPIO dout; 99 | din.input(); 100 | dout.input(); 101 | 102 | BENCHMARK("3.1 Arduino core digitalRead", 1000) { 103 | bool state = digitalRead(DIN_PIN); 104 | (void) state; 105 | } 106 | 107 | BENCHMARK("3.2 Arduino core digitalWrite(HIGH)", 1000) { 108 | digitalWrite(DOUT_PIN, HIGH); 109 | } 110 | 111 | BENCHMARK("3.3 Arduino core digitalWrite(LOW)", 1000) { 112 | digitalWrite(DOUT_PIN, LOW); 113 | } 114 | 115 | BENCHMARK("3.4 Arduino core toggle; digitalRead-digitalWrite", 1000) { 116 | digitalWrite(DOUT_PIN, !digitalRead(DOUT_PIN)); 117 | } 118 | 119 | BENCHMARK("3.5 Arduino core toggle; digitalWrite", 1000) { 120 | digitalWrite(DOUT_PIN, HIGH); 121 | digitalWrite(DOUT_PIN, LOW); 122 | } 123 | 124 | BENCHMARK("4.1 GPIO pin value operator", 1000) { 125 | bool state = din; 126 | (void) state; 127 | } 128 | 129 | BENCHMARK("4.2 GPIO high member function", 1000) { 130 | dout.high(); 131 | } 132 | 133 | BENCHMARK("4.3 GPIO low member function", 1000) { 134 | dout.low(); 135 | } 136 | 137 | BENCHMARK("4.4 GPIO assignment HIGH", 1000) { 138 | dout = HIGH; 139 | } 140 | 141 | BENCHMARK("4.5 GPIO assignment LOW", 1000) { 142 | dout = LOW; 143 | } 144 | 145 | BENCHMARK("4.6 GPIO toggle; value and assignment operator", 1000) { 146 | dout = !dout; 147 | } 148 | 149 | BENCHMARK("4.7 GPIO toggle; high and low member functions", 1000) { 150 | dout.high(); 151 | dout.low(); 152 | } 153 | 154 | BENCHMARK("4.8 GPIO toggle; assignment operator", 1000) { 155 | dout = HIGH; 156 | dout = LOW; 157 | } 158 | 159 | BENCHMARK("4.9 GPIO toggle member function", 1000) { 160 | dout.toggle(); 161 | } 162 | #endif 163 | 164 | Serial.println(); 165 | delay(2000); 166 | } 167 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/src/Hardware/AVR/GPIO.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Hardware/AVR/GPIO.h 3 | * @version 1.6 4 | * 5 | * @section License 6 | * Copyright (C) 2017, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef HARDWARE_AVR_GPIO_H 20 | #define HARDWARE_AVR_GPIO_H 21 | 22 | #include "Hardware/AVR/Board.h" 23 | 24 | /** 25 | * General Purpose Digital I/O pin template class. Highly optimized 26 | * pin access. The PIN address is a bit pointer to the port control 27 | * register. See Hardware/AVR/Board.h for details. 28 | * @param[in] PIN board pin definition. 29 | */ 30 | template 31 | class GPIO { 32 | public: 33 | /** 34 | * Set pin to input mode. 35 | */ 36 | GPIO& input() 37 | __attribute__((always_inline)) 38 | { 39 | GPIO_ATOMIC(SFR()->ddr &= ~MASK); 40 | return (*this); 41 | } 42 | 43 | /** 44 | * Used with input() to activate internal pullup resistor on 45 | * input pin. 46 | */ 47 | void pullup() 48 | __attribute__((always_inline)) 49 | { 50 | high(); 51 | } 52 | 53 | /** 54 | * Set pin to output mode. 55 | */ 56 | void output() 57 | __attribute__((always_inline)) 58 | { 59 | GPIO_ATOMIC(SFR()->ddr |= MASK); 60 | } 61 | 62 | /** 63 | * Open-drain pin. Use input() for high and output() for low. 64 | */ 65 | void open_drain() 66 | __attribute__((always_inline)) 67 | { 68 | input(); 69 | low(); 70 | } 71 | 72 | /** 73 | * Return current pin state. 74 | * @return state. 75 | */ 76 | bool read() 77 | __attribute__((always_inline)) 78 | { 79 | return ((SFR()->pin & MASK) != 0); 80 | } 81 | 82 | /** 83 | * Return current pin state. Shorthand for read(). 84 | * @return state. 85 | */ 86 | operator bool() 87 | __attribute__((always_inline)) 88 | { 89 | return (read()); 90 | } 91 | 92 | /** 93 | * Set pin low(0). Shorthand for write(LOW). 94 | */ 95 | void low() 96 | __attribute__((always_inline)) 97 | { 98 | GPIO_ATOMIC(SFR()->port &= ~MASK); 99 | } 100 | 101 | /** 102 | * Set pin high(1). Shorthand for write(HIGH). 103 | */ 104 | void high() 105 | __attribute__((always_inline)) 106 | { 107 | GPIO_ATOMIC(SFR()->port |= MASK); 108 | } 109 | 110 | /** 111 | * Toggle pin state. Shorthand for write(!read()). 112 | */ 113 | void toggle() 114 | __attribute__((always_inline)) 115 | { 116 | GPIO_ATOMIC(SFR()->pin |= MASK); 117 | } 118 | 119 | /** 120 | * Set pin to given state. Non-zero value will set the pin HIGH(1), 121 | * and zero value will set the pin LOW(0). 122 | * @param[in] value to set pin. 123 | */ 124 | void write(int value) 125 | __attribute__((always_inline)) 126 | { 127 | if (value) high(); else low(); 128 | } 129 | 130 | /** 131 | * Set pin to given state. Non-zero value will set the pin HIGH(1), 132 | * and zero value will set the pin LOW(0). Shorthand for write(value). 133 | * @param[in] value to set pin. 134 | */ 135 | void operator=(int value) 136 | __attribute__((always_inline)) 137 | { 138 | write(value); 139 | } 140 | 141 | /** 142 | * Generate pulse with given width in micro-seconds. Interrupts 143 | * are disabled while generating the pulse. 144 | * @param[in] width in micro-seconds. 145 | */ 146 | void pulse(uint16_t width) 147 | { 148 | if (width == 0) return; 149 | uint16_t count = ((width * (F_CPU / 1000000L)) / 4); 150 | uint8_t sreg = SREG; 151 | __asm__ __volatile__("cli" ::: "memory"); 152 | SFR()->pin |= MASK; 153 | _delay_loop_2(count); 154 | SFR()->pin |= MASK; 155 | SREG = sreg; 156 | __asm__ __volatile__("" ::: "memory"); 157 | } 158 | 159 | /** 160 | * Detect pulse and return width in micro-seconds. 161 | * @return width in micro-seconds. 162 | */ 163 | int pulse() 164 | { 165 | bool s0 = read(); 166 | while (read() == s0); 167 | uint16_t t0 = micros(); 168 | while (read() != s0); 169 | return (micros() - t0); 170 | } 171 | 172 | protected: 173 | /** General Purpose Digital I/O Control Registers. */ 174 | struct gpio_reg_t { 175 | volatile uint8_t pin; //!< Port Input Pins. 176 | volatile uint8_t ddr; //!< Data Direction Register. 177 | volatile uint8_t port; //!< Data Register. 178 | }; 179 | 180 | /** 181 | * Return pointer to control registers. 182 | * @return pointer. 183 | */ 184 | gpio_reg_t* SFR() 185 | __attribute__((always_inline)) 186 | { 187 | return ((gpio_reg_t*) GPIO_REG(PIN)); 188 | } 189 | 190 | /** Pin bit position mask in control registers. */ 191 | static const uint8_t MASK = GPIO_MASK(PIN); 192 | }; 193 | #endif 194 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/src/Hardware/SAM/GPIO.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Hardware/SAM/GPIO.h 3 | * @version 1.1 4 | * 5 | * @section License 6 | * Copyright (C) 2017, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef HARDWARE_SAM_GPIO_H 20 | #define HARDWARE_SAM_GPIO_H 21 | 22 | #include "Hardware/SAM/Board.h" 23 | 24 | /** 25 | * General Purpose Digital I/O pin template class. Highly optimized 26 | * pin access. The PIN address is a port control register index and 27 | * pin bit position. See Hardware/SAM/Board.h for details. 28 | * @param[in] PIN board pin definition. 29 | */ 30 | template 31 | class GPIO { 32 | public: 33 | /** 34 | * Construct pin instance and initiate. 35 | */ 36 | GPIO() 37 | { 38 | pmc_enable_periph_clk(ID_PIO()); 39 | SFR()->PIO_PER = MASK; 40 | } 41 | 42 | /** 43 | * Set pin to input mode. 44 | */ 45 | GPIO& input() 46 | __attribute__((always_inline)) 47 | { 48 | SFR()->PIO_ODR = MASK; 49 | return (*this); 50 | } 51 | 52 | /** 53 | * Used with input() to activate internal pullup resistor on 54 | * input pin. 55 | */ 56 | void pullup() 57 | __attribute__((always_inline)) 58 | { 59 | SFR()->PIO_PUER = MASK; 60 | } 61 | 62 | /** 63 | * Set pin to output mode. 64 | */ 65 | void output() 66 | __attribute__((always_inline)) 67 | { 68 | SFR()->PIO_OER = MASK; 69 | } 70 | 71 | /** 72 | * Open-drain pin. Use input() for high and output() for low. 73 | */ 74 | void open_drain() 75 | __attribute__((always_inline)) 76 | { 77 | SFR()->PIO_CODR = MASK; 78 | SFR()->PIO_MDER = MASK; 79 | } 80 | 81 | /** 82 | * Return current pin state. 83 | * @return state. 84 | */ 85 | bool read() 86 | __attribute__((always_inline)) 87 | { 88 | return ((SFR()->PIO_PDSR & MASK) != 0); 89 | } 90 | 91 | /** 92 | * Return current pin state. Shorthand for read(). 93 | * @return state. 94 | */ 95 | operator bool() 96 | __attribute__((always_inline)) 97 | { 98 | return (read()); 99 | } 100 | 101 | /** 102 | * Set pin low(0). Shorthand for write(LOW). 103 | */ 104 | void low() 105 | __attribute__((always_inline)) 106 | { 107 | SFR()->PIO_CODR = MASK; 108 | } 109 | 110 | /** 111 | * Set pin high(1). Shorthand for write(HIGH). 112 | */ 113 | void high() 114 | __attribute__((always_inline)) 115 | { 116 | SFR()->PIO_SODR = MASK; 117 | } 118 | 119 | /** 120 | * Toggle pin state. Shorthand for write(!read()). 121 | */ 122 | void toggle() 123 | __attribute__((always_inline)) 124 | { 125 | write(!read()); 126 | } 127 | 128 | /** 129 | * Set pin to given state. Non-zero value will set the pin HIGH(1), 130 | * and zero value will set the pin LOW(0). 131 | * @param[in] value to set pin. 132 | */ 133 | void write(int value) 134 | __attribute__((always_inline)) 135 | { 136 | if (value) high(); else low(); 137 | } 138 | 139 | /** 140 | * Set pin to given state. Non-zero value will set the pin HIGH(1), 141 | * and zero value will set the pin LOW(0). Shorthand for write(value). 142 | * @param[in] value to set pin. 143 | */ 144 | void operator=(int value) 145 | __attribute__((always_inline)) 146 | { 147 | write(value); 148 | } 149 | 150 | /** 151 | * Generate pulse with given width in micro-seconds. Interrupts 152 | * are disabled while generating the pulse. 153 | * @param[in] width in micro-seconds. 154 | */ 155 | void pulse(uint16_t width) 156 | { 157 | if (width == 0) return; 158 | toggle(); 159 | delayMicroseconds(width); 160 | toggle(); 161 | } 162 | 163 | /** 164 | * Detect pulse and return width in micro-seconds. 165 | * @return width in micro-seconds. 166 | */ 167 | int pulse() 168 | { 169 | bool s0 = read(); 170 | while (read() == s0); 171 | uint16_t t0 = micros(); 172 | while (read() != s0); 173 | return (micros() - t0); 174 | } 175 | 176 | protected: 177 | /** Pin bit position mask in control registers. */ 178 | static const uint32_t MASK = GPIO_MASK(PIN); 179 | 180 | /** 181 | * Return pointer to control registers. 182 | * @return pointer. 183 | */ 184 | Pio* SFR() 185 | __attribute__((always_inline)) 186 | { 187 | switch (GPIO_REG(PIN)) { 188 | case 0: return (PIOA); 189 | case 1: return (PIOB); 190 | case 2: return (PIOC); 191 | default: 192 | return (PIOD); 193 | } 194 | } 195 | 196 | /** 197 | * Return parallel input/output port identity. 198 | * @return identity. 199 | */ 200 | uint32_t ID_PIO() 201 | __attribute__((always_inline)) 202 | { 203 | switch (GPIO_REG(PIN)) { 204 | case 0: return (ID_PIOA); 205 | case 1: return (ID_PIOB); 206 | case 2: return (ID_PIOC); 207 | default: 208 | return (ID_PIOD); 209 | } 210 | } 211 | }; 212 | #endif 213 | -------------------------------------------------------------------------------- /firmware/lib/DueTimer/TimerCounter.md: -------------------------------------------------------------------------------- 1 | # The Timer Counter blocks of Arduino Due's AT91SAM3X8E 2 | 3 | The AT91SAM3X8E embedds nine general-purpose 32-bit timers/counters. They are organized in three blocks (`TC0`, `TC1`, `TC2`) each containing three channels (`0`, `1`, `2`). 4 | Each block and channel has input lines for their clock and input/output lines which can be used in different ways, such as PWM pins etc. 5 | 6 | 7 | ### Resources 8 | 9 | Information on the Timer Counter and its I/O signals pins can be found here: 10 | 11 | * Section **37 Timer Counter (TC)** in the [Atmel SAM3X Datasheet][] 12 | You find this chapter on the pages 869 through 920. It explains in detail how to operate the counter in different modes and has nice diagrams that show you how the clock input works and how to set up interrupts based on counter values etc. 13 | * [Arduino Due's SAM3X Pin Mapping][] and the 14 | * [Arduino Due pinout diagram][]. 15 | 16 | ### The Timer Counter Signals / Pins 17 | 18 | Many of the I/O lines of the Timer Counter are directly accessible on pin headers of the Arduino Due board. This section helps you to find out which of them are and which are not. 19 | 20 | In order to actually connect those signals (`TCLKx`, `TIOAx` and `TIOBx`) to the pins on the Arduino Due, you must tell the Parallel I/O Controllers (`PIOA`, `PIOB`, `PIOC` or `PIOD`) to set up their mux (multiplexer) accordingly.
21 | A useful resource to find out how to set the PIOs is 22 | [Arduino's const array of PinDescriptions](https://github.com/arduino/Arduino/blob/ide-1.5.x/hardware/arduino/sam/variants/arduino_due_x/variant.cpp#L117) and the 23 | [definition of PinDescription](https://github.com/arduino/Arduino/blob/ide-1.5.x/hardware/arduino/sam/cores/arduino/Arduino.h#L166), the data type of its entries. 24 | 25 | #### Overview of the I/O lines of the Timer Counter 26 | 27 | Here is a table of the Timer Counter channels and their `TCLKx` (external clock input), `TIOAx` (I/O Line _A_) and `TIOBx` (I/O Line _B_) signals: 28 | 29 | Instance | TC | Channel| External Clock Input | I/O Line A | I/O Line B 30 | ---------|-----|--------|----------------------|------------|----------- 31 | T0 | TC0 | 0 | TCLK0 | TIOA0 | TIOB0 32 | T1 | TC0 | 1 | TCLK1 | TIOA1 | TIOB1 33 | T2 | TC0 | 2 | TCLK2 | TIOA2 | TIOB2 34 | T3 | TC1 | 0 | TCLK3 | TIOA3 | TIOB3 35 | T4 | TC1 | 1 | TCLK4 | TIOA4 | TIOB4 36 | T5 | TC1 | 2 | TCLK5 | TIOA5 | TIOB5 37 | T6 | TC2 | 0 | TCLK6 | TIOA6 | TIOB6 38 | T7 | TC2 | 1 | TCLK7 | TIOA7 | TIOB7 39 | T8 | TC2 | 2 | TCLK8 | TIOA8 | TIOB8 40 | 41 | ##### TCLKx 42 | 43 | Here is how the **external clock inputs** are routed to pins on the Arduino Due board: 44 | 45 | Clock Input | Port Pin of µC | Pin on Arduino Due Board 46 | ------------|------------|----------------------------- 47 | TCLK0 | PB 26 | Digital Pin 22 48 | TCLK1 | PA 4 | Analog In 5 49 | TCLK2 | PA 7 | Digital Pin 31 50 | TCLK3 | PA 22 | Analog In 3 51 | TCLK4 | PA 23 | Analog In 2 52 | TCLK5 | PB 16 | DAC1 53 | TCLK6 | PC 27 | / 54 | TCLK7 | PC 30 | LED "RX" 55 | TCLK8 | PD 9 | Digital Pin 30 56 | 57 | ##### TIOAx 58 | 59 | Here is how the **I/O Lines _A_** are routed to pins on the Arduino Due board: 60 | 61 | I/O Line A | Port Pin of µC | Pin on Arduino Due Board 62 | -----------|----------------|----------------------------- 63 | TIOA0 | PB 25 | Digital Pin 2 64 | TIOA1 | PA 2 | Analog In 7 65 | TIOA2 | PA 5 | / 66 | TIOA3 | PE 9 | / 67 | TIOA4 | PE 11 | / 68 | TIOA5 | PE 13 | / 69 | TIOA6 | PC 25 | Digital Pin 5 70 | TIOA7 | PC 28 | Digital Pin 3 71 | TIOA8 | PD 7 | Digital Pin 11 72 | 73 | ##### TIOBx 74 | 75 | Here is how the **I/O Lines _B_** are routed to pins on the Arduino Due board: 76 | 77 | I/O Line B|Port Pin of µC| Pin on Arduino Due Board 78 | ----------|--------------|------------------------------------------ 79 | TIOB0 | PB 27 | Digital Pin 13 / Amber LED "L" 80 | TIOB1 | PA 3 | Analog In 6 81 | TIOB2 | PA 6 | Analog In 4 82 | TIOB3 | PE 10 | / 83 | TIOB4 | PE 12 | / 84 | TIOB5 | PE 14 | / 85 | TIOB6 | PC 26 | Digital Pin 4 (also connected to PA29) 86 | TIOB7 | PC 29 | Digital Pin 10 (also connected to PA28) 87 | TIOB8 | PD 8 | Digital Pin 12 88 | 89 | #### TC Clock Source Selection 90 | 91 | The *clock of the counters* can be set very flexibly to internal or external signals. To *use the channel as a timer*, it makes sense to connect its clock input to an internal timer clock. Here are the options: 92 | 93 | Name | Definition 94 | -------------|----------- 95 | TIMER_CLOCK1 | `MCK / 2` 96 | TIMER_CLOCK2 | `MCK / 8` 97 | TIMER_CLOCK3 | `MCK / 32` 98 | TIMER_CLOCK4 | `MCK / 128` 99 | TIMER_CLOCK5 | `SLCK` 100 | 101 | 102 | Where `MCK` is the master clock (84 MHz for the Arduino Due) and SLCK is the slow clock (which can be clocked at 32.768 kHz by Y2 on the Arduino Due). 103 | 104 | [Atmel SAM3X Datasheet]: http://www.atmel.com/Images/Atmel-11057-32-bit-Cortex-M3-Microcontroller-SAM3X-SAM3A_Datasheet.pdf 105 | [Arduino Due's SAM3X Pin Mapping]: http://arduino.cc/en/Hacking/PinMappingSAM3X 106 | [Arduino Due pinout diagram]: http://www.robgray.com/temp/Due-pinout.pdf 107 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/src/Hardware/SAM/Board.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Hardware/SAM/Board.h 3 | * @version 1.1 4 | * 5 | * @section License 6 | * Copyright (C) 2017, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef HARDWARE_SAM_BOARD_H 20 | #define HARDWARE_SAM_BOARD_H 21 | 22 | /** 23 | * Board pin values are constructed from port control register index 24 | * and pin bit position. 25 | * @param[in] index control register index. 26 | * @param[in] pin pin bit position in control register. 27 | */ 28 | #define GPIO_PIN(index,pin) (((index) << 8) | (pin)) 29 | 30 | /** 31 | * Return port control register index from board pin value. 32 | * @return io port address 33 | */ 34 | #define GPIO_REG(pin) ((pin) >> 8) 35 | 36 | /** 37 | * Return pin mask from board pin value. 38 | * @return pin mask 39 | */ 40 | #define GPIO_MASK(pin) (1U << ((pin) & 0xff)) 41 | 42 | #if defined(__SAM3X8E__) 43 | /** 44 | * GPIO digital pin symbols for SAM3X8E based boards. 45 | * @section Board 46 | * @code 47 | * Arduino Due 48 | * ----- ------- 49 | * +-|(o)|--------------------| USB |---+ 50 | * | | | | | | 51 | * | ----- | | | 52 | * | ------- | 53 | * | | 54 | * | []| SCL 55 | * | []| SDA 56 | * | []| AREF 57 | * | []| GND 58 | * NC |[] []| D13 59 | * IOREF |[] []| D12 60 | * RESET |[] []| D11 61 | * 3V3 |[] []| D10 62 | * 5V |[] []| D9 63 | * GND |[] []| D8 64 | * GND |[] | 65 | * Vin |[] []| D7 66 | * | []| D6 67 | * A0 |[] []| D5 68 | * A1 |[] []| D4 69 | * A2 |[] []| D3 70 | * A3 |[] []| D2 71 | * A4 |[] ICSP []| D1 72 | * A5 |[] [o-o-*] []| D0 73 | * A6 |[] [o-o-o] | 74 | * A7 |[] []| D14 75 | * | []| D15 76 | * A8 |[] []| D16 77 | * A9 |[] []| D17 78 | * A10 |[] []| D18 79 | * A11 |[] []| D19 80 | * A12 |[] []| D20 81 | * A13 |[] []| D21 82 | * A14 |[] | 83 | * A15 |[]52 30 22 | 84 | * GND |[][][][][][][][][][][][][][][][][][]| 5V 85 | * GND |[][][][][][][][][][][][][][][][][][]| 5V 86 | * \ 53 31 / 87 | * +------------------------+ 88 | * @endcode 89 | */ 90 | class BOARD { 91 | public: 92 | enum pin_t { 93 | D0 = GPIO_PIN(0,8), //! Receiver ---- "SEND BUTTON PUSHED" ---> Sender 70 | | | ^_________________________ | 71 | | "DATA RECEIVED" | | 72 | | | | | 73 | | Parse Meta | Create Meta 74 | | | | | 75 | | Receive Data<--------------. | Send Data<---. 76 | | __|____________ | | | | 77 | | | | | | Wait | 78 | .-"NO ERROR" "ERROR(S)"--. | ____|______ | 79 | | | | | 80 | "DONE PACKET" "RESEND" 81 | ``` 82 | 83 | #### Sender States 84 | There are 4 states that are associated with the Sender driver: 85 | 86 | ##### Sender 87 | This state initializes the driver as the sender side and pushes the state machine to the next state 88 | 89 | ##### Create_Meta 90 | This state takes the file data and creates a 64 byte meta packet include a 4 byte index [0x00000000], 15 bytes of data 91 | [4 bytes - number of packets, 1 byte - 0 padding at end of file, 10 bytes - file extension] + 41 bytes of 0s for 92 | padding, and a final 4 bytes for a crc checksukm. Once this packet is created, it is written to the serial port using 93 | pySerial and pushes the state machine to the next state. 94 | 95 | ##### Send_Data 96 | This state takes the data in the file, splits it into 56 byte chunks (or less for the last packet which is padded with 97 | 0s to make it 56 bytes) and add a 4 byte header which increases sequentially, and a 4 byte crc checksum for each 56 98 | byte chunk. This is looped over and each individual packet is written to the serial port using pySerial. It then pushes 99 | the state machine to the next state. 100 | 101 | ##### Wait 102 | This state waits for a reply from the receiver side. If a Finish Packet is received, then it moves the state machine 103 | back to the Receive state. If a Resend Packet is received, then it moves the state machine back to Send_Data, and 104 | resends the packets with errors. 105 | 106 | #### Receiver States 107 | There are 3 states that are associated with the Receiver driver: 108 | 109 | ##### Receiver 110 | This state initializes the driver as the receiver side and is the default state 111 | 112 | ##### Parse_Meta 113 | This state reads in 64 byte, the first full packet, from the serial port using pySerial. It makes sure the index is 0 114 | and the crc checksum calculated with the received data and the crc checksum that was received are equal to one another. 115 | If these checks are both true, the data is then parsed and stored. The state machine is then pushed to Receive_Data. 116 | 117 | ##### Receive Data 118 | This state reads in 64 bytes at a time from the serial port using pySerial. This is then split into index, data, and 119 | checksum. If the calculated and received checksum are equal, the data is then pushed to an array at the index that 120 | packet corresponds to, otherwise "ERROR" is written to the array at the corresponding index. After all data is read and 121 | has been checked, if there are no errors, the data is written to a file and the Finish Packet is sent and the state 122 | machine is pushed to the Receiver state. Otherwise the Resend packet will be sent with up to 14 indices that had errors 123 | and the state machine is pushed back to the Receive_Data state. 124 | 125 | ### Firmware 126 | 127 | #### Bidirectional 128 | Sets DAC0 voltage, Serial, and Serial1. 129 | 130 | If Serial is available (Sending) write to Serial1. If Serial1 is available (Receiving) write to Serial. 131 | 132 | #### Driver_Receive & Driver_Send 133 | These are deprecated. Use the bidirectional code instead. 134 | 135 | ### Hardware 136 | Refer to the README within the subdirectory 137 | 138 | ### Further Development 139 | There are many areas which can be further developed. Some ideas for what could be done are listed below: 140 | 141 | - Create a more sophisticated packet system 142 | - Optimize for distance and speed 143 | - Update driver to allow for more than file transfers 144 | - Possibly be able to connect to internet 145 | - Move from point-to-point communication to a hub-client type communication 146 | -------------------------------------------------------------------------------- /lib/LiFiGUI.py: -------------------------------------------------------------------------------- 1 | """ 2 | LiFiGUI.py 3 | 4 | This file contains our GUI class wich extends pythons threading library, allowing 5 | for the serial port to be polled in parallel with GUI interactions. 6 | """ 7 | 8 | # GUI Imports 9 | from tkinter import Tk, ttk 10 | from tkinter import Label, Button, Entry, messagebox 11 | from tkinter.filedialog import askopenfilename 12 | 13 | # Threading Imports 14 | from fsm import Receiver 15 | import threading 16 | 17 | # Other Imports 18 | import time 19 | import serial 20 | from serial_connect import connectToSerial, disconnectFromSerial 21 | 22 | 23 | class SerialGUI(threading.Thread): 24 | def __init__(self, fsm, sender, receiver): 25 | 26 | # Define GUI Window, Call createWidgets() 27 | self.window = Tk() 28 | self.window.title("LiFi Communication") 29 | 30 | # Global Variables 31 | self.__state_machine = fsm 32 | self.__sd = sender 33 | self.__rd = receiver 34 | 35 | self.__serialPort = serial.Serial(timeout=0.25, rtscts=False, dsrdtr=False) 36 | self.__baudRate = "" 37 | self.__comPort = "" 38 | self.__fileName = "" 39 | 40 | self.window['padx'] = 5 41 | self.window['pady'] = 5 42 | 43 | # - - - - - - - - - - - - - - - - - - - - - 44 | # The Send/Receive frame 45 | fileFrame = ttk.LabelFrame(self.window, text="File Setup") 46 | fileFrame.grid(row=0, columnspan=7, sticky='WE', padx=5, pady=5, ipadx=5, ipady=5) 47 | 48 | inFileLbl = Label(fileFrame, text="Select File:") 49 | inFileLbl.grid(row=0, column=0, sticky='E', padx=5, pady=2) 50 | 51 | self.inFileTxt = Entry(fileFrame) 52 | self.inFileTxt.grid(row=0, column=1, columnspan=7, sticky="WE", pady=3) 53 | 54 | self.inFileBtn = Button(fileFrame, text="Browse...", command=self.loadFile) 55 | self.inFileBtn.grid(row=0, column=8, sticky='W', padx=5, pady=2) 56 | 57 | # - - - - - - - - - - - - - - - - - - - - - 58 | # The Baud Rate/COM Port frame 59 | connectFrame = ttk.LabelFrame(self.window, text="Serial Setup") 60 | connectFrame.grid(row=2, columnspan=7, sticky='WE', padx=5, pady=5, ipadx=5, ipady=5) 61 | 62 | self.inBaudRate = Entry(connectFrame) 63 | self.inBaudRate.grid(row=3, column=2, columnspan=7, sticky="WE", pady=3) 64 | 65 | self.inBaudLbl = Label(connectFrame, text="Baud Rate:") 66 | self.inBaudLbl.grid(row=3, column=1, sticky='W', padx=5, pady=2) 67 | 68 | self.inComPort = Entry(connectFrame) 69 | self.inComPort.grid(row=4, column=2, columnspan=7, sticky="WE", pady=3) 70 | 71 | self.inComLbl = Label(connectFrame, text="COM Port:") 72 | self.inComLbl.grid(row=4, column=1, sticky='W', padx=5, pady=2) 73 | 74 | self.connectButton = Button(connectFrame, text="Connect", command=lambda: connectToSerial(self)) 75 | self.connectButton.grid(row=5, column=2) 76 | 77 | self.disconnectButton = Button(connectFrame, text="Disconnect", command=lambda: disconnectFromSerial(self)) 78 | self.disconnectButton.grid(row=5, column=3) 79 | self.disconnectButton.config(state="disabled") 80 | 81 | # - - - - - - - - - - - - - - - - - - - - - 82 | # Start button in the upper right corner 83 | self.startButton = Button(self.window, text="SEND", command=self.pushToSend) 84 | self.startButton.grid(row=0, column=15) 85 | 86 | threading.Thread.__init__(self) 87 | self.start() 88 | 89 | @property 90 | def my_queue(self): 91 | return self.__my_queue 92 | 93 | @property 94 | def state_machine(self): 95 | return self.__state_machine 96 | 97 | @property 98 | def sd(self): 99 | return self.__sd 100 | 101 | @sd.setter 102 | def sd(self, send): 103 | self.__sd = send 104 | 105 | @property 106 | def rd(self): 107 | return self.__rd 108 | 109 | @rd.setter 110 | def rd(self, receive): 111 | self.__rd = receive 112 | 113 | @property 114 | def serialPort(self): 115 | return self.__serialPort 116 | 117 | @serialPort.setter 118 | def serialPort(self, serial): 119 | self.__serialPort = serial 120 | 121 | @property 122 | def baudRate(self): 123 | return self.__baudRate 124 | 125 | @baudRate.setter 126 | def baudRate(self, baud): 127 | self.__baudRate = baud 128 | 129 | @property 130 | def comPort(self): 131 | return self.__comPort 132 | 133 | @comPort.setter 134 | def comPort(self, port): 135 | self.__comPort = port 136 | 137 | @property 138 | def fileName(self): 139 | return self.__fileName 140 | 141 | @fileName.setter 142 | def fileName(self, name): 143 | self.__fileName = name 144 | 145 | # Opens File Dialog And Saves Selected File to self.fileName 146 | def loadFile(self): 147 | self.fileName = askopenfilename() 148 | self.rd.file_name = self.fileName 149 | self.sd.file_name = self.fileName 150 | self.inFileTxt.insert(0, self.fileName) 151 | 152 | # Call functions associated with sending a file 153 | def pushToSend(self): 154 | if self.fileName != "" and self.serialPort.is_open: 155 | self.state_machine.on_event("send") 156 | self.state_machine.on_event("") 157 | self.sd.meta_creator() 158 | self.startButton["text"] = "SENDING..." 159 | elif self.fileName == "": 160 | messagebox.showerror("Error", "File Must Be Selected To Send") 161 | else: 162 | messagebox.showerror("Error", "A Serial Connection Is Required") 163 | 164 | self.startButton["text"] = "SEND" 165 | 166 | # Thread to check data on serial port 167 | def run(self): 168 | loop_active = True 169 | while loop_active: 170 | try: 171 | if self.serialPort.is_open and isinstance(self.state_machine.state, Receiver): 172 | # Wait until there is an entire packet waiting (1 Packet = 64 Bytes) 173 | if self.serialPort.in_waiting > 63: 174 | loop_active = False 175 | self.state_machine.on_event("") 176 | self.rd.parse_meta() 177 | else: 178 | pass 179 | else: 180 | pass 181 | except OSError: 182 | print("Please Reconnect!") 183 | while not loop_active: 184 | loop_active = (self.rd.flag or self.sd.flag) 185 | self.run() 186 | -------------------------------------------------------------------------------- /lib/Receiver.py: -------------------------------------------------------------------------------- 1 | """ 2 | Receiver.py 3 | 4 | This file contains all functions necessary for processing incoming data. 5 | """ 6 | 7 | import os 8 | import zlib 9 | import time 10 | from fsm import Receiver 11 | 12 | class Receiver_Driver: 13 | 14 | def __init__(self, state_mach, file_name=os.path.join('..', 'files', 'out.txt'), serialPort=None): 15 | self.__packet_list = [] 16 | 17 | self.__my_fsm = state_mach 18 | self.__serialPort = serialPort 19 | 20 | self.__file_name = file_name 21 | self.__file = open(self.__file_name, "w") 22 | self.__file.write('') 23 | self.__file.close() 24 | self.__file = open(self.__file_name, "ab") 25 | 26 | self.__packets_to_receive = 0 27 | self.__zero_padding = 0 28 | 29 | # Used to reset thread in LiFiGUI.py 30 | self.__flag = False 31 | 32 | @property 33 | def packet_list(self): 34 | return self.__packet_list 35 | 36 | @packet_list.setter 37 | def packet_list(self, data): 38 | return self.__packet_list.append(data) 39 | 40 | @property 41 | def my_fsm(self): 42 | return self.__my_fsm 43 | 44 | @property 45 | def serialPort(self): 46 | return self.__serialPort 47 | 48 | @serialPort.setter 49 | def serialPort(self, port): 50 | self.__serialPort = port 51 | 52 | @property 53 | def file_name(self): 54 | return self.__file_name 55 | 56 | @file_name.setter 57 | def file_name(self, fn): 58 | self.__file_name = fn 59 | 60 | @property 61 | def file(self): 62 | return self.__file 63 | 64 | @file.setter 65 | def file(self, f): 66 | self.__file = f 67 | 68 | @property 69 | def packets_to_receive(self): 70 | return self.__packets_to_receive 71 | 72 | @packets_to_receive.setter 73 | def packets_to_receive(self, num): 74 | self.__packets_to_receive = num 75 | 76 | @property 77 | def zero_padding(self): 78 | return self.__zero_padding 79 | 80 | @zero_padding.setter 81 | def zero_padding(self, pad): 82 | self.__zero_padding = pad 83 | 84 | @property 85 | def flag(self): 86 | return self.__flag 87 | 88 | @flag.setter 89 | def flag(self, data): 90 | self.__flag = data 91 | 92 | """ 93 | This function parses the first packet for the number of packets to be received, how many 0's the 94 | final packet will be padded with and the file extension for the received file. 95 | """ 96 | def parse_meta(self): 97 | self.flag = 0 98 | packet_obj = self.serialPort.read(64) 99 | packet_num = int.from_bytes(packet_obj[:4], 'big') 100 | checksum = int.from_bytes(packet_obj[60:], 'big') 101 | data = packet_obj[4:60] 102 | crc = zlib.crc32(data) & 0xffffffff 103 | if (crc == checksum or crc == checksum + 1 or crc == checksum - 1) and packet_num == 0: 104 | self.packets_to_receive = int.from_bytes(data[0:4], 'big') 105 | self.zero_padding = int.from_bytes(data[4:5], 'big') 106 | file_ext = [] 107 | for bit in packet_obj[5:]: 108 | if bit != b'0': 109 | file_ext.append(bit) 110 | else: 111 | pass 112 | time.sleep(.025) 113 | self.my_fsm.on_event("") 114 | self.file = open(self.file_name, "w") 115 | self.file.write('') 116 | self.file.close() 117 | self.file = open(self.file_name, "ab") 118 | self.data_loop() 119 | else: 120 | print(packet_obj) 121 | self.flag = True 122 | self.my_fsm.state = Receiver() 123 | 124 | """ 125 | This function checks to see if the data received is corrupted. If it is it notes it, otherwise it saves the data. 126 | """ 127 | def data_checker(self, data, checksum): 128 | calc_crc = zlib.crc32(data) 129 | if (checksum == calc_crc): 130 | self.packet_list = data 131 | self.file.write(data) 132 | else: 133 | self.packet_list = "ERROR" 134 | 135 | """ 136 | This function reads the data from the sent file packet by packet and sends them individually to data_checker. 137 | If there are no errors it calls finish_packet otherwise it calls resend_packet. 138 | """ 139 | def data_loop(self): 140 | packet_obj = self.serialPort.read(64) 141 | 142 | while packet_obj != b'': 143 | packet_num = int.from_bytes(packet_obj[:4], 'big') 144 | checksum = int.from_bytes(packet_obj[60:], 'big') 145 | payload = packet_obj[4:60] 146 | self.data_checker(payload, checksum) 147 | packet_obj = self.serialPort.read(64) 148 | 149 | i = 0 150 | errors = 0 151 | while i < len(self.packet_list): 152 | if self.packet_list[i] == "ERROR": 153 | errors += 1 154 | else: 155 | i += 1 156 | if errors > 0: 157 | self.resend_packet() 158 | else: 159 | self.finish_packet() 160 | 161 | self.file.close() 162 | 163 | """ 164 | Let the sender know there were no errors in the received file. 165 | """ 166 | def finish_packet(self): 167 | index = "DONE" 168 | index = bytes(index.encode('utf-8')) 169 | payload = "THIS FILE HAS BEEN RECEIVED WITH NO ERRORS" 170 | payload = bytes(payload.encode('utf-8')) 171 | padding = b'0' * 14 172 | done = payload + padding 173 | done_crc = zlib.crc32(done) & 0xffffffff 174 | done_crc = done_crc.to_bytes(4, 'big') 175 | done = index + payload + padding + done_crc 176 | self.flag = True 177 | self.my_fsm.on_event("finish") 178 | self.serialPort.write(done) 179 | 180 | """ 181 | Tell the sender which packets were corrupted. Limited to 12 packets at a time (56 data bytes / 4 index bytes) 182 | """ 183 | def resend_packet(self): 184 | index = "RESE" 185 | index = bytes(index.encode('utf-8')) 186 | error_idx = [i for i, e in enumerate(self.packet_list) if e == "ERROR"] 187 | idx_to_send = [] 188 | for idx in error_idx: 189 | idx_to_send.append(idx.to_bytes(4, 'big')) 190 | padding_size = (14 - len(idx_to_send)) * 4 191 | padding = b'0' * padding_size 192 | resend = index + idx_to_send[:-1] + padding 193 | self.flag = False 194 | self.my_fsm.on_event("resend") 195 | self.serialPort.write(resend) 196 | -------------------------------------------------------------------------------- /lib/Sender.py: -------------------------------------------------------------------------------- 1 | """ 2 | Sender.py 3 | 4 | This file contains all functions necessary for processing outgoing data. 5 | """ 6 | 7 | import math 8 | import zlib 9 | import time 10 | import os 11 | 12 | 13 | class Sender_Driver: 14 | 15 | def __init__(self, state_mach, file_name=os.path.join('..', 'files', 'out.txt'), serialPort=None): 16 | self.__packet_list = [] 17 | 18 | self.__my_fsm = state_mach 19 | self.__serialPort = serialPort 20 | 21 | self.__file_name = file_name 22 | self.__file = open(self.__file_name, 'rb') 23 | self.__file_obj = self.__file.read() 24 | self.__file_size = len(self.__file_obj) 25 | self.__packet_num = math.ceil(self.__file_size/56) 26 | self.__padding_size = 56 - (self.__file_size % 56) 27 | self.__padding = '0' * self.__padding_size 28 | self.__file_obj = self.__file_obj + self.__padding.encode('utf-8') 29 | self.__file_data = list(zip(*[iter(self.__file_obj)]*56)) 30 | 31 | # Used to restart the thread in LiFiGUI.py 32 | self.__flag = False 33 | 34 | @property 35 | def packet_list(self): 36 | return self.__packet_list 37 | 38 | @packet_list.setter 39 | def packet_list(self, data): 40 | self.__packet_list.append(data) 41 | 42 | @property 43 | def my_fsm(self): 44 | return self.__my_fsm 45 | 46 | @property 47 | def serialPort(self): 48 | return self.__serialPort 49 | 50 | @serialPort.setter 51 | def serialPort(self, port): 52 | self.__serialPort = port 53 | 54 | @property 55 | def file_name(self): 56 | return self.__file_name 57 | 58 | @file_name.setter 59 | def file_name(self, fn): 60 | self.__file_name = fn 61 | 62 | @property 63 | def file(self): 64 | return self.__file 65 | 66 | @file.setter 67 | def file(self, f): 68 | self.__file = f 69 | 70 | @property 71 | def packet_num(self): 72 | return self.__packet_num 73 | 74 | @packet_num.setter 75 | def packet_num(self, n): 76 | self.__packet_num = n 77 | 78 | @property 79 | def padding_size(self): 80 | return self.__padding_size 81 | 82 | @padding_size.setter 83 | def padding_size(self, n): 84 | self.__padding_size = n 85 | 86 | @property 87 | def file_data(self): 88 | return self.__file_data 89 | 90 | @file_data.setter 91 | def file_data(self, fn): 92 | self.__file_data = fn 93 | 94 | @property 95 | def flag(self): 96 | return self.__flag 97 | 98 | @flag.setter 99 | def flag(self, data): 100 | self.__flag = data 101 | 102 | """ 103 | This function parses a file and creates a meta packet with the total number of packets to be received (excluding 104 | the meta packet itself), the number of 0's appended to the end of the last packet, and the file extension of the 105 | file to be sent. 106 | """ 107 | def meta_creator(self): 108 | self.serialPort.reset_input_buffer() 109 | self.serialPort.reset_output_buffer() 110 | 111 | self.file = open(self.file_name, 'rb') 112 | self.file_obj = self.file.read() 113 | self.file_size = len(self.file_obj) 114 | self.packet_num = math.ceil(self.file_size / 56) 115 | self.padding_size = 56 - (self.file_size % 56) 116 | self.padding = '0' * self.padding_size 117 | self.file_obj = self.file_obj + self.padding.encode('utf-8') 118 | self.file_data = list(zip(*[iter(self.file_obj)] * 56)) 119 | index = 0 120 | file_name = self.file_name 121 | index = index.to_bytes(4, 'big') 122 | param_1 = self.packet_num.to_bytes(4, 'big') 123 | param_2 = self.padding_size.to_bytes(1, 'big') 124 | # TODO: Better implementation of this 125 | junk, file_extension = os.path.splitext(file_name) 126 | param_3 = bytes(file_extension.encode('utf-8')) 127 | param_3 = int.from_bytes(param_3, 'big') 128 | param_3 = param_3.to_bytes(10, 'big') 129 | padding = b'0' * 41 130 | meta = param_1 + param_2 + param_3 + padding 131 | meta_crc = zlib.crc32(meta) & 0xffffffff 132 | meta_crc = meta_crc.to_bytes(4, 'big') 133 | meta = index + param_1 + param_2 + param_3 + padding + meta_crc 134 | self.serialPort.write(meta) 135 | self.my_fsm.on_event("") 136 | self.packet_loop() 137 | 138 | # Packet Creator adding 4 bytes index to 56 bytes of data and 4 byte checksum 139 | def packet_creator(self, counter): 140 | data = self.file_data[counter] 141 | data_byte = bytes(data) 142 | counter += 1 143 | index = counter.to_bytes(4, 'big') 144 | data_crc = zlib.crc32(data_byte) & 0xffffffff 145 | data_crc = data_crc.to_bytes(4, 'big') 146 | packet = index + data_byte + data_crc 147 | self.packet_list = packet 148 | return packet 149 | 150 | """ 151 | For every 56 bytes in the file, call packet_creator. Sleep for a short time so that the driver has time 152 | to receive a finish or resend packet. 153 | """ 154 | def packet_loop(self): 155 | i = 0 156 | while i < self.packet_num: 157 | out_packet = self.packet_creator(i) 158 | self.serialPort.write(out_packet) 159 | i += 1 160 | 161 | time.sleep(max(self.file_size/4000,.25)) 162 | self.my_fsm.on_event("") 163 | self.file.close() 164 | 165 | self.check_finish() 166 | 167 | """ 168 | This function reads the incoming data and checks if it is a valid resend or finish packet. If it is 169 | it handles it accordingly. Finish -> Receiver State | Resend -> Send_Data State 170 | """ 171 | def check_finish(self): 172 | counter = 0 173 | packet_checker = self.serialPort.read(64) 174 | packet_num = packet_checker[:4] 175 | packet_num = packet_num.decode("utf-8") 176 | checksum = int.from_bytes(packet_checker[60:], 'big') 177 | data = packet_checker[4:60] 178 | crc = zlib.crc32(data) & 0xffffffff 179 | 180 | if (crc == checksum or crc == checksum + 1 or crc == checksum - 1) and packet_num == "DONE": 181 | self.my_fsm.on_event('finish') 182 | self.flag = True 183 | 184 | elif (crc == checksum or crc == checksum + 1 or crc == checksum - 1) and packet_num == "RESE": 185 | self.my_fsm.on_event('resend') 186 | self.flag = False 187 | while data: 188 | idx = int.from_bytes(data[:4], 'big') 189 | del data[:4] 190 | if idx == 0: 191 | pass 192 | else: 193 | self.packet_creator(idx-1) 194 | 195 | else: 196 | while counter < 3: 197 | time.sleep(1) 198 | counter += 1 199 | else: 200 | self.my_fsm.on_event("timeout") 201 | self.flag = True 202 | -------------------------------------------------------------------------------- /firmware/lib/DueTimer/DueTimer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | DueTimer.cpp - Implementation of Timers defined on DueTimer.h 3 | For instructions, go to https://github.com/ivanseidel/DueTimer 4 | 5 | Created by Ivan Seidel Gomes, March, 2013. 6 | Modified by Philipp Klaus, June 2013. 7 | Thanks to stimmer (from Arduino forum), for coding the "timer soul" (Register stuff) 8 | Released into the public domain. 9 | */ 10 | 11 | #include 12 | #if defined(_SAM3XA_) 13 | #include "DueTimer.h" 14 | 15 | const DueTimer::Timer DueTimer::Timers[NUM_TIMERS] = { 16 | {TC0,0,TC0_IRQn}, 17 | {TC0,1,TC1_IRQn}, 18 | {TC0,2,TC2_IRQn}, 19 | {TC1,0,TC3_IRQn}, 20 | {TC1,1,TC4_IRQn}, 21 | {TC1,2,TC5_IRQn}, 22 | {TC2,0,TC6_IRQn}, 23 | {TC2,1,TC7_IRQn}, 24 | {TC2,2,TC8_IRQn}, 25 | }; 26 | 27 | // Fix for compatibility with Servo library 28 | #ifdef USING_SERVO_LIB 29 | // Set callbacks as used, allowing DueTimer::getAvailable() to work 30 | void (*DueTimer::callbacks[NUM_TIMERS])() = { 31 | (void (*)()) 1, // Timer 0 - Occupied 32 | (void (*)()) 0, // Timer 1 33 | (void (*)()) 1, // Timer 2 - Occupied 34 | (void (*)()) 1, // Timer 3 - Occupied 35 | (void (*)()) 1, // Timer 4 - Occupied 36 | (void (*)()) 1, // Timer 5 - Occupied 37 | (void (*)()) 0, // Timer 6 38 | (void (*)()) 0, // Timer 7 39 | (void (*)()) 0 // Timer 8 40 | }; 41 | #else 42 | void (*DueTimer::callbacks[NUM_TIMERS])() = {}; 43 | #endif 44 | double DueTimer::_frequency[NUM_TIMERS] = {-1,-1,-1,-1,-1,-1,-1,-1,-1}; 45 | 46 | /* 47 | Initializing all timers, so you can use them like this: Timer0.start(); 48 | */ 49 | DueTimer Timer(0); 50 | 51 | DueTimer Timer1(1); 52 | // Fix for compatibility with Servo library 53 | #ifndef USING_SERVO_LIB 54 | DueTimer Timer0(0); 55 | DueTimer Timer2(2); 56 | DueTimer Timer3(3); 57 | DueTimer Timer4(4); 58 | DueTimer Timer5(5); 59 | #endif 60 | DueTimer Timer6(6); 61 | DueTimer Timer7(7); 62 | DueTimer Timer8(8); 63 | 64 | DueTimer::DueTimer(unsigned short _timer) : timer(_timer){ 65 | /* 66 | The constructor of the class DueTimer 67 | */ 68 | } 69 | 70 | DueTimer DueTimer::getAvailable(void){ 71 | /* 72 | Return the first timer with no callback set 73 | */ 74 | 75 | for(int i = 0; i < NUM_TIMERS; i++){ 76 | if(!callbacks[i]) 77 | return DueTimer(i); 78 | } 79 | // Default, return Timer0; 80 | return DueTimer(0); 81 | } 82 | 83 | DueTimer& DueTimer::attachInterrupt(void (*isr)()){ 84 | /* 85 | Links the function passed as argument to the timer of the object 86 | */ 87 | 88 | callbacks[timer] = isr; 89 | 90 | return *this; 91 | } 92 | 93 | DueTimer& DueTimer::detachInterrupt(void){ 94 | /* 95 | Links the function passed as argument to the timer of the object 96 | */ 97 | 98 | stop(); // Stop the currently running timer 99 | 100 | callbacks[timer] = NULL; 101 | 102 | return *this; 103 | } 104 | 105 | DueTimer& DueTimer::start(long microseconds){ 106 | /* 107 | Start the timer 108 | If a period is set, then sets the period and start the timer 109 | */ 110 | 111 | if(microseconds > 0) 112 | setPeriod(microseconds); 113 | 114 | if(_frequency[timer] <= 0) 115 | setFrequency(1); 116 | 117 | NVIC_ClearPendingIRQ(Timers[timer].irq); 118 | NVIC_EnableIRQ(Timers[timer].irq); 119 | 120 | TC_Start(Timers[timer].tc, Timers[timer].channel); 121 | 122 | return *this; 123 | } 124 | 125 | DueTimer& DueTimer::stop(void){ 126 | /* 127 | Stop the timer 128 | */ 129 | 130 | NVIC_DisableIRQ(Timers[timer].irq); 131 | 132 | TC_Stop(Timers[timer].tc, Timers[timer].channel); 133 | 134 | return *this; 135 | } 136 | 137 | uint8_t DueTimer::bestClock(double frequency, uint32_t& retRC){ 138 | /* 139 | Pick the best Clock, thanks to Ogle Basil Hall! 140 | 141 | Timer Definition 142 | TIMER_CLOCK1 MCK / 2 143 | TIMER_CLOCK2 MCK / 8 144 | TIMER_CLOCK3 MCK / 32 145 | TIMER_CLOCK4 MCK /128 146 | */ 147 | const struct { 148 | uint8_t flag; 149 | uint8_t divisor; 150 | } clockConfig[] = { 151 | { TC_CMR_TCCLKS_TIMER_CLOCK1, 2 }, 152 | { TC_CMR_TCCLKS_TIMER_CLOCK2, 8 }, 153 | { TC_CMR_TCCLKS_TIMER_CLOCK3, 32 }, 154 | { TC_CMR_TCCLKS_TIMER_CLOCK4, 128 } 155 | }; 156 | float ticks; 157 | float error; 158 | int clkId = 3; 159 | int bestClock = 3; 160 | float bestError = 9.999e99; 161 | do 162 | { 163 | ticks = (float) VARIANT_MCK / frequency / (float) clockConfig[clkId].divisor; 164 | // error = abs(ticks - round(ticks)); 165 | error = clockConfig[clkId].divisor * abs(ticks - round(ticks)); // Error comparison needs scaling 166 | if (error < bestError) 167 | { 168 | bestClock = clkId; 169 | bestError = error; 170 | } 171 | } while (clkId-- > 0); 172 | ticks = (float) VARIANT_MCK / frequency / (float) clockConfig[bestClock].divisor; 173 | retRC = (uint32_t) round(ticks); 174 | return clockConfig[bestClock].flag; 175 | } 176 | 177 | 178 | DueTimer& DueTimer::setFrequency(double frequency){ 179 | /* 180 | Set the timer frequency (in Hz) 181 | */ 182 | 183 | // Prevent negative frequencies 184 | if(frequency <= 0) { frequency = 1; } 185 | 186 | // Remember the frequency — see below how the exact frequency is reported instead 187 | //_frequency[timer] = frequency; 188 | 189 | // Get current timer configuration 190 | Timer t = Timers[timer]; 191 | 192 | uint32_t rc = 0; 193 | uint8_t clock; 194 | 195 | // Tell the Power Management Controller to disable 196 | // the write protection of the (Timer/Counter) registers: 197 | pmc_set_writeprotect(false); 198 | 199 | // Enable clock for the timer 200 | pmc_enable_periph_clk((uint32_t)t.irq); 201 | 202 | // Find the best clock for the wanted frequency 203 | clock = bestClock(frequency, rc); 204 | 205 | switch (clock) { 206 | case TC_CMR_TCCLKS_TIMER_CLOCK1: 207 | _frequency[timer] = (double)VARIANT_MCK / 2.0 / (double)rc; 208 | break; 209 | case TC_CMR_TCCLKS_TIMER_CLOCK2: 210 | _frequency[timer] = (double)VARIANT_MCK / 8.0 / (double)rc; 211 | break; 212 | case TC_CMR_TCCLKS_TIMER_CLOCK3: 213 | _frequency[timer] = (double)VARIANT_MCK / 32.0 / (double)rc; 214 | break; 215 | default: // TC_CMR_TCCLKS_TIMER_CLOCK4 216 | _frequency[timer] = (double)VARIANT_MCK / 128.0 / (double)rc; 217 | break; 218 | } 219 | 220 | // Set up the Timer in waveform mode which creates a PWM 221 | // in UP mode with automatic trigger on RC Compare 222 | // and sets it up with the determined internal clock as clock input. 223 | TC_Configure(t.tc, t.channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | clock); 224 | // Reset counter and fire interrupt when RC value is matched: 225 | TC_SetRC(t.tc, t.channel, rc); 226 | // Enable the RC Compare Interrupt... 227 | t.tc->TC_CHANNEL[t.channel].TC_IER=TC_IER_CPCS; 228 | // ... and disable all others. 229 | t.tc->TC_CHANNEL[t.channel].TC_IDR=~TC_IER_CPCS; 230 | 231 | return *this; 232 | } 233 | 234 | DueTimer& DueTimer::setPeriod(unsigned long microseconds){ 235 | /* 236 | Set the period of the timer (in microseconds) 237 | */ 238 | 239 | // Convert period in microseconds to frequency in Hz 240 | double frequency = 1000000.0 / microseconds; 241 | setFrequency(frequency); 242 | return *this; 243 | } 244 | 245 | double DueTimer::getFrequency(void) const { 246 | /* 247 | Get current time frequency 248 | */ 249 | 250 | return _frequency[timer]; 251 | } 252 | 253 | long DueTimer::getPeriod(void) const { 254 | /* 255 | Get current time period 256 | */ 257 | 258 | return 1.0/getFrequency()*1000000; 259 | } 260 | 261 | 262 | /* 263 | Implementation of the timer callbacks defined in 264 | arduino-1.5.2/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/include/sam3x8e.h 265 | */ 266 | // Fix for compatibility with Servo library 267 | #ifndef USING_SERVO_LIB 268 | void TC0_Handler(void){ 269 | TC_GetStatus(TC0, 0); 270 | DueTimer::callbacks[0](); 271 | } 272 | #endif 273 | void TC1_Handler(void){ 274 | TC_GetStatus(TC0, 1); 275 | DueTimer::callbacks[1](); 276 | } 277 | // Fix for compatibility with Servo library 278 | #ifndef USING_SERVO_LIB 279 | void TC2_Handler(void){ 280 | TC_GetStatus(TC0, 2); 281 | DueTimer::callbacks[2](); 282 | } 283 | void TC3_Handler(void){ 284 | TC_GetStatus(TC1, 0); 285 | DueTimer::callbacks[3](); 286 | } 287 | void TC4_Handler(void){ 288 | TC_GetStatus(TC1, 1); 289 | DueTimer::callbacks[4](); 290 | } 291 | void TC5_Handler(void){ 292 | TC_GetStatus(TC1, 2); 293 | DueTimer::callbacks[5](); 294 | } 295 | #endif 296 | void TC6_Handler(void){ 297 | TC_GetStatus(TC2, 0); 298 | DueTimer::callbacks[6](); 299 | } 300 | void TC7_Handler(void){ 301 | TC_GetStatus(TC2, 1); 302 | DueTimer::callbacks[7](); 303 | } 304 | void TC8_Handler(void){ 305 | TC_GetStatus(TC2, 2); 306 | DueTimer::callbacks[8](); 307 | } 308 | #endif 309 | -------------------------------------------------------------------------------- /firmware/lib/Arduino-GPIO/src/Hardware/AVR/Board.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Board.h 3 | * @version 1.6 4 | * 5 | * @section License 6 | * Copyright (C) 2017, Mikael Patel 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | */ 18 | 19 | #ifndef HARDWARE_AVR_BOARD_H 20 | #define HARDWARE_AVR_BOARD_H 21 | 22 | /** 23 | * Board pin values are bit-pointers and constructed from port control 24 | * register address and pin bit position. 25 | * @param[in] port control register address. 26 | * @param[in] pin pin bit position in control register. 27 | */ 28 | #define GPIO_PIN(port,pin) (((port) << 4) | (pin)) 29 | 30 | /** 31 | * Return port control register address from board pin value. 32 | * @return io port address 33 | */ 34 | #define GPIO_REG(pin) ((pin) >> 4) 35 | 36 | /** 37 | * Return pin mask from board pin value. 38 | * @return pin mask 39 | */ 40 | #define GPIO_MASK(pin) _BV((pin) & 0xf) 41 | 42 | /** Maximum port control register address for atomic bit instructions. */ 43 | #define GPIO_ATOMIC_MAX GPIO_PIN(0x40,0) 44 | 45 | /** 46 | * Forces given expression to be atomic. Higher port addresses 47 | * cannot be accessed with a single instruction and require 48 | * disabling of interrupts to become atomic. 49 | * @param[in] expr expression to be atomic. 50 | */ 51 | #define GPIO_ATOMIC(expr) \ 52 | do { \ 53 | if (PIN < GPIO_ATOMIC_MAX) { \ 54 | expr; \ 55 | } \ 56 | else { \ 57 | uint8_t sreg = SREG; \ 58 | __asm__ __volatile__("cli" ::: "memory"); \ 59 | expr; \ 60 | SREG = sreg; \ 61 | __asm__ __volatile__("" ::: "memory"); \ 62 | } \ 63 | } while (0) 64 | 65 | #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) 66 | /** 67 | * GPIO digital pin symbols for ATmega168/ATmega328P based boards. 68 | * @section Board 69 | * @code 70 | * Arduino Uno 71 | * ----- ------- 72 | * +-|(o)|--------------------| USB |---+ 73 | * | | | | | | 74 | * | ----- | | | 75 | * | ------- | 76 | * | | 77 | * | []| SCL 78 | * | []| SDA 79 | * | []| AREF 80 | * | []| GND 81 | * NC |[] []| D13/SCK 82 | * IOREF |[] []| D12/MISO 83 | * RESET |[] []| D11/MOSI 84 | * 3V3 |[] []| D10/SS 85 | * 5V |[] []| D9 86 | * GND |[] []| D8 87 | * GND |[] | 88 | * Vin |[] []| D7 89 | * | []| D6 90 | * A0/D14 |[] []| D5 91 | * A1/D15 |[] []| D4 92 | * A2/D16 |[] []| D3 93 | * A3/D17 |[] []| D2 94 | * SDA/A4/D18 |[] []| D1 95 | * SCL/A5/D19 |[] ICSP []| D0 96 | * | [o-o-*] +-------+ 97 | * \ [o-o-o] / 98 | * +------------------------+ 99 | * @endcode 100 | */ 101 | class BOARD { 102 | public: 103 | enum pin_t { 104 | D0 = GPIO_PIN(0x29,0), //!< PIND:0 105 | D1 = GPIO_PIN(0x29,1), //!< PIND:1 106 | D2 = GPIO_PIN(0x29,2), //!< PIND:2 107 | D3 = GPIO_PIN(0x29,3), //!< PIND:3 108 | D4 = GPIO_PIN(0x29,4), //!< PIND:4 109 | D5 = GPIO_PIN(0x29,5), //!< PIND:5 110 | D6 = GPIO_PIN(0x29,6), //!< PIND:6 111 | D7 = GPIO_PIN(0x29,7), //!< PIND:7 112 | 113 | D8 = GPIO_PIN(0x23,0), //!< PINB:0 114 | D9 = GPIO_PIN(0x23,1), //!< PINB:1 115 | D10 = GPIO_PIN(0x23,2), //!< PINB:2/SS 116 | D11 = GPIO_PIN(0x23,3), //!< PINB:3/MOSI/ICSP.4 117 | D12 = GPIO_PIN(0x23,4), //!< PINB:4/MISO/ICSP.1 118 | D13 = GPIO_PIN(0x23,5), //!< PINB:5/SCK/ICSP.3 119 | 120 | D14 = GPIO_PIN(0x26,0), //!< PINC:0/A0 121 | D15 = GPIO_PIN(0x26,1), //!< PINC:1/A1 122 | D16 = GPIO_PIN(0x26,2), //!< PINC:2/A2 123 | D17 = GPIO_PIN(0x26,3), //!< PINC:3/A3 124 | D18 = GPIO_PIN(0x26,4), //!< PINC:4/A4/SDA 125 | D19 = GPIO_PIN(0x26,5), //!< PINC:5/A5/SCL 126 | 127 | SS = D10, //!< SPI Slave Select 128 | MOSI = D11, //!< SPI Master Output Slave Input 129 | MISO = D12, //!< SPI Master Input Slave Output 130 | SCK = D13, //!< SPI Clock 131 | 132 | SDA = D18, //!< TWI Data 133 | SCL = D19 //!< TWI Clock 134 | }; 135 | }; 136 | #elif defined(__AVR_ATmega32U4__) 137 | /** 138 | * GPIO digital pin symbols for ATmega32U4 based boards. 139 | * @section Board 140 | * @code 141 | * Arduino Leonardo 142 | * ----- ----- 143 | * +-|(o)|---------------------|USB|----+ 144 | * | | | | | | 145 | * | ----- ----- | 146 | * | | 147 | * | | 148 | * | []| SCL 149 | * | []| SDA 150 | * | []| AREF 151 | * | []| GND 152 | * NC |[] []| D13/ 153 | * IOREF |[] []| D12/A7 154 | * RESET |[] []| D11 155 | * 3V3 |[] []| D10 156 | * 5V |[] []| D9 157 | * GND |[] []| D8 158 | * GND |[] | 159 | * Vin |[] []| D7 160 | * | []| D6 161 | * A0/D14 |[] []| D5 162 | * A1/D15 |[] []| D4 163 | * A2/D16 |[] []| D3/SCL 164 | * A3/D17 |[] []| D2/SDA 165 | * A4/D18 |[] []| D1 166 | * A5/D19 |[] ICSP []| D0 167 | | [o-o-*] +-------+ 168 | * \ [o-o-o] / 169 | * +------------------------+ 170 | * @endcode 171 | * @section ICSP 172 | * The SPI pins (on ICSP) are also numbered as digital pins. SPI SS 173 | * is used for the RX LED. 174 | * @code 175 | * ICSP 176 | * +----+ 177 | * MISO/D20 |* o| VCC 178 | * SCK/D21 |o o| D22/MOSI 179 | * RESET |o o| GND 180 | * +----+ 181 | * @endcode 182 | */ 183 | class BOARD { 184 | public: 185 | enum pin_t { 186 | D0 = GPIO_PIN(0x29,2), //!< PIND:2 187 | D1 = GPIO_PIN(0x29,3), //!< PIND:3 188 | D2 = GPIO_PIN(0x29,1), //!< PIND:1/SDA 189 | D3 = GPIO_PIN(0x29,0), //!< PIND:0/SCL 190 | D4 = GPIO_PIN(0x29,4), //!< PIND:4 191 | D5 = GPIO_PIN(0x26,6), //!< PINC:6 192 | D6 = GPIO_PIN(0x29,7), //!< PIND:7 193 | D7 = GPIO_PIN(0x2c,6), //!< PINE:6 194 | 195 | D8 = GPIO_PIN(0x23,4), //!< PINB:4 196 | D9 = GPIO_PIN(0x23,5), //!< PINB:5 197 | D10 = GPIO_PIN(0x23,6), //!< PINB:6 198 | D11 = GPIO_PIN(0x23,7), //!< PINB:7 199 | D12 = GPIO_PIN(0x29,6), //!< PIND:6 200 | D13 = GPIO_PIN(0x26,7), //!< PINC:7 201 | 202 | D14 = GPIO_PIN(0x2f,7), //!< PINF:7/A0 203 | D15 = GPIO_PIN(0x2f,6), //!< PINF:6/A1 204 | D16 = GPIO_PIN(0x2f,5), //!< PINF:5/A2 205 | D17 = GPIO_PIN(0x2f,4), //!< PINF:4/A3 206 | D18 = GPIO_PIN(0x2f,1), //!< PINF:1/A4 207 | D19 = GPIO_PIN(0x2f,0), //!< PINF:0/A5 208 | 209 | D20 = GPIO_PIN(0x23,0), //!< PINB:0/SS/RXLED 210 | D21 = GPIO_PIN(0x23,2), //!< PINB:2/MOSI/ICSP.4 211 | D22 = GPIO_PIN(0x23,3), //!< PINB:3/MISO/ICSP.1 212 | D23 = GPIO_PIN(0x23,1), //!< PINB:1/SCK/ICSP.3 213 | 214 | SS = D20, //!< SPI Slave Select 215 | MOSI = D22, //!< SPI Master Output Slave Input 216 | MISO = D20, //!< SPI Master Input Slave Output 217 | SCK = D21, //!< SPI Clock 218 | 219 | SDA = D2, //!< TWI Data 220 | SCL = D3 //!< TWI Clock 221 | }; 222 | }; 223 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 224 | /** 225 | * GPIO digital pin symbols for ATmega1280/ATmega2560 based boards. 226 | * @section Board 227 | * @code 228 | * Arduino Mega 229 | * ----- ------- 230 | * +-|(o)|--------------------| USB |---+ 231 | * | | | | | | 232 | * | ----- | | | 233 | * | ------- | 234 | * | | 235 | * | []| SCL 236 | * | []| SDA 237 | * | []| AREF 238 | * | []| GND 239 | * NC |[] []| D13 240 | * IOREF |[] []| D12 241 | * RESET |[] []| D11 242 | * 3V3 |[] []| D10 243 | * 5V |[] []| D9 244 | * GND |[] []| D8 245 | * GND |[] | 246 | * Vin |[] []| D7 247 | * | []| D6 248 | * A0 |[] []| D5 249 | * A1 |[] []| D4 250 | * A2 |[] []| D3 251 | * A3 |[] []| D2 252 | * A4 |[] ICSP []| D1 253 | * A5 |[] [o-o-*] []| D0 254 | * A6 |[] [o-o-o] | 255 | * A7 |[] []| D14 256 | * | []| D15 257 | * A8 |[] []| D16 258 | * A9 |[] []| D17 259 | * A10 |[] []| D18 260 | * A11 |[] []| D19 261 | * A12 |[] []| D20/SDA 262 | * A13 |[] []| D21/SCL 263 | * A14 |[] | 264 | * A15 |[]52 30 22 | 265 | * GND |[][][][][][][][][][][][][][][][][][]| 5V 266 | * GND |[][][][][][][][][][][][][][][][][][]| 5V 267 | * \ 53 31 / 268 | * +------------------------+ 269 | * @endcode 270 | */ 271 | class BOARD { 272 | public: 273 | enum pin_t { 274 | D0 = GPIO_PIN(0x2c,0), //!< PINE:0 275 | D1 = GPIO_PIN(0x2c,1), //!< PINE:1 276 | D2 = GPIO_PIN(0x2c,4), //!< PINE:4 277 | D3 = GPIO_PIN(0x2c,5), //!< PINE:5 278 | D4 = GPIO_PIN(0x32,5), //!< PING:5 279 | D5 = GPIO_PIN(0x2c,3), //!< PINE:3 280 | D6 = GPIO_PIN(0x100,3), //!< PINH:3 281 | D7 = GPIO_PIN(0x100,4), //!< PINH:4 282 | 283 | D8 = GPIO_PIN(0x100,5), //!< PINH:5 284 | D9 = GPIO_PIN(0x100,6), //!< PINH:6 285 | D10 = GPIO_PIN(0x23,4), //!< PINB:4 286 | D11 = GPIO_PIN(0x23,5), //!< PINB:5 287 | D12 = GPIO_PIN(0x23,6), //!< PINB:6 288 | D13 = GPIO_PIN(0x23,7), //!< PINB:7 289 | 290 | D14 = GPIO_PIN(0x103,1), //!< PINJ:1 291 | D15 = GPIO_PIN(0x103,0), //!< PINJ:0 292 | D16 = GPIO_PIN(0x100,1), //!< PINH:1 293 | D17 = GPIO_PIN(0x100,0), //!< PINH:0 294 | D18 = GPIO_PIN(0x29,3), //!< PIND:3 295 | D19 = GPIO_PIN(0x29,2), //!< PIND:2 296 | D20 = GPIO_PIN(0x29,1), //!< PIND:1 297 | D21 = GPIO_PIN(0x29,0), //!< PIND:0 298 | 299 | D22 = GPIO_PIN(0x20,0), //!< PINA:0 300 | D23 = GPIO_PIN(0x20,1), //!< PINA:1 301 | D24 = GPIO_PIN(0x20,2), //!< PINA:2 302 | D25 = GPIO_PIN(0x20,3), //!< PINA:3 303 | D26 = GPIO_PIN(0x20,4), //!< PINA:4 304 | D27 = GPIO_PIN(0x20,5), //!< PINA:5 305 | D28 = GPIO_PIN(0x20,6), //!< PINA:6 306 | D29 = GPIO_PIN(0x20,7), //!< PINA:7 307 | D30 = GPIO_PIN(0x26,7), //!< PINC:7 308 | D31 = GPIO_PIN(0x26,6), //!< PINC:6 309 | D32 = GPIO_PIN(0x26,5), //!< PINC:5 310 | D33 = GPIO_PIN(0x26,4), //!< PINC:4 311 | D34 = GPIO_PIN(0x26,3), //!< PINC:3 312 | D35 = GPIO_PIN(0x26,2), //!< PINC:2 313 | D36 = GPIO_PIN(0x26,1), //!< PINC:1 314 | D37 = GPIO_PIN(0x26,0), //!< PINC:0 315 | D38 = GPIO_PIN(0x29,7), //!< PIND:7 316 | D39 = GPIO_PIN(0x32,2), //!< PING:2 317 | D40 = GPIO_PIN(0x32,1), //!< PING:1 318 | D41 = GPIO_PIN(0x32,0), //!< PING:0 319 | D42 = GPIO_PIN(0x109,7), //!< PINL:7 320 | D43 = GPIO_PIN(0x109,6), //!< PINL:6 321 | D44 = GPIO_PIN(0x109,5), //!< PINL:5 322 | D45 = GPIO_PIN(0x109,4), //!< PINL:4 323 | D46 = GPIO_PIN(0x109,3), //!< PINL:3 324 | D47 = GPIO_PIN(0x109,2), //!< PINL:2 325 | D48 = GPIO_PIN(0x109,1), //!< PINL:1 326 | D49 = GPIO_PIN(0x109,0), //!< PINL:0 327 | D50 = GPIO_PIN(0x23,3), //!< PINB:3/MISO/ICSP.1 328 | D51 = GPIO_PIN(0x23,2), //!< PINB:2/MOSI/ICSP.3 329 | D52 = GPIO_PIN(0x23,1), //!< PINB:1/SCK/ICSP.4 330 | D53 = GPIO_PIN(0x23,0), //!< PINB:0/SS 331 | 332 | D54 = GPIO_PIN(0x2f,0), //!< PINF:0/A0 333 | D55 = GPIO_PIN(0x2f,1), //!< PINF:1/A1 334 | D56 = GPIO_PIN(0x2f,2), //!< PINF:2/A2 335 | D57 = GPIO_PIN(0x2f,3), //!< PINF:3/A3 336 | D58 = GPIO_PIN(0x2f,4), //!< PINF:4/A4 337 | D59 = GPIO_PIN(0x2f,5), //!< PINF:5/A5 338 | D60 = GPIO_PIN(0x2f,6), //!< PINF:6/A6 339 | D61 = GPIO_PIN(0x2f,7), //!< PINF:7/A7 340 | 341 | D62 = GPIO_PIN(0x106,0), //!< PINK:0/A8 342 | D63 = GPIO_PIN(0x106,1), //!< PINK:1/A9 343 | D64 = GPIO_PIN(0x106,2), //!< PINK:2/A10 344 | D65 = GPIO_PIN(0x106,3), //!< PINK:3/A11 345 | D66 = GPIO_PIN(0x106,4), //!< PINK:4/A12 346 | D67 = GPIO_PIN(0x106,5), //!< PINK:5/A13 347 | D68 = GPIO_PIN(0x106,6), //!< PINK:6/A14 348 | D69 = GPIO_PIN(0x106,7), //!< PINK:7/A15 349 | 350 | SS = D53, //!< SPI Slave Select 351 | MOSI = D51, //!< SPI Master Output Slave Input 352 | MISO = D50, //!< SPI Master Input Slave Output 353 | SCK = D52, //!< SPI Clock 354 | 355 | SDA = D20, //!< TWI Data 356 | SCL = D21 //!< TWI Clock 357 | }; 358 | }; 359 | #elif defined(__AVR_ATtiny24__) \ 360 | || defined(__AVR_ATtiny44__) \ 361 | || defined(__AVR_ATtiny84__) 362 | /** 363 | * GPIO digital pin symbols for ATtinyX4 based boards. 364 | * @section Circuit 365 | * @code 366 | * ATinyX4 367 | * +----U----+ 368 | * (VCC)-------------1-|VCC GND|-14------------(GND) 369 | * (D8)--------------2-|PB0 PA0|-13----------(D0/A0) 370 | * (D9)--------------3-|PB1 PA1|-12----------(D1/A1) 371 | * (/RESET)----------4-|PB3 PA2|-11----------(D2/A2) 372 | * (D10).....--------5-|PB2 PA3|-10-------(D3/A3/SS) 373 | * (D7/A7)-----------6-|PA7 PA4|-9---(D4/A4/SCL/SCK) 374 | * (MISO/SDA/D6/A6)--7-|PA6 PA5|-8------(D5/A5/MOSI) 375 | * +---------+ 376 | * @endcode 377 | */ 378 | class BOARD { 379 | public: 380 | enum pin_t { 381 | D0 = GPIO_PIN(0x39,0), //!< PINA:0/A0 382 | D1 = GPIO_PIN(0x39,1), //!< PINA:1/A1 383 | D2 = GPIO_PIN(0x39,2), //!< PINA:2/A2 384 | D3 = GPIO_PIN(0x39,3), //!< PINA:3/A3/SS 385 | D4 = GPIO_PIN(0x39,4), //!< PINA:4/A4/SCL/SCK 386 | D5 = GPIO_PIN(0x39,5), //!< PINA:5/A5/MOSI 387 | D6 = GPIO_PIN(0x39,6), //!< PINA:6/A6/MISO/SDA 388 | D7 = GPIO_PIN(0x39,7), //!< PINA:7/A7 389 | D8 = GPIO_PIN(0x36,2), //!< PINB:2 390 | D9 = GPIO_PIN(0x36,1), //!< PINB:1 391 | D10 = GPIO_PIN(0x36,0), //!< PINB:0 392 | 393 | SS = D3, //!< SPI Slave Select 394 | MOSI = D5, //!< SPI Master Output Slave Input 395 | MISO = D6, //!< SPI Master Input Slave Output 396 | SCK = D4 //!< SPI Clock 397 | }; 398 | }; 399 | #elif defined(__AVR_ATtiny25__) \ 400 | || defined(__AVR_ATtiny45__) \ 401 | || defined(__AVR_ATtiny85__) 402 | /** 403 | * GPIO digital pin symbols for ATtinyX5 based boards. 404 | * @section Circuit 405 | * @code 406 | * ATinyX5 407 | * +----U----+ 408 | * (/RESET)----------1-|PB5 VCC|-8-----------------(VCC) 409 | * (D3/A3)-----------2-|PB3 PB2|-7-------(D2/A1/SCL/SCK) 410 | * (D4/A2)-----------3-|PB4 PB1|-6-------------(D1/MOSI) 411 | * (GND)-------------4-|GND PB0|-5---------(D0/SDA/MISO) 412 | * +---------+ 413 | * @endcode 414 | */ 415 | class BOARD { 416 | public: 417 | enum pin_t { 418 | D0 = GPIO_PIN(0x36,0), //!< PINB:0/SDA/MISO 419 | D1 = GPIO_PIN(0x36,1), //!< PINB:1/MOSI 420 | D2 = GPIO_PIN(0x36,2), //!< PINB:2/A1/SCL/SCK 421 | D3 = GPIO_PIN(0x36,3), //!< PINB:3/A3 422 | D4 = GPIO_PIN(0x36,4), //!< PINB:4/A2 423 | D5 = GPIO_PIN(0x36,5), //!< PINB:5/A0 424 | 425 | SS = D3, //!< SPI Slave Select 426 | MOSI = D1, //!< SPI Master Output Slave Input 427 | MISO = D0, //!< SPI Master Input Slave Output 428 | SCK = D2 //!< SPI Clock 429 | }; 430 | }; 431 | #else 432 | #error Board.h: avr mcu not supported 433 | #endif 434 | #endif 435 | --------------------------------------------------------------------------------