first commit
This commit is contained in:
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