first commit
This commit is contained in:
21
libraries/TinySuite/LICENSE
Normal file
21
libraries/TinySuite/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Alex079
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
149
libraries/TinySuite/README.md
Normal file
149
libraries/TinySuite/README.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# TinySuite
|
||||
|
||||
A collection of utilities for ATTiny85.
|
||||
|
||||
## Pin change interrupt
|
||||
|
||||
### [TinyPinChangeB](src/TinyPinChangeB.h)
|
||||
|
||||
The implementation of ATTiny85 port B pin change interrupt handler.
|
||||
|
||||
This header exposes an object **PinChangeB** of class [TinyPinChange](src/TinyPinChange.h).
|
||||
|
||||
## External interrupt
|
||||
|
||||
### [TinyExternalInterrupt0](src/TinyExternalInterrupt0.h)
|
||||
|
||||
The implementation of ATTiny85 external interrupt handler.
|
||||
|
||||
This header exposes an object **ExternalInterrupt0** of class [TinyExternalInterrupt](src/TinyExternalInterrupt.h).
|
||||
|
||||
[Example](examples/external-interrupt/main.cpp)
|
||||
|
||||
## Timer interrupt
|
||||
|
||||
### [TinyTimer0Compare](src/TinyTimer0Compare.h)
|
||||
|
||||
The implementation of ATTiny85 Timer0 "on compare" interrupt handler.
|
||||
|
||||
This header exposes an object **Timer0Compare** of class [TinyTimer](src/TinyTimer.h).
|
||||
|
||||
### [TinyTimer0Overflow](src/TinyTimer0Overflow.h)
|
||||
|
||||
The implementation of ATTiny85 Timer0 "on overflow" interrupt handler.
|
||||
|
||||
This header exposes an object **Timer0Overflow** of class [TinyTimer](src/TinyTimer.h).
|
||||
|
||||
### [TinyTimer1Compare](src/TinyTimer1Compare.h)
|
||||
|
||||
The implementation of ATTiny85 Timer1 "on compare" interrupt handler.
|
||||
|
||||
This header exposes an object **Timer1Compare** of class [TinyTimer](src/TinyTimer.h).
|
||||
|
||||
### [TinyTimer1Overflow](src/TinyTimer1Overflow.h)
|
||||
|
||||
The implementation of ATTiny85 Timer1 "on overflow" interrupt handler.
|
||||
|
||||
This header exposes an object **Timer1Overflow** of class [TinyTimer](src/TinyTimer.h).
|
||||
|
||||
[Example](examples/timer-overflow/main.cpp)
|
||||
|
||||
## Watchdog interrupt
|
||||
|
||||
### [TinyWatchdog](src/TinyWatchdog.h)
|
||||
|
||||
The implementation of ATTiny85 Watchdog controller.
|
||||
|
||||
This header exposes an object **Watchdog** of class TinyWatchdog.
|
||||
|
||||
[Example](examples/watchdog/main.cpp)
|
||||
|
||||
## Utilities
|
||||
|
||||
### [TinySleep](src/TinySleep.h)
|
||||
|
||||
A set of shortcut defines to put the ATTiny85 in sleep mode. PRR and ADCSRA are intact.
|
||||
|
||||
This header exposes:
|
||||
|
||||
|Name|Description|
|
||||
|-|-|
|
||||
|sleep(mode)|Set the specified mode and sleep.|
|
||||
|deepSleep|Set power down mode, disable BOD, and sleep.|
|
||||
|idleSleep|Set idle mode and sleep.|
|
||||
|
||||
### [TinyBuffer](src/TinyBuffer.h)
|
||||
|
||||
The 16-byte ring buffer implementation. This implementation does not perform any validation (i.e. it is possible to "get" when "empty" and "put" when "full"), the caller is expected to maintain the buffer consistency.
|
||||
|
||||
This header exposes the class **TinyBuffer**.
|
||||
|
||||
## UART
|
||||
|
||||
### [TinyUart](src/TinyUart.h)
|
||||
|
||||
The implementation of UART protocol:
|
||||
- 8-bit value transmission
|
||||
- one start and one stop bit, no parity bit
|
||||
- no overrun / underrun / break detection
|
||||
|
||||
Features:
|
||||
- 16-byte input and 16-byte output buffers
|
||||
- full duplex transmission
|
||||
- up to 19200 baud at 16 MHz internal oscillator
|
||||
- can use any pins for RX and TX
|
||||
- can use Timer0 or Timer1
|
||||
- RX and TX are the IDs from the board definition (i.e. PB0)
|
||||
|
||||
This header exposes an object **uart** of class TinyUart.
|
||||
|
||||
[Example](examples/uart-loop/main.cpp)
|
||||
|
||||
### [TinyUartReader](src/TinyUartReader.h)
|
||||
|
||||
The implementation of receive-only UART.
|
||||
|
||||
This header exposes an object **uartReader** of class TinyUartReader.
|
||||
|
||||
[Example](examples/uart-reader/main.cpp)
|
||||
|
||||
### [TinyUartWriter](src/TinyUartWriter.h)
|
||||
|
||||
The implementation of transmit-only UART.
|
||||
|
||||
This header exposes an object **uartWriter** of class TinyUartWriter.md.
|
||||
|
||||
[Example](examples/uart-writer/main.cpp)
|
||||
|
||||
### [TinySerial](src/TinySerial.h)
|
||||
|
||||
The implementation of UART using Stream interface (Stream.h) and Tiny UART (TinyUart.h) backend.
|
||||
|
||||
This header exposes the class **TinySerial**.
|
||||
|
||||
This class inherits from Stream. See Stream.h from Arduino for details.
|
||||
|
||||
[Example](examples/uart-print/main.cpp)
|
||||
|
||||
## NMEA parser
|
||||
|
||||
### [TinyNmea](src/TinyNmea.h)
|
||||
|
||||
The NMEA sentence delegating parser implementation.
|
||||
|
||||
Features:
|
||||
- checksum validation
|
||||
- sentence filtering by type
|
||||
- delegation of value extraction to provided parsers
|
||||
- orchestration of parsing
|
||||
|
||||
This header exposes
|
||||
- NmeaParser structure
|
||||
- TinyNmea class
|
||||
|
||||
[Example](examples/nmea-time/main.cpp)
|
||||
|
||||
## Known Problems
|
||||
|
||||
- Timer0 and Timer1 may not work correctly with ATTinyCore because of the core-specific initialization.
|
||||
- UART has explicit dependency on port B registers, which makes it harder to use on other ATTinys.
|
||||
18
libraries/TinySuite/examples/external-interrupt/main.cpp
Normal file
18
libraries/TinySuite/examples/external-interrupt/main.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <avr/interrupt.h>
|
||||
#include <TinyExternalInterrupt0.h>
|
||||
#include <TinySleep.h>
|
||||
|
||||
void onInterrupt() {
|
||||
// wakeup and do something
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
sei();
|
||||
// interrupt when INT0 (pin 7) has LOW level (RISING or FALLING do not wake up from deep sleep)
|
||||
ExternalInterrupt0.on(LOW, onInterrupt);
|
||||
while (1) {
|
||||
deepSleep();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
67
libraries/TinySuite/examples/nmea-time/main.cpp
Normal file
67
libraries/TinySuite/examples/nmea-time/main.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <TinySleep.h>
|
||||
#include <TinyTimer1Compare.h>
|
||||
#include <TinyPinChangeB.h>
|
||||
#include <TinyUartReader.h>
|
||||
#include <TinyNmea.h>
|
||||
|
||||
struct NmeaData {
|
||||
bool fresh; // custom data readiness indicator
|
||||
char time[18]; // "hh:mm:ss DD/MM/YY"
|
||||
};
|
||||
|
||||
// result data holder
|
||||
NmeaData data;
|
||||
|
||||
// parser configuration array
|
||||
NmeaParser config[] = {
|
||||
// this function will be called for every term in ZDA statement
|
||||
{{'Z','D','A'}, [](const char* term, const uint8_t index) {
|
||||
// i.e. $GPZDA,201530.00,04,07,2002,00,00*60
|
||||
switch (index) {
|
||||
case 0: // time (term = "201530.00")
|
||||
for (uint8_t i = 0, j = 0; i < 6; i+=2, j+=3) {
|
||||
memcpy(&data.time[j], &term[i], 2);
|
||||
}
|
||||
data.time[2] = ':';
|
||||
data.time[5] = ':';
|
||||
data.time[8] = ' ';
|
||||
break;
|
||||
case 1: // day (term = "04")
|
||||
memcpy(&data.time[9], &term[0], 2);
|
||||
data.time[11] = '/';
|
||||
break;
|
||||
case 2: // month (term = "07")
|
||||
memcpy(&data.time[12], &term[0], 2);
|
||||
data.time[14] = '/';
|
||||
break;
|
||||
case 3: // year (term = "2002")
|
||||
memcpy(&data.time[15], &term[2], 2);
|
||||
data.time[17] = 0;
|
||||
data.fresh = true;
|
||||
break;
|
||||
}
|
||||
}}
|
||||
};
|
||||
|
||||
TinyNmea nmea(config, sizeof(config));
|
||||
|
||||
int main() {
|
||||
sei();
|
||||
// continuously read from PB2 (pin 7) at 9600 baud using Timer1 in compare mode
|
||||
uartReader.on(PB2, 9600, Timer1Compare, PinChangeB);
|
||||
while (1) {
|
||||
while (uartReader.inputAvailable()) {
|
||||
// send each symbol to NMEA parser
|
||||
nmea.next(uartReader.read());
|
||||
}
|
||||
if (data.fresh) {
|
||||
data.fresh = false;
|
||||
// make use of data.time value
|
||||
}
|
||||
idleSleep();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
21
libraries/TinySuite/examples/timer-overflow/main.cpp
Normal file
21
libraries/TinySuite/examples/timer-overflow/main.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <avr/interrupt.h>
|
||||
#include <TinyTimer0Overflow.h>
|
||||
#include <TinyTimer1Overflow.h>
|
||||
|
||||
void runOnTimer0() {
|
||||
//
|
||||
}
|
||||
|
||||
void runOnTimer1() {
|
||||
//
|
||||
}
|
||||
|
||||
int main() {
|
||||
sei();
|
||||
Timer0Overflow.on(0x3fc00, runOnTimer0);
|
||||
Timer1Overflow.on(0x3fc000, runOnTimer1);
|
||||
while (1) {
|
||||
// do nothing
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
27
libraries/TinySuite/examples/uart-loop/main.cpp
Normal file
27
libraries/TinySuite/examples/uart-loop/main.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <avr/interrupt.h>
|
||||
#include <TinySleep.h>
|
||||
#include <TinyUart.h>
|
||||
#include <TinyTimer1Compare.h>
|
||||
#include <TinyPinChangeB.h>
|
||||
|
||||
// continuously read bytes from PB2 (pin 7) and repeat them to PB1 (pin 6)
|
||||
// at 9600 baud using Timer1 in compare mode
|
||||
int main() {
|
||||
sei();
|
||||
uart.on(PB2, PB1, 9600, Timer1Compare, PinChangeB);
|
||||
while (1) {
|
||||
if (uart.inputAvailable()) {
|
||||
uart.write(uart.read());
|
||||
}
|
||||
idleSleep();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Commented out because Arduino dumps ELF file into HEX file for flashing
|
||||
// FUSES = {
|
||||
// .low = 0xFF & FUSE_CKSEL1 & FUSE_CKSEL2 & FUSE_CKSEL3, // F_CPU: 16 MHz
|
||||
// .high = 0xFF & FUSE_SPIEN & FUSE_EESAVE,
|
||||
// .extended = 0xFF
|
||||
// };
|
||||
*/
|
||||
18
libraries/TinySuite/examples/uart-print/main.cpp
Normal file
18
libraries/TinySuite/examples/uart-print/main.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <avr/interrupt.h>
|
||||
#include <Arduino.h>
|
||||
#include <TinySerial.h>
|
||||
#include <TinyTimer1Compare.h>
|
||||
#include <TinyPinChangeB.h>
|
||||
|
||||
TinySerial serial(PB2, PB1, Timer1Compare, PinChangeB);
|
||||
|
||||
void setup() {
|
||||
sei();
|
||||
serial.begin(9600);
|
||||
}
|
||||
|
||||
// continuously output on PB1 (pin 6) at 9600 baud using Timer1 in compare mode
|
||||
void loop() {
|
||||
delay(5000);
|
||||
serial.print(F("this is a test\n"));
|
||||
}
|
||||
19
libraries/TinySuite/examples/uart-reader/main.cpp
Normal file
19
libraries/TinySuite/examples/uart-reader/main.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include <avr/interrupt.h>
|
||||
#include <TinyUartReader.h>
|
||||
#include <TinySleep.h>
|
||||
#include <TinyTimer1Compare.h>
|
||||
#include <TinyPinChangeB.h>
|
||||
|
||||
// continuously read from PB2 (pin 7) at 9600 baud using Timer1 in compare mode
|
||||
int main() {
|
||||
sei();
|
||||
uartReader.on(PB2, 9600, Timer1Compare, PinChangeB);
|
||||
while (1) {
|
||||
if (uartReader.inputAvailable()) {
|
||||
uint8_t value = uartReader.read();
|
||||
// do something with the value
|
||||
}
|
||||
idleSleep();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
16
libraries/TinySuite/examples/uart-writer/main.cpp
Normal file
16
libraries/TinySuite/examples/uart-writer/main.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <avr/interrupt.h>
|
||||
#include <TinyUartWriter.h>
|
||||
#include <TinySleep.h>
|
||||
#include <TinyTimer1Compare.h>
|
||||
#include <TinyPinChangeB.h>
|
||||
|
||||
// output "A"+<LF> on PB1 (pin 6) at 9600 baud using Timer1 in compare mode and then stop
|
||||
int main() {
|
||||
sei();
|
||||
uartWriter.on(PB1, 9600, Timer1Compare);
|
||||
uartWriter.write('A');
|
||||
uartWriter.write(10);
|
||||
while (uartWriter.outputRemaining()) idleSleep();
|
||||
uartWriter.off();
|
||||
return 0;
|
||||
}
|
||||
14
libraries/TinySuite/examples/watchdog/main.cpp
Normal file
14
libraries/TinySuite/examples/watchdog/main.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <avr/interrupt.h>
|
||||
#include <TinyWatchdog.h>
|
||||
#include <TinySleep.h>
|
||||
|
||||
int main() {
|
||||
sei();
|
||||
Watchdog.arm(9, [](){
|
||||
// do something after 8 seconds (prescaler value of 9 translates to 8 seconds)
|
||||
});
|
||||
deepSleep();
|
||||
// at this point the watchdog will interrupt the sleep
|
||||
cli();
|
||||
deepSleep();
|
||||
}
|
||||
0
libraries/TinySuite/examples/watchdog/watchdog.ino
Normal file
0
libraries/TinySuite/examples/watchdog/watchdog.ino
Normal file
78
libraries/TinySuite/keywords.txt
Normal file
78
libraries/TinySuite/keywords.txt
Normal file
@@ -0,0 +1,78 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
TinyPinChange KEYWORD1
|
||||
TinyExternalInterrupt KEYWORD1
|
||||
TinyTimer KEYWORD1
|
||||
TinyWatchdog KEYWORD1
|
||||
TinyUart KEYWORD1
|
||||
TinyUartReader KEYWORD1
|
||||
TinyUartWriter KEYWORD1
|
||||
TinySerial KEYWORD1
|
||||
TinyBuffer KEYWORD1
|
||||
NmeaParser KEYWORD1
|
||||
TinyNmea KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
on KEYWORD2
|
||||
off KEYWORD2
|
||||
begin KEYWORD2
|
||||
end KEYWORD2
|
||||
|
||||
inputAvailable KEYWORD2
|
||||
inputCapacity KEYWORD2
|
||||
read KEYWORD2
|
||||
blockingRead KEYWORD2
|
||||
peek KEYWORD2
|
||||
skip KEYWORD2
|
||||
skipAll KEYWORD2
|
||||
|
||||
outputRemaining KEYWORD2
|
||||
outputCapacity KEYWORD2
|
||||
write KEYWORD2
|
||||
blockingWrite KEYWORD2
|
||||
|
||||
countBusy KEYWORD2
|
||||
countFree KEYWORD2
|
||||
clear KEYWORD2
|
||||
put KEYWORD2
|
||||
get KEYWORD2
|
||||
peek KEYWORD2
|
||||
skip KEYWORD2
|
||||
|
||||
arm KEYWORD2
|
||||
armReset KEYWORD2
|
||||
disarm KEYWORD2
|
||||
|
||||
sleep KEYWORD2
|
||||
deepSleep KEYWORD2
|
||||
idleSleep KEYWORD2
|
||||
|
||||
next KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Instances (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
uart KEYWORD2
|
||||
uartReader KEYWORD2
|
||||
uartWriter KEYWORD2
|
||||
PinChangeB KEYWORD2
|
||||
ExternalInterrupt0 KEYWORD2
|
||||
Timer0Compare KEYWORD2
|
||||
Timer0Overflow KEYWORD2
|
||||
Timer1Compare KEYWORD2
|
||||
Timer1Overflow KEYWORD2
|
||||
Watchdog KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
10
libraries/TinySuite/library.properties
Normal file
10
libraries/TinySuite/library.properties
Normal file
@@ -0,0 +1,10 @@
|
||||
name=TinySuite
|
||||
version=2.1.0
|
||||
author=Alex079
|
||||
maintainer=Alex079
|
||||
sentence=A collection of tools for ATTiny85
|
||||
paragraph=Includes wrapper classes for timer, pin change, watchdog, UART, NMEA
|
||||
category=
|
||||
url=https://github.com/Alex079/TinySuite
|
||||
architectures=avr
|
||||
includes=TinyPinChangeB.h, TinyExternalInterrupt0.h, TinyTimer0Compare.h, TinyTimer0Overflow.h, TinyTimer1Compare.h, TinyTimer1Overflow.h, TinyUart.h, TinyUartReader.h, TinyUartWriter.h, TinySerial.h, TinySleep.h, TinyWatchdog.h, TinyBuffer.h, TinyNmea.h
|
||||
37
libraries/TinySuite/src/TinyBuffer.cpp
Normal file
37
libraries/TinySuite/src/TinyBuffer.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <stdint.h>
|
||||
#include "TinyBuffer.h"
|
||||
|
||||
#define next_buffer_index(p) ((p+1) % TINY_BUFFER_SIZE)
|
||||
#define TINY_BUFFER_CAPACITY (TINY_BUFFER_SIZE - 1)
|
||||
|
||||
uint8_t TinyBuffer::countBusy() {
|
||||
uint8_t h = head;
|
||||
uint8_t t = tail;
|
||||
return (h < t) ? (TINY_BUFFER_SIZE + h - t) : (h - t);
|
||||
}
|
||||
|
||||
uint8_t TinyBuffer::countFree() {
|
||||
uint8_t h = head;
|
||||
uint8_t t = tail;
|
||||
return (h < t) ? (t - h - 1) : (TINY_BUFFER_CAPACITY + t - h);
|
||||
}
|
||||
|
||||
void TinyBuffer::clear() {
|
||||
tail = head;
|
||||
}
|
||||
|
||||
void TinyBuffer::put(const uint8_t v) {
|
||||
data[head = next_buffer_index(head)] = v;
|
||||
}
|
||||
|
||||
uint8_t TinyBuffer::get() {
|
||||
return data[tail = next_buffer_index(tail)];
|
||||
}
|
||||
|
||||
uint8_t TinyBuffer::peek() {
|
||||
return data[next_buffer_index(tail)];
|
||||
}
|
||||
|
||||
void TinyBuffer::skip() {
|
||||
tail = next_buffer_index(tail);
|
||||
}
|
||||
48
libraries/TinySuite/src/TinyBuffer.h
Normal file
48
libraries/TinySuite/src/TinyBuffer.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef TinyBuffer_h
|
||||
#define TinyBuffer_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define TINY_BUFFER_SIZE 16
|
||||
|
||||
/**
|
||||
* The 16-byte circular (ring) buffer implementation.
|
||||
* This implementation does not perform any validation (i.e. it is possible to "get" when "empty" and "put" when "full"), the caller is expected to maintain the buffer consistency.
|
||||
*/
|
||||
class TinyBuffer {
|
||||
private:
|
||||
volatile uint8_t data[TINY_BUFFER_SIZE];
|
||||
volatile uint8_t head = 0;
|
||||
volatile uint8_t tail = 0;
|
||||
public:
|
||||
/**
|
||||
* Get the count of bytes in this buffer.
|
||||
*/
|
||||
uint8_t countBusy();
|
||||
/**
|
||||
* Get the size of free space in this buffer.
|
||||
*/
|
||||
uint8_t countFree();
|
||||
/**
|
||||
* Mark this buffer as empty.
|
||||
*/
|
||||
void clear();
|
||||
/**
|
||||
* Write one byte.
|
||||
*/
|
||||
void put(const uint8_t);
|
||||
/**
|
||||
* Read next byte.
|
||||
*/
|
||||
uint8_t get();
|
||||
/**
|
||||
* Get next byte from this buffer but do not mark it as read.
|
||||
*/
|
||||
uint8_t peek();
|
||||
/**
|
||||
* Mark next byte as read without returning it.
|
||||
*/
|
||||
void skip();
|
||||
};
|
||||
|
||||
#endif
|
||||
12
libraries/TinySuite/src/TinyExternalInterrupt.cpp
Normal file
12
libraries/TinySuite/src/TinyExternalInterrupt.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include <stdint.h>
|
||||
#include "TinyExternalInterrupt.h"
|
||||
|
||||
void TinyExternalInterrupt::on(ExternalInterruptDetection detection, ExternalInterruptCallback callback) {
|
||||
onInterrupt = callback;
|
||||
setup(detection);
|
||||
}
|
||||
|
||||
void TinyExternalInterrupt::off() {
|
||||
teardown();
|
||||
onInterrupt = 0;
|
||||
}
|
||||
47
libraries/TinySuite/src/TinyExternalInterrupt.h
Normal file
47
libraries/TinySuite/src/TinyExternalInterrupt.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef TinyExternalInterrupt_h
|
||||
#define TinyExternalInterrupt_h
|
||||
|
||||
enum ExternalInterruptDetection {
|
||||
LOW, ANY, FALLING, RISING
|
||||
};
|
||||
|
||||
typedef void (*ExternalInterruptCallback)();
|
||||
|
||||
typedef void (*ExternalInterruptSetup)(ExternalInterruptDetection);
|
||||
|
||||
typedef void (*ExternalInterruptTeardown)();
|
||||
|
||||
/**
|
||||
* The interface of an external interrupt handler implementation.
|
||||
*/
|
||||
class TinyExternalInterrupt {
|
||||
friend void _ISRExternalInterruptCallbackFunction();
|
||||
public:
|
||||
/**
|
||||
* Instantiate the handler using the provided setup and teardown functions.
|
||||
* Normally, the constructor should be invoked only once by an implementation
|
||||
* to instantiate the wrapper and make it available for the "ISR" and "main".
|
||||
* @param setup A pointer to ExternalInterruptSetup function.
|
||||
* The function should accept "ExternalInterruptDetection" as an argument and should return void.
|
||||
* @param teardown A pointer to ExternalInterruptTeardown function.
|
||||
* The function should have no arguments and should return void.
|
||||
*/
|
||||
TinyExternalInterrupt(ExternalInterruptSetup setup, ExternalInterruptTeardown teardown) : setup(setup), teardown(teardown) {}
|
||||
/**
|
||||
* Register the callback function to run when the configured INT0 pin level is detected.
|
||||
* @param detection One of available ExternalInterruptDetection types: LOW, ANY, FALLING, RISING.
|
||||
* @param callback A pointer to a callback function.
|
||||
* The function should have no arguments and should return void.
|
||||
*/
|
||||
void on(ExternalInterruptDetection detection, ExternalInterruptCallback callback);
|
||||
/**
|
||||
* Unregister the callback function.
|
||||
*/
|
||||
void off();
|
||||
private:
|
||||
volatile ExternalInterruptCallback onInterrupt;
|
||||
ExternalInterruptSetup setup;
|
||||
ExternalInterruptTeardown teardown;
|
||||
};
|
||||
|
||||
#endif
|
||||
28
libraries/TinySuite/src/TinyExternalInterrupt0.cpp
Normal file
28
libraries/TinySuite/src/TinyExternalInterrupt0.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "TinyExternalInterrupt0.h"
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
volatile uint8_t storedGIMSK;
|
||||
volatile uint8_t storedMCUCR;
|
||||
|
||||
#define maskGIMSK (1 << INT0)
|
||||
#define maskMCUCR ( (1 << ISC01) | (1 << ISC00) )
|
||||
|
||||
TinyExternalInterrupt ExternalInterrupt0(
|
||||
[](ExternalInterruptDetection detection) {
|
||||
storedGIMSK = GIMSK & maskGIMSK;
|
||||
storedMCUCR = MCUCR & maskMCUCR;
|
||||
MCUCR |= (MCUCR & ~maskMCUCR) | detection;
|
||||
GIMSK |= maskGIMSK;
|
||||
},
|
||||
[]() {
|
||||
GIMSK = (GIMSK & ~maskGIMSK) | storedGIMSK;
|
||||
MCUCR = (MCUCR & ~maskMCUCR) | storedMCUCR;
|
||||
});
|
||||
|
||||
inline void _ISRExternalInterruptCallbackFunction() {
|
||||
if (ExternalInterrupt0.onInterrupt) ExternalInterrupt0.onInterrupt();
|
||||
}
|
||||
|
||||
ISR(INT0_vect) {
|
||||
_ISRExternalInterruptCallbackFunction();
|
||||
}
|
||||
11
libraries/TinySuite/src/TinyExternalInterrupt0.h
Normal file
11
libraries/TinySuite/src/TinyExternalInterrupt0.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef TinyExternalInterrupt0_h
|
||||
#define TinyExternalInterrupt0_h
|
||||
|
||||
#include "TinyExternalInterrupt.h"
|
||||
|
||||
/**
|
||||
* The instance of external interrupt handler for INT0 pin: ISR(INT0_vect)
|
||||
*/
|
||||
extern TinyExternalInterrupt ExternalInterrupt0;
|
||||
|
||||
#endif
|
||||
90
libraries/TinySuite/src/TinyNmea.cpp
Normal file
90
libraries/TinySuite/src/TinyNmea.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "TinyNmea.h"
|
||||
|
||||
enum NmeaMarker: char {
|
||||
START_MARKER = '$',
|
||||
SPLIT_MARKER = ',',
|
||||
STOP_MARKER = '*'
|
||||
};
|
||||
|
||||
void TinyNmea::next(const char x) {
|
||||
switch (state) {
|
||||
case NONE:
|
||||
switch (x) {
|
||||
case START_MARKER:
|
||||
state = TYPE;
|
||||
charIndex = 0;
|
||||
termsCount = 0;
|
||||
checksum = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TYPE:
|
||||
checksum ^= x;
|
||||
switch (x) {
|
||||
case SPLIT_MARKER:
|
||||
if (charIndex > 2) {
|
||||
for (parserIndex = 0; parserIndex < parsersCount; parserIndex++) {
|
||||
if (parsers[parserIndex].type[0] == temp[charIndex-3] &&
|
||||
parsers[parserIndex].type[1] == temp[charIndex-2] &&
|
||||
parsers[parserIndex].type[2] == temp[charIndex-1]) {
|
||||
state = DATA;
|
||||
charIndex = 0;
|
||||
termsCount = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
state = NONE;
|
||||
break;
|
||||
default:
|
||||
if (charIndex < 5) {
|
||||
temp[charIndex++] = x;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DATA:
|
||||
switch (x) {
|
||||
case SPLIT_MARKER:
|
||||
checksum ^= x;
|
||||
buffer[charIndex++] = 0;
|
||||
termsCount++;
|
||||
break;
|
||||
case STOP_MARKER:
|
||||
buffer[charIndex] = 0;
|
||||
termsCount++;
|
||||
state = SUM;
|
||||
charIndex = 0;
|
||||
break;
|
||||
default:
|
||||
checksum ^= x;
|
||||
if (charIndex < TINY_NMEA_SENTENCE_BUFFER_SIZE) {
|
||||
buffer[charIndex++] = x;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SUM:
|
||||
if (charIndex > 1) {
|
||||
state = NONE;
|
||||
temp[charIndex] = 0;
|
||||
if (strtol(temp, 0, 16) == checksum) {
|
||||
dispatch();
|
||||
}
|
||||
}
|
||||
else {
|
||||
temp[charIndex++] = x;
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TinyNmea::dispatch() {
|
||||
uint8_t position = 0;
|
||||
for (uint8_t termIndex = 0; termIndex < termsCount; termIndex++) {
|
||||
parsers[parserIndex].call(&buffer[position], termIndex);
|
||||
while (buffer[position++]);
|
||||
}
|
||||
}
|
||||
45
libraries/TinySuite/src/TinyNmea.h
Normal file
45
libraries/TinySuite/src/TinyNmea.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef TinyNmea_h
|
||||
#define TinyNmea_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct NmeaParser {
|
||||
/**
|
||||
* Last three symbols of NMEA sentence type designator. Used in parser lookup, type match is "ends with", case-sensitive.
|
||||
*/
|
||||
char type[3];
|
||||
/**
|
||||
* A pointer to parser function to invoke when the matching NMEA sentence is received.
|
||||
* @param term a C-string containing one term from the last NMEA sentence.
|
||||
* @param termIndex a 0-based index of the term in the sentence.
|
||||
*/
|
||||
void (*call) (const char* term, const uint8_t termIndex);
|
||||
};
|
||||
|
||||
#define TINY_NMEA_SENTENCE_BUFFER_SIZE 70
|
||||
|
||||
class TinyNmea {
|
||||
public:
|
||||
/**
|
||||
* Instantiate the parser.
|
||||
* @param parsers A pointer to an array of "NmeaParser" structures.
|
||||
* @param parsersCount Size of the "parsers" array.
|
||||
*/
|
||||
TinyNmea(const NmeaParser parsers[], const uint8_t parsersCount) : parsers(parsers), parsersCount(parsersCount) {}
|
||||
/**
|
||||
* Feed the parser with one character.
|
||||
* @param x the next character to process.
|
||||
*/
|
||||
void next(const char x);
|
||||
private:
|
||||
void dispatch();
|
||||
const NmeaParser* parsers;
|
||||
const uint8_t parsersCount;
|
||||
uint8_t parserIndex;
|
||||
uint8_t charIndex, termsCount, checksum;
|
||||
enum NmeaState: uint8_t { NONE, TYPE, DATA, SUM } state = NONE;
|
||||
char temp[5];
|
||||
char buffer[TINY_NMEA_SENTENCE_BUFFER_SIZE + 1] = {}; // ${talker:1-2}{type:3},{data:70}*{sum:2} total max length is 80
|
||||
};
|
||||
|
||||
#endif
|
||||
10
libraries/TinySuite/src/TinyPinChange.cpp
Normal file
10
libraries/TinySuite/src/TinyPinChange.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <stdint.h>
|
||||
#include "TinyPinChange.h"
|
||||
|
||||
void TinyPinChange::on(uint8_t pin, PinChangeCallback callback) {
|
||||
setup(pin, callback);
|
||||
}
|
||||
|
||||
void TinyPinChange::off(uint8_t pin) {
|
||||
teardown(pin);
|
||||
}
|
||||
43
libraries/TinySuite/src/TinyPinChange.h
Normal file
43
libraries/TinySuite/src/TinyPinChange.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef TinyPinChange_h
|
||||
#define TinyPinChange_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void (*PinChangeCallback)(uint8_t pin, bool level);
|
||||
|
||||
typedef void (*PinChangeSetup)(uint8_t pin, PinChangeCallback callback);
|
||||
|
||||
typedef void (*PinChangeTeardown)(uint8_t pin);
|
||||
|
||||
/**
|
||||
* The interface of a pin change interrupt handler implementation.
|
||||
*/
|
||||
class TinyPinChange {
|
||||
public:
|
||||
/**
|
||||
* Instantiate the handler using the provided setup and teardown functions.
|
||||
* Normally, this constructor should be invoked only once by an implementation
|
||||
* to instantiate the wrapper and make it available for the "ISR" and "main".
|
||||
* @param setup A pointer to PinChangeSetup function.
|
||||
* The function should accept "pin" and "callback" as arguments and should return void.
|
||||
* @param teardown A pointer to PinChangeTeardown function.
|
||||
* The function should accept "pin" as an argument and should return void.
|
||||
*/
|
||||
TinyPinChange(PinChangeSetup setup, PinChangeTeardown teardown) : setup(setup), teardown(teardown) {}
|
||||
/**
|
||||
* Register the callback function for the pin.
|
||||
* @param pin The pin identifier (i.e. PB0, PB1 etc.)
|
||||
* @param callback A pointer to PinChangeCallback function.
|
||||
* The function should accept "pin" and "level" as arguments and should return void.
|
||||
*/
|
||||
void on(uint8_t pin, PinChangeCallback callback);
|
||||
/**
|
||||
* Unregister the callback function.
|
||||
*/
|
||||
void off(uint8_t pin);
|
||||
private:
|
||||
PinChangeSetup setup;
|
||||
PinChangeTeardown teardown;
|
||||
};
|
||||
|
||||
#endif
|
||||
37
libraries/TinySuite/src/TinyPinChangeB.cpp
Normal file
37
libraries/TinySuite/src/TinyPinChangeB.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "TinyPinChangeB.h"
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#define TINY_PINB_CHANGE_MAX 6
|
||||
|
||||
volatile PinChangeCallback onPinChangeB[TINY_PINB_CHANGE_MAX] = {};
|
||||
volatile uint8_t storedPINB;
|
||||
volatile uint8_t storedGIMSKB;
|
||||
|
||||
TinyPinChange PinChangeB(
|
||||
[](uint8_t pin, PinChangeCallback callback) {
|
||||
storedGIMSKB = GIMSK & (1 << PCIE);
|
||||
GIMSK |= (1 << PCIE);
|
||||
onPinChangeB[pin] = callback;
|
||||
storedPINB = PINB;
|
||||
PCMSK |= (1 << pin);
|
||||
},
|
||||
[](uint8_t pin) {
|
||||
PCMSK &= ~(1 << pin);
|
||||
onPinChangeB[pin] = 0;
|
||||
GIMSK = (GIMSK & ~(1 << PCIE)) | storedGIMSKB;
|
||||
});
|
||||
|
||||
ISR(PCINT0_vect) {
|
||||
uint8_t data = PINB;
|
||||
uint8_t changes = (data ^ storedPINB);
|
||||
storedPINB = data;
|
||||
uint8_t pin = 0;
|
||||
while (changes) {
|
||||
if ( (changes & 1) && (onPinChangeB[pin]) ) {
|
||||
onPinChangeB[pin](pin, data & 1);
|
||||
}
|
||||
changes >>= 1;
|
||||
data >>= 1;
|
||||
pin++;
|
||||
}
|
||||
}
|
||||
11
libraries/TinySuite/src/TinyPinChangeB.h
Normal file
11
libraries/TinySuite/src/TinyPinChangeB.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef TinyPinChangeB_h
|
||||
#define TinyPinChangeB_h
|
||||
|
||||
#include "TinyPinChange.h"
|
||||
|
||||
/**
|
||||
* The instance of pin change interrupt handler on portB: ISR(PCINT0_vect)
|
||||
*/
|
||||
extern TinyPinChange PinChangeB;
|
||||
|
||||
#endif
|
||||
39
libraries/TinySuite/src/TinySerial.cpp
Normal file
39
libraries/TinySuite/src/TinySerial.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include <stdint.h>
|
||||
#include "TinySerial.h"
|
||||
#include "TinyUart.h"
|
||||
|
||||
TinySerial::TinySerial(const uint8_t& rx, const uint8_t& tx, TinyTimer& clockInterrupt, TinyPinChange& rxInterrupt) {
|
||||
timer = &clockInterrupt;
|
||||
pinChange = &rxInterrupt;
|
||||
input = rx;
|
||||
output = tx;
|
||||
}
|
||||
|
||||
void TinySerial::begin(const uint32_t& baud) {
|
||||
uart.on(input, output, baud, *timer, *pinChange);
|
||||
}
|
||||
|
||||
void TinySerial::end() {
|
||||
uart.off();
|
||||
}
|
||||
|
||||
int TinySerial::peek() {
|
||||
while (!uart.inputAvailable()) { idleSleep(); }
|
||||
return uart.peek();
|
||||
}
|
||||
|
||||
int TinySerial::available() {
|
||||
return uart.inputAvailable();
|
||||
}
|
||||
|
||||
int TinySerial::read() {
|
||||
return uart.blockingRead();
|
||||
}
|
||||
|
||||
size_t TinySerial::write(uint8_t v) {
|
||||
uart.blockingWrite(v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void TinySerial::flush() {
|
||||
}
|
||||
25
libraries/TinySuite/src/TinySerial.h
Normal file
25
libraries/TinySuite/src/TinySerial.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef TinySerial_h
|
||||
#define TinySerial_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <Stream.h>
|
||||
#include "TinyPinChange.h"
|
||||
#include "TinyTimer.h"
|
||||
|
||||
class TinySerial : public Stream {
|
||||
private:
|
||||
uint8_t input, output;
|
||||
TinyTimer* timer;
|
||||
TinyPinChange* pinChange;
|
||||
public:
|
||||
TinySerial(const uint8_t& rx, const uint8_t& tx, TinyTimer& clockInterrupt, TinyPinChange& rxInterrupt);
|
||||
void begin(const uint32_t& baud);
|
||||
void end();
|
||||
virtual int peek() override;
|
||||
virtual int available() override;
|
||||
virtual int read() override;
|
||||
virtual size_t write(uint8_t) override;
|
||||
virtual void flush() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
12
libraries/TinySuite/src/TinySleep.h
Normal file
12
libraries/TinySuite/src/TinySleep.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef TinySleep_h
|
||||
#define TinySleep_h
|
||||
|
||||
#include <avr/sleep.h>
|
||||
|
||||
#define sleep(mode) set_sleep_mode(mode); sleep_mode()
|
||||
|
||||
#define deepSleep() set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_bod_disable(); sleep_mode()
|
||||
|
||||
#define idleSleep() sleep(SLEEP_MODE_IDLE)
|
||||
|
||||
#endif
|
||||
12
libraries/TinySuite/src/TinyTimer.cpp
Normal file
12
libraries/TinySuite/src/TinyTimer.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include <stdint.h>
|
||||
#include "TinyTimer.h"
|
||||
|
||||
void TinyTimer::on(const uint32_t match, TimerCallback callback) {
|
||||
onTimer = callback;
|
||||
setup(match);
|
||||
}
|
||||
|
||||
void TinyTimer::off() {
|
||||
teardown();
|
||||
onTimer = 0;
|
||||
}
|
||||
46
libraries/TinySuite/src/TinyTimer.h
Normal file
46
libraries/TinySuite/src/TinyTimer.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef TinyTimer_h
|
||||
#define TinyTimer_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void (*TimerCallback)();
|
||||
|
||||
typedef void (*TimerSetup)(uint32_t match);
|
||||
|
||||
typedef void (*TimerTeardown)();
|
||||
|
||||
/**
|
||||
* An interface of a timer interrupt handler implementation.
|
||||
*/
|
||||
class TinyTimer {
|
||||
friend void _ISRTimerCallbackFunction();
|
||||
public:
|
||||
/**
|
||||
* Instantiate the wrapper using the provided setup and teardown functions.
|
||||
* Normally, the constructor should be invoked only once by an implementation
|
||||
* to instantiate the wrapper and make it available for the "ISR" and "main".
|
||||
* @param setup A pointer to TimerSetup function.
|
||||
* The function should accept "match" value as an argument and should return void.
|
||||
* @param teardown A pointer to TimerTeardown function.
|
||||
* The function should accept no arguments and return void.
|
||||
*/
|
||||
TinyTimer(TimerSetup setup, TimerTeardown teardown) : setup(setup), teardown(teardown) {}
|
||||
/**
|
||||
* Register the callback function to run when a condition is met.
|
||||
* @param match An amount of timer ticks to count before the callback is invoked.
|
||||
* High match values may be not precise because of coarse step of timer prescaler.
|
||||
* @param callback A pointer to TimerCallback function.
|
||||
* The function should accept no arguments and should return void.
|
||||
*/
|
||||
void on(const uint32_t match, TimerCallback callback);
|
||||
/**
|
||||
* Unregister the callback function.
|
||||
*/
|
||||
void off();
|
||||
private:
|
||||
volatile TimerCallback onTimer;
|
||||
TimerSetup setup;
|
||||
TimerTeardown teardown;
|
||||
};
|
||||
|
||||
#endif
|
||||
44
libraries/TinySuite/src/TinyTimer0Compare.cpp
Normal file
44
libraries/TinySuite/src/TinyTimer0Compare.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "TinyTimer0Compare.h"
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#define onCompareEnable0A() TIMSK |= (1 << OCIE0A)
|
||||
#define onCompareDisable0A() TIMSK &= ~(1 << OCIE0A)
|
||||
|
||||
#define setPrescale0(prescale) TCCR0B |= (prescale % 6)
|
||||
#define cleanPrescale0() TCCR0B &= 0xF8
|
||||
#define normalMode0() TCCR0A &= ~(1 << WGM00) & ~(1 << WGM01); TCCR0B &= ~(1 << WGM02)
|
||||
#define compareMode0() TCCR0A &= ~(1 << WGM00); TCCR0A |= (1 << WGM01); TCCR0B &= ~(1 << WGM02)
|
||||
|
||||
#define setMatch0A(match) OCR0A = match
|
||||
|
||||
TinyTimer Timer0Compare(
|
||||
[](uint32_t match) {
|
||||
if (match > 0x3FC00) return;
|
||||
compareMode0();
|
||||
cleanPrescale0();
|
||||
uint8_t prescale = 1;
|
||||
while (match > 256) {
|
||||
prescale++;
|
||||
if (prescale > 3) {
|
||||
match = (match + 2) >> 2;
|
||||
}
|
||||
else {
|
||||
match = (match + 4) >> 3;
|
||||
}
|
||||
}
|
||||
setPrescale0(prescale);
|
||||
setMatch0A(match - 1);
|
||||
onCompareEnable0A();
|
||||
},
|
||||
[]() {
|
||||
onCompareDisable0A();
|
||||
normalMode0();
|
||||
});
|
||||
|
||||
inline void _ISRTimerCallbackFunction() {
|
||||
if (Timer0Compare.onTimer) Timer0Compare.onTimer();
|
||||
}
|
||||
|
||||
ISR(TIMER0_COMPA_vect) {
|
||||
_ISRTimerCallbackFunction();
|
||||
}
|
||||
22
libraries/TinySuite/src/TinyTimer0Compare.h
Normal file
22
libraries/TinySuite/src/TinyTimer0Compare.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef TinyTimer0Compare_h
|
||||
#define TinyTimer0Compare_h
|
||||
|
||||
#include "TinyTimer.h"
|
||||
|
||||
/**
|
||||
* The instance of Timer0 Compare interrupt handler: ISR(TIMER0_COMPA_vect)
|
||||
*
|
||||
* Max match value: 0x3FC00
|
||||
*
|
||||
* Prescaler reference:
|
||||
* CS02 CS01 CS00 Result
|
||||
* 0 0 0 stopped
|
||||
* 0 0 1 clock
|
||||
* 0 1 0 clock /8
|
||||
* 0 1 1 clock /64
|
||||
* 1 0 0 clock /256
|
||||
* 1 0 1 clock /1024
|
||||
*/
|
||||
extern TinyTimer Timer0Compare;
|
||||
|
||||
#endif
|
||||
39
libraries/TinySuite/src/TinyTimer0Overflow.cpp
Normal file
39
libraries/TinySuite/src/TinyTimer0Overflow.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include <avr/interrupt.h>
|
||||
#include "TinyTimer0Overflow.h"
|
||||
|
||||
#define onOverflowEnable0() TIMSK |= (1 << TOIE0)
|
||||
#define onOverflowDisable0() TIMSK &= ~(1 << TOIE0)
|
||||
|
||||
#define setPrescale0(prescale) TCCR0B |= (prescale % 6)
|
||||
#define cleanPrescale0() TCCR0B &= 0xF8
|
||||
#define normalMode0() TCCR0A &= ~(1 << WGM00) & ~(1 << WGM01); TCCR0B &= ~(1 << WGM02)
|
||||
|
||||
TinyTimer Timer0Overflow(
|
||||
[](uint32_t match) {
|
||||
if (match > 0x3FC00) return;
|
||||
normalMode0();
|
||||
cleanPrescale0();
|
||||
uint8_t prescale = 1;
|
||||
while (match > 256) {
|
||||
prescale++;
|
||||
if (prescale > 3) {
|
||||
match = (match + 2) >> 2;
|
||||
}
|
||||
else {
|
||||
match = (match + 4) >> 3;
|
||||
}
|
||||
}
|
||||
setPrescale0(prescale);
|
||||
onOverflowEnable0();
|
||||
},
|
||||
[]() {
|
||||
onOverflowDisable0();
|
||||
});
|
||||
|
||||
inline void _ISRTimerCallbackFunction() {
|
||||
if (Timer0Overflow.onTimer) Timer0Overflow.onTimer();
|
||||
}
|
||||
|
||||
ISR(TIMER0_OVF_vect) {
|
||||
_ISRTimerCallbackFunction();
|
||||
}
|
||||
22
libraries/TinySuite/src/TinyTimer0Overflow.h
Normal file
22
libraries/TinySuite/src/TinyTimer0Overflow.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef TinyTimer0Overflow_h
|
||||
#define TinyTimer0Overflow_h
|
||||
|
||||
#include "TinyTimer.h"
|
||||
|
||||
/**
|
||||
* The instance of Timer0 Overflow interrupt handler: ISR(TIMER0_OVF_vect)
|
||||
*
|
||||
* Max match value: 0x3FC00
|
||||
*
|
||||
* Prescaler reference:
|
||||
* CS02 CS01 CS00 Result
|
||||
* 0 0 0 stopped
|
||||
* 0 0 1 clock
|
||||
* 0 1 0 clock /8
|
||||
* 0 1 1 clock /64
|
||||
* 1 0 0 clock /256
|
||||
* 1 0 1 clock /1024
|
||||
*/
|
||||
extern TinyTimer Timer0Overflow;
|
||||
|
||||
#endif
|
||||
39
libraries/TinySuite/src/TinyTimer1Compare.cpp
Normal file
39
libraries/TinySuite/src/TinyTimer1Compare.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include <avr/interrupt.h>
|
||||
#include "TinyTimer1Compare.h"
|
||||
|
||||
#define onCompareEnable1A() TIMSK |= (1 << OCIE1A)
|
||||
#define onCompareDisable1A() TIMSK &= ~(1 << OCIE1A)
|
||||
|
||||
#define setPrescale1(prescale) TCCR1 |= (prescale & 0x0F)
|
||||
#define cleanPrescale1() TCCR1 &= 0xF0
|
||||
#define normalMode1() TCCR1 &= ~(1 << CTC1)
|
||||
#define compareMode1() TCCR1 |= (1 << CTC1)
|
||||
|
||||
#define setMatch1C(match) OCR1C = match
|
||||
|
||||
TinyTimer Timer1Compare(
|
||||
[](uint32_t match) {
|
||||
if (match > 0x3FC000) return;
|
||||
compareMode1();
|
||||
cleanPrescale1();
|
||||
uint8_t prescale = 1;
|
||||
while (match > 256) {
|
||||
prescale++;
|
||||
match = (match + 1) >> 1;
|
||||
}
|
||||
setPrescale1(prescale);
|
||||
setMatch1C(match - 1);
|
||||
onCompareEnable1A();
|
||||
},
|
||||
[]() {
|
||||
onCompareDisable1A();
|
||||
normalMode1();
|
||||
});
|
||||
|
||||
inline void _ISRTimerCallbackFunction() {
|
||||
if (Timer1Compare.onTimer) Timer1Compare.onTimer();
|
||||
}
|
||||
|
||||
ISR(TIMER1_COMPA_vect) {
|
||||
_ISRTimerCallbackFunction();
|
||||
}
|
||||
32
libraries/TinySuite/src/TinyTimer1Compare.h
Normal file
32
libraries/TinySuite/src/TinyTimer1Compare.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef TinyTimer1Compare_h
|
||||
#define TinyTimer1Compare_h
|
||||
|
||||
#include "TinyTimer.h"
|
||||
|
||||
/**
|
||||
* The instance of Timer1 Compare interrupt handler: ISR(TIMER1_COMPA_vect)
|
||||
*
|
||||
* Max match value: 0x3FC000
|
||||
*
|
||||
* Prescaler reference:
|
||||
* CS13 CS12 CS11 CS10 Result
|
||||
* 0 0 0 0 stopped
|
||||
* 0 0 0 1 clock
|
||||
* 0 0 1 0 clock /2
|
||||
* 0 0 1 1 clock /4
|
||||
* 0 1 0 0 clock /8
|
||||
* 0 1 0 1 clock /16
|
||||
* 0 1 1 0 clock /32
|
||||
* 0 1 1 1 clock /64
|
||||
* 1 0 0 0 clock /128
|
||||
* 1 0 0 1 clock /256
|
||||
* 1 0 1 0 clock /512
|
||||
* 1 0 1 1 clock /1024
|
||||
* 1 1 0 0 clock /2048
|
||||
* 1 1 0 1 clock /4096
|
||||
* 1 1 1 0 clock /8192
|
||||
* 1 1 1 1 clock /16384
|
||||
*/
|
||||
extern TinyTimer Timer1Compare;
|
||||
|
||||
#endif
|
||||
34
libraries/TinySuite/src/TinyTimer1Overflow.cpp
Normal file
34
libraries/TinySuite/src/TinyTimer1Overflow.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <avr/interrupt.h>
|
||||
#include "TinyTimer1Overflow.h"
|
||||
|
||||
#define onOverflowEnable1() TIMSK |= (1 << TOIE1)
|
||||
#define onOverflowDisable1() TIMSK &= ~(1 << TOIE1)
|
||||
|
||||
#define setPrescale1(prescale) TCCR1 |= (prescale & 0x0F)
|
||||
#define cleanPrescale1() TCCR1 &= 0xF0
|
||||
#define normalMode1() TCCR1 &= ~(1 << CTC1)
|
||||
|
||||
TinyTimer Timer1Overflow(
|
||||
[](uint32_t match) {
|
||||
if (match > 0x3FC000) return;
|
||||
normalMode1();
|
||||
cleanPrescale1();
|
||||
uint8_t prescale = 1;
|
||||
while (match > 256) {
|
||||
prescale++;
|
||||
match = (match + 1) >> 1;
|
||||
}
|
||||
setPrescale1(prescale);
|
||||
onOverflowEnable1();
|
||||
},
|
||||
[]() {
|
||||
onOverflowDisable1();
|
||||
});
|
||||
|
||||
inline void _ISRTimerCallbackFunction() {
|
||||
if (Timer1Overflow.onTimer) Timer1Overflow.onTimer();
|
||||
}
|
||||
|
||||
ISR(TIMER1_OVF_vect) {
|
||||
_ISRTimerCallbackFunction();
|
||||
}
|
||||
32
libraries/TinySuite/src/TinyTimer1Overflow.h
Normal file
32
libraries/TinySuite/src/TinyTimer1Overflow.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef TinyTimer1Overflow_h
|
||||
#define TinyTimer1Overflow_h
|
||||
|
||||
#include "TinyTimer.h"
|
||||
|
||||
/**
|
||||
* The instance of Timer1 Overflow interrupt handler: ISR(TIMER1_OVF_vect)
|
||||
*
|
||||
* Max match value: 0x3FC000
|
||||
*
|
||||
* Prescaler reference:
|
||||
* CS13 CS12 CS11 CS10 Result
|
||||
* 0 0 0 0 stopped
|
||||
* 0 0 0 1 clock
|
||||
* 0 0 1 0 clock /2
|
||||
* 0 0 1 1 clock /4
|
||||
* 0 1 0 0 clock /8
|
||||
* 0 1 0 1 clock /16
|
||||
* 0 1 1 0 clock /32
|
||||
* 0 1 1 1 clock /64
|
||||
* 1 0 0 0 clock /128
|
||||
* 1 0 0 1 clock /256
|
||||
* 1 0 1 0 clock /512
|
||||
* 1 0 1 1 clock /1024
|
||||
* 1 1 0 0 clock /2048
|
||||
* 1 1 0 1 clock /4096
|
||||
* 1 1 1 0 clock /8192
|
||||
* 1 1 1 1 clock /16384
|
||||
*/
|
||||
extern TinyTimer Timer1Overflow;
|
||||
|
||||
#endif
|
||||
45
libraries/TinySuite/src/TinyUart.cpp
Normal file
45
libraries/TinySuite/src/TinyUart.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include "TinyUart.h"
|
||||
#include "TinyUartConst.h"
|
||||
|
||||
void TinyUart::on(const uint8_t rx, const uint8_t tx, const uint32_t baud, TinyTimer& clockInterrupt, TinyPinChange& rxInterrupt) {
|
||||
input = rx;
|
||||
output = tx;
|
||||
timer = &clockInterrupt;
|
||||
pinChange = &rxInterrupt;
|
||||
storedMask = (1 << input) | (1 << output);
|
||||
|
||||
inputBuffer.clear();
|
||||
outputBuffer.clear();
|
||||
|
||||
inputState = TINY_UART_STATE_IDLE;
|
||||
outputState = TINY_UART_STATE_IDLE;
|
||||
|
||||
storedDDR = DDRB & storedMask;
|
||||
storedPORT = PORTB & storedMask;
|
||||
PORTB |= storedMask;
|
||||
DDRB &= ~(1 << input);
|
||||
DDRB |= (1 << output);
|
||||
|
||||
uint32_t match = (F_CPU * 2) / (baud * TINY_UART_ONE_BIT_CLK);
|
||||
if (1 & match) match++;
|
||||
match >>= 1;
|
||||
timer->on(match, [](){
|
||||
uart.onTimerRx();
|
||||
uart.onTimerTx();
|
||||
});
|
||||
|
||||
pinChange->on(input, [](uint8_t, bool value){
|
||||
uart.onRxPinChange(value);
|
||||
});
|
||||
}
|
||||
|
||||
void TinyUart::off() {
|
||||
timer->off();
|
||||
pinChange->off(input);
|
||||
DDRB = (DDRB & ~storedMask) | storedDDR;
|
||||
PORTB = (PORTB & ~storedMask) | storedPORT;
|
||||
}
|
||||
|
||||
TinyUart uart;
|
||||
41
libraries/TinySuite/src/TinyUart.h
Normal file
41
libraries/TinySuite/src/TinyUart.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef TinyUart_h
|
||||
#define TinyUart_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include "TinyUartBase.h"
|
||||
#include "TinyPinChange.h"
|
||||
#include "TinyTimer.h"
|
||||
|
||||
/**
|
||||
* Bi-directional UART.
|
||||
*/
|
||||
class TinyUart : public TinyUartRead, public TinyUartWrite {
|
||||
public:
|
||||
/**
|
||||
* Start the UART.
|
||||
* The "timer" will be enabled to interrupt at around "baud" * "TINY_UART_ONE_BIT_CLK" rate.
|
||||
* The "pinChange" will be enabled to interrupt on "rx" pin level change.
|
||||
* @param rx The receiving pin identifier (i.e. PB0, PB1 etc.)
|
||||
* @param tx The tansmitting pin identifier (i.e. PB0, PB1 etc.)
|
||||
* @param baud The baud rate for this communication session.
|
||||
* @param clockInterrupt Clock interrupt handler, an instance of "TinyTimer" class.
|
||||
* @param rxInterrupt RX pin interrupt handler, an instance of "TinyPinChange" class.
|
||||
*/
|
||||
void on(const uint8_t rx, const uint8_t tx, const uint32_t baud, TinyTimer& clockInterrupt, TinyPinChange& rxInterrupt);
|
||||
/**
|
||||
* Stop the UART. The "timer" will be stopped, the "pinChange" will be disabled.
|
||||
*/
|
||||
void off();
|
||||
private:
|
||||
TinyTimer* timer;
|
||||
TinyPinChange* pinChange;
|
||||
uint8_t storedDDR, storedPORT, storedMask;
|
||||
};
|
||||
|
||||
/**
|
||||
* The instance of bi-directional UART.
|
||||
*/
|
||||
extern TinyUart uart;
|
||||
|
||||
#endif
|
||||
166
libraries/TinySuite/src/TinyUartBase.cpp
Normal file
166
libraries/TinySuite/src/TinyUartBase.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
#include <avr/io.h>
|
||||
#include "TinyUartBase.h"
|
||||
#include "TinyUartConst.h"
|
||||
|
||||
#define setHigh(p) PORTB |= (1 << p)
|
||||
#define setLow(p) PORTB &= ~(1 << p)
|
||||
|
||||
uint8_t TinyUartRead::inputAvailable() {
|
||||
return inputBuffer.countBusy();
|
||||
}
|
||||
|
||||
uint8_t TinyUartRead::inputCapacity() {
|
||||
return inputBuffer.countFree();
|
||||
}
|
||||
|
||||
uint8_t TinyUartRead::peek() {
|
||||
return inputBuffer.peek();
|
||||
}
|
||||
|
||||
void TinyUartRead::skip() {
|
||||
inputBuffer.skip();
|
||||
}
|
||||
|
||||
void TinyUartRead::skipAll() {
|
||||
inputBuffer.clear();
|
||||
}
|
||||
|
||||
uint8_t TinyUartRead::read() {
|
||||
return inputBuffer.get();
|
||||
}
|
||||
|
||||
uint8_t TinyUartRead::blockingRead() {
|
||||
while (!inputBuffer.countBusy()) {
|
||||
idleSleep();
|
||||
}
|
||||
return inputBuffer.get();
|
||||
}
|
||||
|
||||
void TinyUartRead::onRxPinChange(bool value) {
|
||||
inputBit = value;
|
||||
|
||||
switch (inputState) {
|
||||
|
||||
case TINY_UART_STATE_IDLE:
|
||||
if (!inputBit) {
|
||||
inputBitInProgress = TINY_UART_HALF_BIT_CLK;
|
||||
inputState++;
|
||||
}
|
||||
break;
|
||||
|
||||
case TINY_UART_STATE_STOP:
|
||||
if (inputBit) {
|
||||
inputBuffer.put(inputByte);
|
||||
inputState = TINY_UART_STATE_IDLE;
|
||||
}
|
||||
else { // emergency restart
|
||||
inputBitInProgress = TINY_UART_HALF_BIT_CLK;
|
||||
inputState = TINY_UART_STATE_START;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
inputByte >>= 1;
|
||||
if (inputBit) inputByte |= 128;
|
||||
inputState++;
|
||||
if (inputState == TINY_UART_STATE_STOP) { // early stop on level change
|
||||
inputBuffer.put(inputByte);
|
||||
inputState = TINY_UART_STATE_IDLE;
|
||||
}
|
||||
else {
|
||||
inputBitInProgress = TINY_UART_ONE_AND_HALF_BIT_CLK;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void TinyUartRead::onTimerRx() {
|
||||
|
||||
if (!inputState) return; // idle line state
|
||||
|
||||
if (--inputBitInProgress) return; // keep current state
|
||||
|
||||
switch (inputState) {
|
||||
|
||||
case TINY_UART_STATE_START:
|
||||
if (inputBit) {
|
||||
inputState = TINY_UART_STATE_IDLE;
|
||||
}
|
||||
else {
|
||||
inputBitInProgress = TINY_UART_ONE_BIT_CLK;
|
||||
inputState++;
|
||||
}
|
||||
break;
|
||||
|
||||
case TINY_UART_STATE_STOP:
|
||||
if (inputBit) inputBuffer.put(inputByte);
|
||||
inputState = TINY_UART_STATE_IDLE;
|
||||
break;
|
||||
|
||||
default:
|
||||
inputByte >>= 1;
|
||||
if (inputBit) inputByte |= 128;
|
||||
inputBitInProgress = TINY_UART_ONE_BIT_CLK;
|
||||
inputState++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t TinyUartWrite::outputRemaining() {
|
||||
return outputBuffer.countBusy();
|
||||
}
|
||||
|
||||
uint8_t TinyUartWrite::outputCapacity() {
|
||||
return outputBuffer.countFree();
|
||||
}
|
||||
|
||||
void TinyUartWrite::write(const uint8_t v) {
|
||||
outputBuffer.put(v);
|
||||
}
|
||||
|
||||
void TinyUartWrite::blockingWrite(const uint8_t v) {
|
||||
while (!outputBuffer.countFree()) {
|
||||
idleSleep();
|
||||
}
|
||||
outputBuffer.put(v);
|
||||
while (outputBuffer.countBusy()) {
|
||||
idleSleep();
|
||||
}
|
||||
}
|
||||
|
||||
void TinyUartWrite::onTimerTx() {
|
||||
|
||||
if (!outputState) { // idle line state
|
||||
if (outputBuffer.countBusy()) {
|
||||
outputBitInProgress = TINY_UART_ONE_BIT_CLK;
|
||||
outputState++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (--outputBitInProgress) return; // hold the line
|
||||
|
||||
switch (outputState) {
|
||||
|
||||
case TINY_UART_STATE_START:
|
||||
setLow(output);
|
||||
outputByte = outputBuffer.peek();
|
||||
outputBitInProgress = TINY_UART_ONE_BIT_CLK;
|
||||
outputState++;
|
||||
break;
|
||||
|
||||
case TINY_UART_STATE_STOP:
|
||||
setHigh(output);
|
||||
outputBuffer.skip();
|
||||
outputState = TINY_UART_STATE_IDLE;
|
||||
break;
|
||||
|
||||
default:
|
||||
(outputByte & 1) ? setHigh(output) : setLow(output);
|
||||
outputByte >>= 1;
|
||||
outputBitInProgress = TINY_UART_ONE_BIT_CLK;
|
||||
outputState++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
83
libraries/TinySuite/src/TinyUartBase.h
Normal file
83
libraries/TinySuite/src/TinyUartBase.h
Normal file
@@ -0,0 +1,83 @@
|
||||
#ifndef TinyUartBase_h
|
||||
#define TinyUartBase_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include "TinySleep.h"
|
||||
#include "TinyBuffer.h"
|
||||
|
||||
class TinyUartRead {
|
||||
public:
|
||||
/**
|
||||
* Get the amount of buffered incoming bytes.
|
||||
*/
|
||||
uint8_t inputAvailable();
|
||||
/**
|
||||
* Get the amount of free space left in the input buffer.
|
||||
*/
|
||||
uint8_t inputCapacity();
|
||||
/**
|
||||
* Get one byte from the input buffer. The buffer is not changed.
|
||||
*/
|
||||
uint8_t peek();
|
||||
/**
|
||||
* Remove one byte from the input buffer.
|
||||
*/
|
||||
void skip();
|
||||
/**
|
||||
* Clear the input buffer.
|
||||
*/
|
||||
void skipAll();
|
||||
/**
|
||||
* Get one byte from the input buffer. The value is removed from the buffer.
|
||||
*/
|
||||
uint8_t read();
|
||||
/**
|
||||
* Perform checked "read".
|
||||
* If there is no data in the input buffer, the main control flow will idle until the data is available.
|
||||
*/
|
||||
uint8_t blockingRead();
|
||||
protected:
|
||||
void onRxPinChange(bool);
|
||||
void onTimerRx();
|
||||
uint8_t input;
|
||||
volatile uint8_t inputState;
|
||||
TinyBuffer inputBuffer;
|
||||
private:
|
||||
volatile uint8_t inputBitInProgress;
|
||||
volatile uint8_t inputByte;
|
||||
volatile bool inputBit;
|
||||
};
|
||||
|
||||
class TinyUartWrite {
|
||||
public:
|
||||
/**
|
||||
* Get the amount of buffered outgoing bytes.
|
||||
*/
|
||||
uint8_t outputRemaining();
|
||||
/**
|
||||
* Get the amount of free space left in the output buffer.
|
||||
*/
|
||||
uint8_t outputCapacity();
|
||||
/**
|
||||
* Put one byte into the output buffer.
|
||||
* @param x The value to output.
|
||||
*/
|
||||
void write(const uint8_t x);
|
||||
/**
|
||||
* Perform checked "write".
|
||||
* If there is no free space left in the output buffer, the main control flow will idle until the free space is available.
|
||||
* Additionally, the main control flow will idle until all the outgoing data is sent.
|
||||
* @param x The value to output.
|
||||
*/
|
||||
void blockingWrite(const uint8_t x);
|
||||
protected:
|
||||
void onTimerTx();
|
||||
uint8_t output;
|
||||
volatile uint8_t outputState;
|
||||
TinyBuffer outputBuffer;
|
||||
private:
|
||||
volatile uint8_t outputBitInProgress;
|
||||
volatile uint8_t outputByte;
|
||||
};
|
||||
|
||||
#endif
|
||||
13
libraries/TinySuite/src/TinyUartConst.h
Normal file
13
libraries/TinySuite/src/TinyUartConst.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef TinyUartConst_h
|
||||
#define TinyUartConst_h
|
||||
|
||||
#define TINY_UART_HALF_BIT_CLK 2
|
||||
#define TINY_UART_ONE_BIT_CLK 3
|
||||
#define TINY_UART_ONE_AND_HALF_BIT_CLK 5
|
||||
|
||||
#define TINY_UART_STATE_IDLE 0
|
||||
#define TINY_UART_STATE_START 1
|
||||
// ... data bit states in between
|
||||
#define TINY_UART_STATE_STOP 10
|
||||
|
||||
#endif
|
||||
40
libraries/TinySuite/src/TinyUartReader.cpp
Normal file
40
libraries/TinySuite/src/TinyUartReader.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include "TinyUartReader.h"
|
||||
#include "TinyUartConst.h"
|
||||
|
||||
void TinyUartReader::on(const uint8_t rx, const uint32_t baud, TinyTimer& clockInterrupt, TinyPinChange& rxInterrupt) {
|
||||
input = rx;
|
||||
timer = &clockInterrupt;
|
||||
pinChange = &rxInterrupt;
|
||||
|
||||
inputBuffer.clear();
|
||||
|
||||
inputState = TINY_UART_STATE_IDLE;
|
||||
|
||||
storedMask = (1 << input);
|
||||
storedDDR = DDRB & storedMask;
|
||||
storedPORT = PORTB & storedMask;
|
||||
PORTB |= storedMask;
|
||||
DDRB &= ~storedMask;
|
||||
|
||||
uint32_t match = (F_CPU * 2) / (baud * TINY_UART_ONE_BIT_CLK);
|
||||
if (1 & match) match++;
|
||||
match >>= 1;
|
||||
timer->on(match, [](){
|
||||
uartReader.onTimerRx();
|
||||
});
|
||||
|
||||
pinChange->on(input, [](uint8_t, bool value){
|
||||
uartReader.onRxPinChange(value);
|
||||
});
|
||||
}
|
||||
|
||||
void TinyUartReader::off() {
|
||||
timer->off();
|
||||
pinChange->off(input);
|
||||
DDRB = (DDRB & ~storedMask) | storedDDR;
|
||||
PORTB = (PORTB & ~storedMask) | storedPORT;
|
||||
}
|
||||
|
||||
TinyUartReader uartReader;
|
||||
39
libraries/TinySuite/src/TinyUartReader.h
Normal file
39
libraries/TinySuite/src/TinyUartReader.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef TinyUartReader_h
|
||||
#define TinyUartReader_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include "TinyUartBase.h"
|
||||
#include "TinyPinChange.h"
|
||||
#include "TinyTimer.h"
|
||||
|
||||
/**
|
||||
* Receive-only UART.
|
||||
*/
|
||||
class TinyUartReader : public TinyUartRead {
|
||||
public:
|
||||
/**
|
||||
* Start the UART.
|
||||
* The "timer" will be enabled to interrupt at around "baud" * "TINY_UART_ONE_BIT_CLK" rate.
|
||||
* The "pinChange" will be enabled to interrupt on "rx" pin level change.
|
||||
* @param rx The receiving pin identifier (i.e. PB0, PB1 etc.)
|
||||
* @param baud The baud rate for this communication session.
|
||||
* @param clockInterrupt Clock interrupt handler, an instance of "TinyTimer" class.
|
||||
* @param rxInterrupt RX pin interrupt handler, an instance of "TinyPinChange" class.
|
||||
*/
|
||||
void on(const uint8_t rx, const uint32_t baud, TinyTimer& clockInterrupt, TinyPinChange& rxInterrupt);
|
||||
/**
|
||||
* Stop the UART. The "timer" will be stopped, the "pinChange" will be disabled.
|
||||
*/
|
||||
void off();
|
||||
private:
|
||||
TinyTimer* timer;
|
||||
TinyPinChange* pinChange;
|
||||
uint8_t storedDDR, storedPORT, storedMask;
|
||||
};
|
||||
|
||||
/**
|
||||
* The instance of receive-only UART.
|
||||
*/
|
||||
extern TinyUartReader uartReader;
|
||||
|
||||
#endif
|
||||
34
libraries/TinySuite/src/TinyUartWriter.cpp
Normal file
34
libraries/TinySuite/src/TinyUartWriter.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include "TinyUartWriter.h"
|
||||
#include "TinyUartConst.h"
|
||||
|
||||
void TinyUartWriter::on(const uint8_t tx, const uint32_t baud, TinyTimer& clockInterrupt) {
|
||||
output = tx;
|
||||
timer = &clockInterrupt;
|
||||
|
||||
outputBuffer.clear();
|
||||
|
||||
outputState = TINY_UART_STATE_IDLE;
|
||||
|
||||
storedMask = (1 << output);
|
||||
storedDDR = DDRB & storedMask;
|
||||
storedPORT = PORTB & storedMask;
|
||||
PORTB |= storedMask;
|
||||
DDRB |= storedMask;
|
||||
|
||||
uint32_t match = (F_CPU * 2) / (baud * TINY_UART_ONE_BIT_CLK);
|
||||
if (1 & match) match++;
|
||||
match >>= 1;
|
||||
timer->on(match, [](){
|
||||
uartWriter.onTimerTx();
|
||||
});
|
||||
}
|
||||
|
||||
void TinyUartWriter::off() {
|
||||
timer->off();
|
||||
DDRB = (DDRB & ~storedMask) | storedDDR;
|
||||
PORTB = (PORTB & ~storedMask) | storedPORT;
|
||||
}
|
||||
|
||||
TinyUartWriter uartWriter;
|
||||
35
libraries/TinySuite/src/TinyUartWriter.h
Normal file
35
libraries/TinySuite/src/TinyUartWriter.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef TinyUartWriter_h
|
||||
#define TinyUartWriter_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include "TinyUartBase.h"
|
||||
#include "TinyTimer.h"
|
||||
|
||||
/**
|
||||
* Transmit-only UART.
|
||||
*/
|
||||
class TinyUartWriter : public TinyUartWrite {
|
||||
public:
|
||||
/**
|
||||
* Start the UART.
|
||||
* The "timer" will be enabled to interrupt at around "baud" * "TINY_UART_ONE_BIT_CLK" rate.
|
||||
* @param tx The tansmitting pin identifier (i.e. PB0, PB1 etc.)
|
||||
* @param baud The baud rate for this communication session.
|
||||
* @param clockInterrupt Clock interrupt handler, an instance of "TinyTimer" class.
|
||||
*/
|
||||
void on(const uint8_t tx, const uint32_t baud, TinyTimer& clockInterrupt);
|
||||
/**
|
||||
* Stop the UART. The "timer" will be stopped.
|
||||
*/
|
||||
void off();
|
||||
private:
|
||||
TinyTimer* timer;
|
||||
uint8_t storedDDR, storedPORT, storedMask;
|
||||
};
|
||||
|
||||
/**
|
||||
* The instance of transmit-only UART.
|
||||
*/
|
||||
extern TinyUartWriter uartWriter;
|
||||
|
||||
#endif
|
||||
31
libraries/TinySuite/src/TinyWatchdog.cpp
Normal file
31
libraries/TinySuite/src/TinyWatchdog.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <stdint.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include "TinyWatchdog.h"
|
||||
|
||||
#define watchdogArm(i, r, p) WDTCR = ((i) << WDIE) | ((r) << WDE) | (((p) & 0b1000) << 2) | ((p) & 0b0111)
|
||||
#define watchdogDisarm() WDTCR = (1 << WDCE) | (1 << WDE); WDTCR = 0
|
||||
|
||||
void TinyWatchdog::arm(const uint8_t prescaler, WatchdogCallback callback) {
|
||||
onEvent = callback;
|
||||
watchdogArm(true, false, prescaler);
|
||||
}
|
||||
|
||||
void TinyWatchdog::armReset(const uint8_t prescaler, WatchdogCallback callback) {
|
||||
onEvent = callback;
|
||||
watchdogArm(callback!=0, true, prescaler);
|
||||
}
|
||||
|
||||
void TinyWatchdog::disarm() {
|
||||
onEvent = 0;
|
||||
watchdogDisarm();
|
||||
}
|
||||
|
||||
TinyWatchdog Watchdog;
|
||||
|
||||
inline void _ISRWatchdogEventCallback() {
|
||||
if (Watchdog.onEvent) Watchdog.onEvent();
|
||||
}
|
||||
|
||||
ISR(WDT_vect) {
|
||||
_ISRWatchdogEventCallback();
|
||||
}
|
||||
56
libraries/TinySuite/src/TinyWatchdog.h
Normal file
56
libraries/TinySuite/src/TinyWatchdog.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef TinyWatchdog_h
|
||||
#define TinyWatchdog_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void (*WatchdogCallback)();
|
||||
|
||||
/**
|
||||
* An interface of the watchog interrupt handler.
|
||||
*/
|
||||
class TinyWatchdog {
|
||||
friend void _ISRWatchdogEventCallback();
|
||||
public:
|
||||
/**
|
||||
* Run the callback inside an ISR after timeout.
|
||||
* @param prescaler An integer value from 0 to 9.
|
||||
* Higher prescaler value will cause longer delay.
|
||||
* @param callback A pointer to WatchdogCallback function.
|
||||
* The function should accept no arguments and return void.
|
||||
*/
|
||||
void arm(const uint8_t prescaler, WatchdogCallback callback);
|
||||
/**
|
||||
* Run the callback inside an ISR after timeout and then reset after another timeout.
|
||||
* If the callback is null, the reset is done after the first timeout.
|
||||
* @param prescaler An integer value from 0 to 9.
|
||||
* Higher prescaler value will cause longer delay.
|
||||
* @param callback A pointer to WatchdogCallback function.
|
||||
* The function should accept no arguments and return void.
|
||||
*/
|
||||
void armReset(const uint8_t prescaler, WatchdogCallback callback);
|
||||
/**
|
||||
* Disable the watchdog.
|
||||
*/
|
||||
void disarm();
|
||||
private:
|
||||
volatile WatchdogCallback onEvent;
|
||||
};
|
||||
|
||||
/**
|
||||
* The instance of watchdog interrupt handler: ISR(WDT_vect)
|
||||
*
|
||||
* Watchdog prescaler reference:
|
||||
* 0 -> 16 ms
|
||||
* 1 -> 32 ms
|
||||
* 2 -> 64 ms
|
||||
* 3 -> 0.125 s
|
||||
* 4 -> 0.25 s
|
||||
* 5 -> 0.5 s
|
||||
* 6 -> 1.0 s
|
||||
* 7 -> 2.0 s
|
||||
* 8 -> 4.0 s
|
||||
* 9 -> 8.0 s
|
||||
*/
|
||||
extern TinyWatchdog Watchdog;
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user