Repo restyled using astyle (#683)

The rules are in .tools/astyle/config/style.cfg
and can also be reviewed at
https://www.mysensors.org/view/260#coding-guidelines-core-library
This commit is contained in:
Patrick Fallberg
2016-12-07 23:44:29 +01:00
committed by GitHub
parent d4c4ab82ea
commit 8e1ef13804
167 changed files with 16103 additions and 15168 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ max-code-length=100
break-after-logical break-after-logical
# Preprocessor blocks should be indented # Preprocessor blocks should be indented
indent-preproc-block #indent-preproc-block
# Preprocessor definitions should be indented if linebroken # Preprocessor definitions should be indented if linebroken
indent-preproc-define indent-preproc-define
+4 -2
View File
@@ -25,7 +25,8 @@ extern bool transportSendRoute(MyMessage &message);
extern MyMessage _msg; extern MyMessage _msg;
extern MyMessage _msgTmp; extern MyMessage _msgTmp;
inline void gatewayTransportProcess() { inline void gatewayTransportProcess()
{
if (gatewayTransportAvailable()) { if (gatewayTransportAvailable()) {
_msg = gatewayTransportReceive(); _msg = gatewayTransportReceive();
if (_msg.destination == GATEWAY_ADDRESS) { if (_msg.destination == GATEWAY_ADDRESS) {
@@ -34,7 +35,8 @@ inline void gatewayTransportProcess() {
if (mGetRequestAck(_msg)) { if (mGetRequestAck(_msg)) {
// Copy message // Copy message
_msgTmp = _msg; _msgTmp = _msg;
mSetRequestAck(_msgTmp, false); // Reply without ack flag (otherwise we would end up in an eternal loop) mSetRequestAck(_msgTmp,
false); // Reply without ack flag (otherwise we would end up in an eternal loop)
mSetAck(_msgTmp, true); mSetAck(_msgTmp, true);
_msgTmp.sender = getNodeId(); _msgTmp.sender = getNodeId();
_msgTmp.destination = _msg.sender; _msgTmp.destination = _msg.sender;
+13 -18
View File
@@ -35,8 +35,7 @@ MyMessage _ethernetMsg;
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
typedef struct typedef struct {
{
char string[MY_GATEWAY_MAX_RECEIVE_LENGTH]; char string[MY_GATEWAY_MAX_RECEIVE_LENGTH];
uint8_t idx; uint8_t idx;
} inputBuffer; } inputBuffer;
@@ -84,14 +83,11 @@ typedef struct
#ifdef MY_W5100_SPI_EN #ifdef MY_W5100_SPI_EN
void _w5100_spi_en(bool enable) void _w5100_spi_en(bool enable)
{ {
if (enable) if (enable) {
{
// Pull up pin // Pull up pin
hwPinMode(MY_W5100_SPI_EN, INPUT); hwPinMode(MY_W5100_SPI_EN, INPUT);
hwDigitalWrite(MY_W5100_SPI_EN, HIGH); hwDigitalWrite(MY_W5100_SPI_EN, HIGH);
} } else {
else
{
// Ground pin // Ground pin
hwPinMode(MY_W5100_SPI_EN, OUTPUT); hwPinMode(MY_W5100_SPI_EN, OUTPUT);
hwDigitalWrite(MY_W5100_SPI_EN, LOW); hwDigitalWrite(MY_W5100_SPI_EN, LOW);
@@ -101,7 +97,8 @@ typedef struct
#define _w5100_spi_en(x) #define _w5100_spi_en(x)
#endif #endif
bool gatewayTransportInit() { bool gatewayTransportInit()
{
_w5100_spi_en(true); _w5100_spi_en(true);
#if defined(MY_GATEWAY_ESP8266) #if defined(MY_GATEWAY_ESP8266)
#if defined(MY_ESP8266_SSID) #if defined(MY_ESP8266_SSID)
@@ -114,8 +111,7 @@ bool gatewayTransportInit() {
WiFi.config(_ethernetGatewayIP, _gatewayIp, _subnetIp); WiFi.config(_ethernetGatewayIP, _gatewayIp, _subnetIp);
#endif #endif
(void)WiFi.begin(MY_ESP8266_SSID, MY_ESP8266_PASSWORD); (void)WiFi.begin(MY_ESP8266_SSID, MY_ESP8266_PASSWORD);
while (WiFi.status() != WL_CONNECTED) while (WiFi.status() != WL_CONNECTED) {
{
wait(500); wait(500);
MY_SERIALDEVICE.print(F(".")); MY_SERIALDEVICE.print(F("."));
} }
@@ -213,10 +209,8 @@ bool gatewayTransportSend(MyMessage &message)
#else #else
// Send message to connected clients // Send message to connected clients
#if defined(MY_GATEWAY_ESP8266) #if defined(MY_GATEWAY_ESP8266)
for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) {
{ if (clients[i] && clients[i].connected()) {
if (clients[i] && clients[i].connected())
{
nbytes += clients[i].write((uint8_t*)_ethernetMsg, strlen(_ethernetMsg)); nbytes += clients[i].write((uint8_t*)_ethernetMsg, strlen(_ethernetMsg));
} }
} }
@@ -229,7 +223,8 @@ bool gatewayTransportSend(MyMessage &message)
} }
#if (defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_LINUX)) && !defined(MY_GATEWAY_CLIENT_MODE) #if (defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_LINUX)) && !defined(MY_GATEWAY_CLIENT_MODE)
bool _readFromClient(uint8_t i) { bool _readFromClient(uint8_t i)
{
while (clients[i].connected() && clients[i].available()) { while (clients[i].connected() && clients[i].available()) {
char inChar = clients[i].read(); char inChar = clients[i].read();
if (inputString[i].idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) { if (inputString[i].idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) {
@@ -258,7 +253,8 @@ bool gatewayTransportSend(MyMessage &message)
return false; return false;
} }
#else #else
bool _readFromClient() { bool _readFromClient()
{
while (client.connected() && client.available()) { while (client.connected() && client.available()) {
char inChar = client.read(); char inChar = client.read();
if (inputString.idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) { if (inputString.idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) {
@@ -314,8 +310,7 @@ bool gatewayTransportAvailable()
_w5100_spi_en(false); _w5100_spi_en(false);
const bool ok = protocolParse(_ethernetMsg, inputString.string); const bool ok = protocolParse(_ethernetMsg, inputString.string);
#endif #endif
if (ok) if (ok) {
{
setIndication(INDICATION_GW_RX); setIndication(INDICATION_GW_RX);
} }
return ok; return ok;
+14 -7
View File
@@ -48,7 +48,8 @@ static bool _MQTT_connecting = true;
static bool _MQTT_available = false; static bool _MQTT_available = false;
static MyMessage _MQTT_msg; static MyMessage _MQTT_msg;
bool gatewayTransportSend(MyMessage &message) { bool gatewayTransportSend(MyMessage &message)
{
if (!_MQTT_client.connected()) { if (!_MQTT_client.connected()) {
return false; return false;
} }
@@ -58,12 +59,14 @@ bool gatewayTransportSend(MyMessage &message) {
return _MQTT_client.publish(topic, message.getString(_convBuffer)); return _MQTT_client.publish(topic, message.getString(_convBuffer));
} }
void incomingMQTT(char* topic, uint8_t* payload, unsigned int length) { void incomingMQTT(char* topic, uint8_t* payload, unsigned int length)
{
debug(PSTR("Message arrived on topic: %s\n"), topic); debug(PSTR("Message arrived on topic: %s\n"), topic);
_MQTT_available = protocolMQTTParse(_MQTT_msg, topic, payload, length); _MQTT_available = protocolMQTTParse(_MQTT_msg, topic, payload, length);
} }
bool reconnectMQTT() { bool reconnectMQTT()
{
debug(PSTR("Attempting MQTT connection...\n")); debug(PSTR("Attempting MQTT connection...\n"));
// Attempt to connect // Attempt to connect
if (_MQTT_client.connect(MY_MQTT_CLIENT_ID if (_MQTT_client.connect(MY_MQTT_CLIENT_ID
@@ -85,7 +88,8 @@ bool reconnectMQTT() {
return false; return false;
} }
bool gatewayTransportConnect() { bool gatewayTransportConnect()
{
#if defined(MY_GATEWAY_ESP8266) #if defined(MY_GATEWAY_ESP8266)
while (WiFi.status() != WL_CONNECTED) { while (WiFi.status() != WL_CONNECTED) {
wait(500); wait(500);
@@ -116,7 +120,8 @@ bool gatewayTransportConnect() {
return true; return true;
} }
bool gatewayTransportInit() { bool gatewayTransportInit()
{
_MQTT_connecting = true; _MQTT_connecting = true;
#if defined(MY_CONTROLLER_IP_ADDRESS) #if defined(MY_CONTROLLER_IP_ADDRESS)
_MQTT_client.setServer(_brokerIp, MY_PORT); _MQTT_client.setServer(_brokerIp, MY_PORT);
@@ -144,7 +149,8 @@ bool gatewayTransportInit() {
return true; return true;
} }
bool gatewayTransportAvailable() { bool gatewayTransportAvailable()
{
if (_MQTT_connecting) { if (_MQTT_connecting) {
return false; return false;
} }
@@ -161,7 +167,8 @@ bool gatewayTransportAvailable() {
return _MQTT_available; return _MQTT_available;
} }
MyMessage & gatewayTransportReceive() { MyMessage & gatewayTransportReceive()
{
// Return the last parsed message // Return the last parsed message
_MQTT_available = false; _MQTT_available = false;
return _MQTT_msg; return _MQTT_msg;
+9 -6
View File
@@ -30,14 +30,16 @@ char _serialInputString[MY_GATEWAY_MAX_RECEIVE_LENGTH]; // A buffer for incom
uint8_t _serialInputPos; uint8_t _serialInputPos;
MyMessage _serialMsg; MyMessage _serialMsg;
bool gatewayTransportSend(MyMessage &message) { bool gatewayTransportSend(MyMessage &message)
{
setIndication(INDICATION_GW_TX); setIndication(INDICATION_GW_TX);
MY_SERIALDEVICE.print(protocolFormat(message)); MY_SERIALDEVICE.print(protocolFormat(message));
// Serial print is always successful // Serial print is always successful
return true; return true;
} }
bool gatewayTransportInit() { bool gatewayTransportInit()
{
gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete.")); gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete."));
// Send presentation of locally attached sensors (and node if applicable) // Send presentation of locally attached sensors (and node if applicable)
presentNode(); presentNode();
@@ -45,7 +47,8 @@ bool gatewayTransportInit() {
return true; return true;
} }
bool gatewayTransportAvailable() { bool gatewayTransportAvailable()
{
while (MY_SERIALDEVICE.available()) { while (MY_SERIALDEVICE.available()) {
// get the new byte: // get the new byte:
char inChar = (char) MY_SERIALDEVICE.read(); char inChar = (char) MY_SERIALDEVICE.read();
@@ -55,8 +58,7 @@ bool gatewayTransportAvailable() {
if (inChar == '\n') { if (inChar == '\n') {
_serialInputString[_serialInputPos] = 0; _serialInputString[_serialInputPos] = 0;
bool ok = protocolParse(_serialMsg, _serialInputString); bool ok = protocolParse(_serialMsg, _serialInputString);
if (ok) if (ok) {
{
setIndication(INDICATION_GW_RX); setIndication(INDICATION_GW_RX);
} }
_serialInputPos = 0; _serialInputPos = 0;
@@ -74,7 +76,8 @@ bool gatewayTransportAvailable() {
return false; return false;
} }
MyMessage & gatewayTransportReceive() { MyMessage & gatewayTransportReceive()
{
// Return the last parsed message // Return the last parsed message
return _serialMsg; return _serialMsg;
} }
+2 -1
View File
@@ -76,7 +76,8 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms);
* @param ms Time to sleep, in [ms]. * @param ms Time to sleep, in [ms].
* @return -1 when woken by timer, or interrupt number when woken by interrupt. * @return -1 when woken by timer, or interrupt number when woken by interrupt.
*/ */
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms); int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
unsigned long ms);
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG) #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
/** /**
+68 -28
View File
@@ -23,15 +23,17 @@
#define INVALID_INTERRUPT_NUM (0xFFu) #define INVALID_INTERRUPT_NUM (0xFFu)
volatile uint8_t _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; // Interrupt number that woke the mcu. volatile uint8_t _wokeUpByInterrupt =
volatile uint8_t _wakeUp1Interrupt = INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp1-callback. INVALID_INTERRUPT_NUM; // Interrupt number that woke the mcu.
volatile uint8_t _wakeUp2Interrupt = INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp2-callback. volatile uint8_t _wakeUp1Interrupt =
INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp1-callback.
volatile uint8_t _wakeUp2Interrupt =
INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp2-callback.
void wakeUp1() //place to send the interrupts void wakeUp1() //place to send the interrupts
{ {
detachInterrupt(_wakeUp1Interrupt); detachInterrupt(_wakeUp1Interrupt);
if (_wakeUp2Interrupt != INVALID_INTERRUPT_NUM) if (_wakeUp2Interrupt != INVALID_INTERRUPT_NUM) {
{
detachInterrupt(_wakeUp2Interrupt); detachInterrupt(_wakeUp2Interrupt);
} }
_wokeUpByInterrupt = _wakeUp1Interrupt; _wokeUpByInterrupt = _wakeUp1Interrupt;
@@ -39,8 +41,7 @@ void wakeUp1() //place to send the interrupts
void wakeUp2() //place to send the second interrupts void wakeUp2() //place to send the second interrupts
{ {
detachInterrupt(_wakeUp2Interrupt); detachInterrupt(_wakeUp2Interrupt);
if (_wakeUp1Interrupt != INVALID_INTERRUPT_NUM) if (_wakeUp1Interrupt != INVALID_INTERRUPT_NUM) {
{
detachInterrupt(_wakeUp1Interrupt); detachInterrupt(_wakeUp1Interrupt);
} }
_wokeUpByInterrupt = _wakeUp2Interrupt; _wokeUpByInterrupt = _wakeUp2Interrupt;
@@ -57,13 +58,13 @@ ISR (WDT_vect)
{ {
} }
void hwPowerDown(period_t period) { void hwPowerDown(period_t period)
{
// disable ADC for power saving // disable ADC for power saving
ADCSRA &= ~(1 << ADEN); ADCSRA &= ~(1 << ADEN);
// save WDT settings // save WDT settings
uint8_t WDTsave = WDTCSR; uint8_t WDTsave = WDTCSR;
if (period != SLEEP_FOREVER) if (period != SLEEP_FOREVER) {
{
wdt_enable(period); wdt_enable(period);
// enable WDT interrupt before system reset // enable WDT interrupt before system reset
WDTCSR |= (1 << WDCE) | (1 << WDIE); WDTCSR |= (1 << WDCE) | (1 << WDIE);
@@ -94,33 +95,68 @@ void hwPowerDown(period_t period) {
ADCSRA |= (1 << ADEN); ADCSRA |= (1 << ADEN);
} }
void hwInternalSleep(unsigned long ms) { void hwInternalSleep(unsigned long ms)
{
// Let serial prints finish (debug, log etc) // Let serial prints finish (debug, log etc)
#ifndef MY_DISABLED_SERIAL #ifndef MY_DISABLED_SERIAL
MY_SERIALDEVICE.flush(); MY_SERIALDEVICE.flush();
#endif #endif
while (!interruptWakeUp() && ms >= 8000) { hwPowerDown(SLEEP_8S); ms -= 8000; } while (!interruptWakeUp() && ms >= 8000) {
if (!interruptWakeUp() && ms >= 4000) { hwPowerDown(SLEEP_4S); ms -= 4000; } hwPowerDown(SLEEP_8S);
if (!interruptWakeUp() && ms >= 2000) { hwPowerDown(SLEEP_2S); ms -= 2000; } ms -= 8000;
if (!interruptWakeUp() && ms >= 1000) { hwPowerDown(SLEEP_1S); ms -= 1000; } }
if (!interruptWakeUp() && ms >= 500) { hwPowerDown(SLEEP_500MS); ms -= 500; } if (!interruptWakeUp() && ms >= 4000) {
if (!interruptWakeUp() && ms >= 250) { hwPowerDown(SLEEP_250MS); ms -= 250; } hwPowerDown(SLEEP_4S);
if (!interruptWakeUp() && ms >= 125) { hwPowerDown(SLEEP_120MS); ms -= 120; } ms -= 4000;
if (!interruptWakeUp() && ms >= 64) { hwPowerDown(SLEEP_60MS); ms -= 60; } }
if (!interruptWakeUp() && ms >= 32) { hwPowerDown(SLEEP_30MS); ms -= 30; } if (!interruptWakeUp() && ms >= 2000) {
if (!interruptWakeUp() && ms >= 16) { hwPowerDown(SLEEP_15MS); ms -= 15; } hwPowerDown(SLEEP_2S);
ms -= 2000;
}
if (!interruptWakeUp() && ms >= 1000) {
hwPowerDown(SLEEP_1S);
ms -= 1000;
}
if (!interruptWakeUp() && ms >= 500) {
hwPowerDown(SLEEP_500MS);
ms -= 500;
}
if (!interruptWakeUp() && ms >= 250) {
hwPowerDown(SLEEP_250MS);
ms -= 250;
}
if (!interruptWakeUp() && ms >= 125) {
hwPowerDown(SLEEP_120MS);
ms -= 120;
}
if (!interruptWakeUp() && ms >= 64) {
hwPowerDown(SLEEP_60MS);
ms -= 60;
}
if (!interruptWakeUp() && ms >= 32) {
hwPowerDown(SLEEP_30MS);
ms -= 30;
}
if (!interruptWakeUp() && ms >= 16) {
hwPowerDown(SLEEP_15MS);
ms -= 15;
}
} }
int8_t hwSleep(unsigned long ms) { int8_t hwSleep(unsigned long ms)
{
hwInternalSleep(ms); hwInternalSleep(ms);
return MY_WAKE_UP_BY_TIMER; return MY_WAKE_UP_BY_TIMER;
} }
int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
{
return hwSleep(interrupt,mode,INVALID_INTERRUPT_NUM,0u,ms); return hwSleep(interrupt,mode,INVALID_INTERRUPT_NUM,0u,ms);
} }
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
unsigned long ms)
{
// Disable interrupts until going to sleep, otherwise interrupts occurring between attachInterrupt() // Disable interrupts until going to sleep, otherwise interrupts occurring between attachInterrupt()
// and sleep might cause the ATMega to not wakeup from sleep as interrupt has already be handled! // and sleep might cause the ATMega to not wakeup from sleep as interrupt has already be handled!
cli(); cli();
@@ -162,7 +198,8 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo
} }
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG) #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
uint16_t hwCPUVoltage() { uint16_t hwCPUVoltage()
{
// Measure Vcc against 1.1V Vref // Measure Vcc against 1.1V Vref
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ADMUX = (_BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1)); ADMUX = (_BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1));
@@ -182,7 +219,8 @@ uint16_t hwCPUVoltage() {
return (1125300UL) / ADC; return (1125300UL) / ADC;
} }
uint16_t hwCPUFrequency() { uint16_t hwCPUFrequency()
{
cli(); cli();
// setup timer1 // setup timer1
TIFR1 = 0xFF; TIFR1 = 0xFF;
@@ -210,7 +248,8 @@ uint16_t hwCPUFrequency() {
return TCNT1 * 2048UL / 100000UL; return TCNT1 * 2048UL / 100000UL;
} }
uint16_t hwFreeMem() { uint16_t hwFreeMem()
{
extern int __heap_start, *__brkval; extern int __heap_start, *__brkval;
int v; int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
@@ -218,7 +257,8 @@ uint16_t hwFreeMem() {
#endif #endif
#ifdef MY_DEBUG #ifdef MY_DEBUG
void hwDebugPrint(const char *fmt, ... ) { void hwDebugPrint(const char *fmt, ... )
{
char fmtBuffer[MY_SERIAL_OUTPUT_SIZE]; char fmtBuffer[MY_SERIAL_OUTPUT_SIZE];
#ifdef MY_GATEWAY_FEATURE #ifdef MY_GATEWAY_FEATURE
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
+16 -9
View File
@@ -33,8 +33,7 @@ void hwReadConfigBlock(void* buf, void* addr, size_t length)
{ {
uint8_t* dst = static_cast<uint8_t*>(buf); uint8_t* dst = static_cast<uint8_t*>(buf);
int pos = reinterpret_cast<int>(addr); int pos = reinterpret_cast<int>(addr);
while (length-- > 0) while (length-- > 0) {
{
*dst++ = EEPROM.read(pos++); *dst++ = EEPROM.read(pos++);
} }
} }
@@ -63,13 +62,15 @@ void hwWriteConfig(const int addr, uint8_t value)
} }
int8_t hwSleep(unsigned long ms) { int8_t hwSleep(unsigned long ms)
{
// TODO: Not supported! // TODO: Not supported!
(void)ms; (void)ms;
return MY_SLEEP_NOT_POSSIBLE; return MY_SLEEP_NOT_POSSIBLE;
} }
int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
{
// TODO: Not supported! // TODO: Not supported!
(void)interrupt; (void)interrupt;
(void)mode; (void)mode;
@@ -77,7 +78,9 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) {
return MY_SLEEP_NOT_POSSIBLE; return MY_SLEEP_NOT_POSSIBLE;
} }
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
unsigned long ms)
{
// TODO: Not supported! // TODO: Not supported!
(void)interrupt1; (void)interrupt1;
(void)mode1; (void)mode1;
@@ -90,23 +93,27 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG) #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
ADC_MODE(ADC_VCC); ADC_MODE(ADC_VCC);
uint16_t hwCPUVoltage() { uint16_t hwCPUVoltage()
{
// in mV // in mV
return ESP.getVcc(); return ESP.getVcc();
} }
uint16_t hwCPUFrequency() { uint16_t hwCPUFrequency()
{
// in 1/10Mhz // in 1/10Mhz
return ESP.getCpuFreqMHz()*10; return ESP.getCpuFreqMHz()*10;
} }
uint16_t hwFreeMem() { uint16_t hwFreeMem()
{
return ESP.getFreeHeap(); return ESP.getFreeHeap();
} }
#endif #endif
#ifdef MY_DEBUG #ifdef MY_DEBUG
void hwDebugPrint(const char *fmt, ... ) { void hwDebugPrint(const char *fmt, ... )
{
char fmtBuffer[MY_SERIAL_OUTPUT_SIZE]; char fmtBuffer[MY_SERIAL_OUTPUT_SIZE];
#ifdef MY_GATEWAY_FEATURE #ifdef MY_GATEWAY_FEATURE
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
+2 -1
View File
@@ -88,7 +88,8 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
} }
// Not supported! // Not supported!
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
unsigned long ms)
{ {
(void)interrupt1; (void)interrupt1;
(void)mode1; (void)mode1;
+4 -2
View File
@@ -52,12 +52,14 @@ inline unsigned long hwMillis();
#ifdef MY_RF24_IRQ_PIN #ifdef MY_RF24_IRQ_PIN
static pthread_mutex_t hw_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t hw_mutex = PTHREAD_MUTEX_INITIALIZER;
static __inline__ void __hwUnlock(const uint8_t *__s) { static __inline__ void __hwUnlock(const uint8_t *__s)
{
pthread_mutex_unlock(&hw_mutex); pthread_mutex_unlock(&hw_mutex);
(void)__s; (void)__s;
} }
static __inline__ void __hwLock() { static __inline__ void __hwLock()
{
pthread_mutex_lock(&hw_mutex); pthread_mutex_lock(&hw_mutex);
} }
#endif #endif
+2 -1
View File
@@ -87,7 +87,8 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
} }
// Not supported! // Not supported!
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
unsigned long ms)
{ {
(void)interrupt1; (void)interrupt1;
(void)mode1; (void)mode1;
+6 -3
View File
@@ -26,15 +26,18 @@
#include "log.h" #include "log.h"
#include "bcm2835.h" #include "bcm2835.h"
class Bcm2835Init { class Bcm2835Init
{
public: public:
Bcm2835Init() { Bcm2835Init()
{
if (!bcm2835_init()) { if (!bcm2835_init()) {
logError("Failed to initialized bcm2835.\n"); logError("Failed to initialized bcm2835.\n");
exit(1); exit(1);
} }
} }
~Bcm2835Init() { ~Bcm2835Init()
{
bcm2835_close(); bcm2835_close();
} }
}; };
+28 -18
View File
@@ -42,7 +42,8 @@ ISR (WDT_vect)
void i2c_eeprom_write_byte(unsigned int eeaddress, byte data ) { void i2c_eeprom_write_byte(unsigned int eeaddress, byte data )
{
int rdata = data; int rdata = data;
Wire.beginTransmission(I2C_EEP_ADDRESS); Wire.beginTransmission(I2C_EEP_ADDRESS);
Wire.write((int)(eeaddress >> 8)); // MSB Wire.write((int)(eeaddress >> 8)); // MSB
@@ -51,7 +52,8 @@ void i2c_eeprom_write_byte(unsigned int eeaddress, byte data ) {
Wire.endTransmission(); Wire.endTransmission();
} }
byte i2c_eeprom_read_byte(unsigned int eeaddress ) { byte i2c_eeprom_read_byte(unsigned int eeaddress )
{
byte rdata = 0xFF; byte rdata = 0xFF;
Wire.beginTransmission(I2C_EEP_ADDRESS); Wire.beginTransmission(I2C_EEP_ADDRESS);
Wire.write((int)(eeaddress >> 8)); // MSB Wire.write((int)(eeaddress >> 8)); // MSB
@@ -68,8 +70,7 @@ void hwReadConfigBlock(void* buf, void* adr, size_t length)
{ {
uint8_t* dst = static_cast<uint8_t*>(buf); uint8_t* dst = static_cast<uint8_t*>(buf);
int offs = reinterpret_cast<int>(adr); int offs = reinterpret_cast<int>(adr);
while (length-- > 0) while (length-- > 0) {
{
*dst++ = i2c_eeprom_read_byte(offs++); *dst++ = i2c_eeprom_read_byte(offs++);
} }
} }
@@ -78,8 +79,7 @@ void hwWriteConfigBlock(void* buf, void* adr, size_t length)
{ {
uint8_t* src = static_cast<uint8_t*>(buf); uint8_t* src = static_cast<uint8_t*>(buf);
int offs = reinterpret_cast<int>(adr); int offs = reinterpret_cast<int>(adr);
while (length-- > 0) while (length-- > 0) {
{
i2c_eeprom_write_byte(offs++, *src++); i2c_eeprom_write_byte(offs++, *src++);
} }
} }
@@ -94,13 +94,13 @@ uint8_t hwReadConfig(int adr)
void hwWriteConfig(int adr, uint8_t value) void hwWriteConfig(int adr, uint8_t value)
{ {
uint8_t curr = hwReadConfig(adr); uint8_t curr = hwReadConfig(adr);
if (curr != value) if (curr != value) {
{
hwWriteConfigBlock(&value, reinterpret_cast<void*>(adr), 1); hwWriteConfigBlock(&value, reinterpret_cast<void*>(adr), 1);
} }
} }
void hwInit() { void hwInit()
{
MY_SERIALDEVICE.begin(MY_BAUD_RATE); MY_SERIALDEVICE.begin(MY_BAUD_RATE);
#if defined(MY_GATEWAY_SERIAL) #if defined(MY_GATEWAY_SERIAL)
while (!MY_SERIALDEVICE) {} while (!MY_SERIALDEVICE) {}
@@ -108,22 +108,26 @@ void hwInit() {
Wire.begin(); Wire.begin();
} }
void hwWatchdogReset() { void hwWatchdogReset()
{
// TODO: Not supported! // TODO: Not supported!
} }
void hwReboot() { void hwReboot()
{
NVIC_SystemReset(); NVIC_SystemReset();
while (true); while (true);
} }
int8_t hwSleep(unsigned long ms) { int8_t hwSleep(unsigned long ms)
{
// TODO: Not supported! // TODO: Not supported!
(void)ms; (void)ms;
return MY_SLEEP_NOT_POSSIBLE; return MY_SLEEP_NOT_POSSIBLE;
} }
int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
{
// TODO: Not supported! // TODO: Not supported!
(void)interrupt; (void)interrupt;
(void)mode; (void)mode;
@@ -131,7 +135,9 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) {
return MY_SLEEP_NOT_POSSIBLE; return MY_SLEEP_NOT_POSSIBLE;
} }
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
unsigned long ms)
{
// TODO: Not supported! // TODO: Not supported!
(void)interrupt1; (void)interrupt1;
(void)mode1; (void)mode1;
@@ -142,7 +148,8 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo
} }
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG) #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
uint16_t hwCPUVoltage() { uint16_t hwCPUVoltage()
{
// disable ADC // disable ADC
while (ADC->STATUS.bit.SYNCBUSY); while (ADC->STATUS.bit.SYNCBUSY);
@@ -178,19 +185,22 @@ uint16_t hwCPUVoltage() {
return valueRead * 4; return valueRead * 4;
} }
uint16_t hwCPUFrequency() { uint16_t hwCPUFrequency()
{
// TODO: currently reporting compile time frequency (in 1/10MHz) // TODO: currently reporting compile time frequency (in 1/10MHz)
return F_CPU / 100000UL; return F_CPU / 100000UL;
} }
uint16_t hwFreeMem() { uint16_t hwFreeMem()
{
// TODO: Not supported! // TODO: Not supported!
return 0; return 0;
} }
#endif #endif
#ifdef MY_DEBUG #ifdef MY_DEBUG
void hwDebugPrint(const char *fmt, ... ) { void hwDebugPrint(const char *fmt, ... )
{
if (MY_SERIALDEVICE) { if (MY_SERIALDEVICE) {
char fmtBuffer[MY_SERIAL_OUTPUT_SIZE]; char fmtBuffer[MY_SERIAL_OUTPUT_SIZE];
#ifdef MY_GATEWAY_FEATURE #ifdef MY_GATEWAY_FEATURE
+6 -3
View File
@@ -25,7 +25,8 @@ extern MyMessage _msgTmp;
unsigned long _inclusionStartTime; unsigned long _inclusionStartTime;
bool _inclusionMode; bool _inclusionMode;
inline void inclusionInit() { inline void inclusionInit()
{
_inclusionMode = false; _inclusionMode = false;
#if defined(MY_INCLUSION_BUTTON_FEATURE) #if defined(MY_INCLUSION_BUTTON_FEATURE)
// Setup digital in that triggers inclusion mode // Setup digital in that triggers inclusion mode
@@ -36,7 +37,8 @@ inline void inclusionInit() {
} }
void inclusionModeSet(bool newMode) { void inclusionModeSet(bool newMode)
{
if (newMode != _inclusionMode) { if (newMode != _inclusionMode) {
_inclusionMode = newMode; _inclusionMode = newMode;
// Send back mode change to controller // Send back mode change to controller
@@ -47,7 +49,8 @@ void inclusionModeSet(bool newMode) {
} }
} }
inline void inclusionProcess() { inline void inclusionProcess()
{
#ifdef MY_INCLUSION_BUTTON_FEATURE #ifdef MY_INCLUSION_BUTTON_FEATURE
if (!_inclusionMode && hwDigitalRead(MY_INCLUSION_MODE_BUTTON_PIN) == MY_INCLUSION_BUTTON_PRESSED) { if (!_inclusionMode && hwDigitalRead(MY_INCLUSION_MODE_BUTTON_PIN) == MY_INCLUSION_BUTTON_PRESSED) {
// Start inclusion mode // Start inclusion mode
+3 -6
View File
@@ -25,20 +25,17 @@
void setIndication( const indication_t ind ) void setIndication( const indication_t ind )
{ {
#if defined(MY_DEFAULT_TX_LED_PIN) #if defined(MY_DEFAULT_TX_LED_PIN)
if ((INDICATION_TX == ind) || (INDICATION_GW_TX == ind)) if ((INDICATION_TX == ind) || (INDICATION_GW_TX == ind)) {
{
ledsBlinkTx(1); ledsBlinkTx(1);
} else } else
#endif #endif
#if defined(MY_DEFAULT_RX_LED_PIN) #if defined(MY_DEFAULT_RX_LED_PIN)
if ((INDICATION_RX == ind) || (INDICATION_GW_RX == ind)) if ((INDICATION_RX == ind) || (INDICATION_GW_RX == ind)) {
{
ledsBlinkRx(1); ledsBlinkRx(1);
} else } else
#endif #endif
#if defined(MY_DEFAULT_ERR_LED_PIN) #if defined(MY_DEFAULT_ERR_LED_PIN)
if (ind > INDICATION_ERR_START) if (ind > INDICATION_ERR_START) {
{
// Number of blinks indicates which error occurred. // Number of blinks indicates which error occurred.
ledsBlinkErr(ind-INDICATION_ERR_START); ledsBlinkErr(ind-INDICATION_ERR_START);
} }
+12 -6
View File
@@ -45,11 +45,13 @@ inline void ledsInit()
#if defined(MY_DEFAULT_ERR_LED_PIN) #if defined(MY_DEFAULT_ERR_LED_PIN)
hwPinMode(MY_DEFAULT_ERR_LED_PIN, OUTPUT); hwPinMode(MY_DEFAULT_ERR_LED_PIN, OUTPUT);
#endif #endif
prevTime = hwMillis() - LED_PROCESS_INTERVAL_MS; // Substract some, to make sure leds gets updated on first run. prevTime = hwMillis() -
LED_PROCESS_INTERVAL_MS; // Substract some, to make sure leds gets updated on first run.
ledsProcess(); ledsProcess();
} }
void ledsProcess() { void ledsProcess()
{
// Just return if it is not the time... // Just return if it is not the time...
if ((hwMillis() - prevTime) < LED_PROCESS_INTERVAL_MS) { if ((hwMillis() - prevTime) < LED_PROCESS_INTERVAL_MS) {
return; return;
@@ -85,27 +87,31 @@ void ledsProcess() {
#endif #endif
} }
void ledsBlinkRx(uint8_t cnt) { void ledsBlinkRx(uint8_t cnt)
{
if (!countRx) { if (!countRx) {
countRx = cnt*LED_ON_OFF_RATIO; countRx = cnt*LED_ON_OFF_RATIO;
} }
ledsProcess(); ledsProcess();
} }
void ledsBlinkTx(uint8_t cnt) { void ledsBlinkTx(uint8_t cnt)
{
if(!countTx) { if(!countTx) {
countTx = cnt*LED_ON_OFF_RATIO; countTx = cnt*LED_ON_OFF_RATIO;
} }
ledsProcess(); ledsProcess();
} }
void ledsBlinkErr(uint8_t cnt) { void ledsBlinkErr(uint8_t cnt)
{
if(!countErr) { if(!countErr) {
countErr = cnt*LED_ON_OFF_RATIO; countErr = cnt*LED_ON_OFF_RATIO;
} }
ledsProcess(); ledsProcess();
} }
bool ledsBlinking() { bool ledsBlinking()
{
return countRx || countTx || countErr; return countRx || countTx || countErr;
} }
+2 -1
View File
@@ -21,7 +21,8 @@
extern "C" void __libc_init_array(void); extern "C" void __libc_init_array(void);
int main(void) { int main(void)
{
init(); init();
#if defined(USBCON) #if defined(USBCON)
#if defined(ARDUINO_ARCH_SAMD) #if defined(ARDUINO_ARCH_SAMD)
+28 -17
View File
@@ -38,7 +38,8 @@ extern "C" {
struct rst_info resetInfo; struct rst_info resetInfo;
extern "C" { extern "C" {
extern const uint32_t __attribute__((section(".ver_number"))) core_version = ARDUINO_ESP8266_GIT_VER; extern const uint32_t __attribute__((section(".ver_number"))) core_version =
ARDUINO_ESP8266_GIT_VER;
const char* core_release = const char* core_release =
#ifdef ARDUINO_ESP8266_RELEASE #ifdef ARDUINO_ESP8266_RELEASE
ARDUINO_ESP8266_RELEASE; ARDUINO_ESP8266_RELEASE;
@@ -47,18 +48,21 @@ extern "C" {
#endif #endif
} // extern "C" } // extern "C"
int atexit(void(*func)()) { int atexit(void(*func)())
{
(void)func; (void)func;
return 0; return 0;
} }
extern "C" void ets_update_cpu_frequency(int freqmhz); extern "C" void ets_update_cpu_frequency(int freqmhz);
void initVariant() __attribute__((weak)); void initVariant() __attribute__((weak));
void initVariant() { void initVariant()
{
} }
void preloop_update_frequency() __attribute__((weak)); void preloop_update_frequency() __attribute__((weak));
void preloop_update_frequency() { void preloop_update_frequency()
{
#if defined(F_CPU) && (F_CPU == 160000000L) #if defined(F_CPU) && (F_CPU == 160000000L)
REG_SET_BIT(0x3ff00014, BIT(0)); REG_SET_BIT(0x3ff00014, BIT(0));
ets_update_cpu_frequency(160); ets_update_cpu_frequency(160);
@@ -73,37 +77,40 @@ static os_event_t g_loop_queue[LOOP_QUEUE_SIZE];
static uint32_t g_micros_at_task_start; static uint32_t g_micros_at_task_start;
extern "C" void esp_yield() { extern "C" void esp_yield()
{
if (cont_can_yield(&g_cont)) { if (cont_can_yield(&g_cont)) {
cont_yield(&g_cont); cont_yield(&g_cont);
} }
} }
extern "C" void esp_schedule() { extern "C" void esp_schedule()
{
ets_post(LOOP_TASK_PRIORITY, 0, 0); ets_post(LOOP_TASK_PRIORITY, 0, 0);
} }
extern "C" void __yield() { extern "C" void __yield()
{
if (cont_can_yield(&g_cont)) { if (cont_can_yield(&g_cont)) {
esp_schedule(); esp_schedule();
esp_yield(); esp_yield();
} } else {
else {
panic(); panic();
} }
} }
extern "C" void yield(void) __attribute__((weak, alias("__yield"))); extern "C" void yield(void) __attribute__((weak, alias("__yield")));
extern "C" void optimistic_yield(uint32_t interval_us) { extern "C" void optimistic_yield(uint32_t interval_us)
if (cont_can_yield(&g_cont) &&
(system_get_time() - g_micros_at_task_start) > interval_us)
{ {
if (cont_can_yield(&g_cont) &&
(system_get_time() - g_micros_at_task_start) > interval_us) {
yield(); yield();
} }
} }
static void loop_wrapper() { static void loop_wrapper()
{
static bool setup_done = false; static bool setup_done = false;
preloop_update_frequency(); preloop_update_frequency();
if (!setup_done) { if (!setup_done) {
@@ -116,7 +123,8 @@ static void loop_wrapper() {
esp_schedule(); esp_schedule();
} }
static void loop_task(os_event_t *events) { static void loop_task(os_event_t *events)
{
(void)events; (void)events;
g_micros_at_task_start = system_get_time(); g_micros_at_task_start = system_get_time();
cont_run(&g_cont, &loop_wrapper); cont_run(&g_cont, &loop_wrapper);
@@ -125,7 +133,8 @@ static void loop_task(os_event_t *events) {
} }
} }
static void do_global_ctors(void) { static void do_global_ctors(void)
{
void(**p)(void) = &__init_array_end; void(**p)(void) = &__init_array_end;
while (p != &__init_array_start) { while (p != &__init_array_start) {
(*--p)(); (*--p)();
@@ -138,7 +147,8 @@ extern "C" void gdb_init(void) __attribute__((weak, alias("__gdb_init")));
extern "C" void __gdb_do_break() {} extern "C" void __gdb_do_break() {}
extern "C" void gdb_do_break(void) __attribute__((weak, alias("__gdb_do_break"))); extern "C" void gdb_do_break(void) __attribute__((weak, alias("__gdb_do_break")));
void init_done() { void init_done()
{
system_set_os_print(1); system_set_os_print(1);
gdb_init(); gdb_init();
do_global_ctors(); do_global_ctors();
@@ -146,7 +156,8 @@ void init_done() {
} }
extern "C" void user_init(void) { extern "C" void user_init(void)
{
struct rst_info *rtc_info_ptr = system_get_rst_info(); struct rst_info *rtc_info_ptr = system_get_rst_info();
memcpy((void *)&resetInfo, (void *)rtc_info_ptr, sizeof(resetInfo)); memcpy((void *)&resetInfo, (void *)rtc_info_ptr, sizeof(resetInfo));
+21 -12
View File
@@ -137,7 +137,9 @@ void print_soft_sign_hmac_key(uint8_t *key_ptr = NULL)
printf("#define MY_SOFT_HMAC_KEY "); printf("#define MY_SOFT_HMAC_KEY ");
for (int i=0; i<32; i++) { for (int i=0; i<32; i++) {
printf("%#02X", key_ptr[i]); printf("%#02X", key_ptr[i]);
if (i < 31) printf(","); if (i < 31) {
printf(",");
}
} }
printf("\n\n"); printf("\n\n");
} }
@@ -172,12 +174,13 @@ void set_soft_sign_hmac_key(char *key_str)
} else { } else {
for (int i = 0; i < 64; ++i) { for (int i = 0; i < 64; ++i) {
char c = key_str[i]; char c = key_str[i];
if (c <= '9') if (c <= '9') {
n = c - '0'; n = c - '0';
else if (c >= 'a') } else if (c >= 'a') {
n = c - 'a' + 10; n = c - 'a' + 10;
else } else {
n = c - 'A' + 10; n = c - 'A' + 10;
}
if ((i & 0x1) == 0) { if ((i & 0x1) == 0) {
key[i/2] = n * 16; key[i/2] = n * 16;
@@ -209,7 +212,9 @@ void print_soft_sign_serial_key(uint8_t *key_ptr = NULL)
printf("#define MY_SOFT_SERIAL "); printf("#define MY_SOFT_SERIAL ");
for (int i=0; i<9; i++) { for (int i=0; i<9; i++) {
printf("%#02X", key_ptr[i]); printf("%#02X", key_ptr[i]);
if (i < 8) printf(","); if (i < 8) {
printf(",");
}
} }
printf("\n\n"); printf("\n\n");
} }
@@ -244,12 +249,13 @@ void set_soft_sign_serial_key(char *key_str)
} else { } else {
for (int i = 0; i < 18; ++i) { for (int i = 0; i < 18; ++i) {
char c = key_str[i]; char c = key_str[i];
if (c <= '9') if (c <= '9') {
n = c - '0'; n = c - '0';
else if (c >= 'a') } else if (c >= 'a') {
n = c - 'a' + 10; n = c - 'a' + 10;
else } else {
n = c - 'A' + 10; n = c - 'A' + 10;
}
if ((i & 0x1) == 0) { if ((i & 0x1) == 0) {
key[i/2] = n * 16; key[i/2] = n * 16;
@@ -281,7 +287,9 @@ void print_aes_key(uint8_t *key_ptr = NULL)
printf("#define MY_AES_KEY "); printf("#define MY_AES_KEY ");
for (int i=0; i<16; i++) { for (int i=0; i<16; i++) {
printf("%#02X", key_ptr[i]); printf("%#02X", key_ptr[i]);
if (i < 15) printf(","); if (i < 15) {
printf(",");
}
} }
printf("\n\n"); printf("\n\n");
} }
@@ -316,12 +324,13 @@ void set_aes_key(char *key_str)
} else { } else {
for (int i = 0; i < 32; ++i) { for (int i = 0; i < 32; ++i) {
char c = key_str[i]; char c = key_str[i];
if (c <= '9') if (c <= '9') {
n = c - '0'; n = c - '0';
else if (c >= 'a') } else if (c >= 'a') {
n = c - 'a' + 10; n = c - 'a' + 10;
else } else {
n = c - 'A' + 10; n = c - 'A' + 10;
}
if ((i & 0x1) == 0) { if ((i & 0x1) == 0) {
key[i/2] = n * 16; key[i/2] = n * 16;
+55 -30
View File
@@ -50,20 +50,24 @@ void MyMessage::clear()
miSetVersion(PROTOCOL_VERSION); miSetVersion(PROTOCOL_VERSION);
} }
bool MyMessage::isAck() const { bool MyMessage::isAck() const
{
return miGetAck(); return miGetAck();
} }
uint8_t MyMessage::getCommand() const { uint8_t MyMessage::getCommand() const
{
return miGetCommand(); return miGetCommand();
} }
/* Getters for payload converted to desired form */ /* Getters for payload converted to desired form */
void* MyMessage::getCustom() const { void* MyMessage::getCustom() const
{
return (void *)data; return (void *)data;
} }
const char* MyMessage::getString() const { const char* MyMessage::getString() const
{
uint8_t payloadType = miGetPayloadType(); uint8_t payloadType = miGetPayloadType();
if (payloadType == P_STRING) { if (payloadType == P_STRING) {
return data; return data;
@@ -73,19 +77,19 @@ const char* MyMessage::getString() const {
} }
// handles single character hex (0 - 15) // handles single character hex (0 - 15)
char MyMessage::i2h(uint8_t i) const { char MyMessage::i2h(uint8_t i) const
{
uint8_t k = i & 0x0F; uint8_t k = i & 0x0F;
if (k <= 9) { if (k <= 9) {
return '0' + k; return '0' + k;
} } else {
else {
return 'A' + k - 10; return 'A' + k - 10;
} }
} }
char* MyMessage::getCustomString(char *buffer) const { char* MyMessage::getCustomString(char *buffer) const
for (uint8_t i = 0; i < miGetLength(); i++)
{ {
for (uint8_t i = 0; i < miGetLength(); i++) {
buffer[i * 2] = i2h(data[i] >> 4); buffer[i * 2] = i2h(data[i] >> 4);
buffer[(i * 2) + 1] = i2h(data[i]); buffer[(i * 2) + 1] = i2h(data[i]);
} }
@@ -93,7 +97,8 @@ char* MyMessage::getCustomString(char *buffer) const {
return buffer; return buffer;
} }
char* MyMessage::getStream(char *buffer) const { char* MyMessage::getStream(char *buffer) const
{
uint8_t cmd = miGetCommand(); uint8_t cmd = miGetCommand();
if ((cmd == C_STREAM) && (buffer != NULL)) { if ((cmd == C_STREAM) && (buffer != NULL)) {
return getCustomString(buffer); return getCustomString(buffer);
@@ -102,7 +107,8 @@ char* MyMessage::getStream(char *buffer) const {
} }
} }
char* MyMessage::getString(char *buffer) const { char* MyMessage::getString(char *buffer) const
{
uint8_t payloadType = miGetPayloadType(); uint8_t payloadType = miGetPayloadType();
if (buffer != NULL) { if (buffer != NULL) {
if (payloadType == P_STRING) { if (payloadType == P_STRING) {
@@ -129,11 +135,13 @@ char* MyMessage::getString(char *buffer) const {
} }
} }
bool MyMessage::getBool() const { bool MyMessage::getBool() const
{
return getByte(); return getByte();
} }
uint8_t MyMessage::getByte() const { uint8_t MyMessage::getByte() const
{
if (miGetPayloadType() == P_BYTE) { if (miGetPayloadType() == P_BYTE) {
return data[0]; return data[0];
} else if (miGetPayloadType() == P_STRING) { } else if (miGetPayloadType() == P_STRING) {
@@ -144,7 +152,8 @@ uint8_t MyMessage::getByte() const {
} }
float MyMessage::getFloat() const { float MyMessage::getFloat() const
{
if (miGetPayloadType() == P_FLOAT32) { if (miGetPayloadType() == P_FLOAT32) {
return fValue; return fValue;
} else if (miGetPayloadType() == P_STRING) { } else if (miGetPayloadType() == P_STRING) {
@@ -154,7 +163,8 @@ float MyMessage::getFloat() const {
} }
} }
int32_t MyMessage::getLong() const { int32_t MyMessage::getLong() const
{
if (miGetPayloadType() == P_LONG32) { if (miGetPayloadType() == P_LONG32) {
return lValue; return lValue;
} else if (miGetPayloadType() == P_STRING) { } else if (miGetPayloadType() == P_STRING) {
@@ -164,7 +174,8 @@ int32_t MyMessage::getLong() const {
} }
} }
uint32_t MyMessage::getULong() const { uint32_t MyMessage::getULong() const
{
if (miGetPayloadType() == P_ULONG32) { if (miGetPayloadType() == P_ULONG32) {
return ulValue; return ulValue;
} else if (miGetPayloadType() == P_STRING) { } else if (miGetPayloadType() == P_STRING) {
@@ -174,7 +185,8 @@ uint32_t MyMessage::getULong() const {
} }
} }
int16_t MyMessage::getInt() const { int16_t MyMessage::getInt() const
{
if (miGetPayloadType() == P_INT16) { if (miGetPayloadType() == P_INT16) {
return iValue; return iValue;
} else if (miGetPayloadType() == P_STRING) { } else if (miGetPayloadType() == P_STRING) {
@@ -184,7 +196,8 @@ int16_t MyMessage::getInt() const {
} }
} }
uint16_t MyMessage::getUInt() const { uint16_t MyMessage::getUInt() const
{
if (miGetPayloadType() == P_UINT16) { if (miGetPayloadType() == P_UINT16) {
return uiValue; return uiValue;
} else if (miGetPayloadType() == P_STRING) { } else if (miGetPayloadType() == P_STRING) {
@@ -195,23 +208,27 @@ uint16_t MyMessage::getUInt() const {
} }
MyMessage& MyMessage::setType(uint8_t _type) { MyMessage& MyMessage::setType(uint8_t _type)
{
type = _type; type = _type;
return *this; return *this;
} }
MyMessage& MyMessage::setSensor(uint8_t _sensor) { MyMessage& MyMessage::setSensor(uint8_t _sensor)
{
sensor = _sensor; sensor = _sensor;
return *this; return *this;
} }
MyMessage& MyMessage::setDestination(uint8_t _destination) { MyMessage& MyMessage::setDestination(uint8_t _destination)
{
destination = _destination; destination = _destination;
return *this; return *this;
} }
// Set payload // Set payload
MyMessage& MyMessage::set(void* value, uint8_t length) { MyMessage& MyMessage::set(void* value, uint8_t length)
{
uint8_t payloadLength = value == NULL ? 0 : min(length, (uint8_t)MAX_PAYLOAD); uint8_t payloadLength = value == NULL ? 0 : min(length, (uint8_t)MAX_PAYLOAD);
miSetLength(payloadLength); miSetLength(payloadLength);
miSetPayloadType(P_CUSTOM); miSetPayloadType(P_CUSTOM);
@@ -219,7 +236,8 @@ MyMessage& MyMessage::set(void* value, uint8_t length) {
return *this; return *this;
} }
MyMessage& MyMessage::set(const char* value) { MyMessage& MyMessage::set(const char* value)
{
uint8_t length = value == NULL ? 0 : min(strlen(value), (size_t)MAX_PAYLOAD); uint8_t length = value == NULL ? 0 : min(strlen(value), (size_t)MAX_PAYLOAD);
miSetLength(length); miSetLength(length);
miSetPayloadType(P_STRING); miSetPayloadType(P_STRING);
@@ -231,21 +249,24 @@ MyMessage& MyMessage::set(const char* value) {
return *this; return *this;
} }
MyMessage& MyMessage::set(bool value) { MyMessage& MyMessage::set(bool value)
{
miSetLength(1); miSetLength(1);
miSetPayloadType(P_BYTE); miSetPayloadType(P_BYTE);
data[0] = value; data[0] = value;
return *this; return *this;
} }
MyMessage& MyMessage::set(uint8_t value) { MyMessage& MyMessage::set(uint8_t value)
{
miSetLength(1); miSetLength(1);
miSetPayloadType(P_BYTE); miSetPayloadType(P_BYTE);
data[0] = value; data[0] = value;
return *this; return *this;
} }
MyMessage& MyMessage::set(float value, uint8_t decimals) { MyMessage& MyMessage::set(float value, uint8_t decimals)
{
miSetLength(5); // 32 bit float + persi miSetLength(5); // 32 bit float + persi
miSetPayloadType(P_FLOAT32); miSetPayloadType(P_FLOAT32);
fValue=value; fValue=value;
@@ -253,28 +274,32 @@ MyMessage& MyMessage::set(float value, uint8_t decimals) {
return *this; return *this;
} }
MyMessage& MyMessage::set(uint32_t value) { MyMessage& MyMessage::set(uint32_t value)
{
miSetPayloadType(P_ULONG32); miSetPayloadType(P_ULONG32);
miSetLength(4); miSetLength(4);
ulValue = value; ulValue = value;
return *this; return *this;
} }
MyMessage& MyMessage::set(int32_t value) { MyMessage& MyMessage::set(int32_t value)
{
miSetPayloadType(P_LONG32); miSetPayloadType(P_LONG32);
miSetLength(4); miSetLength(4);
lValue = value; lValue = value;
return *this; return *this;
} }
MyMessage& MyMessage::set(uint16_t value) { MyMessage& MyMessage::set(uint16_t value)
{
miSetPayloadType(P_UINT16); miSetPayloadType(P_UINT16);
miSetLength(2); miSetLength(2);
uiValue = value; uiValue = value;
return *this; return *this;
} }
MyMessage& MyMessage::set(int16_t value) { MyMessage& MyMessage::set(int16_t value)
{
miSetPayloadType(P_INT16); miSetPayloadType(P_INT16);
miSetLength(2); miSetLength(2);
iValue = value; iValue = value;
+1 -2
View File
@@ -331,8 +331,7 @@ public:
#else #else
typedef union { typedef union {
struct struct {
{
#endif #endif
uint8_t last; // 8 bit - Id of last node this message passed uint8_t last; // 8 bit - Id of last node this message passed
+13 -8
View File
@@ -33,7 +33,8 @@ uint8_t _firmwareRetry;
void readFirmwareSettings(void) void readFirmwareSettings(void)
{ {
hwReadConfigBlock((void*)&_nodeFirmwareConfig, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(nodeFirmwareConfig_t)); hwReadConfigBlock((void*)&_nodeFirmwareConfig, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS,
sizeof(nodeFirmwareConfig_t));
} }
void firmwareOTAUpdateRequest(void) void firmwareOTAUpdateRequest(void)
@@ -54,8 +55,10 @@ void firmwareOTAUpdateRequest(void)
firmwareRequest.type = _nodeFirmwareConfig.type; firmwareRequest.type = _nodeFirmwareConfig.type;
firmwareRequest.version = _nodeFirmwareConfig.version; firmwareRequest.version = _nodeFirmwareConfig.version;
firmwareRequest.block = (_firmwareBlock - 1); firmwareRequest.block = (_firmwareBlock - 1);
OTA_DEBUG(PSTR("OTA:FRQ:FW REQ,T=%04X,V=%04X,B=%04X\n"), _nodeFirmwareConfig.type, _nodeFirmwareConfig.version, _firmwareBlock - 1); // request FW update block OTA_DEBUG(PSTR("OTA:FRQ:FW REQ,T=%04X,V=%04X,B=%04X\n"), _nodeFirmwareConfig.type,
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_REQUEST, false).set(&firmwareRequest, sizeof(requestFirmwareBlock_t))); _nodeFirmwareConfig.version, _firmwareBlock - 1); // request FW update block
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_REQUEST,
false).set(&firmwareRequest, sizeof(requestFirmwareBlock_t)));
} }
} }
@@ -96,7 +99,8 @@ bool firmwareOTAUpdateProcess(void)
// extract FW block // extract FW block
replyFirmwareBlock_t *firmwareResponse = (replyFirmwareBlock_t *)_msg.data; replyFirmwareBlock_t *firmwareResponse = (replyFirmwareBlock_t *)_msg.data;
// write to flash // write to flash
_flash.writeBytes( ((_firmwareBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET, firmwareResponse->data, FIRMWARE_BLOCK_SIZE); _flash.writeBytes( ((_firmwareBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET,
firmwareResponse->data, FIRMWARE_BLOCK_SIZE);
// wait until flash written // wait until flash written
while (_flash.busy()) {} while (_flash.busy()) {}
_firmwareBlock--; _firmwareBlock--;
@@ -107,7 +111,8 @@ bool firmwareOTAUpdateProcess(void)
if (transportIsValidFirmware()) { if (transportIsValidFirmware()) {
OTA_DEBUG(PSTR("OTA:FWP:CRC OK\n")); // FW checksum ok OTA_DEBUG(PSTR("OTA:FWP:CRC OK\n")); // FW checksum ok
// Write the new firmware config to eeprom // Write the new firmware config to eeprom
hwWriteConfigBlock((void*)&_nodeFirmwareConfig, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(nodeFirmwareConfig_t)); hwWriteConfigBlock((void*)&_nodeFirmwareConfig, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS,
sizeof(nodeFirmwareConfig_t));
// All seems ok, write size and signature to flash (DualOptiboot will pick this up and flash it) // All seems ok, write size and signature to flash (DualOptiboot will pick this up and flash it)
const uint16_t firmwareSize = FIRMWARE_BLOCK_SIZE * _nodeFirmwareConfig.blocks; const uint16_t firmwareSize = FIRMWARE_BLOCK_SIZE * _nodeFirmwareConfig.blocks;
const uint8_t OTAbuffer[FIRMWARE_START_OFFSET] = {'F','L','X','I','M','G',':', (uint8_t)(firmwareSize >> 8), (uint8_t)(firmwareSize & 0xff),':'}; const uint8_t OTAbuffer[FIRMWARE_START_OFFSET] = {'F','L','X','I','M','G',':', (uint8_t)(firmwareSize >> 8), (uint8_t)(firmwareSize & 0xff),':'};
@@ -142,7 +147,8 @@ void presentBootloaderInformation(void)
// add bootloader information // add bootloader information
requestFirmwareConfig->BLVersion = MY_OTA_BOOTLOADER_VERSION; requestFirmwareConfig->BLVersion = MY_OTA_BOOTLOADER_VERSION;
_firmwareUpdateOngoing = false; _firmwareUpdateOngoing = false;
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_CONFIG_REQUEST, false)); (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM,
ST_FIRMWARE_CONFIG_REQUEST, false));
} }
bool isFirmwareUpdateOngoing(void) bool isFirmwareUpdateOngoing(void)
{ {
@@ -158,8 +164,7 @@ bool transportIsValidFirmware(void)
for (int8_t j = 0; j < 8; ++j) { for (int8_t j = 0; j < 8; ++j) {
if (crc & 1) { if (crc & 1) {
crc = (crc >> 1) ^ 0xA001; crc = (crc >> 1) ^ 0xA001;
} } else {
else {
crc = (crc >> 1); crc = (crc >> 1);
} }
} }
+20 -14
View File
@@ -27,7 +27,8 @@ uint8_t protocolH2i(char c);
char _fmtBuffer[MY_GATEWAY_MAX_SEND_LENGTH]; char _fmtBuffer[MY_GATEWAY_MAX_SEND_LENGTH];
char _convBuffer[MAX_PAYLOAD*2+1]; char _convBuffer[MAX_PAYLOAD*2+1];
bool protocolParse(MyMessage &message, char *inputString) { bool protocolParse(MyMessage &message, char *inputString)
{
char *str, *p, *value=NULL; char *str, *p, *value=NULL;
uint8_t bvalue[MAX_PAYLOAD]; uint8_t bvalue[MAX_PAYLOAD];
uint8_t blen = 0; uint8_t blen = 0;
@@ -91,30 +92,36 @@ bool protocolParse(MyMessage &message, char *inputString) {
mSetAck(message, false); mSetAck(message, false);
if (command == C_STREAM) { if (command == C_STREAM) {
message.set(bvalue, blen); message.set(bvalue, blen);
} } else {
else {
message.set(value); message.set(value);
} }
return true; return true;
} }
char * protocolFormat(MyMessage &message) { char * protocolFormat(MyMessage &message)
snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%d;%d;%d;%d;%d;%s\n"), message.sender, message.sensor, (uint8_t)mGetCommand(message), (uint8_t)mGetAck(message), message.type, message.getString(_convBuffer)); {
snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%d;%d;%d;%d;%d;%s\n"), message.sender,
message.sensor, (uint8_t)mGetCommand(message), (uint8_t)mGetAck(message), message.type,
message.getString(_convBuffer));
return _fmtBuffer; return _fmtBuffer;
} }
char * protocolFormatMQTTTopic(const char* prefix, MyMessage &message) { char * protocolFormatMQTTTopic(const char* prefix, MyMessage &message)
snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%s/%d/%d/%d/%d/%d"), prefix, message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type); {
snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%s/%d/%d/%d/%d/%d"), prefix,
message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type);
return _fmtBuffer; return _fmtBuffer;
} }
char * protocolFormatMQTTSubscribe(const char* prefix) { char * protocolFormatMQTTSubscribe(const char* prefix)
{
snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%s/+/+/+/+/+"), prefix); snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%s/+/+/+/+/+"), prefix);
return _fmtBuffer; return _fmtBuffer;
} }
#ifdef MY_GATEWAY_MQTT_CLIENT #ifdef MY_GATEWAY_MQTT_CLIENT
bool protocolMQTTParse(MyMessage &message, char* topic, uint8_t* payload, unsigned int length) { bool protocolMQTTParse(MyMessage &message, char* topic, uint8_t* payload, unsigned int length)
{
char *str, *p; char *str, *p;
uint8_t i = 0; uint8_t i = 0;
uint8_t bvalue[MAX_PAYLOAD]; uint8_t bvalue[MAX_PAYLOAD];
@@ -188,15 +195,14 @@ bool protocolMQTTParse(MyMessage &message, char* topic, uint8_t* payload, unsign
} }
#endif #endif
uint8_t protocolH2i(char c) { uint8_t protocolH2i(char c)
{
uint8_t i = 0; uint8_t i = 0;
if (c <= '9') { if (c <= '9') {
i += c - '0'; i += c - '0';
} } else if (c >= 'a') {
else if (c >= 'a') {
i += c - 'a' + 10; i += c - 'a' + 10;
} } else {
else {
i += c - 'A' + 10; i += c - 'A' + 10;
} }
return i; return i;
+115 -82
View File
@@ -47,7 +47,8 @@ void _callbackTransportReady(void)
} }
} }
void _process(void) { void _process(void)
{
doYield(); doYield();
#if defined(MY_INCLUSION_MODE_FEATURE) #if defined(MY_INCLUSION_MODE_FEATURE)
@@ -68,7 +69,8 @@ void _process(void) {
#endif #endif
} }
void _infiniteLoop(void) { void _infiniteLoop(void)
{
while(1) { while(1) {
doYield(); doYield();
#if defined(__linux__) #if defined(__linux__)
@@ -77,7 +79,8 @@ void _infiniteLoop(void) {
} }
} }
void _begin(void) { void _begin(void)
{
// reset wdt // reset wdt
hwWatchdogReset(); hwWatchdogReset();
@@ -87,7 +90,8 @@ void _begin(void) {
hwInit(); hwInit();
CORE_DEBUG(PSTR("MCO:BGN:INIT " MY_NODE_TYPE ",CP=" MY_CAPABILITIES ",VER=" MYSENSORS_LIBRARY_VERSION "\n")); CORE_DEBUG(PSTR("MCO:BGN:INIT " MY_NODE_TYPE ",CP=" MY_CAPABILITIES ",VER="
MYSENSORS_LIBRARY_VERSION "\n"));
// set defaults // set defaults
_coreConfig.presentationSent = false; _coreConfig.presentationSent = false;
@@ -106,7 +110,8 @@ void _begin(void) {
// Read latest received controller configuration from EEPROM // Read latest received controller configuration from EEPROM
// Note: _coreConfig.isMetric is bool, hence empty EEPROM (=0xFF) evaluates to true (default) // Note: _coreConfig.isMetric is bool, hence empty EEPROM (=0xFF) evaluates to true (default)
hwReadConfigBlock((void*)&_coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(controllerConfig_t)); hwReadConfigBlock((void*)&_coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS,
sizeof(controllerConfig_t));
#if defined(MY_OTA_FIRMWARE_FEATURE) #if defined(MY_OTA_FIRMWARE_FEATURE)
// Read firmware config from EEPROM, i.e. type, version, CRC, blocks // Read firmware config from EEPROM, i.e. type, version, CRC, blocks
@@ -164,7 +169,8 @@ void _registerNode(void)
uint8_t counter = MY_REGISTRATION_RETRIES; uint8_t counter = MY_REGISTRATION_RETRIES;
// only proceed if register response received or retries exceeded // only proceed if register response received or retries exceeded
do { do {
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_REGISTRATION_REQUEST).set(MY_CORE_VERSION)); (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
I_REGISTRATION_REQUEST).set(MY_CORE_VERSION));
} while (!wait(2000, C_INTERNAL, I_REGISTRATION_RESPONSE) && counter--); } while (!wait(2000, C_INTERNAL, I_REGISTRATION_RESPONSE) && counter--);
#else #else
_coreConfig.nodeRegistered = true; _coreConfig.nodeRegistered = true;
@@ -172,7 +178,8 @@ void _registerNode(void)
#endif #endif
} }
void presentNode(void) { void presentNode(void)
{
setIndication(INDICATION_PRESENT); setIndication(INDICATION_PRESENT);
// Present node and request config // Present node and request config
#if defined(MY_GATEWAY_FEATURE) #if defined(MY_GATEWAY_FEATURE)
@@ -200,7 +207,8 @@ void presentNode(void) {
// Send a configuration exchange request to controller // Send a configuration exchange request to controller
// Node sends parent node. Controller answers with latest node configuration // Node sends parent node. Controller answers with latest node configuration
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CONFIG).set(getParentNodeId())); (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
I_CONFIG).set(getParentNodeId()));
// Wait configuration reply. // Wait configuration reply.
(void)wait(2000, C_INTERNAL, I_CONFIG); (void)wait(2000, C_INTERNAL, I_CONFIG);
@@ -240,12 +248,14 @@ uint8_t getDistanceGW(void)
#endif #endif
} }
controllerConfig_t getConfig(void) { controllerConfig_t getConfig(void)
{
return _coreConfig.controllerConfig; return _coreConfig.controllerConfig;
} }
bool _sendRoute(MyMessage &message) { bool _sendRoute(MyMessage &message)
{
#if defined(MY_CORE_ONLY) #if defined(MY_CORE_ONLY)
(void)message; (void)message;
#endif #endif
@@ -263,7 +273,8 @@ bool _sendRoute(MyMessage &message) {
#endif #endif
} }
bool send(MyMessage &message, const bool enableAck) { bool send(MyMessage &message, const bool enableAck)
{
message.sender = getNodeId(); message.sender = getNodeId();
mSetCommand(message, C_SET); mSetCommand(message, C_SET);
mSetRequestAck(message, enableAck); mSetRequestAck(message, enableAck);
@@ -271,8 +282,7 @@ bool send(MyMessage &message, const bool enableAck) {
#if defined(MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE) #if defined(MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE)
if (_coreConfig.nodeRegistered) { if (_coreConfig.nodeRegistered) {
return _sendRoute(message); return _sendRoute(message);
} } else {
else {
CORE_DEBUG(PSTR("!MCO:SND:NODE NOT REG\n")); // node not registered CORE_DEBUG(PSTR("!MCO:SND:NODE NOT REG\n")); // node not registered
return false; return false;
} }
@@ -281,45 +291,58 @@ bool send(MyMessage &message, const bool enableAck) {
#endif #endif
} }
bool sendBatteryLevel(const uint8_t value, const bool ack) { bool sendBatteryLevel(const uint8_t value, const bool ack)
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_BATTERY_LEVEL, ack).set(value)); {
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_BATTERY_LEVEL,
ack).set(value));
} }
bool sendHeartbeat(const bool ack) { bool sendHeartbeat(const bool ack)
{
#if defined(MY_SENSOR_NETWORK) #if defined(MY_SENSOR_NETWORK)
const uint32_t heartbeat = transportGetHeartbeat(); const uint32_t heartbeat = transportGetHeartbeat();
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT_RESPONSE, ack).set(heartbeat)); return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT_RESPONSE,
ack).set(heartbeat));
#else #else
(void)ack; (void)ack;
return false; return false;
#endif #endif
} }
bool present(const uint8_t childSensorId, const uint8_t sensorType, const char *description, const bool ack) { bool present(const uint8_t childSensorId, const uint8_t sensorType, const char *description,
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType, ack).set(childSensorId==NODE_SENSOR_ID?MYSENSORS_LIBRARY_VERSION:description)); const bool ack)
{
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType,
ack).set(childSensorId==NODE_SENSOR_ID?MYSENSORS_LIBRARY_VERSION:description));
} }
bool sendSketchInfo(const char *name, const char *version, const bool ack) { bool sendSketchInfo(const char *name, const char *version, const bool ack)
{
bool result = true; bool result = true;
if (name) { if (name) {
result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME, ack).set(name)); result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME,
ack).set(name));
} }
if (version) { if (version) {
result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION, ack).set(version)); result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION,
ack).set(version));
} }
return result; return result;
} }
bool request(const uint8_t childSensorId, const uint8_t variableType, const uint8_t destination) { bool request(const uint8_t childSensorId, const uint8_t variableType, const uint8_t destination)
{
return _sendRoute(build(_msgTmp, destination, childSensorId, C_REQ, variableType).set("")); return _sendRoute(build(_msgTmp, destination, childSensorId, C_REQ, variableType).set(""));
} }
bool requestTime(const bool ack) { bool requestTime(const bool ack)
{
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_TIME, ack).set("")); return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_TIME, ack).set(""));
} }
// Message delivered through _msg // Message delivered through _msg
bool _processInternalMessages(void) { bool _processInternalMessages(void)
{
const uint8_t type = _msg.type; const uint8_t type = _msg.type;
if (_msg.sender == GATEWAY_ADDRESS) { if (_msg.sender == GATEWAY_ADDRESS) {
@@ -329,33 +352,29 @@ bool _processInternalMessages(void) {
setIndication(INDICATION_REBOOT); setIndication(INDICATION_REBOOT);
hwReboot(); hwReboot();
#endif #endif
} } else if (type == I_REGISTRATION_RESPONSE) {
else if (type == I_REGISTRATION_RESPONSE) {
#if defined (MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE) #if defined (MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE)
_coreConfig.nodeRegistered = _msg.getBool(); _coreConfig.nodeRegistered = _msg.getBool();
setIndication(INDICATION_GOT_REGISTRATION); setIndication(INDICATION_GOT_REGISTRATION);
CORE_DEBUG(PSTR("MCO:PIM:NODE REG=%d\n"), _coreConfig.nodeRegistered); // node registration CORE_DEBUG(PSTR("MCO:PIM:NODE REG=%d\n"), _coreConfig.nodeRegistered); // node registration
#endif #endif
} } else if (type == I_CONFIG) {
else if (type == I_CONFIG) {
// Pick up configuration from controller (currently only metric/imperial) and store it in eeprom if changed // Pick up configuration from controller (currently only metric/imperial) and store it in eeprom if changed
_coreConfig.controllerConfig.isMetric = _msg.data[0] == 0x00 || _msg.data[0] == 'M'; // metric if null terminated or M _coreConfig.controllerConfig.isMetric = _msg.data[0] == 0x00 ||
hwWriteConfigBlock((void*)&_coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(controllerConfig_t)); _msg.data[0] == 'M'; // metric if null terminated or M
} hwWriteConfigBlock((void*)&_coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS,
else if (type == I_PRESENTATION) { sizeof(controllerConfig_t));
} else if (type == I_PRESENTATION) {
// Re-send node presentation to controller // Re-send node presentation to controller
presentNode(); presentNode();
} } else if (type == I_HEARTBEAT_REQUEST) {
else if (type == I_HEARTBEAT_REQUEST) {
(void)sendHeartbeat(); (void)sendHeartbeat();
} } else if (type == I_TIME) {
else if (type == I_TIME) {
// Deliver time to callback // Deliver time to callback
if (receiveTime) { if (receiveTime) {
receiveTime(_msg.getULong()); receiveTime(_msg.getULong());
} }
} } else if (type == I_CHILDREN) {
else if (type == I_CHILDREN) {
#if defined(MY_REPEATER_FEATURE) #if defined(MY_REPEATER_FEATURE)
if (_msg.data[0] == 'C') { if (_msg.data[0] == 'C') {
// Clears child relay data for this node // Clears child relay data for this node
@@ -364,8 +383,7 @@ bool _processInternalMessages(void) {
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN).set("OK")); (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN).set("OK"));
} }
#endif #endif
} } else if (type == I_DEBUG) {
else if (type == I_DEBUG) {
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG) #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
const char debug_msg = _msg.data[0]; const char debug_msg = _msg.data[0];
if (debug_msg == 'R') { // routing table if (debug_msg == 'R') { // routing table
@@ -375,22 +393,22 @@ bool _processInternalMessages(void) {
if (route != BROADCAST_ADDRESS) { if (route != BROADCAST_ADDRESS) {
CORE_DEBUG(PSTR("MCO:PIM:ROUTE N=%d,R=%d\n"), cnt, route); CORE_DEBUG(PSTR("MCO:PIM:ROUTE N=%d,R=%d\n"), cnt, route);
uint8_t outBuf[2] = { (uint8_t)cnt,route }; uint8_t outBuf[2] = { (uint8_t)cnt,route };
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(outBuf, 2)); (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(outBuf,
2));
wait(200); wait(200);
} }
} }
#endif #endif
} } else if (debug_msg == 'V') { // CPU voltage
else if (debug_msg == 'V') { // CPU voltage (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(hwCPUVoltage())); I_DEBUG).set(hwCPUVoltage()));
} } else if (debug_msg == 'F') { // CPU frequency in 1/10Mhz
else if (debug_msg == 'F') { // CPU frequency in 1/10Mhz (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(hwCPUFrequency())); I_DEBUG).set(hwCPUFrequency()));
} } else if (debug_msg == 'M') { // free memory
else if (debug_msg == 'M') { // free memory (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(hwFreeMem())); I_DEBUG).set(hwFreeMem()));
} } else if (debug_msg == 'E') { // clear MySensors eeprom area and reboot
else if (debug_msg == 'E') { // clear MySensors eeprom area and reboot
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set("OK")); (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set("OK"));
for (int i = EEPROM_START; i<EEPROM_LOCAL_CONFIG_ADDRESS; i++) { for (int i = EEPROM_START; i<EEPROM_LOCAL_CONFIG_ADDRESS; i++) {
hwWriteConfig(i, 0xFF); hwWriteConfig(i, 0xFF);
@@ -399,10 +417,10 @@ bool _processInternalMessages(void) {
hwReboot(); hwReboot();
} }
#endif #endif
} else {
return false;
} }
else return false; } else {
}
else {
// sender is a node // sender is a node
if (type == I_REGISTRATION_REQUEST) { if (type == I_REGISTRATION_REQUEST) {
#if defined(MY_GATEWAY_FEATURE) #if defined(MY_GATEWAY_FEATURE)
@@ -419,34 +437,40 @@ bool _processInternalMessages(void) {
// delay for fast GW and slow nodes // delay for fast GW and slow nodes
delay(5); delay(5);
#endif #endif
(void)_sendRoute(build(_msgTmp, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_REGISTRATION_RESPONSE).set(approveRegistration)); (void)_sendRoute(build(_msgTmp, _msg.sender, NODE_SENSOR_ID, C_INTERNAL,
I_REGISTRATION_RESPONSE).set(approveRegistration));
#else #else
return false; // processing of this request via controller return false; // processing of this request via controller
#endif #endif
#endif #endif
} else {
return false;
} }
else return false;
} }
return true; return true;
} }
void saveState(const uint8_t pos, const uint8_t value) { void saveState(const uint8_t pos, const uint8_t value)
{
hwWriteConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos, value); hwWriteConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos, value);
} }
uint8_t loadState(const uint8_t pos) { uint8_t loadState(const uint8_t pos)
{
return hwReadConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos); return hwReadConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos);
} }
void wait(const uint32_t waitingMS) { void wait(const uint32_t waitingMS)
{
const uint32_t enteringMS = hwMillis(); const uint32_t enteringMS = hwMillis();
while (hwMillis() - enteringMS < waitingMS) { while (hwMillis() - enteringMS < waitingMS) {
_process(); _process();
} }
} }
bool wait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType) { bool wait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType)
{
const uint32_t enteringMS = hwMillis(); const uint32_t enteringMS = hwMillis();
// invalidate msg type // invalidate msg type
_msg.type = !msgType; _msg.type = !msgType;
@@ -458,7 +482,8 @@ bool wait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType) {
return expectedResponse; return expectedResponse;
} }
void doYield(void) { void doYield(void)
{
hwWatchdogReset(); hwWatchdogReset();
yield(); yield();
@@ -468,8 +493,11 @@ void doYield(void) {
#endif #endif
} }
int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2) { int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t interrupt1,
CORE_DEBUG(PSTR("MCO:SLP:MS=%lu,SMS=%d,I1=%d,M1=%d,I2=%d,M2=%d\n"), sleepingMS, smartSleep, interrupt1, mode1, interrupt2, mode2); const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2)
{
CORE_DEBUG(PSTR("MCO:SLP:MS=%lu,SMS=%d,I1=%d,M1=%d,I2=%d,M2=%d\n"), sleepingMS, smartSleep,
interrupt1, mode1, interrupt2, mode2);
// OTA FW feature: do not sleep if FW update ongoing // OTA FW feature: do not sleep if FW update ongoing
#if defined(MY_OTA_FIRMWARE_FEATURE) #if defined(MY_OTA_FIRMWARE_FEATURE)
if (isFirmwareUpdateOngoing()) { if (isFirmwareUpdateOngoing()) {
@@ -497,7 +525,8 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
CORE_DEBUG(PSTR("!MCO:SLP:TNR\n")); // sleeping not possible, transport not ready CORE_DEBUG(PSTR("!MCO:SLP:TNR\n")); // sleeping not possible, transport not ready
const uint32_t sleepEnterMS = hwMillis(); const uint32_t sleepEnterMS = hwMillis();
uint32_t sleepDeltaMS = 0; uint32_t sleepDeltaMS = 0;
while (!isTransportReady() && (sleepDeltaMS < sleepingTimeMS) && (sleepDeltaMS < MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS)) { while (!isTransportReady() && (sleepDeltaMS < sleepingTimeMS) &&
(sleepDeltaMS < MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS)) {
_process(); _process();
sleepDeltaMS = hwMillis() - sleepEnterMS; sleepDeltaMS = hwMillis() - sleepEnterMS;
} }
@@ -505,8 +534,7 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
if (sleepDeltaMS < sleepingTimeMS) { if (sleepDeltaMS < sleepingTimeMS) {
sleepingTimeMS -= sleepDeltaMS; // calculate remaining sleeping time sleepingTimeMS -= sleepDeltaMS; // calculate remaining sleeping time
CORE_DEBUG(PSTR("MCO:SLP:MS=%lu\n"), sleepingTimeMS); CORE_DEBUG(PSTR("MCO:SLP:MS=%lu\n"), sleepingTimeMS);
} } else {
else {
// no sleeping time left // no sleeping time left
return MY_SLEEP_NOT_POSSIBLE; return MY_SLEEP_NOT_POSSIBLE;
} }
@@ -538,12 +566,10 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 != INTERRUPT_NOT_DEFINED) { if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 != INTERRUPT_NOT_DEFINED) {
// both IRQs // both IRQs
result = hwSleep(interrupt1, mode1, interrupt2, mode2, sleepingTimeMS); result = hwSleep(interrupt1, mode1, interrupt2, mode2, sleepingTimeMS);
} } else if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) {
else if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) {
// one IRQ // one IRQ
result = hwSleep(interrupt1, mode1, sleepingTimeMS); result = hwSleep(interrupt1, mode1, sleepingTimeMS);
} } else if (interrupt1 == INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) {
else if (interrupt1 == INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) {
// no IRQ // no IRQ
result = hwSleep(sleepingTimeMS); result = hwSleep(sleepingTimeMS);
} }
@@ -555,30 +581,39 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
} }
// sleep functions // sleep functions
int8_t sleep(const uint32_t sleepingMS, const bool smartSleep) { int8_t sleep(const uint32_t sleepingMS, const bool smartSleep)
{
return _sleep(sleepingMS, smartSleep); return _sleep(sleepingMS, smartSleep);
} }
int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS, const bool smartSleep) { int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS,
const bool smartSleep)
{
return _sleep(sleepingMS, smartSleep, interrupt, mode); return _sleep(sleepingMS, smartSleep, interrupt, mode);
} }
int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t sleepingMS, const bool smartSleep) { int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2,
const uint8_t mode2, const uint32_t sleepingMS, const bool smartSleep)
{
return _sleep(sleepingMS, smartSleep, interrupt1, mode1, interrupt2, mode2); return _sleep(sleepingMS, smartSleep, interrupt1, mode1, interrupt2, mode2);
} }
// deprecated smartSleep() functions // deprecated smartSleep() functions
int8_t smartSleep(const uint32_t sleepingMS) { int8_t smartSleep(const uint32_t sleepingMS)
{
// compatibility // compatibility
return _sleep(sleepingMS, true); return _sleep(sleepingMS, true);
} }
int8_t smartSleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS) { int8_t smartSleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS)
{
// compatibility // compatibility
return _sleep(sleepingMS, true, interrupt, mode); return _sleep(sleepingMS, true, interrupt, mode);
} }
int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t sleepingMS) { int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2,
const uint8_t mode2, const uint32_t sleepingMS)
{
// compatibility // compatibility
return _sleep(sleepingMS, true, interrupt1, mode1, interrupt2, mode2); return _sleep(sleepingMS, true, interrupt1, mode1, interrupt2, mode2);
} }
@@ -625,14 +660,12 @@ void _checkNodeLock(void)
hwPinMode(MY_NODE_UNLOCK_PIN, INPUT); hwPinMode(MY_NODE_UNLOCK_PIN, INPUT);
setIndication(INDICATION_ERR_LOCKED); setIndication(INDICATION_ERR_LOCKED);
CORE_DEBUG(PSTR("MCO:BGN:NODE UNLOCKED\n")); CORE_DEBUG(PSTR("MCO:BGN:NODE UNLOCKED\n"));
} } else {
else {
// Disable pullup // Disable pullup
hwPinMode(MY_NODE_UNLOCK_PIN, INPUT); hwPinMode(MY_NODE_UNLOCK_PIN, INPUT);
_nodeLock("LDB"); //Locked during boot _nodeLock("LDB"); //Locked during boot
} }
} } else if (hwReadConfig(EEPROM_NODE_LOCK_COUNTER) == 0xFF) {
else if (hwReadConfig(EEPROM_NODE_LOCK_COUNTER) == 0xFF) {
// Reset walue // Reset walue
hwWriteConfig(EEPROM_NODE_LOCK_COUNTER, MY_NODE_LOCK_COUNTER_MAX); hwWriteConfig(EEPROM_NODE_LOCK_COUNTER, MY_NODE_LOCK_COUNTER_MAX);
} }
+18 -8
View File
@@ -143,7 +143,8 @@ void presentNode(void);
* @param description A textual description of the sensor. * @param description A textual description of the sensor.
* @return true Returns true if message reached the first stop on its way to destination. * @return true Returns true if message reached the first stop on its way to destination.
*/ */
bool present(const uint8_t sensorId, const uint8_t sensorType, const char *description="", const bool ack = false); bool present(const uint8_t sensorId, const uint8_t sensorType, const char *description="",
const bool ack = false);
/** /**
* Sends sketch meta information to the gateway. Not mandatory but a nice thing to do. * Sends sketch meta information to the gateway. Not mandatory but a nice thing to do.
@@ -189,7 +190,8 @@ bool sendHeartbeat(const bool ack = false);
* @param destination The nodeId of other node in radio network. Default is gateway * @param destination The nodeId of other node in radio network. Default is gateway
* @return true Returns true if message reached the first stop on its way to destination. * @return true Returns true if message reached the first stop on its way to destination.
*/ */
bool request(const uint8_t childSensorId, const uint8_t variableType, const uint8_t destination = GATEWAY_ADDRESS); bool request(const uint8_t childSensorId, const uint8_t variableType,
const uint8_t destination = GATEWAY_ADDRESS);
/** /**
* Requests time from controller. Answer will be delivered to receiveTime function in sketch. * Requests time from controller. Answer will be delivered to receiveTime function in sketch.
@@ -269,7 +271,8 @@ int8_t sleep(const uint32_t sleepingMS, const bool smartSleep = false);
* @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep * @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep
* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) * @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update)
*/ */
int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS = 0, const bool smartSleep = false); int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS = 0,
const bool smartSleep = false);
/** /**
* Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts. * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts.
@@ -283,7 +286,8 @@ int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepin
* @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep. * @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep.
* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) * @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update)
*/ */
int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t sleepingMS = 0, const bool smartSleep = false); int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2,
const uint8_t mode2, const uint32_t sleepingMS = 0, const bool smartSleep = false);
/** /**
* \deprecated Use sleep(ms, true) instead * \deprecated Use sleep(ms, true) instead
@@ -316,7 +320,8 @@ int8_t smartSleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sl
* @param sleepingMS Number of milliseconds to sleep or 0 to sleep forever * @param sleepingMS Number of milliseconds to sleep or 0 to sleep forever
* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) * @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update)
*/ */
int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t sleepingMS = 0); int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2,
const uint8_t mode2, const uint32_t sleepingMS = 0);
/** /**
* Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts. * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts.
@@ -330,7 +335,9 @@ int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t i
* @param smartSleep (optional) Set True if sending heartbeat and process incoming messages before going to sleep. * @param smartSleep (optional) Set True if sending heartbeat and process incoming messages before going to sleep.
* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) * @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update)
*/ */
int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep = false, const uint8_t interrupt1 = INTERRUPT_NOT_DEFINED, const uint8_t mode1 = MODE_NOT_DEFINED, const uint8_t interrupt2 = INTERRUPT_NOT_DEFINED, const uint8_t mode2 = MODE_NOT_DEFINED); int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep = false,
const uint8_t interrupt1 = INTERRUPT_NOT_DEFINED, const uint8_t mode1 = MODE_NOT_DEFINED,
const uint8_t interrupt2 = INTERRUPT_NOT_DEFINED, const uint8_t mode2 = MODE_NOT_DEFINED);
/** /**
@@ -412,7 +419,9 @@ void loop(void) __attribute__((weak));
// Inline function and macros // Inline function and macros
static inline MyMessage& build(MyMessage &msg, const uint8_t destination, const uint8_t sensor, const uint8_t command, const uint8_t type, const bool ack = false) { static inline MyMessage& build(MyMessage &msg, const uint8_t destination, const uint8_t sensor,
const uint8_t command, const uint8_t type, const bool ack = false)
{
msg.sender = getNodeId(); msg.sender = getNodeId();
msg.destination = destination; msg.destination = destination;
msg.sensor = sensor; msg.sensor = sensor;
@@ -423,7 +432,8 @@ static inline MyMessage& build(MyMessage &msg, const uint8_t destination, const
return msg; return msg;
} }
static inline MyMessage& buildGw(MyMessage &msg, const uint8_t type) { static inline MyMessage& buildGw(MyMessage &msg, const uint8_t type)
{
msg.sender = GATEWAY_ADDRESS; msg.sender = GATEWAY_ADDRESS;
msg.destination = GATEWAY_ADDRESS; msg.destination = GATEWAY_ADDRESS;
msg.sensor = NODE_SENSOR_ID; msg.sensor = NODE_SENSOR_ID;
+23 -13
View File
@@ -82,12 +82,14 @@ extern bool signerAtsha204SignMsg(MyMessage &msg);
#endif #endif
// Helper function to centralize signing/verification exceptions // Helper function to centralize signing/verification exceptions
static bool skipSign(MyMessage &msg) { static bool skipSign(MyMessage &msg)
{
if mGetAck(msg) { if mGetAck(msg) {
SIGN_DEBUG(PSTR("Skipping security for ACK on command %d type %d\n"), mGetCommand(msg), msg.type); SIGN_DEBUG(PSTR("Skipping security for ACK on command %d type %d\n"), mGetCommand(msg), msg.type);
return true; return true;
} else if (mGetCommand(msg) == C_INTERNAL && } else if (mGetCommand(msg) == C_INTERNAL &&
(msg.type == I_NONCE_REQUEST || msg.type == I_NONCE_RESPONSE || msg.type == I_SIGNING_PRESENTATION || (msg.type == I_NONCE_REQUEST || msg.type == I_NONCE_RESPONSE ||
msg.type == I_SIGNING_PRESENTATION ||
msg.type == I_ID_REQUEST || msg.type == I_ID_RESPONSE || msg.type == I_ID_REQUEST || msg.type == I_ID_RESPONSE ||
msg.type == I_FIND_PARENT_REQUEST || msg.type == I_FIND_PARENT_RESPONSE || msg.type == I_FIND_PARENT_REQUEST || msg.type == I_FIND_PARENT_RESPONSE ||
msg.type == I_HEARTBEAT_REQUEST || msg.type == I_HEARTBEAT_RESPONSE || msg.type == I_HEARTBEAT_REQUEST || msg.type == I_HEARTBEAT_RESPONSE ||
@@ -107,7 +109,8 @@ static bool skipSign(MyMessage &msg) {
#endif // MY_SIGNING_FEATURE #endif // MY_SIGNING_FEATURE
// Helper to prepare a signing presentation message // Helper to prepare a signing presentation message
static void prepareSigningPresentation(MyMessage &msg, uint8_t destination) { static void prepareSigningPresentation(MyMessage &msg, uint8_t destination)
{
// Only supports version 1 for now // Only supports version 1 for now
(void)build(msg, destination, NODE_SENSOR_ID, C_INTERNAL, I_SIGNING_PRESENTATION).set(""); (void)build(msg, destination, NODE_SENSOR_ID, C_INTERNAL, I_SIGNING_PRESENTATION).set("");
mSetLength(msg, 2); mSetLength(msg, 2);
@@ -116,7 +119,8 @@ static void prepareSigningPresentation(MyMessage &msg, uint8_t destination) {
msg.data[1] = 0; msg.data[1] = 0;
} }
void signerInit(void) { void signerInit(void)
{
#if defined(MY_SIGNING_FEATURE) #if defined(MY_SIGNING_FEATURE)
// Read out the signing requirements from EEPROM // Read out the signing requirements from EEPROM
hwReadConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, hwReadConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS,
@@ -135,7 +139,8 @@ void signerInit(void) {
#endif #endif
} }
void signerPresentation(MyMessage &msg, uint8_t destination) { void signerPresentation(MyMessage &msg, uint8_t destination)
{
prepareSigningPresentation(msg, destination); prepareSigningPresentation(msg, destination);
#if defined(MY_SIGNING_REQUEST_SIGNATURES) #if defined(MY_SIGNING_REQUEST_SIGNATURES)
@@ -157,7 +162,8 @@ void signerPresentation(MyMessage &msg, uint8_t destination) {
} }
} }
bool signerProcessInternal(MyMessage &msg) { bool signerProcessInternal(MyMessage &msg)
{
uint8_t sender = msg.sender; uint8_t sender = msg.sender;
(void)sender; (void)sender;
#if !defined(MY_SIGNING_FEATURE) #if !defined(MY_SIGNING_FEATURE)
@@ -166,7 +172,8 @@ bool signerProcessInternal(MyMessage &msg) {
// If we act as gateway and do not have the signing feature and receive a signing request we still // If we act as gateway and do not have the signing feature and receive a signing request we still
// need to do make sure the requester does not believe the gateway still require signatures // need to do make sure the requester does not believe the gateway still require signatures
prepareSigningPresentation(msg, sender); prepareSigningPresentation(msg, sender);
SIGN_DEBUG(PSTR("Informing node %d that we do not require signatures because we do not support it\n"), SIGN_DEBUG(
PSTR("Informing node %d that we do not require signatures because we do not support it\n"),
sender); sender);
if (!_sendRoute(msg)) { if (!_sendRoute(msg)) {
SIGN_DEBUG(PSTR("Failed to transmit signing presentation!\n")); SIGN_DEBUG(PSTR("Failed to transmit signing presentation!\n"));
@@ -183,7 +190,8 @@ bool signerProcessInternal(MyMessage &msg) {
if (msg.type == I_NONCE_REQUEST) { if (msg.type == I_NONCE_REQUEST) {
#if defined(MY_NODE_LOCK_FEATURE) #if defined(MY_NODE_LOCK_FEATURE)
nof_nonce_requests++; nof_nonce_requests++;
SIGN_DEBUG(PSTR("Nonce requests left until lockdown: %d\n"), MY_NODE_LOCK_COUNTER_MAX-nof_nonce_requests); SIGN_DEBUG(PSTR("Nonce requests left until lockdown: %d\n"),
MY_NODE_LOCK_COUNTER_MAX-nof_nonce_requests);
if (nof_nonce_requests >= MY_NODE_LOCK_COUNTER_MAX) { if (nof_nonce_requests >= MY_NODE_LOCK_COUNTER_MAX) {
_nodeLock("TMNR"); //Too many nonces requested _nodeLock("TMNR"); //Too many nonces requested
} }
@@ -323,7 +331,8 @@ bool signerSignMsg(MyMessage &msg) {
} else { } else {
// Send nonce-request // Send nonce-request
_signingNonceStatus=SIGN_WAITING_FOR_NONCE; _signingNonceStatus=SIGN_WAITING_FOR_NONCE;
if (!_sendRoute(build(_msgSign, msg.destination, msg.sensor, C_INTERNAL, I_NONCE_REQUEST).set(""))) { if (!_sendRoute(build(_msgSign, msg.destination, msg.sensor, C_INTERNAL,
I_NONCE_REQUEST).set(""))) {
SIGN_DEBUG(PSTR("Failed to transmit nonce request!\n")); SIGN_DEBUG(PSTR("Failed to transmit nonce request!\n"));
return false; return false;
} }
@@ -332,7 +341,8 @@ bool signerSignMsg(MyMessage &msg) {
// Other messages could come in-between. We trust _process() takes care of them // Other messages could come in-between. We trust _process() takes care of them
unsigned long enter = hwMillis(); unsigned long enter = hwMillis();
_msgSign = msg; // Copy the message to sign since message buffer might be touched in _process() _msgSign = msg; // Copy the message to sign since message buffer might be touched in _process()
while (hwMillis() - enter < MY_VERIFICATION_TIMEOUT_MS && _signingNonceStatus==SIGN_WAITING_FOR_NONCE) { while (hwMillis() - enter < MY_VERIFICATION_TIMEOUT_MS &&
_signingNonceStatus==SIGN_WAITING_FOR_NONCE) {
_process(); _process();
} }
if (hwMillis() - enter > MY_VERIFICATION_TIMEOUT_MS) { if (hwMillis() - enter > MY_VERIFICATION_TIMEOUT_MS) {
@@ -375,8 +385,7 @@ bool signerVerifyMsg(MyMessage &msg) {
// Internal messages of certain types are not verified // Internal messages of certain types are not verified
if (skipSign(msg)) { if (skipSign(msg)) {
verificationResult = true; verificationResult = true;
} } else if (!mGetSigned(msg)) {
else if (!mGetSigned(msg)) {
// Got unsigned message that should have been signed // Got unsigned message that should have been signed
SIGN_DEBUG(PSTR("Message is not signed, but it should have been!\n")); SIGN_DEBUG(PSTR("Message is not signed, but it should have been!\n"));
verificationResult = false; verificationResult = false;
@@ -397,7 +406,8 @@ bool signerVerifyMsg(MyMessage &msg) {
nof_failed_verifications = 0; nof_failed_verifications = 0;
} else { } else {
nof_failed_verifications++; nof_failed_verifications++;
SIGN_DEBUG(PSTR("Failed verification attempts left until lockdown: %d\n"), MY_NODE_LOCK_COUNTER_MAX-nof_failed_verifications); SIGN_DEBUG(PSTR("Failed verification attempts left until lockdown: %d\n"),
MY_NODE_LOCK_COUNTER_MAX-nof_failed_verifications);
if (nof_failed_verifications >= MY_NODE_LOCK_COUNTER_MAX) { if (nof_failed_verifications >= MY_NODE_LOCK_COUNTER_MAX) {
_nodeLock("TMFV"); //Too many failed verifications _nodeLock("TMFV"); //Too many failed verifications
} }
+51 -30
View File
@@ -54,21 +54,20 @@ static char i2h(uint8_t i)
uint8_t k = i & 0x0F; uint8_t k = i & 0x0F;
if (k <= 9) { if (k <= 9) {
return '0' + k; return '0' + k;
} } else {
else {
return 'A' + k - 10; return 'A' + k - 10;
} }
} }
static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz) { static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz)
{
static char printBuffer[300]; static char printBuffer[300];
#ifdef MY_GATEWAY_FEATURE #ifdef MY_GATEWAY_FEATURE
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
snprintf_P(printBuffer, 299, PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE); snprintf_P(printBuffer, 299, PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE);
MY_SERIALDEVICE.print(printBuffer); MY_SERIALDEVICE.print(printBuffer);
#endif #endif
for (int i=0; i<sz; i++) for (int i=0; i<sz; i++) {
{
printBuffer[i * 2] = i2h(buf[i] >> 4); printBuffer[i * 2] = i2h(buf[i] >> 4);
printBuffer[(i * 2) + 1] = i2h(buf[i]); printBuffer[(i * 2) + 1] = i2h(buf[i]);
} }
@@ -78,8 +77,7 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf,
printBuffer[MY_GATEWAY_MAX_SEND_LENGTH-1-strlen_P((const char*)str)] = '\0'; printBuffer[MY_GATEWAY_MAX_SEND_LENGTH-1-strlen_P((const char*)str)] = '\0';
#endif #endif
MY_SERIALDEVICE.print(str); MY_SERIALDEVICE.print(str);
if (sz > 0) if (sz > 0) {
{
MY_SERIALDEVICE.print(printBuffer); MY_SERIALDEVICE.print(printBuffer);
} }
MY_SERIALDEVICE.println(""); MY_SERIALDEVICE.println("");
@@ -88,13 +86,16 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf,
#define DEBUG_SIGNING_PRINTBUF(str, buf, sz) #define DEBUG_SIGNING_PRINTBUF(str, buf, sz)
#endif #endif
void signerAtsha204Init(void) { void signerAtsha204Init(void)
{
atsha204_init(MY_SIGNING_ATSHA204_PIN); atsha204_init(MY_SIGNING_ATSHA204_PIN);
} }
bool signerAtsha204CheckTimer(void) { bool signerAtsha204CheckTimer(void)
{
if (_signing_verification_ongoing) { if (_signing_verification_ongoing) {
if (hwMillis() < _signing_timestamp || hwMillis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) { if (hwMillis() < _signing_timestamp ||
hwMillis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) {
DEBUG_SIGNING_PRINTBUF(F("Verification timeout"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Verification timeout"), NULL, 0);
// Purge nonce // Purge nonce
memset(_signing_signing_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH); memset(_signing_signing_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH);
@@ -106,7 +107,8 @@ bool signerAtsha204CheckTimer(void) {
return true; return true;
} }
bool signerAtsha204GetNonce(MyMessage &msg) { bool signerAtsha204GetNonce(MyMessage &msg)
{
DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204"), NULL, 0);
// Generate random number for use as nonce // Generate random number for use as nonce
// We used a basic whitening technique that XORs each byte in a 32byte random value with current hwMillis() counter // We used a basic whitening technique that XORs each byte in a 32byte random value with current hwMillis() counter
@@ -140,7 +142,8 @@ bool signerAtsha204GetNonce(MyMessage &msg) {
return true; return true;
} }
void signerAtsha204PutNonce(MyMessage &msg) { void signerAtsha204PutNonce(MyMessage &msg)
{
DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204"), NULL, 0);
memcpy(_signing_signing_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD); memcpy(_signing_signing_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD);
@@ -148,7 +151,8 @@ void signerAtsha204PutNonce(MyMessage &msg) {
memset(&_signing_signing_nonce[MAX_PAYLOAD], 0xAA, sizeof(_signing_signing_nonce)-MAX_PAYLOAD); memset(&_signing_signing_nonce[MAX_PAYLOAD], 0xAA, sizeof(_signing_signing_nonce)-MAX_PAYLOAD);
} }
bool signerAtsha204SignMsg(MyMessage &msg) { bool signerAtsha204SignMsg(MyMessage &msg)
{
// If we cannot fit any signature in the message, refuse to sign it // If we cannot fit any signature in the message, refuse to sign it
if (mGetLength(msg) > MAX_PAYLOAD-2) { if (mGetLength(msg) > MAX_PAYLOAD-2) {
DEBUG_SIGNING_PRINTBUF(F("Message too large"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Message too large"), NULL, 0);
@@ -161,10 +165,12 @@ bool signerAtsha204SignMsg(MyMessage &msg) {
if (DO_WHITELIST(msg.destination)) { if (DO_WHITELIST(msg.destination)) {
// Salt the signature with the senders nodeId and the unique serial of the ATSHA device // Salt the signature with the senders nodeId and the unique serial of the ATSHA device
memcpy(_signing_signing_nonce, &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed memcpy(_signing_signing_nonce, &_signing_rx_buffer[SHA204_BUFFER_POS_DATA],
32); // We can reuse the nonce buffer now since it is no longer needed
_signing_signing_nonce[32] = msg.sender; _signing_signing_nonce[32] = msg.sender;
atsha204_getSerialNumber(&_signing_signing_nonce[33]); atsha204_getSerialNumber(&_signing_signing_nonce[33]);
(void)signerSha256(_signing_signing_nonce, 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place (void)signerSha256(_signing_signing_nonce,
32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place
DEBUG_SIGNING_PRINTBUF(F("Signature salted with serial"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Signature salted with serial"), NULL, 0);
} }
@@ -175,13 +181,16 @@ bool signerAtsha204SignMsg(MyMessage &msg) {
_signing_rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER; _signing_rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER;
// Transfer as much signature data as the remaining space in the message permits // Transfer as much signature data as the remaining space in the message permits
memcpy(&msg.data[mGetLength(msg)], &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg)); memcpy(&msg.data[mGetLength(msg)], &_signing_rx_buffer[SHA204_BUFFER_POS_DATA],
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg)); MAX_PAYLOAD-mGetLength(msg));
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)],
MAX_PAYLOAD-mGetLength(msg));
return true; return true;
} }
bool signerAtsha204VerifyMsg(MyMessage &msg) { bool signerAtsha204VerifyMsg(MyMessage &msg)
{
if (!_signing_verification_ongoing) { if (!_signing_verification_ongoing) {
DEBUG_SIGNING_PRINTBUF(F("No active verification session"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("No active verification session"), NULL, 0);
return false; return false;
@@ -198,7 +207,8 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) {
return false; return false;
} }
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg)); DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)],
MAX_PAYLOAD-mGetLength(msg));
signerCalculateSignature(msg, false); // Get signature of message signerCalculateSignature(msg, false); // Get signature of message
#ifdef MY_SIGNING_NODE_WHITELISTING #ifdef MY_SIGNING_NODE_WHITELISTING
@@ -207,10 +217,12 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) {
for (j=0; j < NUM_OF(_signing_whitelist); j++) { for (j=0; j < NUM_OF(_signing_whitelist); j++) {
if (_signing_whitelist[j].nodeId == msg.sender) { if (_signing_whitelist[j].nodeId == msg.sender) {
DEBUG_SIGNING_PRINTBUF(F("Sender found in whitelist"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Sender found in whitelist"), NULL, 0);
memcpy(_signing_verifying_nonce, &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed memcpy(_signing_verifying_nonce, &_signing_rx_buffer[SHA204_BUFFER_POS_DATA],
32); // We can reuse the nonce buffer now since it is no longer needed
_signing_verifying_nonce[32] = msg.sender; _signing_verifying_nonce[32] = msg.sender;
memcpy(&_signing_verifying_nonce[33], _signing_whitelist[j].serial, SHA204_SERIAL_SZ); memcpy(&_signing_verifying_nonce[33], _signing_whitelist[j].serial, SHA204_SERIAL_SZ);
(void)signerSha256(_signing_verifying_nonce, 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place (void)signerSha256(_signing_verifying_nonce,
32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place
break; break;
} }
} }
@@ -229,8 +241,10 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) {
_signing_rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER; _signing_rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER;
// Compare the caluclated signature with the provided signature // Compare the caluclated signature with the provided signature
if (signerMemcmp(&msg.data[mGetLength(msg)], &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg))) { if (signerMemcmp(&msg.data[mGetLength(msg)], &_signing_rx_buffer[SHA204_BUFFER_POS_DATA],
DEBUG_SIGNING_PRINTBUF(F("Signature bad: "), &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg)); MAX_PAYLOAD-mGetLength(msg))) {
DEBUG_SIGNING_PRINTBUF(F("Signature bad: "), &_signing_rx_buffer[SHA204_BUFFER_POS_DATA],
MAX_PAYLOAD-mGetLength(msg));
#ifdef MY_SIGNING_NODE_WHITELISTING #ifdef MY_SIGNING_NODE_WHITELISTING
DEBUG_SIGNING_PRINTBUF(F("Is the sender whitelisted and serial correct?"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Is the sender whitelisted and serial correct?"), NULL, 0);
#endif #endif
@@ -243,15 +257,20 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) {
} }
// Helper to calculate signature of msg (returned in _signing_rx_buffer[SHA204_BUFFER_POS_DATA]) // Helper to calculate signature of msg (returned in _signing_rx_buffer[SHA204_BUFFER_POS_DATA])
static void signerCalculateSignature(MyMessage &msg, bool signing) { static void signerCalculateSignature(MyMessage &msg, bool signing)
{
(void)atsha204_wakeup(_signing_temp_message); (void)atsha204_wakeup(_signing_temp_message);
memset(_signing_temp_message, 0, 32); memset(_signing_temp_message, 0, 32);
memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE],
MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
// Program the data to sign into the ATSHA204 // Program the data to sign into the ATSHA204
DEBUG_SIGNING_PRINTBUF(F("Message to process: "), (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); DEBUG_SIGNING_PRINTBUF(F("Message to process: "), (uint8_t*)&msg.data[1-HEADER_SIZE],
DEBUG_SIGNING_PRINTBUF(F("Current nonce: "), signing ? _signing_signing_nonce : _signing_verifying_nonce, 32); MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
(void)atsha204_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, 8 << 3, 32, _signing_temp_message, DEBUG_SIGNING_PRINTBUF(F("Current nonce: "),
signing ? _signing_signing_nonce : _signing_verifying_nonce, 32);
(void)atsha204_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, 8 << 3, 32,
_signing_temp_message,
WRITE_COUNT_LONG, _signing_tx_buffer, WRITE_RSP_SIZE, _signing_rx_buffer); WRITE_COUNT_LONG, _signing_tx_buffer, WRITE_RSP_SIZE, _signing_rx_buffer);
// Program the nonce to use for the signature (has to be done just before GENDIG due to chip limitations) // Program the nonce to use for the signature (has to be done just before GENDIG due to chip limitations)
@@ -260,7 +279,8 @@ static void signerCalculateSignature(MyMessage &msg, bool signing) {
NONCE_COUNT_LONG, _signing_tx_buffer, NONCE_RSP_SIZE_SHORT, _signing_rx_buffer); NONCE_COUNT_LONG, _signing_tx_buffer, NONCE_RSP_SIZE_SHORT, _signing_rx_buffer);
// Purge nonce when used // Purge nonce when used
memset(signing ? _signing_signing_nonce : _signing_verifying_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH); memset(signing ? _signing_signing_nonce : _signing_verifying_nonce, 0x00,
NONCE_NUMIN_SIZE_PASSTHROUGH);
// Generate digest of data and nonce // Generate digest of data and nonce
(void)atsha204_execute(SHA204_GENDIG, GENDIG_ZONE_DATA, 8, 0, NULL, (void)atsha204_execute(SHA204_GENDIG, GENDIG_ZONE_DATA, 8, 0, NULL,
@@ -275,7 +295,8 @@ static void signerCalculateSignature(MyMessage &msg, bool signing) {
// Helper to calculate a generic SHA256 digest of provided buffer (only supports one block) // Helper to calculate a generic SHA256 digest of provided buffer (only supports one block)
// The pointer to the hash is returned, but the hash is also stored in _signing_rx_buffer[SHA204_BUFFER_POS_DATA]) // The pointer to the hash is returned, but the hash is also stored in _signing_rx_buffer[SHA204_BUFFER_POS_DATA])
static uint8_t* signerSha256(const uint8_t* data, size_t sz) { static uint8_t* signerSha256(const uint8_t* data, size_t sz)
{
// Initiate SHA256 calculator // Initiate SHA256 calculator
(void)atsha204_execute(SHA204_SHA, SHA_INIT, 0, 0, NULL, (void)atsha204_execute(SHA204_SHA, SHA_INIT, 0, 0, NULL,
SHA_COUNT_SHORT, _signing_tx_buffer, SHA_RSP_SIZE_SHORT, _signing_rx_buffer); SHA_COUNT_SHORT, _signing_tx_buffer, SHA_RSP_SIZE_SHORT, _signing_rx_buffer);
+35 -25
View File
@@ -58,38 +58,36 @@ static char i2h(uint8_t i)
uint8_t k = i & 0x0F; uint8_t k = i & 0x0F;
if (k <= 9) { if (k <= 9) {
return '0' + k; return '0' + k;
} } else {
else {
return 'A' + k - 10; return 'A' + k - 10;
} }
} }
#ifdef __linux__ #ifdef __linux__
static void DEBUG_SIGNING_PRINTBUF(const char *str, uint8_t* buf, uint8_t sz) { static void DEBUG_SIGNING_PRINTBUF(const char *str, uint8_t* buf, uint8_t sz)
{
static char printBuffer[300]; static char printBuffer[300];
for (int i=0; i<sz; i++) for (int i=0; i<sz; i++) {
{
printBuffer[i * 2] = i2h(buf[i] >> 4); printBuffer[i * 2] = i2h(buf[i] >> 4);
printBuffer[(i * 2) + 1] = i2h(buf[i]); printBuffer[(i * 2) + 1] = i2h(buf[i]);
} }
printBuffer[sz * 2] = '\0'; printBuffer[sz * 2] = '\0';
debug(str); debug(str);
if (sz > 0) if (sz > 0) {
{
debug(printBuffer); debug(printBuffer);
} }
} }
#else #else
static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz) { static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz)
{
static char printBuffer[300]; static char printBuffer[300];
#ifdef MY_GATEWAY_FEATURE #ifdef MY_GATEWAY_FEATURE
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
snprintf_P(printBuffer, 299, PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE); snprintf_P(printBuffer, 299, PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE);
MY_SERIALDEVICE.print(printBuffer); MY_SERIALDEVICE.print(printBuffer);
#endif #endif
for (int i=0; i<sz; i++) for (int i=0; i<sz; i++) {
{
printBuffer[i * 2] = i2h(buf[i] >> 4); printBuffer[i * 2] = i2h(buf[i] >> 4);
printBuffer[(i * 2) + 1] = i2h(buf[i]); printBuffer[(i * 2) + 1] = i2h(buf[i]);
} }
@@ -99,8 +97,7 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf,
printBuffer[MY_GATEWAY_MAX_SEND_LENGTH-1-strlen_P((const char*)str)] = '\0'; printBuffer[MY_GATEWAY_MAX_SEND_LENGTH-1-strlen_P((const char*)str)] = '\0';
#endif #endif
MY_SERIALDEVICE.print(str); MY_SERIALDEVICE.print(str);
if (sz > 0) if (sz > 0) {
{
MY_SERIALDEVICE.print(printBuffer); MY_SERIALDEVICE.print(printBuffer);
} }
MY_SERIALDEVICE.println(""); MY_SERIALDEVICE.println("");
@@ -110,7 +107,8 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf,
#define DEBUG_SIGNING_PRINTBUF(str, buf, sz) #define DEBUG_SIGNING_PRINTBUF(str, buf, sz)
#endif #endif
void signerAtsha204SoftInit(void) { void signerAtsha204SoftInit(void)
{
// initialize pseudo-RNG // initialize pseudo-RNG
hwRandomNumberInit(); hwRandomNumberInit();
// Set secrets // Set secrets
@@ -118,9 +116,11 @@ void signerAtsha204SoftInit(void) {
hwReadConfigBlock((void*)_signing_node_serial_info, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9); hwReadConfigBlock((void*)_signing_node_serial_info, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9);
} }
bool signerAtsha204SoftCheckTimer(void) { bool signerAtsha204SoftCheckTimer(void)
{
if (_signing_verification_ongoing) { if (_signing_verification_ongoing) {
if (hwMillis() < _signing_timestamp || hwMillis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) { if (hwMillis() < _signing_timestamp ||
hwMillis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) {
DEBUG_SIGNING_PRINTBUF(F("Verification timeout"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Verification timeout"), NULL, 0);
// Purge nonce // Purge nonce
memset(_signing_signing_nonce, 0xAA, 32); memset(_signing_signing_nonce, 0xAA, 32);
@@ -132,7 +132,8 @@ bool signerAtsha204SoftCheckTimer(void) {
return true; return true;
} }
bool signerAtsha204SoftGetNonce(MyMessage &msg) { bool signerAtsha204SoftGetNonce(MyMessage &msg)
{
DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204Soft"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204Soft"), NULL, 0);
// We used a basic whitening technique that XORs a random byte with the current hwMillis() counter and then the byte is // We used a basic whitening technique that XORs a random byte with the current hwMillis() counter and then the byte is
@@ -160,7 +161,8 @@ bool signerAtsha204SoftGetNonce(MyMessage &msg) {
return true; return true;
} }
void signerAtsha204SoftPutNonce(MyMessage &msg) { void signerAtsha204SoftPutNonce(MyMessage &msg)
{
DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204Soft"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204Soft"), NULL, 0);
memcpy(_signing_signing_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD); memcpy(_signing_signing_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD);
@@ -168,7 +170,8 @@ void signerAtsha204SoftPutNonce(MyMessage &msg) {
memset(&_signing_signing_nonce[MAX_PAYLOAD], 0xAA, sizeof(_signing_signing_nonce)-MAX_PAYLOAD); memset(&_signing_signing_nonce[MAX_PAYLOAD], 0xAA, sizeof(_signing_signing_nonce)-MAX_PAYLOAD);
} }
bool signerAtsha204SoftSignMsg(MyMessage &msg) { bool signerAtsha204SoftSignMsg(MyMessage &msg)
{
// If we cannot fit any signature in the message, refuse to sign it // If we cannot fit any signature in the message, refuse to sign it
if (mGetLength(msg) > MAX_PAYLOAD-2) { if (mGetLength(msg) > MAX_PAYLOAD-2) {
DEBUG_SIGNING_PRINTBUF(F("Message too large"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Message too large"), NULL, 0);
@@ -199,12 +202,14 @@ bool signerAtsha204SoftSignMsg(MyMessage &msg) {
// Transfer as much signature data as the remaining space in the message permits // Transfer as much signature data as the remaining space in the message permits
memcpy(&msg.data[mGetLength(msg)], _signing_hmac, MAX_PAYLOAD-mGetLength(msg)); memcpy(&msg.data[mGetLength(msg)], _signing_hmac, MAX_PAYLOAD-mGetLength(msg));
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg)); DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)],
MAX_PAYLOAD-mGetLength(msg));
return true; return true;
} }
bool signerAtsha204SoftVerifyMsg(MyMessage &msg) { bool signerAtsha204SoftVerifyMsg(MyMessage &msg)
{
if (!_signing_verification_ongoing) { if (!_signing_verification_ongoing) {
DEBUG_SIGNING_PRINTBUF(F("No active verification session"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("No active verification session"), NULL, 0);
return false; return false;
@@ -222,7 +227,8 @@ bool signerAtsha204SoftVerifyMsg(MyMessage &msg) {
} }
// Get signature of message // Get signature of message
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg)); DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)],
MAX_PAYLOAD-mGetLength(msg));
signerCalculateSignature(msg, false); signerCalculateSignature(msg, false);
#ifdef MY_SIGNING_NODE_WHITELISTING #ifdef MY_SIGNING_NODE_WHITELISTING
@@ -268,11 +274,15 @@ bool signerAtsha204SoftVerifyMsg(MyMessage &msg) {
} }
// Helper to calculate signature of msg (returned in hmac) // Helper to calculate signature of msg (returned in hmac)
static void signerCalculateSignature(MyMessage &msg, bool signing) { static void signerCalculateSignature(MyMessage &msg, bool signing)
{
memset(_signing_temp_message, 0, 32); memset(_signing_temp_message, 0, 32);
memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE],
DEBUG_SIGNING_PRINTBUF(F("Message to process: "), (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
DEBUG_SIGNING_PRINTBUF(F("Current nonce: "), signing ? _signing_signing_nonce : _signing_verifying_nonce, 32); DEBUG_SIGNING_PRINTBUF(F("Message to process: "), (uint8_t*)&msg.data[1-HEADER_SIZE],
MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
DEBUG_SIGNING_PRINTBUF(F("Current nonce: "),
signing ? _signing_signing_nonce : _signing_verifying_nonce, 32);
// ATSHA204 calculates the HMAC with a PSK and a SHA256 digest of the following data: // ATSHA204 calculates the HMAC with a PSK and a SHA256 digest of the following data:
// 32 bytes zeroes // 32 bytes zeroes
+155 -115
View File
@@ -57,7 +57,8 @@ extern MyMessage _msgTmp; // outgoing message
#endif #endif
// stInit: initialise transport HW // stInit: initialise transport HW
void stInitTransition(void) { void stInitTransition(void)
{
TRANSPORT_DEBUG(PSTR("TSM:INIT\n")); TRANSPORT_DEBUG(PSTR("TSM:INIT\n"));
// initialise status variables // initialise status variables
_transportSM.pingActive = false; _transportSM.pingActive = false;
@@ -75,17 +76,18 @@ void stInitTransition(void) {
#endif #endif
// Read node settings (ID, parent ID, GW distance) from EEPROM // Read node settings (ID, parent ID, GW distance) from EEPROM
hwReadConfigBlock((void*)&_transportConfig, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(transportConfig_t)); hwReadConfigBlock((void*)&_transportConfig, (void*)EEPROM_NODE_ID_ADDRESS,
sizeof(transportConfig_t));
} }
void stInitUpdate(void) { void stInitUpdate(void)
{
// initialise radio // initialise radio
if (!transportInit()) { if (!transportInit()) {
TRANSPORT_DEBUG(PSTR("!TSM:INIT:TSP FAIL\n")); TRANSPORT_DEBUG(PSTR("!TSM:INIT:TSP FAIL\n"));
setIndication(INDICATION_ERR_INIT_TRANSPORT); setIndication(INDICATION_ERR_INIT_TRANSPORT);
transportSwitchSM(stFailure); transportSwitchSM(stFailure);
} } else {
else {
TRANSPORT_DEBUG(PSTR("TSM:INIT:TSP OK\n")); TRANSPORT_DEBUG(PSTR("TSM:INIT:TSP OK\n"));
_transportSM.transportActive = true; _transportSM.transportActive = true;
#if defined(MY_GATEWAY_FEATURE) #if defined(MY_GATEWAY_FEATURE)
@@ -109,8 +111,7 @@ void stInitUpdate(void) {
if (_transportConfig.nodeId == AUTO || transportAssignNodeID(_transportConfig.nodeId)) { if (_transportConfig.nodeId == AUTO || transportAssignNodeID(_transportConfig.nodeId)) {
// if node ID valid (>0 and <255), proceed to next state // if node ID valid (>0 and <255), proceed to next state
transportSwitchSM(stParent); transportSwitchSM(stParent);
} } else {
else {
// ID invalid (0 or 255) // ID invalid (0 or 255)
transportSwitchSM(stFailure); transportSwitchSM(stFailure);
} }
@@ -119,7 +120,8 @@ void stInitUpdate(void) {
} }
// stParent: find parent // stParent: find parent
void stParentTransition(void) { void stParentTransition(void)
{
TRANSPORT_DEBUG(PSTR("TSM:FPAR\n")); // find parent TRANSPORT_DEBUG(PSTR("TSM:FPAR\n")); // find parent
setIndication(INDICATION_FIND_PARENT); setIndication(INDICATION_FIND_PARENT);
_transportSM.uplinkOk = false; _transportSM.uplinkOk = false;
@@ -136,12 +138,14 @@ void stParentTransition(void) {
_transportConfig.distanceGW = DISTANCE_INVALID; // Set distance to max and invalidate parent node ID _transportConfig.distanceGW = DISTANCE_INVALID; // Set distance to max and invalidate parent node ID
_transportConfig.parentNodeId = AUTO; _transportConfig.parentNodeId = AUTO;
// Broadcast find parent request // Broadcast find parent request
(void)transportRouteMessage(build(_msgTmp, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_REQUEST).set("")); (void)transportRouteMessage(build(_msgTmp, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
I_FIND_PARENT_REQUEST).set(""));
#endif #endif
} }
// stParentUpdate // stParentUpdate
void stParentUpdate(void) { void stParentUpdate(void)
{
#if defined(MY_PARENT_NODE_IS_STATIC) #if defined(MY_PARENT_NODE_IS_STATIC)
// skipping find parent // skipping find parent
setIndication(INDICATION_GOT_PARENT); setIndication(INDICATION_GOT_PARENT);
@@ -156,16 +160,14 @@ void stParentUpdate(void) {
setIndication(INDICATION_GOT_PARENT); setIndication(INDICATION_GOT_PARENT);
// go to next state // go to next state
transportSwitchSM(stID); transportSwitchSM(stID);
} } else {
else {
// timeout w/o reply or valid parent // timeout w/o reply or valid parent
if (_transportSM.stateRetries < MY_TRANSPORT_STATE_RETRIES) { if (_transportSM.stateRetries < MY_TRANSPORT_STATE_RETRIES) {
// retries left // retries left
TRANSPORT_DEBUG(PSTR("!TSM:FPAR:NO REPLY\n")); // find parent, no reply TRANSPORT_DEBUG(PSTR("!TSM:FPAR:NO REPLY\n")); // find parent, no reply
// reenter state // reenter state
transportSwitchSM(stParent); transportSwitchSM(stParent);
} } else {
else {
// no retries left, finding parent failed // no retries left, finding parent failed
TRANSPORT_DEBUG(PSTR("!TSM:FPAR:FAIL\n")); TRANSPORT_DEBUG(PSTR("!TSM:FPAR:FAIL\n"));
setIndication(INDICATION_ERR_FIND_PARENT); setIndication(INDICATION_ERR_FIND_PARENT);
@@ -177,31 +179,32 @@ void stParentUpdate(void) {
} }
// stID: verify and request ID if necessary // stID: verify and request ID if necessary
void stIDTransition(void) { void stIDTransition(void)
{
TRANSPORT_DEBUG(PSTR("TSM:ID\n")); // verify/request node ID TRANSPORT_DEBUG(PSTR("TSM:ID\n")); // verify/request node ID
if (_transportConfig.nodeId == AUTO) { if (_transportConfig.nodeId == AUTO) {
// send ID request // send ID request
setIndication(INDICATION_REQ_NODEID); setIndication(INDICATION_REQ_NODEID);
TRANSPORT_DEBUG(PSTR("TSM:ID:REQ\n")); // request node ID TRANSPORT_DEBUG(PSTR("TSM:ID:REQ\n")); // request node ID
(void)transportRouteMessage(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_ID_REQUEST).set("")); (void)transportRouteMessage(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
I_ID_REQUEST).set(""));
} }
} }
void stIDUpdate(void) { void stIDUpdate(void)
{
if (_transportConfig.nodeId != AUTO) { if (_transportConfig.nodeId != AUTO) {
// current node ID is valid // current node ID is valid
TRANSPORT_DEBUG(PSTR("TSM:ID:OK\n")); TRANSPORT_DEBUG(PSTR("TSM:ID:OK\n"));
setIndication(INDICATION_GOT_NODEID); setIndication(INDICATION_GOT_NODEID);
// proceed to next state // proceed to next state
transportSwitchSM(stUplink); transportSwitchSM(stUplink);
} } else if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS) {
else if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS) {
// timeout // timeout
if (_transportSM.stateRetries < MY_TRANSPORT_STATE_RETRIES) { if (_transportSM.stateRetries < MY_TRANSPORT_STATE_RETRIES) {
// retries left: reenter state // retries left: reenter state
transportSwitchSM(stID); transportSwitchSM(stID);
} } else {
else {
// no retries left // no retries left
TRANSPORT_DEBUG(PSTR("!TSM:ID:FAIL\n")); TRANSPORT_DEBUG(PSTR("!TSM:ID:FAIL\n"));
setIndication(INDICATION_ERR_GET_NODEID); setIndication(INDICATION_ERR_GET_NODEID);
@@ -210,35 +213,37 @@ void stIDUpdate(void) {
} }
} }
void stUplinkTransition(void) { void stUplinkTransition(void)
{
#if !defined(MY_TRANSPORT_UPLINK_CHECK_DISABLED) #if !defined(MY_TRANSPORT_UPLINK_CHECK_DISABLED)
TRANSPORT_DEBUG(PSTR("TSM:UPL\n")); TRANSPORT_DEBUG(PSTR("TSM:UPL\n"));
setIndication(INDICATION_CHECK_UPLINK); setIndication(INDICATION_CHECK_UPLINK);
_transportSM.pingResponse = INVALID_HOPS; _transportSM.pingResponse = INVALID_HOPS;
_transportSM.pingActive = true; _transportSM.pingActive = true;
(void)transportRouteMessage(build(_msgTmp,GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_PING).set((uint8_t)0x01)); (void)transportRouteMessage(build(_msgTmp,GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
I_PING).set((uint8_t)0x01));
#endif #endif
} }
void stUplinkUpdate(void) { void stUplinkUpdate(void)
{
#if !defined(MY_TRANSPORT_UPLINK_CHECK_DISABLED) #if !defined(MY_TRANSPORT_UPLINK_CHECK_DISABLED)
if (_transportSM.pingResponse != INVALID_HOPS) { if (_transportSM.pingResponse != INVALID_HOPS) {
_transportSM.lastUplinkCheck = hwMillis(); _transportSM.lastUplinkCheck = hwMillis();
// uplink ok, i.e. GW replied // uplink ok, i.e. GW replied
TRANSPORT_DEBUG(PSTR("TSM:UPL:OK\n")); // uplink ok TRANSPORT_DEBUG(PSTR("TSM:UPL:OK\n")); // uplink ok
if (_transportSM.pingResponse != _transportConfig.distanceGW) { if (_transportSM.pingResponse != _transportConfig.distanceGW) {
TRANSPORT_DEBUG(PSTR("TSM:UPL:DGWC,O=%d,N=%d\n"), _transportConfig.distanceGW, _transportSM.pingResponse); // distance to GW changed TRANSPORT_DEBUG(PSTR("TSM:UPL:DGWC,O=%d,N=%d\n"), _transportConfig.distanceGW,
_transportSM.pingResponse); // distance to GW changed
_transportConfig.distanceGW = _transportSM.pingResponse; _transportConfig.distanceGW = _transportSM.pingResponse;
} }
transportSwitchSM(stReady); // proceed to next state transportSwitchSM(stReady); // proceed to next state
} } else if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS) {
else if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS) {
// timeout // timeout
if (_transportSM.stateRetries < MY_TRANSPORT_STATE_RETRIES) { if (_transportSM.stateRetries < MY_TRANSPORT_STATE_RETRIES) {
// retries left: reenter state // retries left: reenter state
transportSwitchSM(stUplink); transportSwitchSM(stUplink);
} } else {
else {
// no retries left // no retries left
TRANSPORT_DEBUG(PSTR("!TSM:UPL:FAIL\n")); // uplink check failed TRANSPORT_DEBUG(PSTR("!TSM:UPL:FAIL\n")); // uplink check failed
_transportSM.pingActive = false; _transportSM.pingActive = false;
@@ -252,9 +257,11 @@ void stUplinkUpdate(void) {
#endif #endif
} }
void stReadyTransition(void) { void stReadyTransition(void)
{
// transport is ready and fully operational // transport is ready and fully operational
TRANSPORT_DEBUG(PSTR("TSM:READY:ID=%d,PAR=%d,DIS=%d\n"), _transportConfig.nodeId, _transportConfig.parentNodeId, _transportConfig.distanceGW); TRANSPORT_DEBUG(PSTR("TSM:READY:ID=%d,PAR=%d,DIS=%d\n"), _transportConfig.nodeId,
_transportConfig.parentNodeId, _transportConfig.distanceGW);
_transportSM.uplinkOk = true; _transportSM.uplinkOk = true;
_transportSM.failureCounter = 0u; // reset failure counter _transportSM.failureCounter = 0u; // reset failure counter
_transportSM.failedUplinkTransmissions = 0u; // reset failed uplink TX counter _transportSM.failedUplinkTransmissions = 0u; // reset failed uplink TX counter
@@ -265,12 +272,14 @@ void stReadyTransition(void) {
} }
// stReadyUpdate: monitors link // stReadyUpdate: monitors link
void stReadyUpdate(void) { void stReadyUpdate(void)
{
#if defined(MY_GATEWAY_FEATURE) #if defined(MY_GATEWAY_FEATURE)
if (hwMillis() - _lastNetworkDiscovery > MY_TRANSPORT_DISCOVERY_INTERVAL_MS) { if (hwMillis() - _lastNetworkDiscovery > MY_TRANSPORT_DISCOVERY_INTERVAL_MS) {
_lastNetworkDiscovery = hwMillis(); _lastNetworkDiscovery = hwMillis();
TRANSPORT_DEBUG(PSTR("TSM:READY:NWD REQ\n")); // send transport network discovery TRANSPORT_DEBUG(PSTR("TSM:READY:NWD REQ\n")); // send transport network discovery
(void)transportRouteMessage(build(_msgTmp, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DISCOVER_REQUEST).set("")); (void)transportRouteMessage(build(_msgTmp, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
I_DISCOVER_REQUEST).set(""));
} }
#else #else
if (_transportSM.failedUplinkTransmissions > MY_TRANSPORT_MAX_TX_FAILURES) { if (_transportSM.failedUplinkTransmissions > MY_TRANSPORT_MAX_TX_FAILURES) {
@@ -295,7 +304,8 @@ void stReadyUpdate(void) {
} }
// stFailure: entered upon HW init failure or max retries exceeded // stFailure: entered upon HW init failure or max retries exceeded
void stFailureTransition(void) { void stFailureTransition(void)
{
if (_transportSM.failureCounter < MY_TRANSPORT_MAX_TSM_FAILURES) { if (_transportSM.failureCounter < MY_TRANSPORT_MAX_TSM_FAILURES) {
_transportSM.failureCounter++; // increment consecutive TSM failure counter _transportSM.failureCounter++; // increment consecutive TSM failure counter
} }
@@ -309,19 +319,21 @@ void stFailureTransition(void) {
#endif #endif
} }
void stFailureUpdate(void) { void stFailureUpdate(void)
if (transportTimeInState() > ( isTransportExtendedFailure()? MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE: MY_TRANSPORT_TIMEOUT_FAILURE_STATE) ) { {
if (transportTimeInState() > ( isTransportExtendedFailure()? MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE:
MY_TRANSPORT_TIMEOUT_FAILURE_STATE) ) {
TRANSPORT_DEBUG(PSTR("TSM:FAIL:RE-INIT\n")); // attempt to re-initialise transport TRANSPORT_DEBUG(PSTR("TSM:FAIL:RE-INIT\n")); // attempt to re-initialise transport
transportSwitchSM(stInit); transportSwitchSM(stInit);
} }
} }
void transportSwitchSM(transportState_t& newState) { void transportSwitchSM(transportState_t& newState)
{
if (_transportSM.currentState != &newState) { if (_transportSM.currentState != &newState) {
_transportSM.stateRetries = 0u; // state change, reset retry counter _transportSM.stateRetries = 0u; // state change, reset retry counter
_transportSM.currentState = &newState; // change state _transportSM.currentState = &newState; // change state
} } else {
else {
_transportSM.stateRetries++; // increment retries _transportSM.stateRetries++; // increment retries
} }
if (_transportSM.currentState->Transition) { if (_transportSM.currentState->Transition) {
@@ -330,38 +342,46 @@ void transportSwitchSM(transportState_t& newState) {
_transportSM.stateEnter = hwMillis(); // save time _transportSM.stateEnter = hwMillis(); // save time
} }
uint32_t transportTimeInState(void) { uint32_t transportTimeInState(void)
{
return hwMillis() - _transportSM.stateEnter; return hwMillis() - _transportSM.stateEnter;
} }
void transportUpdateSM(void) { void transportUpdateSM(void)
{
if (_transportSM.currentState->Update) { if (_transportSM.currentState->Update) {
_transportSM.currentState->Update(); _transportSM.currentState->Update();
} }
} }
bool isTransportReady(void) { bool isTransportReady(void)
{
return _transportSM.uplinkOk; return _transportSM.uplinkOk;
} }
bool isTransportExtendedFailure(void) { bool isTransportExtendedFailure(void)
{
return _transportSM.failureCounter == MY_TRANSPORT_MAX_TSM_FAILURES; return _transportSM.failureCounter == MY_TRANSPORT_MAX_TSM_FAILURES;
} }
bool isTransportSearchingParent(void) { bool isTransportSearchingParent(void)
{
return _transportSM.findingParentNode; return _transportSM.findingParentNode;
} }
bool isMessageReceived(void) { bool isMessageReceived(void)
{
return _transportSM.msgReceived; return _transportSM.msgReceived;
} }
void resetMessageReceived(void) { void resetMessageReceived(void)
{
_transportSM.msgReceived = false; _transportSM.msgReceived = false;
} }
void transportInitialise(void) { void transportInitialise(void)
{
_transportSM.failureCounter = 0u; // reset failure counter _transportSM.failureCounter = 0u; // reset failure counter
transportLoadRoutingTable(); // load routing table to RAM (if feature enabled) transportLoadRoutingTable(); // load routing table to RAM (if feature enabled)
// intial state // intial state
@@ -369,7 +389,8 @@ void transportInitialise(void) {
transportSwitchSM(stInit); transportSwitchSM(stInit);
} }
bool transportWaitUntilReady(const uint32_t waitingMS) { bool transportWaitUntilReady(const uint32_t waitingMS)
{
// check if transport ready // check if transport ready
TRANSPORT_DEBUG(PSTR("TSF:WUR:MS=%lu\n"), waitingMS); // timeout TRANSPORT_DEBUG(PSTR("TSF:WUR:MS=%lu\n"), waitingMS); // timeout
uint32_t enterMS = hwMillis(); uint32_t enterMS = hwMillis();
@@ -383,7 +404,8 @@ bool transportWaitUntilReady(const uint32_t waitingMS) {
} }
// update TSM and process incoming messages // update TSM and process incoming messages
void transportProcess(void) { void transportProcess(void)
{
// update state machine // update state machine
transportUpdateSM(); transportUpdateSM();
// process transport FIFO // process transport FIFO
@@ -391,7 +413,8 @@ void transportProcess(void) {
} }
bool transportCheckUplink(const bool force) { bool transportCheckUplink(const bool force)
{
if (!force && (hwMillis() - _transportSM.lastUplinkCheck) < MY_TRANSPORT_CHKUPL_INTERVAL_MS) { if (!force && (hwMillis() - _transportSM.lastUplinkCheck) < MY_TRANSPORT_CHKUPL_INTERVAL_MS) {
TRANSPORT_DEBUG(PSTR("TSF:CKU:OK,FCTRL\n")); // flood control TRANSPORT_DEBUG(PSTR("TSF:CKU:OK,FCTRL\n")); // flood control
return true; return true;
@@ -405,18 +428,19 @@ bool transportCheckUplink(const bool force) {
TRANSPORT_DEBUG(PSTR("TSF:CKU:OK\n")); TRANSPORT_DEBUG(PSTR("TSF:CKU:OK\n"));
// did distance to GW change upstream, eg. re-routing of uplink nodes // did distance to GW change upstream, eg. re-routing of uplink nodes
if (hopsCount != _transportConfig.distanceGW) { if (hopsCount != _transportConfig.distanceGW) {
TRANSPORT_DEBUG(PSTR("TSF:CKU:DGWC,O=%d,N=%d\n"), _transportConfig.distanceGW, hopsCount); // distance to GW changed TRANSPORT_DEBUG(PSTR("TSF:CKU:DGWC,O=%d,N=%d\n"), _transportConfig.distanceGW,
hopsCount); // distance to GW changed
_transportConfig.distanceGW = hopsCount; _transportConfig.distanceGW = hopsCount;
} }
return true; return true;
} } else {
else {
TRANSPORT_DEBUG(PSTR("TSF:CKU:FAIL\n")); TRANSPORT_DEBUG(PSTR("TSF:CKU:FAIL\n"));
return false; return false;
} }
} }
bool transportAssignNodeID(const uint8_t newNodeId) { bool transportAssignNodeID(const uint8_t newNodeId)
{
// verify if ID valid // verify if ID valid
if (newNodeId != GATEWAY_ADDRESS && newNodeId != AUTO) { if (newNodeId != GATEWAY_ADDRESS && newNodeId != AUTO) {
_transportConfig.nodeId = newNodeId; _transportConfig.nodeId = newNodeId;
@@ -425,8 +449,7 @@ bool transportAssignNodeID(const uint8_t newNodeId) {
hwWriteConfig(EEPROM_NODE_ID_ADDRESS, newNodeId); hwWriteConfig(EEPROM_NODE_ID_ADDRESS, newNodeId);
TRANSPORT_DEBUG(PSTR("TSF:SID:OK,ID=%d\n"),newNodeId); // Node ID assigned TRANSPORT_DEBUG(PSTR("TSF:SID:OK,ID=%d\n"),newNodeId); // Node ID assigned
return true; return true;
} } else {
else {
TRANSPORT_DEBUG(PSTR("!TSF:SID:FAIL,ID=%d\n"),newNodeId); // ID is invalid, cannot assign ID TRANSPORT_DEBUG(PSTR("!TSF:SID:FAIL,ID=%d\n"),newNodeId); // ID is invalid, cannot assign ID
setIndication(INDICATION_ERR_NET_FULL); setIndication(INDICATION_ERR_NET_FULL);
_transportConfig.nodeId = AUTO; _transportConfig.nodeId = AUTO;
@@ -434,7 +457,8 @@ bool transportAssignNodeID(const uint8_t newNodeId) {
} }
} }
bool transportRouteMessage(MyMessage &message) { bool transportRouteMessage(MyMessage &message)
{
const uint8_t destination = message.destination; const uint8_t destination = message.destination;
uint8_t route = _transportConfig.parentNodeId; // by default, all traffic is routed via parent node uint8_t route = _transportConfig.parentNodeId; // by default, all traffic is routed via parent node
@@ -446,11 +470,9 @@ bool transportRouteMessage(MyMessage &message) {
if (destination == GATEWAY_ADDRESS) { if (destination == GATEWAY_ADDRESS) {
route = _transportConfig.parentNodeId; // message to GW always routes via parent route = _transportConfig.parentNodeId; // message to GW always routes via parent
} } else if (destination == BROADCAST_ADDRESS) {
else if (destination == BROADCAST_ADDRESS) {
route = BROADCAST_ADDRESS; // message to BC does not require routing route = BROADCAST_ADDRESS; // message to BC does not require routing
} } else {
else {
#if defined(MY_REPEATER_FEATURE) #if defined(MY_REPEATER_FEATURE)
// destination not GW & not BC, get route // destination not GW & not BC, get route
route = transportGetRoute(destination); route = transportGetRoute(destination);
@@ -460,8 +482,7 @@ bool transportRouteMessage(MyMessage &message) {
if (message.last != _transportConfig.parentNodeId) { if (message.last != _transportConfig.parentNodeId) {
// message not from parent, i.e. child node - route it to parent // message not from parent, i.e. child node - route it to parent
route = _transportConfig.parentNodeId; route = _transportConfig.parentNodeId;
} } else {
else {
// route unknown and msg received from parent, send it to destination assuming in rx radius // route unknown and msg received from parent, send it to destination assuming in rx radius
route = destination; route = destination;
} }
@@ -482,8 +503,9 @@ bool transportRouteMessage(MyMessage &message) {
if (!result) { if (!result) {
setIndication(INDICATION_ERR_TX); setIndication(INDICATION_ERR_TX);
_transportSM.failedUplinkTransmissions++; _transportSM.failedUplinkTransmissions++;
} else {
_transportSM.failedUplinkTransmissions = 0u;
} }
else _transportSM.failedUplinkTransmissions = 0u;
} }
#else #else
if(!result) { if(!result) {
@@ -494,12 +516,12 @@ bool transportRouteMessage(MyMessage &message) {
return result; return result;
} }
bool transportSendRoute(MyMessage &message) { bool transportSendRoute(MyMessage &message)
{
bool result = false; bool result = false;
if (isTransportReady()) { if (isTransportReady()) {
result = transportRouteMessage(message); result = transportRouteMessage(message);
} } else {
else {
// TNR: transport not ready // TNR: transport not ready
TRANSPORT_DEBUG(PSTR("!TSF:SND:TNR\n")); TRANSPORT_DEBUG(PSTR("!TSF:SND:TNR\n"));
} }
@@ -507,7 +529,8 @@ bool transportSendRoute(MyMessage &message) {
} }
// only be used inside transport // only be used inside transport
bool transportWait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType){ bool transportWait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType)
{
const uint32_t enterMS = hwMillis(); const uint32_t enterMS = hwMillis();
// invalidate msg type // invalidate msg type
_msg.type = !msgType; _msg.type = !msgType;
@@ -521,35 +544,37 @@ bool transportWait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t ms
return expectedResponse; return expectedResponse;
} }
uint8_t transportPingNode(const uint8_t targetId) { uint8_t transportPingNode(const uint8_t targetId)
{
if(!_transportSM.pingActive) { if(!_transportSM.pingActive) {
TRANSPORT_DEBUG(PSTR("TSF:PNG:SEND,TO=%d\n"), targetId); TRANSPORT_DEBUG(PSTR("TSF:PNG:SEND,TO=%d\n"), targetId);
if(targetId == _transportConfig.nodeId) { if(targetId == _transportConfig.nodeId) {
// pinging self // pinging self
_transportSM.pingResponse = 0u; _transportSM.pingResponse = 0u;
} } else {
else {
_transportSM.pingActive = true; _transportSM.pingActive = true;
_transportSM.pingResponse = INVALID_HOPS; _transportSM.pingResponse = INVALID_HOPS;
(void)transportRouteMessage(build(_msgTmp, targetId, NODE_SENSOR_ID, C_INTERNAL, I_PING).set((uint8_t)0x01)); (void)transportRouteMessage(build(_msgTmp, targetId, NODE_SENSOR_ID, C_INTERNAL,
I_PING).set((uint8_t)0x01));
// Wait for ping reply or timeout // Wait for ping reply or timeout
(void)transportWait(2000, C_INTERNAL, I_PONG); (void)transportWait(2000, C_INTERNAL, I_PONG);
} }
// make sure missing I_PONG msg does not block pinging function by leaving pignActive=true // make sure missing I_PONG msg does not block pinging function by leaving pignActive=true
_transportSM.pingActive = false; _transportSM.pingActive = false;
return _transportSM.pingResponse; return _transportSM.pingResponse;
} } else {
else {
TRANSPORT_DEBUG(PSTR("!TSF:PNG:ACTIVE\n")); // ping active, cannot start new ping TRANSPORT_DEBUG(PSTR("!TSF:PNG:ACTIVE\n")); // ping active, cannot start new ping
return INVALID_HOPS; return INVALID_HOPS;
} }
} }
uint32_t transportGetHeartbeat(void) { uint32_t transportGetHeartbeat(void)
{
return transportTimeInState(); return transportTimeInState();
} }
void transportProcessMessage(void) { void transportProcessMessage(void)
{
// Manage signing timeout // Manage signing timeout
(void)signerCheckTimer(); (void)signerCheckTimer();
// receive message // receive message
@@ -571,19 +596,22 @@ void transportProcessMessage(void) {
const uint8_t destination = _msg.destination; const uint8_t destination = _msg.destination;
TRANSPORT_DEBUG(PSTR("TSF:MSG:READ,%d-%d-%d,s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d:%s\n"), TRANSPORT_DEBUG(PSTR("TSF:MSG:READ,%d-%d-%d,s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d:%s\n"),
sender, last, destination, _msg.sensor, command, type, mGetPayloadType(_msg), msgLength, mGetSigned(_msg), _msg.getString(_convBuf)); sender, last, destination, _msg.sensor, command, type, mGetPayloadType(_msg), msgLength,
mGetSigned(_msg), _msg.getString(_convBuf));
// Reject payloads with incorrect length // Reject payloads with incorrect length
if (payloadLength != expectedMessageLength) { if (payloadLength != expectedMessageLength) {
setIndication(INDICATION_ERR_LENGTH); setIndication(INDICATION_ERR_LENGTH);
TRANSPORT_DEBUG(PSTR("!TSF:MSG:LEN,%d!=%d\n"), payloadLength, expectedMessageLength); // invalid payload length TRANSPORT_DEBUG(PSTR("!TSF:MSG:LEN,%d!=%d\n"), payloadLength,
expectedMessageLength); // invalid payload length
return; return;
} }
// Reject messages with incorrect protocol version // Reject messages with incorrect protocol version
if (mGetVersion(_msg) != PROTOCOL_VERSION) { if (mGetVersion(_msg) != PROTOCOL_VERSION) {
setIndication(INDICATION_ERR_VERSION); setIndication(INDICATION_ERR_VERSION);
TRANSPORT_DEBUG(PSTR("!TSF:MSG:PVER,%d=%d\n"), mGetVersion(_msg), PROTOCOL_VERSION); // protocol version mismatch TRANSPORT_DEBUG(PSTR("!TSF:MSG:PVER,%d=%d\n"), mGetVersion(_msg),
PROTOCOL_VERSION); // protocol version mismatch
return; return;
} }
@@ -597,14 +625,14 @@ void transportProcessMessage(void) {
// update routing table if msg not from parent // update routing table if msg not from parent
#if defined(MY_REPEATER_FEATURE) #if defined(MY_REPEATER_FEATURE)
#if !defined(MY_GATEWAY_FEATURE) #if !defined(MY_GATEWAY_FEATURE)
if (last != getParentNodeId()) if (last != getParentNodeId()) {
{
#else #else
// GW doesn't have parent // GW doesn't have parent
{ {
#endif #endif
// Message is from one of the child nodes and not sent from this node. Add it to routing table. // Message is from one of the child nodes and not sent from this node. Add it to routing table.
if (sender != getNodeId()) { if (sender != getNodeId())
{
transportSetRoute(sender, last); transportSetRoute(sender, last);
} }
} }
@@ -623,7 +651,8 @@ void transportProcessMessage(void) {
if (mGetRequestAck(_msg)) { if (mGetRequestAck(_msg)) {
TRANSPORT_DEBUG(PSTR("TSF:MSG:ACK REQ\n")); // ACK requested TRANSPORT_DEBUG(PSTR("TSF:MSG:ACK REQ\n")); // ACK requested
_msgTmp = _msg; // Copy message _msgTmp = _msg; // Copy message
mSetRequestAck(_msgTmp, false); // Reply without ack flag (otherwise we would end up in an eternal loop) mSetRequestAck(_msgTmp,
false); // Reply without ack flag (otherwise we would end up in an eternal loop)
mSetAck(_msgTmp, true); // set ACK flag mSetAck(_msgTmp, true); // set ACK flag
_msgTmp.sender = _transportConfig.nodeId; _msgTmp.sender = _transportConfig.nodeId;
_msgTmp.destination = sender; _msgTmp.destination = sender;
@@ -653,7 +682,8 @@ void transportProcessMessage(void) {
if (isValidDistance(distance)) { if (isValidDistance(distance)) {
distance++; // Distance to gateway is one more for us w.r.t. parent distance++; // Distance to gateway is one more for us w.r.t. parent
// update settings if distance shorter or preferred parent found // update settings if distance shorter or preferred parent found
if (((isValidDistance(distance) && distance < _transportConfig.distanceGW) || (!_autoFindParent && sender == (uint8_t)MY_PARENT_NODE_ID)) && !_transportSM.preferredParentFound) { if (((isValidDistance(distance) && distance < _transportConfig.distanceGW) || (!_autoFindParent &&
sender == (uint8_t)MY_PARENT_NODE_ID)) && !_transportSM.preferredParentFound) {
// Found a neighbor closer to GW than previously found // Found a neighbor closer to GW than previously found
if (!_autoFindParent && sender == (uint8_t)MY_PARENT_NODE_ID) { if (!_autoFindParent && sender == (uint8_t)MY_PARENT_NODE_ID) {
_transportSM.preferredParentFound = true; _transportSM.preferredParentFound = true;
@@ -661,11 +691,11 @@ void transportProcessMessage(void) {
} }
_transportConfig.distanceGW = distance; _transportConfig.distanceGW = distance;
_transportConfig.parentNodeId = sender; _transportConfig.parentNodeId = sender;
TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR OK,ID=%d,D=%d\n"), _transportConfig.parentNodeId, _transportConfig.distanceGW); TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR OK,ID=%d,D=%d\n"), _transportConfig.parentNodeId,
_transportConfig.distanceGW);
} }
} }
} } else {
else {
TRANSPORT_DEBUG(PSTR("!TSF:MSG:FPAR INACTIVE\n")); // find parent response received, but inactive TRANSPORT_DEBUG(PSTR("!TSF:MSG:FPAR INACTIVE\n")); // find parent response received, but inactive
} }
return; return;
@@ -679,7 +709,8 @@ void transportProcessMessage(void) {
// delay for fast GW and slow nodes // delay for fast GW and slow nodes
delay(5); delay(5);
#endif #endif
(void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, I_PONG).set((uint8_t)1)); (void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL,
I_PONG).set((uint8_t)1));
return; // no further processing required return; // no further processing required
} }
if (type == I_PONG) { if (type == I_PONG) {
@@ -687,8 +718,7 @@ void transportProcessMessage(void) {
_transportSM.pingActive = false; _transportSM.pingActive = false;
_transportSM.pingResponse = _msg.getByte(); _transportSM.pingResponse = _msg.getByte();
TRANSPORT_DEBUG(PSTR("TSF:MSG:PONG RECV,HP=%d\n"), _transportSM.pingResponse); // pong received TRANSPORT_DEBUG(PSTR("TSF:MSG:PONG RECV,HP=%d\n"), _transportSM.pingResponse); // pong received
} } else {
else {
TRANSPORT_DEBUG(PSTR("!TSF:MSG:PONG RECV,INACTIVE\n")); // pong received, but !pingActive TRANSPORT_DEBUG(PSTR("!TSF:MSG:PONG RECV,INACTIVE\n")); // pong received, but !pingActive
} }
return; // no further processing required return; // no further processing required
@@ -703,9 +733,9 @@ void transportProcessMessage(void) {
} }
#endif #endif
} }
} } else {
else { TRANSPORT_DEBUG(
TRANSPORT_DEBUG(PSTR("TSF:MSG:ACK\n")); // received message is ACK, no internal processing, handover to msg callback PSTR("TSF:MSG:ACK\n")); // received message is ACK, no internal processing, handover to msg callback
} }
#if defined(MY_GATEWAY_FEATURE) #if defined(MY_GATEWAY_FEATURE)
// Hand over message to controller // Hand over message to controller
@@ -715,8 +745,7 @@ void transportProcessMessage(void) {
if (receive) { if (receive) {
receive(_msg); receive(_msg);
} }
} } else if (destination == BROADCAST_ADDRESS) {
else if (destination == BROADCAST_ADDRESS) {
TRANSPORT_DEBUG(PSTR("TSF:MSG:BC\n")); // broadcast msg TRANSPORT_DEBUG(PSTR("TSF:MSG:BC\n")); // broadcast msg
if (command == C_INTERNAL) { if (command == C_INTERNAL) {
if (isTransportReady()) { if (isTransportReady()) {
@@ -732,9 +761,9 @@ void transportProcessMessage(void) {
TRANSPORT_DEBUG(PSTR("TSF:MSG:GWL OK\n")); // GW uplink ok TRANSPORT_DEBUG(PSTR("TSF:MSG:GWL OK\n")); // GW uplink ok
// random delay minimizes collisions // random delay minimizes collisions
delay(hwMillis() & 0x3ff); delay(hwMillis() & 0x3ff);
(void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_RESPONSE).set(_transportConfig.distanceGW)); (void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL,
} I_FIND_PARENT_RESPONSE).set(_transportConfig.distanceGW));
else { } else {
TRANSPORT_DEBUG(PSTR("!TSF:MSG:GWL FAIL\n")); // GW uplink fail, do not respond to parent request TRANSPORT_DEBUG(PSTR("!TSF:MSG:GWL FAIL\n")); // GW uplink fail, do not respond to parent request
} }
} }
@@ -750,7 +779,8 @@ void transportProcessMessage(void) {
if (last == _transportConfig.parentNodeId) { if (last == _transportConfig.parentNodeId) {
// random wait to minimize collisions // random wait to minimize collisions
delay(hwMillis() & 0x3ff); delay(hwMillis() & 0x3ff);
(void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, I_DISCOVER_RESPONSE).set(_transportConfig.parentNodeId)); (void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL,
I_DISCOVER_RESPONSE).set(_transportConfig.parentNodeId));
// no return here (for fwd if repeater) // no return here (for fwd if repeater)
} }
} }
@@ -759,7 +789,8 @@ void transportProcessMessage(void) {
// controlled BC relay // controlled BC relay
#if defined(MY_REPEATER_FEATURE) #if defined(MY_REPEATER_FEATURE)
// controlled BC repeating: forward only if message received from parent and sender not self to prevent circular fwds // controlled BC repeating: forward only if message received from parent and sender not self to prevent circular fwds
if(last == _transportConfig.parentNodeId && sender != _transportConfig.nodeId && isTransportReady()){ if(last == _transportConfig.parentNodeId && sender != _transportConfig.nodeId &&
isTransportReady()) {
TRANSPORT_DEBUG(PSTR("TSF:MSG:FWD BC MSG\n")); // controlled broadcast msg forwarding TRANSPORT_DEBUG(PSTR("TSF:MSG:FWD BC MSG\n")); // controlled broadcast msg forwarding
(void)transportRouteMessage(_msg); (void)transportRouteMessage(_msg);
} }
@@ -782,8 +813,7 @@ void transportProcessMessage(void) {
} }
} }
} } else {
else {
// msg not to us and not BC, relay msg // msg not to us and not BC, relay msg
#if defined(MY_REPEATER_FEATURE) #if defined(MY_REPEATER_FEATURE)
if (isTransportReady()) { if (isTransportReady()) {
@@ -807,17 +837,18 @@ void transportProcessMessage(void) {
} }
} }
void transportInvokeSanityCheck(void) { void transportInvokeSanityCheck(void)
{
if (!transportSanityCheck()) { if (!transportSanityCheck()) {
TRANSPORT_DEBUG(PSTR("!TSF:SNK:FAIL\n")); // sanity check fail TRANSPORT_DEBUG(PSTR("!TSF:SNK:FAIL\n")); // sanity check fail
transportSwitchSM(stFailure); transportSwitchSM(stFailure);
} } else {
else {
TRANSPORT_DEBUG(PSTR("TSF:SNK:OK\n")); // sanity check ok TRANSPORT_DEBUG(PSTR("TSF:SNK:OK\n")); // sanity check ok
} }
} }
void transportProcessFIFO(void) { void transportProcessFIFO(void)
{
if (!_transportSM.transportActive) { if (!_transportSM.transportActive) {
// transport not active, no further processing required // transport not active, no further processing required
return; return;
@@ -843,7 +874,8 @@ void transportProcessFIFO(void) {
#endif #endif
} }
bool transportSendWrite(const uint8_t to, MyMessage &message) { bool transportSendWrite(const uint8_t to, MyMessage &message)
{
message.last = _transportConfig.nodeId; // Update last message.last = _transportConfig.nodeId; // Update last
// sign message if required // sign message if required
if (!signerSignMsg(message)) { if (!signerSignMsg(message)) {
@@ -853,7 +885,8 @@ bool transportSendWrite(const uint8_t to, MyMessage &message) {
} }
// msg length changes if signed // msg length changes if signed
const uint8_t totalMsgLength = HEADER_SIZE + ( mGetSigned(message) ? MAX_PAYLOAD : mGetLength(message) ); const uint8_t totalMsgLength = HEADER_SIZE + ( mGetSigned(message) ? MAX_PAYLOAD : mGetLength(
message) );
// send // send
setIndication(INDICATION_TX); setIndication(INDICATION_TX);
@@ -862,8 +895,10 @@ bool transportSendWrite(const uint8_t to, MyMessage &message) {
result |= (to == BROADCAST_ADDRESS); result |= (to == BROADCAST_ADDRESS);
TRANSPORT_DEBUG(PSTR("%sTSF:MSG:SEND,%d-%d-%d-%d,s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d,ft=%d,st=%s:%s\n"), TRANSPORT_DEBUG(PSTR("%sTSF:MSG:SEND,%d-%d-%d-%d,s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d,ft=%d,st=%s:%s\n"),
(result ? "" : "!"), message.sender, message.last, to, message.destination, message.sensor, mGetCommand(message), message.type, (result ? "" : "!"), message.sender, message.last, to, message.destination, message.sensor,
mGetPayloadType(message), mGetLength(message), mGetSigned(message), _transportSM.failedUplinkTransmissions, (result ? "OK" : "NACK"), message.getString(_convBuf)); mGetCommand(message), message.type,
mGetPayloadType(message), mGetLength(message), mGetSigned(message),
_transportSM.failedUplinkTransmissions, (result ? "OK" : "NACK"), message.getString(_convBuf));
return result; return result;
} }
@@ -887,7 +922,8 @@ uint8_t transportGetDistanceGW(void)
} }
void transportClearRoutingTable(void) { void transportClearRoutingTable(void)
{
for (uint16_t i = 0; i < SIZE_ROUTES; i++) { for (uint16_t i = 0; i < SIZE_ROUTES; i++) {
transportSetRoute((uint8_t)i, BROADCAST_ADDRESS); transportSetRoute((uint8_t)i, BROADCAST_ADDRESS);
} }
@@ -895,21 +931,24 @@ void transportClearRoutingTable(void) {
TRANSPORT_DEBUG(PSTR("TSF:CRT:OK\n")); // clear routing table TRANSPORT_DEBUG(PSTR("TSF:CRT:OK\n")); // clear routing table
} }
void transportLoadRoutingTable(void) { void transportLoadRoutingTable(void)
{
#if defined(MY_RAM_ROUTING_TABLE_ENABLED) #if defined(MY_RAM_ROUTING_TABLE_ENABLED)
hwReadConfigBlock((void*)&_transportRoutingTable.route, (void*)EEPROM_ROUTES_ADDRESS, SIZE_ROUTES); hwReadConfigBlock((void*)&_transportRoutingTable.route, (void*)EEPROM_ROUTES_ADDRESS, SIZE_ROUTES);
TRANSPORT_DEBUG(PSTR("TSF:LRT:OK\n")); // load routing table TRANSPORT_DEBUG(PSTR("TSF:LRT:OK\n")); // load routing table
#endif #endif
} }
void transportSaveRoutingTable(void) { void transportSaveRoutingTable(void)
{
#if defined(MY_RAM_ROUTING_TABLE_ENABLED) #if defined(MY_RAM_ROUTING_TABLE_ENABLED)
hwWriteConfigBlock((void*)&_transportRoutingTable.route, (void*)EEPROM_ROUTES_ADDRESS, SIZE_ROUTES); hwWriteConfigBlock((void*)&_transportRoutingTable.route, (void*)EEPROM_ROUTES_ADDRESS, SIZE_ROUTES);
TRANSPORT_DEBUG(PSTR("TSF:SRT:OK\n")); // save routing table TRANSPORT_DEBUG(PSTR("TSF:SRT:OK\n")); // save routing table
#endif #endif
} }
void transportSetRoute(const uint8_t node, const uint8_t route) { void transportSetRoute(const uint8_t node, const uint8_t route)
{
#if defined(MY_RAM_ROUTING_TABLE_ENABLED) #if defined(MY_RAM_ROUTING_TABLE_ENABLED)
_transportRoutingTable.route[node] = route; _transportRoutingTable.route[node] = route;
#else #else
@@ -917,7 +956,8 @@ void transportSetRoute(const uint8_t node, const uint8_t route) {
#endif #endif
} }
uint8_t transportGetRoute(const uint8_t node) { uint8_t transportGetRoute(const uint8_t node)
{
uint8_t result; uint8_t result;
#if defined(MY_RAM_ROUTING_TABLE_ENABLED) #if defined(MY_RAM_ROUTING_TABLE_ENABLED)
result = _transportRoutingTable.route[node]; result = _transportRoutingTable.route[node];
+2 -1
View File
@@ -37,7 +37,8 @@ typedef struct _transportQueuedMessage {
/** Buffer to store queued messages in. */ /** Buffer to store queued messages in. */
static transportQueuedMessage transportRxQueueStorage[MY_RX_MESSAGE_BUFFER_SIZE]; static transportQueuedMessage transportRxQueueStorage[MY_RX_MESSAGE_BUFFER_SIZE];
/** Circular buffer, which uses the transportRxQueueStorage and administers stored messages. */ /** Circular buffer, which uses the transportRxQueueStorage and administers stored messages. */
static CircularBuffer<transportQueuedMessage> transportRxQueue(transportRxQueueStorage, MY_RX_MESSAGE_BUFFER_SIZE); static CircularBuffer<transportQueuedMessage> transportRxQueue(transportRxQueueStorage,
MY_RX_MESSAGE_BUFFER_SIZE);
static volatile uint8_t transportLostMessageCount = 0; static volatile uint8_t transportLostMessageCount = 0;
+16 -8
View File
@@ -26,7 +26,8 @@ RFM69 _radio(MY_RF69_SPI_CS, MY_RF69_IRQ_PIN, MY_RFM69HW, MY_RF69_IRQ_NUM);
uint8_t _address; uint8_t _address;
bool transportInit() { bool transportInit()
{
// Start up the radio library (_address will be set later by the MySensors library) // Start up the radio library (_address will be set later by the MySensors library)
if (_radio.initialize(MY_RFM69_FREQUENCY, _address, MY_RFM69_NETWORKID)) { if (_radio.initialize(MY_RFM69_FREQUENCY, _address, MY_RFM69_NETWORKID)) {
#ifdef MY_RFM69_ENABLE_ENCRYPTION #ifdef MY_RFM69_ENABLE_ENCRYPTION
@@ -40,29 +41,35 @@ bool transportInit() {
return false; return false;
} }
void transportSetAddress(uint8_t address) { void transportSetAddress(uint8_t address)
{
_address = address; _address = address;
_radio.setAddress(address); _radio.setAddress(address);
} }
uint8_t transportGetAddress() { uint8_t transportGetAddress()
{
return _address; return _address;
} }
bool transportSend(uint8_t to, const void* data, uint8_t len) { bool transportSend(uint8_t to, const void* data, uint8_t len)
{
return _radio.sendWithRetry(to,data,len); return _radio.sendWithRetry(to,data,len);
} }
bool transportAvailable() { bool transportAvailable()
{
return _radio.receiveDone(); return _radio.receiveDone();
} }
bool transportSanityCheck() { bool transportSanityCheck()
{
// not implemented yet // not implemented yet
return true; return true;
} }
uint8_t transportReceive(void* data) { uint8_t transportReceive(void* data)
{
memcpy(data,(const void *)_radio.DATA, _radio.DATALEN); memcpy(data,(const void *)_radio.DATA, _radio.DATALEN);
// save payload length // save payload length
const uint8_t dataLen = _radio.DATALEN; const uint8_t dataLen = _radio.DATALEN;
@@ -73,6 +80,7 @@ uint8_t transportReceive(void* data) {
return dataLen; return dataLen;
} }
void transportPowerDown() { void transportPowerDown()
{
_radio.sleep(); _radio.sleep();
} }
+18 -9
View File
@@ -22,7 +22,8 @@
#include "MyTransport.h" #include "MyTransport.h"
#include "drivers/RFM95/RFM95.h" #include "drivers/RFM95/RFM95.h"
bool transportInit(void) { bool transportInit(void)
{
const bool result = RFM95_initialise(MY_RFM95_FREQUENCY); const bool result = RFM95_initialise(MY_RFM95_FREQUENCY);
#if !defined(MY_GATEWAY_FEATURE) && !defined(MY_RFM95_ATC_MODE_DISABLED) #if !defined(MY_GATEWAY_FEATURE) && !defined(MY_RFM95_ATC_MODE_DISABLED)
// only enable ATC mode nodes // only enable ATC mode nodes
@@ -31,34 +32,42 @@ bool transportInit(void) {
return result; return result;
} }
void transportSetAddress(uint8_t address) { void transportSetAddress(uint8_t address)
{
RFM95_setAddress(address); RFM95_setAddress(address);
} }
uint8_t transportGetAddress(void) { uint8_t transportGetAddress(void)
{
return RFM95_getAddress(); return RFM95_getAddress();
} }
bool transportSend(uint8_t to, const void* data, uint8_t len) { bool transportSend(uint8_t to, const void* data, uint8_t len)
{
return RFM95_sendWithRetry(to, data, len); return RFM95_sendWithRetry(to, data, len);
} }
bool transportAvailable(void) { bool transportAvailable(void)
{
return RFM95_available(); return RFM95_available();
} }
bool transportSanityCheck(void) { bool transportSanityCheck(void)
{
return RFM95_sanityCheck(); return RFM95_sanityCheck();
} }
uint8_t transportReceive(void* data) { uint8_t transportReceive(void* data)
{
return RFM95_recv((uint8_t*)data); return RFM95_recv((uint8_t*)data);
} }
void transportPowerDown(void) { void transportPowerDown(void)
{
(void)RFM95_sleep(); (void)RFM95_sleep();
} }
int16_t transportGetSignalStrength(void) { int16_t transportGetSignalStrength(void)
{
return RFM95_getRSSI(); return RFM95_getRSSI();
} }
+17 -10
View File
@@ -114,7 +114,8 @@ bool _packet_received;
//Reset the state machine and release the data pointer //Reset the state machine and release the data pointer
void _serialReset(){ void _serialReset()
{
_recPhase = 0; _recPhase = 0;
_recPos = 0; _recPos = 0;
_recLen = 0; _recLen = 0;
@@ -318,7 +319,8 @@ bool transportSend(uint8_t to, const void* data, uint8_t len)
bool transportInit() { bool transportInit()
{
// Reset the state machine // Reset the state machine
_dev.begin(MY_RS485_BAUD_RATE); _dev.begin(MY_RS485_BAUD_RATE);
_serialReset(); _serialReset();
@@ -329,36 +331,41 @@ bool transportInit() {
return true; return true;
} }
void transportSetAddress(uint8_t address) { void transportSetAddress(uint8_t address)
{
_nodeId = address; _nodeId = address;
} }
uint8_t transportGetAddress() { uint8_t transportGetAddress()
{
return _nodeId; return _nodeId;
} }
bool transportAvailable() { bool transportAvailable()
{
_serialProcess(); _serialProcess();
return _packet_received; return _packet_received;
} }
bool transportSanityCheck() { bool transportSanityCheck()
{
// not implemented yet // not implemented yet
return true; return true;
} }
uint8_t transportReceive(void* data) { uint8_t transportReceive(void* data)
{
if (_packet_received) { if (_packet_received) {
memcpy(data,_data,_packet_len); memcpy(data,_data,_packet_len);
_packet_received = false; _packet_received = false;
return _packet_len; return _packet_len;
} } else {
else {
return (0); return (0);
} }
} }
void transportPowerDown() { void transportPowerDown()
{
// Nothing to shut down here // Nothing to shut down here
} }
+102 -82
View File
@@ -65,8 +65,7 @@
#define WPOLY 0x011B #define WPOLY 0x011B
#define DPOLY 0x008D #define DPOLY 0x008D
const static byte s_fwd [0x100] PROGMEM = const static byte s_fwd [0x100] PROGMEM = {
{
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
@@ -85,8 +84,7 @@ const static byte s_fwd [0x100] PROGMEM =
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
} ; } ;
const static byte s_inv [0x100] PROGMEM = const static byte s_inv [0x100] PROGMEM = {
{
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
@@ -125,8 +123,7 @@ static byte is_box (byte x)
static void xor_block (byte * d, byte * s) static void xor_block (byte * d, byte * s)
{ {
for (byte i = 0 ; i < N_BLOCK ; i += 4) for (byte i = 0 ; i < N_BLOCK ; i += 4) {
{
*d++ ^= *s++ ; // some unrolling *d++ ^= *s++ ; // some unrolling
*d++ ^= *s++ ; *d++ ^= *s++ ;
*d++ ^= *s++ ; *d++ ^= *s++ ;
@@ -136,8 +133,7 @@ static void xor_block (byte * d, byte * s)
static void copy_and_key (byte * d, byte * s, byte * k) static void copy_and_key (byte * d, byte * s, byte * k)
{ {
for (byte i = 0 ; i < N_BLOCK ; i += 4) for (byte i = 0 ; i < N_BLOCK ; i += 4) {
{
*d++ = *s++ ^ *k++ ; // some unrolling *d++ = *s++ ^ *k++ ; // some unrolling
*d++ = *s++ ^ *k++ ; *d++ = *s++ ^ *k++ ;
*d++ = *s++ ^ *k++ ; *d++ = *s++ ^ *k++ ;
@@ -151,36 +147,56 @@ static void copy_and_key (byte * d, byte * s, byte * k)
static void shift_sub_rows (byte st [N_BLOCK]) static void shift_sub_rows (byte st [N_BLOCK])
{ {
st [0] = s_box (st [0]) ; st [4] = s_box (st [4]) ; st [0] = s_box (st [0]) ;
st [8] = s_box (st [8]) ; st [12] = s_box (st [12]) ; st [4] = s_box (st [4]) ;
st [8] = s_box (st [8]) ;
st [12] = s_box (st [12]) ;
byte tt = st [1] ; byte tt = st [1] ;
st [1] = s_box (st [5]) ; st [5] = s_box (st [9]) ; st [1] = s_box (st [5]) ;
st [9] = s_box (st [13]) ; st [13] = s_box (tt) ; st [5] = s_box (st [9]) ;
st [9] = s_box (st [13]) ;
st [13] = s_box (tt) ;
tt = st[2] ; st [2] = s_box (st [10]) ; st [10] = s_box (tt) ; tt = st[2] ;
tt = st[6] ; st [6] = s_box (st [14]) ; st [14] = s_box (tt) ; st [2] = s_box (st [10]) ;
st [10] = s_box (tt) ;
tt = st[6] ;
st [6] = s_box (st [14]) ;
st [14] = s_box (tt) ;
tt = st[15] ; tt = st[15] ;
st [15] = s_box (st [11]) ; st [11] = s_box (st [7]) ; st [15] = s_box (st [11]) ;
st [7] = s_box (st [3]) ; st [3] = s_box (tt) ; st [11] = s_box (st [7]) ;
st [7] = s_box (st [3]) ;
st [3] = s_box (tt) ;
} }
static void inv_shift_sub_rows (byte st[N_BLOCK]) static void inv_shift_sub_rows (byte st[N_BLOCK])
{ {
st [0] = is_box (st[0]) ; st [4] = is_box (st [4]); st [0] = is_box (st[0]) ;
st [8] = is_box (st[8]) ; st [12] = is_box (st [12]); st [4] = is_box (st [4]);
st [8] = is_box (st[8]) ;
st [12] = is_box (st [12]);
byte tt = st[13] ; byte tt = st[13] ;
st [13] = is_box (st [9]) ; st [9] = is_box (st [5]) ; st [13] = is_box (st [9]) ;
st [5] = is_box (st [1]) ; st [1] = is_box (tt) ; st [9] = is_box (st [5]) ;
st [5] = is_box (st [1]) ;
st [1] = is_box (tt) ;
tt = st [2] ; st [2] = is_box (st [10]) ; st [10] = is_box (tt) ; tt = st [2] ;
tt = st [6] ; st [6] = is_box (st [14]) ; st [14] = is_box (tt) ; st [2] = is_box (st [10]) ;
st [10] = is_box (tt) ;
tt = st [6] ;
st [6] = is_box (st [14]) ;
st [14] = is_box (tt) ;
tt = st [3] ; tt = st [3] ;
st [3] = is_box (st [7]) ; st [7] = is_box (st [11]) ; st [3] = is_box (st [7]) ;
st [11] = is_box (st [15]) ; st [15] = is_box (tt) ; st [7] = is_box (st [11]) ;
st [11] = is_box (st [15]) ;
st [15] = is_box (tt) ;
} }
/* SUB COLUMNS PHASE */ /* SUB COLUMNS PHASE */
@@ -190,12 +206,14 @@ static void mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
byte j = 5 ; byte j = 5 ;
byte k = 10 ; byte k = 10 ;
byte l = 15 ; byte l = 15 ;
for (byte i = 0 ; i < N_BLOCK ; i += N_COL) for (byte i = 0 ; i < N_BLOCK ; i += N_COL) {
{
byte a = st [i] ; byte a = st [i] ;
byte b = st [j] ; j = (j+N_COL) & 15 ; byte b = st [j] ;
byte c = st [k] ; k = (k+N_COL) & 15 ; j = (j+N_COL) & 15 ;
byte d = st [l] ; l = (l+N_COL) & 15 ; byte c = st [k] ;
k = (k+N_COL) & 15 ;
byte d = st [l] ;
l = (l+N_COL) & 15 ;
byte a1 = s_box (a), b1 = s_box (b), c1 = s_box (c), d1 = s_box (d) ; byte a1 = s_box (a), b1 = s_box (b), c1 = s_box (c), d1 = s_box (d) ;
byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ; byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ;
dt[i] = a2 ^ b2^b1 ^ c1 ^ d1 ; dt[i] = a2 ^ b2^b1 ^ c1 ^ d1 ;
@@ -207,8 +225,7 @@ static void mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
static void inv_mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK]) static void inv_mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
{ {
for (byte i = 0 ; i < N_BLOCK ; i += N_COL) for (byte i = 0 ; i < N_BLOCK ; i += N_COL) {
{
byte a1 = st [i] ; byte a1 = st [i] ;
byte b1 = st [i+1] ; byte b1 = st [i+1] ;
byte c1 = st [i+2] ; byte c1 = st [i+2] ;
@@ -228,7 +245,8 @@ static void inv_mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
/******************************************************************************/ /******************************************************************************/
AES::AES(){ AES::AES()
{
byte ar_iv[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 }; byte ar_iv[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 };
memcpy(iv,ar_iv,8); memcpy(iv,ar_iv,8);
memcpy(iv+8,ar_iv,8); memcpy(iv+8,ar_iv,8);
@@ -254,8 +272,7 @@ AES::AES(){
byte AES::set_key (byte key [], int keylen) byte AES::set_key (byte key [], int keylen)
{ {
byte hi ; byte hi ;
switch (keylen) switch (keylen) {
{
case 16: case 16:
case 128: case 128:
keylen = 16; // 10 rounds keylen = 16; // 10 rounds
@@ -279,13 +296,11 @@ byte AES::set_key (byte key [], int keylen)
copy_n_bytes (key_sched, key, keylen) ; copy_n_bytes (key_sched, key, keylen) ;
byte t[4] ; byte t[4] ;
byte next = keylen ; byte next = keylen ;
for (byte cc = keylen, rc = 1 ; cc < hi ; cc += N_COL) for (byte cc = keylen, rc = 1 ; cc < hi ; cc += N_COL) {
{
for (byte i = 0 ; i < N_COL ; i++) { for (byte i = 0 ; i < N_COL ; i++) {
t[i] = key_sched [cc-4+i] ; t[i] = key_sched [cc-4+i] ;
} }
if (cc == next) if (cc == next) {
{
next += keylen ; next += keylen ;
byte ttt = t[0] ; byte ttt = t[0] ;
t[0] = s_box (t[1]) ^ rc ; t[0] = s_box (t[1]) ^ rc ;
@@ -293,9 +308,7 @@ byte AES::set_key (byte key [], int keylen)
t[2] = s_box (t[3]) ; t[2] = s_box (t[3]) ;
t[3] = s_box (ttt) ; t[3] = s_box (ttt) ;
rc = f2 (rc) ; rc = f2 (rc) ;
} } else if (keylen == 32 && (cc & 31) == 16) {
else if (keylen == 32 && (cc & 31) == 16)
{
for (byte i = 0 ; i < 4 ; i++) { for (byte i = 0 ; i < 4 ; i++) {
t[i] = s_box (t[i]) ; t[i] = s_box (t[i]) ;
} }
@@ -322,38 +335,36 @@ void AES::clean ()
void AES::copy_n_bytes (byte * d, byte * s, byte nn) void AES::copy_n_bytes (byte * d, byte * s, byte nn)
{ {
while (nn >= 4) while (nn >= 4) {
{
*d++ = *s++ ; // some unrolling *d++ = *s++ ; // some unrolling
*d++ = *s++ ; *d++ = *s++ ;
*d++ = *s++ ; *d++ = *s++ ;
*d++ = *s++ ; *d++ = *s++ ;
nn -= 4 ; nn -= 4 ;
} }
while (nn--) while (nn--) {
*d++ = *s++ ; *d++ = *s++ ;
} }
}
/******************************************************************************/ /******************************************************************************/
byte AES::encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK]) byte AES::encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
{ {
if (round) if (round) {
{
byte s1 [N_BLOCK], r ; byte s1 [N_BLOCK], r ;
copy_and_key (s1, plain, (byte*) (key_sched)) ; copy_and_key (s1, plain, (byte*) (key_sched)) ;
for (r = 1 ; r < round ; r++) for (r = 1 ; r < round ; r++) {
{
byte s2 [N_BLOCK] ; byte s2 [N_BLOCK] ;
mix_sub_columns (s2, s1) ; mix_sub_columns (s2, s1) ;
copy_and_key (s1, s2, (byte*) (key_sched + r * N_BLOCK)) ; copy_and_key (s1, s2, (byte*) (key_sched + r * N_BLOCK)) ;
} }
shift_sub_rows (s1) ; shift_sub_rows (s1) ;
copy_and_key (cipher, s1, (byte*) (key_sched + r * N_BLOCK)) ; copy_and_key (cipher, s1, (byte*) (key_sched + r * N_BLOCK)) ;
} } else {
else
return AES_FAILURE ; return AES_FAILURE ;
}
return AES_SUCCESS ; return AES_SUCCESS ;
} }
@@ -361,8 +372,7 @@ byte AES::encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOCK]) byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOCK])
{ {
while (n_block--) while (n_block--) {
{
xor_block (iv, plain) ; xor_block (iv, plain) ;
if (encrypt (iv, iv) != AES_SUCCESS) { if (encrypt (iv, iv) != AES_SUCCESS) {
return AES_FAILURE ; return AES_FAILURE ;
@@ -378,8 +388,7 @@ byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOC
byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block) byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block)
{ {
while (n_block--) while (n_block--) {
{
xor_block (iv, plain) ; xor_block (iv, plain) ;
if (encrypt (iv, iv) != AES_SUCCESS) { if (encrypt (iv, iv) != AES_SUCCESS) {
return AES_FAILURE ; return AES_FAILURE ;
@@ -395,22 +404,20 @@ byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block)
byte AES::decrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK]) byte AES::decrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
{ {
if (round) if (round) {
{
byte s1 [N_BLOCK] ; byte s1 [N_BLOCK] ;
copy_and_key (s1, plain, (byte*) (key_sched + round * N_BLOCK)) ; copy_and_key (s1, plain, (byte*) (key_sched + round * N_BLOCK)) ;
inv_shift_sub_rows (s1) ; inv_shift_sub_rows (s1) ;
for (byte r = round ; --r ; ) for (byte r = round ; --r ; ) {
{
byte s2 [N_BLOCK] ; byte s2 [N_BLOCK] ;
copy_and_key (s2, s1, (byte*) (key_sched + r * N_BLOCK)) ; copy_and_key (s2, s1, (byte*) (key_sched + r * N_BLOCK)) ;
inv_mix_sub_columns (s1, s2) ; inv_mix_sub_columns (s1, s2) ;
} }
copy_and_key (cipher, s1, (byte*) (key_sched)) ; copy_and_key (cipher, s1, (byte*) (key_sched)) ;
} } else {
else
return AES_FAILURE ; return AES_FAILURE ;
}
return AES_SUCCESS ; return AES_SUCCESS ;
} }
@@ -418,8 +425,7 @@ byte AES::decrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK]) byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK])
{ {
while (n_block--) while (n_block--) {
{
byte tmp [N_BLOCK] ; byte tmp [N_BLOCK] ;
copy_n_bytes (tmp, cipher, N_BLOCK) ; copy_n_bytes (tmp, cipher, N_BLOCK) ;
if (decrypt (cipher, plain) != AES_SUCCESS) { if (decrypt (cipher, plain) != AES_SUCCESS) {
@@ -437,8 +443,7 @@ byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOC
byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block) byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block)
{ {
while (n_block--) while (n_block--) {
{
byte tmp [N_BLOCK] ; byte tmp [N_BLOCK] ;
copy_n_bytes (tmp, cipher, N_BLOCK) ; copy_n_bytes (tmp, cipher, N_BLOCK) ;
if (decrypt (cipher, plain) != AES_SUCCESS) { if (decrypt (cipher, plain) != AES_SUCCESS) {
@@ -454,7 +459,8 @@ byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block)
/*****************************************************************************/ /*****************************************************************************/
void AES::set_IV(unsigned long long int IVCl){ void AES::set_IV(unsigned long long int IVCl)
{
memcpy(iv,&IVCl,8); memcpy(iv,&IVCl,8);
memcpy(iv+8,&IVCl,8); memcpy(iv+8,&IVCl,8);
IVC = IVCl; IVC = IVCl;
@@ -462,7 +468,8 @@ void AES::set_IV(unsigned long long int IVCl){
/******************************************************************************/ /******************************************************************************/
void AES::iv_inc(){ void AES::iv_inc()
{
IVC += 1; IVC += 1;
memcpy(iv,&IVC,8); memcpy(iv,&IVC,8);
memcpy(iv+8,&IVC,8); memcpy(iv+8,&IVC,8);
@@ -470,27 +477,31 @@ void AES::iv_inc(){
/******************************************************************************/ /******************************************************************************/
int AES::get_size(){ int AES::get_size()
{
return size; return size;
} }
/******************************************************************************/ /******************************************************************************/
void AES::set_size(int sizel){ void AES::set_size(int sizel)
{
size = sizel; size = sizel;
} }
/******************************************************************************/ /******************************************************************************/
void AES::get_IV(byte *out){ void AES::get_IV(byte *out)
{
memcpy(out,&IVC,8); memcpy(out,&IVC,8);
memcpy(out+8,&IVC,8); memcpy(out+8,&IVC,8);
} }
/******************************************************************************/ /******************************************************************************/
void AES::calc_size_n_pad(int p_size){ void AES::calc_size_n_pad(int p_size)
{
int s_of_p = p_size - 1; int s_of_p = p_size - 1;
if ( s_of_p % N_BLOCK == 0) { if ( s_of_p % N_BLOCK == 0) {
size = s_of_p; size = s_of_p;
@@ -505,14 +516,16 @@ void AES::calc_size_n_pad(int p_size){
void AES::padPlaintext(void* in,byte* out) void AES::padPlaintext(void* in,byte* out)
{ {
memcpy(out,in,size); memcpy(out,in,size);
for (int i = size-pad; i < size; i++){; for (int i = size-pad; i < size; i++) {
;
out[i] = arr_pad[pad - 1]; out[i] = arr_pad[pad - 1];
} }
} }
/******************************************************************************/ /******************************************************************************/
bool AES::CheckPad(byte* in,int lsize){ bool AES::CheckPad(byte* in,int lsize)
{
if (in[lsize-1] <= 0x0f) { if (in[lsize-1] <= 0x0f) {
int lpad = (int)in[lsize-1]; int lpad = (int)in[lsize-1];
for (int i = lsize - 1; i >= lsize-lpad; i--) { for (int i = lsize - 1; i >= lsize-lpad; i--) {
@@ -534,9 +547,10 @@ uint8_t i,j;
uint8_t loops = size/N_BLOCK; uint8_t loops = size/N_BLOCK;
uint8_t outp = N_BLOCK; uint8_t outp = N_BLOCK;
for (j = 0; j < loops; j += 1) { for (j = 0; j < loops; j += 1) {
if (p_pad && (j == (loops - 1)) ) { outp = N_BLOCK - pad; } if (p_pad && (j == (loops - 1)) ) {
for (i = 0; i < outp; i++) outp = N_BLOCK - pad;
{ }
for (i = 0; i < outp; i++) {
printf_P(PSTR("%c"),output[j*N_BLOCK + i]); printf_P(PSTR("%c"),output[j*N_BLOCK + i]);
} }
} }
@@ -547,8 +561,7 @@ for (j = 0; j < loops; j += 1){
void AES::printArray(byte output[],int sizel) void AES::printArray(byte output[],int sizel)
{ {
for (int i = 0; i < sizel; i++) for (int i = 0; i < sizel; i++) {
{
printf_P(PSTR("%x"),output[i]); printf_P(PSTR("%x"),output[i]);
} }
printf_P(PSTR("\n")); printf_P(PSTR("\n"));
@@ -557,7 +570,9 @@ void AES::printArray(byte output[],int sizel)
/******************************************************************************/ /******************************************************************************/
void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits, byte ivl [N_BLOCK]){ void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits,
byte ivl [N_BLOCK])
{
calc_size_n_pad(size_p); calc_size_n_pad(size_p);
byte plain_p[get_size()]; byte plain_p[get_size()];
padPlaintext(plain,plain_p); padPlaintext(plain,plain_p);
@@ -568,7 +583,8 @@ void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits
/******************************************************************************/ /******************************************************************************/
void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits){ void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits)
{
calc_size_n_pad(size_p); calc_size_n_pad(size_p);
byte plain_p[get_size()]; byte plain_p[get_size()];
padPlaintext(plain,plain_p); padPlaintext(plain,plain_p);
@@ -579,7 +595,9 @@ void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits
/******************************************************************************/ /******************************************************************************/
void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits, byte ivl [N_BLOCK]){ void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits,
byte ivl [N_BLOCK])
{
set_size(size_c); set_size(size_c);
int blocks = size_c / N_BLOCK; int blocks = size_c / N_BLOCK;
set_key (key, bits); set_key (key, bits);
@@ -588,7 +606,8 @@ void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits
/******************************************************************************/ /******************************************************************************/
void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits){ void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits)
{
set_size(size_c); set_size(size_c);
int blocks = size_c / N_BLOCK; int blocks = size_c / N_BLOCK;
set_key (key, bits); set_key (key, bits);
@@ -599,7 +618,8 @@ void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits
/******************************************************************************/ /******************************************************************************/
#if defined(AES_LINUX) #if defined(AES_LINUX)
double AES::millis(){ double AES::millis()
{
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
return (tv.tv_sec + 0.000001 * tv.tv_usec); return (tv.tv_sec + 0.000001 * tv.tv_usec);
} }
+2 -1
View File
@@ -295,7 +295,8 @@ class AES
#endif #endif
private: private:
int round ;/**< holds the number of rounds to be used. */ int round ;/**< holds the number of rounds to be used. */
byte key_sched [KEY_SCHEDULE_BYTES] ;/**< holds the pre-computed key for the encryption/decrpytion. */ byte key_sched [KEY_SCHEDULE_BYTES]
;/**< holds the pre-computed key for the encryption/decrpytion. */
unsigned long long int IVC;/**< holds the initialization vector counter in numerical format. */ unsigned long long int IVC;/**< holds the initialization vector counter in numerical format. */
byte iv[16];/**< holds the initialization vector that will be used in the cipher. */ byte iv[16];/**< holds the initialization vector that will be used in the cipher. */
int pad;/**< holds the size of the padding. */ int pad;/**< holds the size of the padding. */
+38 -39
View File
@@ -22,8 +22,7 @@ int main(int argc, char** argv)
monte_carlo (128) ; monte_carlo (128) ;
for (int keysize = 128 ; keysize <= 256 ; keysize += 64) for (int keysize = 128 ; keysize <= 256 ; keysize += 64) {
{
prekey_test_var_plaintext (keysize) ; prekey_test_var_plaintext (keysize) ;
prekey_test_var_key (keysize) ; prekey_test_var_key (keysize) ;
} }
@@ -37,12 +36,12 @@ void prekey_test_var_plaintext (int bits)
byte succ ; byte succ ;
set_bits (bits, key, 0) ; // all zero key set_bits (bits, key, 0) ; // all zero key
succ = aes.set_key (key, bits) ; succ = aes.set_key (key, bits) ;
if (succ != SUCCESS) if (succ != SUCCESS) {
printf("Failure set_key\n") ; printf("Failure set_key\n") ;
}
for (int bitcount = 1 ; bitcount <= 128 ; bitcount++) for (int bitcount = 1 ; bitcount <= 128 ; bitcount++) {
{
printf ("COUNT = %i \n",bitcount-1); printf ("COUNT = %i \n",bitcount-1);
print_value ("KEY = ", key, bits) ; print_value ("KEY = ", key, bits) ;
set_bits (128, plain, bitcount) ; set_bits (128, plain, bitcount) ;
@@ -50,14 +49,16 @@ void prekey_test_var_plaintext (int bits)
print_value ("PLAINTEXT = ", plain, 128) ; print_value ("PLAINTEXT = ", plain, 128) ;
succ = aes.encrypt (plain, cipher) ; succ = aes.encrypt (plain, cipher) ;
if (succ != SUCCESS) if (succ != SUCCESS) {
printf ("Failure encrypt\n") ; printf ("Failure encrypt\n") ;
}
print_value ("CIPHERTEXT = ", cipher, 128) ; print_value ("CIPHERTEXT = ", cipher, 128) ;
succ = aes.decrypt (cipher, check) ; succ = aes.decrypt (cipher, check) ;
if (succ != SUCCESS) if (succ != SUCCESS) {
printf ("Failure decrypt\n") ; printf ("Failure decrypt\n") ;
}
//print_value ("CHECK = ", check, 128) ; //print_value ("CHECK = ", check, 128) ;
check_same (plain, check, 128) ; check_same (plain, check, 128) ;
@@ -73,26 +74,28 @@ void prekey_test_var_key (int bits)
byte succ ; byte succ ;
set_bits (128, plain, 0) ; set_bits (128, plain, 0) ;
for (int bitcount = 1 ; bitcount <= bits ; bitcount++) for (int bitcount = 1 ; bitcount <= bits ; bitcount++) {
{
set_bits (bits, key, bitcount) ; // all zero key set_bits (bits, key, bitcount) ; // all zero key
succ = aes.set_key (key, bits) ; succ = aes.set_key (key, bits) ;
if (succ != SUCCESS) if (succ != SUCCESS) {
printf ("Failure set_key\n") ; printf ("Failure set_key\n") ;
}
printf ("COUNT = %i\n",bitcount-1); printf ("COUNT = %i\n",bitcount-1);
print_value ("KEY = ", key, bits) ; print_value ("KEY = ", key, bits) ;
print_value ("PLAINTEXT = ", plain, 128) ; print_value ("PLAINTEXT = ", plain, 128) ;
succ = aes.encrypt (plain, cipher) ; succ = aes.encrypt (plain, cipher) ;
if (succ != SUCCESS) if (succ != SUCCESS) {
printf ("Failure encrypt\n") ; printf ("Failure encrypt\n") ;
}
print_value ("CIPHERTEXT = ", cipher, 128) ; print_value ("CIPHERTEXT = ", cipher, 128) ;
succ = aes.decrypt (cipher, check) ; succ = aes.decrypt (cipher, check) ;
if (succ != SUCCESS) if (succ != SUCCESS) {
printf ("Failure decrypt\n") ; printf ("Failure decrypt\n") ;
}
check_same (plain, check, 128) ; check_same (plain, check, 128) ;
printf("\n"); printf("\n");
@@ -103,20 +106,22 @@ void set_bits (int bits, byte * a, int count)
{ {
bits >>= 3 ; bits >>= 3 ;
byte bcount = count >> 3 ; byte bcount = count >> 3 ;
for (byte i = 0 ; i < bcount ; i++) for (byte i = 0 ; i < bcount ; i++) {
a [i] = 0xFF ; a [i] = 0xFF ;
if ((count & 7) != 0) }
if ((count & 7) != 0) {
a [bcount++] = 0xFF & (0xFF00 >> (count & 7)) ; a [bcount++] = 0xFF & (0xFF00 >> (count & 7)) ;
for (byte i = bcount ; i < bits ; i++) }
for (byte i = bcount ; i < bits ; i++) {
a [i] = 0x00 ; a [i] = 0x00 ;
} }
}
void check_same (byte * a, byte * b, int bits) void check_same (byte * a, byte * b, int bits)
{ {
bits >>= 3 ; bits >>= 3 ;
for (byte i = 0 ; i < bits ; i++) for (byte i = 0 ; i < bits ; i++)
if (a[i] != b[i]) if (a[i] != b[i]) {
{
printf ("Failure plain != check\n") ; printf ("Failure plain != check\n") ;
return ; return ;
} }
@@ -129,8 +134,7 @@ void print_value (const char * str, byte * a, int bits)
{ {
printf ("%s",str) ; printf ("%s",str) ;
bits >>= 3 ; bits >>= 3 ;
for (int i = 0 ; i < bits ; i++) for (int i = 0 ; i < bits ; i++) {
{
byte b = a[i] ; byte b = a[i] ;
printf("%c%c",hex[b >> 4],hex [b & 15]); printf("%c%c",hex[b >> 4],hex [b & 15]);
//Serial.print (hex [b >> 4]) ; //Serial.print (hex [b >> 4]) ;
@@ -139,45 +143,40 @@ void print_value (const char * str, byte * a, int bits)
printf("\n") ; printf("\n") ;
} }
byte monteplain [] = byte monteplain [] = {
{ 0xb9, 0x14, 0x5a, 0x76, 0x8b, 0x7d, 0xc4, 0x89, 0xb9, 0x14, 0x5a, 0x76, 0x8b, 0x7d, 0xc4, 0x89,
0xa0, 0x96, 0xb5, 0x46, 0xf4, 0x3b, 0x23, 0x1f } ; 0xa0, 0x96, 0xb5, 0x46, 0xf4, 0x3b, 0x23, 0x1f
byte montekey [] = } ;
{ 0x13, 0x9a, 0x35, 0x42, 0x2f, 0x1d, 0x61, 0xde, byte montekey [] = {
0x3c, 0x91, 0x78, 0x7f, 0xe0, 0x50, 0x7a, 0xfd } ; 0x13, 0x9a, 0x35, 0x42, 0x2f, 0x1d, 0x61, 0xde,
0x3c, 0x91, 0x78, 0x7f, 0xe0, 0x50, 0x7a, 0xfd
} ;
void monte_carlo (int bits) void monte_carlo (int bits)
{ {
printf ("\nMonte Carlo %i bits\n",bits); printf ("\nMonte Carlo %i bits\n",bits);
byte succ; byte succ;
for (int i = 0 ; i < 16 ; i++) for (int i = 0 ; i < 16 ; i++) {
{
plain [i] = monteplain [i] ; plain [i] = monteplain [i] ;
key [i] = montekey [i] ; key [i] = montekey [i] ;
} }
for (int i = 0 ; i < 100 ; i++) for (int i = 0 ; i < 100 ; i++) {
{
printf ("COUNT = %i\n",i); printf ("COUNT = %i\n",i);
print_value ("KEY = ", key, bits) ; print_value ("KEY = ", key, bits) ;
print_value ("PLAINTEXT = ", plain, 128) ; print_value ("PLAINTEXT = ", plain, 128) ;
succ = aes.set_key (key, bits) ; succ = aes.set_key (key, bits) ;
for (int j = 0 ; j < 1000 ; j++) for (int j = 0 ; j < 1000 ; j++) {
{
succ = aes.encrypt (plain, cipher) ; succ = aes.encrypt (plain, cipher) ;
aes.copy_n_bytes (plain, cipher, 16) ; aes.copy_n_bytes (plain, cipher, 16) ;
} }
print_value ("CIPHERTEXT = ", cipher, 128) ; print_value ("CIPHERTEXT = ", cipher, 128) ;
printf("\n"); printf("\n");
if (bits == 128) if (bits == 128) {
{ for (byte k = 0 ; k < 16 ; k++) {
for (byte k = 0 ; k < 16 ; k++)
key [k] ^= cipher [k] ; key [k] ^= cipher [k] ;
} }
else if (bits == 192) } else if (bits == 192) {
{ } else {
}
else
{
} }
} }
} }
+52 -89
View File
@@ -16,7 +16,8 @@ static uint8_t swi_send_byte(uint8_t value);
static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response); static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response);
static uint8_t sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, uint16_t address); static uint8_t sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, uint16_t address);
static uint8_t sha204c_resync(uint8_t size, uint8_t *response); static uint8_t sha204c_resync(uint8_t size, uint8_t *response);
static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, uint8_t execution_delay, uint8_t execution_timeout); static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer,
uint8_t execution_delay, uint8_t execution_timeout);
/* SWI bit bang functions */ /* SWI bit bang functions */
@@ -26,8 +27,7 @@ static void swi_set_signal_pin(uint8_t is_high)
if (is_high) { if (is_high) {
SHA204_POUT_HIGH(); SHA204_POUT_HIGH();
} } else {
else {
SHA204_POUT_LOW(); SHA204_POUT_LOW();
} }
} }
@@ -47,19 +47,14 @@ static uint8_t swi_send_bytes(uint8_t count, uint8_t *buffer)
// Wait turn around time. // Wait turn around time.
delayMicroseconds(RX_TX_DELAY); //RX_TX_DELAY; delayMicroseconds(RX_TX_DELAY); //RX_TX_DELAY;
for (i = 0; i < count; i++) for (i = 0; i < count; i++) {
{ for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) {
for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) if (bit_mask & buffer[i]) {
{
if (bit_mask & buffer[i])
{
SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin; SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin;
delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; delayMicroseconds(BIT_DELAY); //BIT_DELAY_1;
SHA204_POUT_HIGH(); //*device_port_OUT |= device_pin; SHA204_POUT_HIGH(); //*device_port_OUT |= device_pin;
delayMicroseconds(7*BIT_DELAY); //BIT_DELAY_7; delayMicroseconds(7*BIT_DELAY); //BIT_DELAY_7;
} } else {
else
{
// Send a zero bit. // Send a zero bit.
SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin; SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin;
delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; delayMicroseconds(BIT_DELAY); //BIT_DELAY_1;
@@ -96,10 +91,8 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
SHA204_SET_INPUT(); SHA204_SET_INPUT();
// Receive bits and store in buffer. // Receive bits and store in buffer.
for (i = 0; i < count; i++) for (i = 0; i < count; i++) {
{ for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) {
for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1)
{
pulse_count = 0; pulse_count = 0;
// Make sure that the variable below is big enough. // Make sure that the variable below is big enough.
@@ -108,33 +101,28 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
timeout_count = START_PULSE_TIME_OUT; timeout_count = START_PULSE_TIME_OUT;
// Detect start bit. // Detect start bit.
while (--timeout_count > 0) while (--timeout_count > 0) {
{
// Wait for falling edge. // Wait for falling edge.
if (SHA204_PIN_READ() == 0) { if (SHA204_PIN_READ() == 0) {
break; break;
} }
} }
if (timeout_count == 0) if (timeout_count == 0) {
{
status = SWI_FUNCTION_RETCODE_TIMEOUT; status = SWI_FUNCTION_RETCODE_TIMEOUT;
break; break;
} }
do do {
{
// Wait for rising edge. // Wait for rising edge.
if (SHA204_PIN_READ() != 0) if (SHA204_PIN_READ() != 0) {
{
// For an Atmel microcontroller this might be faster than "pulse_count++". // For an Atmel microcontroller this might be faster than "pulse_count++".
pulse_count = 1; pulse_count = 1;
break; break;
} }
} while (--timeout_count > 0); } while (--timeout_count > 0);
if (pulse_count == 0) if (pulse_count == 0) {
{
status = SWI_FUNCTION_RETCODE_TIMEOUT; status = SWI_FUNCTION_RETCODE_TIMEOUT;
break; break;
} }
@@ -146,10 +134,8 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
timeout_count = ZERO_PULSE_TIME_OUT; timeout_count = ZERO_PULSE_TIME_OUT;
// Detect possible edge indicating zero bit. // Detect possible edge indicating zero bit.
do do {
{ if (SHA204_PIN_READ() == 0) {
if (SHA204_PIN_READ() == 0)
{
// For an Atmel microcontroller this might be faster than "pulse_count++". // For an Atmel microcontroller this might be faster than "pulse_count++".
pulse_count = 2; pulse_count = 2;
break; break;
@@ -158,10 +144,8 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
// Wait for rising edge of zero pulse before returning. Otherwise we might interpret // Wait for rising edge of zero pulse before returning. Otherwise we might interpret
// its rising edge as the next start pulse. // its rising edge as the next start pulse.
if (pulse_count == 2) if (pulse_count == 2) {
{ do {
do
{
if (SHA204_PIN_READ() != 0) { if (SHA204_PIN_READ() != 0) {
break; break;
} }
@@ -169,9 +153,10 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
} }
// Update byte at current buffer index. // Update byte at current buffer index.
else else {
buffer[i] |= bit_mask; // received "one" bit buffer[i] |= bit_mask; // received "one" bit
} }
}
if (status != SWI_FUNCTION_RETCODE_SUCCESS) { if (status != SWI_FUNCTION_RETCODE_SUCCESS) {
break; break;
@@ -179,8 +164,7 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
} }
interrupts(); //swi_enable_interrupts(); interrupts(); //swi_enable_interrupts();
if (status == SWI_FUNCTION_RETCODE_TIMEOUT) if (status == SWI_FUNCTION_RETCODE_TIMEOUT) {
{
if (i > 0) { if (i > 0) {
// Indicate that we timed out after having received at least one byte. // Indicate that we timed out after having received at least one byte.
status = SWI_FUNCTION_RETCODE_RX_FAIL; status = SWI_FUNCTION_RETCODE_RX_FAIL;
@@ -204,8 +188,7 @@ static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response)
(void) swi_send_byte(SHA204_SWI_FLAG_TX); (void) swi_send_byte(SHA204_SWI_FLAG_TX);
ret_code = swi_receive_bytes(size, response); ret_code = swi_receive_bytes(size, response);
if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) {
{
count_byte = response[SHA204_BUFFER_POS_COUNT]; count_byte = response[SHA204_BUFFER_POS_COUNT];
if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) { if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) {
return SHA204_INVALID_SIZE; return SHA204_INVALID_SIZE;
@@ -219,8 +202,7 @@ static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response)
// device being busy executing a command. // device being busy executing a command.
if (ret_code == SWI_FUNCTION_RETCODE_TIMEOUT) { if (ret_code == SWI_FUNCTION_RETCODE_TIMEOUT) {
return SHA204_RX_NO_RESPONSE; return SHA204_RX_NO_RESPONSE;
} } else {
else {
return SHA204_RX_FAIL; return SHA204_RX_FAIL;
} }
} }
@@ -249,7 +231,8 @@ static uint8_t sha204c_resync(uint8_t size, uint8_t *response)
return (ret_code == SHA204_SUCCESS ? SHA204_RESYNC_WITH_WAKEUP : ret_code); return (ret_code == SHA204_SUCCESS ? SHA204_RESYNC_WITH_WAKEUP : ret_code);
} }
static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, uint8_t execution_delay, uint8_t execution_timeout) static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer,
uint8_t execution_delay, uint8_t execution_timeout)
{ {
uint8_t ret_code = SHA204_FUNC_FAIL; uint8_t ret_code = SHA204_FUNC_FAIL;
uint8_t ret_code_resync; uint8_t ret_code_resync;
@@ -268,23 +251,19 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
// Retry loop for sending a command and receiving a response. // Retry loop for sending a command and receiving a response.
n_retries_send = SHA204_RETRY_COUNT + 1; n_retries_send = SHA204_RETRY_COUNT + 1;
while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS)) while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS)) {
{
// Send command. // Send command.
ret_code = swi_send_byte(SHA204_SWI_FLAG_CMD); ret_code = swi_send_byte(SHA204_SWI_FLAG_CMD);
if (ret_code != SWI_FUNCTION_RETCODE_SUCCESS) { if (ret_code != SWI_FUNCTION_RETCODE_SUCCESS) {
ret_code = SHA204_COMM_FAIL; ret_code = SHA204_COMM_FAIL;
} } else {
else {
ret_code = swi_send_bytes(count, tx_buffer); ret_code = swi_send_bytes(count, tx_buffer);
} }
if (ret_code != SHA204_SUCCESS) if (ret_code != SHA204_SUCCESS) {
{
if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) { if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) {
return ret_code; // The device seems to be dead in the water. return ret_code; // The device seems to be dead in the water.
} } else {
else {
continue; continue;
} }
} }
@@ -294,8 +273,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
// Retry loop for receiving a response. // Retry loop for receiving a response.
n_retries_receive = SHA204_RETRY_COUNT + 1; n_retries_receive = SHA204_RETRY_COUNT + 1;
while (n_retries_receive-- > 0) while (n_retries_receive-- > 0) {
{
// Reset response buffer. // Reset response buffer.
for (i = 0; i < rx_size; i++) { for (i = 0; i < rx_size; i++) {
rx_buffer[i] = 0; rx_buffer[i] = 0;
@@ -303,28 +281,23 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
// Poll for response. // Poll for response.
timeout_countdown = execution_timeout_us; timeout_countdown = execution_timeout_us;
do do {
{
ret_code = sha204p_receive_response(rx_size, rx_buffer); ret_code = sha204p_receive_response(rx_size, rx_buffer);
timeout_countdown -= SHA204_RESPONSE_TIMEOUT; timeout_countdown -= SHA204_RESPONSE_TIMEOUT;
} } while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (ret_code == SHA204_RX_NO_RESPONSE));
while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (ret_code == SHA204_RX_NO_RESPONSE));
if (ret_code == SHA204_RX_NO_RESPONSE) if (ret_code == SHA204_RX_NO_RESPONSE) {
{
// We did not receive a response. Re-synchronize and send command again. // We did not receive a response. Re-synchronize and send command again.
if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) { if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) {
// The device seems to be dead in the water. // The device seems to be dead in the water.
return ret_code; return ret_code;
} } else {
else {
break; break;
} }
} }
// Check whether we received a valid response. // Check whether we received a valid response.
if (ret_code == SHA204_INVALID_SIZE) if (ret_code == SHA204_INVALID_SIZE) {
{
// We see 0xFF for the count when communication got out of sync. // We see 0xFF for the count when communication got out of sync.
ret_code_resync = sha204c_resync(rx_size, rx_buffer); ret_code_resync = sha204c_resync(rx_size, rx_buffer);
if (ret_code_resync == SHA204_SUCCESS) { if (ret_code_resync == SHA204_SUCCESS) {
@@ -335,8 +308,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
// We could re-synchronize, but only after waking up the device. // We could re-synchronize, but only after waking up the device.
// Re-send command. // Re-send command.
break; break;
} } else {
else {
// We failed to re-synchronize. // We failed to re-synchronize.
return ret_code; return ret_code;
} }
@@ -345,8 +317,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
// We received a response of valid size. // We received a response of valid size.
// Check the consistency of the response. // Check the consistency of the response.
ret_code = sha204c_check_crc(rx_buffer); ret_code = sha204c_check_crc(rx_buffer);
if (ret_code == SHA204_SUCCESS) if (ret_code == SHA204_SUCCESS) {
{
// Received valid response. // Received valid response.
if (rx_buffer[SHA204_BUFFER_POS_COUNT] > SHA204_RSP_SIZE_MIN) { if (rx_buffer[SHA204_BUFFER_POS_COUNT] > SHA204_RSP_SIZE_MIN) {
// Received non-status response. We are done. // Received non-status response. We are done.
@@ -364,8 +335,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
if (status_byte == SHA204_STATUS_BYTE_EXEC) { if (status_byte == SHA204_STATUS_BYTE_EXEC) {
return SHA204_CMD_FAIL; return SHA204_CMD_FAIL;
} }
if (status_byte == SHA204_STATUS_BYTE_COMM) if (status_byte == SHA204_STATUS_BYTE_COMM) {
{
// In case of the device status byte indicating a communication // In case of the device status byte indicating a communication
// error this function exits the retry loop for receiving a response // error this function exits the retry loop for receiving a response
// and enters the overall retry loop // and enters the overall retry loop
@@ -379,8 +349,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
return ret_code; return ret_code;
} }
else else {
{
// Received response with incorrect CRC. // Received response with incorrect CRC.
ret_code_resync = sha204c_resync(rx_size, rx_buffer); ret_code_resync = sha204c_resync(rx_size, rx_buffer);
if (ret_code_resync == SHA204_SUCCESS) { if (ret_code_resync == SHA204_SUCCESS) {
@@ -391,8 +360,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
// We could re-synchronize, but only after waking up the device. // We could re-synchronize, but only after waking up the device.
// Re-send command. // Re-send command.
break; break;
} } else {
else {
// We failed to re-synchronize. // We failed to re-synchronize.
return ret_code; return ret_code;
} }
@@ -422,7 +390,8 @@ static uint8_t sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone
rx_size = (zone & SHA204_ZONE_COUNT_FLAG) ? READ_32_RSP_SIZE : READ_4_RSP_SIZE; rx_size = (zone & SHA204_ZONE_COUNT_FLAG) ? READ_32_RSP_SIZE : READ_4_RSP_SIZE;
return sha204c_send_and_receive(&tx_buffer[0], rx_size, &rx_buffer[0], READ_DELAY, READ_EXEC_MAX - READ_DELAY); return sha204c_send_and_receive(&tx_buffer[0], rx_size, &rx_buffer[0], READ_DELAY,
READ_EXEC_MAX - READ_DELAY);
} }
/* CRC Calculator and Checker */ /* CRC Calculator and Checker */
@@ -435,10 +404,8 @@ static void sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc)
uint8_t shift_register; uint8_t shift_register;
uint8_t data_bit, crc_bit; uint8_t data_bit, crc_bit;
for (counter = 0; counter < length; counter++) for (counter = 0; counter < length; counter++) {
{ for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) {
for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1)
{
data_bit = (data[counter] & shift_register) ? 1 : 0; data_bit = (data[counter] & shift_register) ? 1 : 0;
crc_bit = crc_register >> 15; crc_bit = crc_register >> 15;
@@ -510,12 +477,9 @@ uint8_t atsha204_wakeup(uint8_t *response)
// Verify status response. // Verify status response.
if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN) { if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN) {
ret_code = SHA204_INVALID_SIZE; ret_code = SHA204_INVALID_SIZE;
} } else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP) {
else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP) {
ret_code = SHA204_COMM_FAIL; ret_code = SHA204_COMM_FAIL;
} } else {
else
{
if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33) if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33)
|| (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43)) { || (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43)) {
ret_code = SHA204_BAD_CRC; ret_code = SHA204_BAD_CRC;
@@ -529,7 +493,8 @@ uint8_t atsha204_wakeup(uint8_t *response)
} }
uint8_t atsha204_execute(uint8_t op_code, uint8_t param1, uint16_t param2, uint8_t atsha204_execute(uint8_t op_code, uint8_t param1, uint16_t param2,
uint8_t datalen1, uint8_t *data1, uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer) uint8_t datalen1, uint8_t *data1, uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size,
uint8_t *rx_buffer)
{ {
uint8_t poll_delay, poll_timeout, response_size; uint8_t poll_delay, poll_timeout, response_size;
uint8_t *p_buffer; uint8_t *p_buffer;
@@ -537,8 +502,7 @@ uint8_t atsha204_execute(uint8_t op_code, uint8_t param1, uint16_t param2,
(void)tx_size; (void)tx_size;
// Supply delays and response size. // Supply delays and response size.
switch (op_code) switch (op_code) {
{
case SHA204_GENDIG: case SHA204_GENDIG:
poll_delay = GENDIG_DELAY; poll_delay = GENDIG_DELAY;
poll_timeout = GENDIG_EXEC_MAX - GENDIG_DELAY; poll_timeout = GENDIG_EXEC_MAX - GENDIG_DELAY;
@@ -611,8 +575,7 @@ uint8_t atsha204_getSerialNumber(uint8_t * response)
/* read from bytes 0->3 of config zone */ /* read from bytes 0->3 of config zone */
uint8_t returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN03); uint8_t returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN03);
if (!returnCode) if (!returnCode) {
{
for (int i=0; i<4; i++) {// store bytes 0-3 into respones array for (int i=0; i<4; i++) {// store bytes 0-3 into respones array
response[i] = readResponse[SHA204_BUFFER_POS_DATA+i]; response[i] = readResponse[SHA204_BUFFER_POS_DATA+i];
} }
@@ -624,8 +587,8 @@ uint8_t atsha204_getSerialNumber(uint8_t * response)
response[i] = readResponse[SHA204_BUFFER_POS_DATA+(i-4)]; response[i] = readResponse[SHA204_BUFFER_POS_DATA+(i-4)];
} }
if (!returnCode) if (!returnCode) {
{ /* Finally if last two reads were successful, read byte 8 of the SN */ /* Finally if last two reads were successful, read byte 8 of the SN */
returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN8); returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN8);
response[8] = readResponse[SHA204_BUFFER_POS_DATA]; // Byte 8 of SN should always be 0xEE response[8] = readResponse[SHA204_BUFFER_POS_DATA]; // Byte 8 of SN should always be 0xEE
} }
+26 -10
View File
@@ -32,17 +32,20 @@ const uint8_t sha256InitState[] PROGMEM = {
0x19,0xcd,0xe0,0x5b // H7 0x19,0xcd,0xe0,0x5b // H7
}; };
void Sha256Class::init(void) { void Sha256Class::init(void)
{
memcpy_P(state.b,sha256InitState,32); memcpy_P(state.b,sha256InitState,32);
byteCount = 0; byteCount = 0;
bufferOffset = 0; bufferOffset = 0;
} }
uint32_t Sha256Class::ror32(uint32_t number, uint8_t bits) { uint32_t Sha256Class::ror32(uint32_t number, uint8_t bits)
{
return ((number << (32-bits)) | (number >> bits)); return ((number << (32-bits)) | (number >> bits));
} }
void Sha256Class::hashBlock() { void Sha256Class::hashBlock()
{
uint8_t i; uint8_t i;
uint32_t a,b,c,d,e,f,g,h,t1,t2; uint32_t a,b,c,d,e,f,g,h,t1,t2;
@@ -71,7 +74,14 @@ void Sha256Class::hashBlock() {
t1 += buffer.w[i&15]; // Wi t1 += buffer.w[i&15]; // Wi
t2 = ror32(a,2) ^ ror32(a,13) ^ ror32(a,22); // ∑0(a) t2 = ror32(a,2) ^ ror32(a,13) ^ ror32(a,22); // ∑0(a)
t2 += ((b & c) | (a & (b | c))); // Maj(a,b,c) t2 += ((b & c) | (a & (b | c))); // Maj(a,b,c)
h=g; g=f; f=e; e=d+t1; d=c; c=b; b=a; a=t1+t2; h=g;
g=f;
f=e;
e=d+t1;
d=c;
c=b;
b=a;
a=t1+t2;
} }
state.w[0] += a; state.w[0] += a;
state.w[1] += b; state.w[1] += b;
@@ -83,7 +93,8 @@ void Sha256Class::hashBlock() {
state.w[7] += h; state.w[7] += h;
} }
void Sha256Class::addUncounted(uint8_t data) { void Sha256Class::addUncounted(uint8_t data)
{
buffer.b[bufferOffset ^ 3] = data; buffer.b[bufferOffset ^ 3] = data;
bufferOffset++; bufferOffset++;
if (bufferOffset == BUFFER_SIZE) { if (bufferOffset == BUFFER_SIZE) {
@@ -92,12 +103,14 @@ void Sha256Class::addUncounted(uint8_t data) {
} }
} }
void Sha256Class::write(uint8_t data) { void Sha256Class::write(uint8_t data)
{
++byteCount; ++byteCount;
addUncounted(data); addUncounted(data);
} }
void Sha256Class::pad() { void Sha256Class::pad()
{
// Implement SHA-256 padding (fips180-2 §5.1.1) // Implement SHA-256 padding (fips180-2 §5.1.1)
// Pad with 0x80 followed by 0x00 until the end of the block // Pad with 0x80 followed by 0x00 until the end of the block
@@ -118,7 +131,8 @@ void Sha256Class::pad() {
} }
uint8_t* Sha256Class::result(void) { uint8_t* Sha256Class::result(void)
{
// Pad to complete the last block // Pad to complete the last block
pad(); pad();
@@ -143,7 +157,8 @@ uint8_t* Sha256Class::result(void) {
uint8_t keyBuffer[BLOCK_LENGTH]; // K0 in FIPS-198a uint8_t keyBuffer[BLOCK_LENGTH]; // K0 in FIPS-198a
uint8_t innerHash[HASH_LENGTH]; uint8_t innerHash[HASH_LENGTH];
void Sha256Class::initHmac(const uint8_t* key, int keyLength) { void Sha256Class::initHmac(const uint8_t* key, int keyLength)
{
uint8_t i; uint8_t i;
memset(keyBuffer,0,BLOCK_LENGTH); memset(keyBuffer,0,BLOCK_LENGTH);
if (keyLength > BLOCK_LENGTH) { if (keyLength > BLOCK_LENGTH) {
@@ -164,7 +179,8 @@ void Sha256Class::initHmac(const uint8_t* key, int keyLength) {
} }
} }
uint8_t* Sha256Class::resultHmac(void) { uint8_t* Sha256Class::resultHmac(void)
{
uint8_t i; uint8_t i;
// Complete inner hash // Complete inner hash
memcpy(innerHash,result(),HASH_LENGTH); memcpy(innerHash,result(),HASH_LENGTH);
+42 -19
View File
@@ -402,7 +402,8 @@ void badPinNumber(void)
/** Check for valid pin number /** Check for valid pin number
* @param[in] pin Number of pin to be checked. * @param[in] pin Number of pin to be checked.
*/ */
static ALWAYS_INLINE void badPinCheck(uint8_t pin) { static ALWAYS_INLINE void badPinCheck(uint8_t pin)
{
if (!__builtin_constant_p(pin) || pin >= digitalPinCount) { if (!__builtin_constant_p(pin) || pin >= digitalPinCount) {
badPinNumber(); badPinNumber();
} }
@@ -413,7 +414,8 @@ static ALWAYS_INLINE void badPinCheck(uint8_t pin) {
* @param[in] bit bit number to write * @param[in] bit bit number to write
* @param[in] level value for bit * @param[in] level value for bit
*/ */
static ALWAYS_INLINE void fastBitWriteSafe(volatile uint8_t* address, uint8_t bit, bool level) { static ALWAYS_INLINE void fastBitWriteSafe(volatile uint8_t* address, uint8_t bit, bool level)
{
uint8_t oldSREG; uint8_t oldSREG;
if (address > (uint8_t*)0X5F) { if (address > (uint8_t*)0X5F) {
oldSREG = SREG; oldSREG = SREG;
@@ -433,7 +435,8 @@ static ALWAYS_INLINE void fastBitWriteSafe(volatile uint8_t* address, uint8_t bi
* @param[in] pin Arduino pin number * @param[in] pin Arduino pin number
* @return value read * @return value read
*/ */
static ALWAYS_INLINE bool fastDigitalRead(uint8_t pin) { static ALWAYS_INLINE bool fastDigitalRead(uint8_t pin)
{
badPinCheck(pin); badPinCheck(pin);
return (*pinMap[pin].pin >> pinMap[pin].bit) & 1; return (*pinMap[pin].pin >> pinMap[pin].bit) & 1;
} }
@@ -444,7 +447,8 @@ static ALWAYS_INLINE bool fastDigitalRead(uint8_t pin) {
* If the pin is in output mode toggle the pin level. * If the pin is in output mode toggle the pin level.
* If the pin is in input mode toggle the state of the 20K pullup. * If the pin is in input mode toggle the state of the 20K pullup.
*/ */
static ALWAYS_INLINE void fastDigitalToggle(uint8_t pin) { static ALWAYS_INLINE void fastDigitalToggle(uint8_t pin)
{
badPinCheck(pin); badPinCheck(pin);
if (pinMap[pin].pin > (uint8_t*)0X5F) { if (pinMap[pin].pin > (uint8_t*)0X5F) {
// must write bit to high address port // must write bit to high address port
@@ -459,7 +463,8 @@ static ALWAYS_INLINE void fastDigitalToggle(uint8_t pin) {
* @param[in] pin Arduino pin number * @param[in] pin Arduino pin number
* @param[in] level value to write * @param[in] level value to write
*/ */
static ALWAYS_INLINE void fastDigitalWrite(uint8_t pin, bool level) { static ALWAYS_INLINE void fastDigitalWrite(uint8_t pin, bool level)
{
badPinCheck(pin); badPinCheck(pin);
fastBitWriteSafe(pinMap[pin].port, pinMap[pin].bit, level); fastBitWriteSafe(pinMap[pin].port, pinMap[pin].bit, level);
} }
@@ -470,7 +475,8 @@ static ALWAYS_INLINE void fastDigitalWrite(uint8_t pin, bool level) {
* *
* fastPinMode does not enable or disable the 20K pullup for input mode. * fastPinMode does not enable or disable the 20K pullup for input mode.
*/ */
static ALWAYS_INLINE void fastPinMode(uint8_t pin, bool mode) { static ALWAYS_INLINE void fastPinMode(uint8_t pin, bool mode)
{
badPinCheck(pin); badPinCheck(pin);
fastBitWriteSafe(pinMap[pin].ddr, pinMap[pin].bit, mode); fastBitWriteSafe(pinMap[pin].ddr, pinMap[pin].bit, mode);
} }
@@ -481,7 +487,8 @@ static ALWAYS_INLINE void fastPinMode(uint8_t pin, bool mode) {
* @param[in] level If mode is output, set level high/low. * @param[in] level If mode is output, set level high/low.
* If mode is input, enable or disable the pin's 20K pullup. * If mode is input, enable or disable the pin's 20K pullup.
*/ */
static ALWAYS_INLINE void fastPinConfig(uint8_t pin, bool mode, bool level) { static ALWAYS_INLINE void fastPinConfig(uint8_t pin, bool mode, bool level)
{
fastPinMode(pin, mode); fastPinMode(pin, mode);
fastDigitalWrite(pin, level); fastDigitalWrite(pin, level);
} }
@@ -491,7 +498,8 @@ static ALWAYS_INLINE void fastPinConfig(uint8_t pin, bool mode, bool level) {
* @brief Fast AVR digital port I/O * @brief Fast AVR digital port I/O
*/ */
template<uint8_t PinNumber> template<uint8_t PinNumber>
class DigitalPin { class DigitalPin
{
public: public:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Constructor */ /** Constructor */
@@ -500,7 +508,8 @@ class DigitalPin {
/** Constructor /** Constructor
* @param[in] pinMode if true set output mode else input mode. * @param[in] pinMode if true set output mode else input mode.
*/ */
explicit DigitalPin(bool pinMode) { explicit DigitalPin(bool pinMode)
{
mode(pinMode); mode(pinMode);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -509,7 +518,8 @@ class DigitalPin {
* @param[in] level If mode is output, set level high/low. * @param[in] level If mode is output, set level high/low.
* If mode is input, enable or disable the pin's 20K pullup. * If mode is input, enable or disable the pin's 20K pullup.
*/ */
DigitalPin(bool mode, bool level) { DigitalPin(bool mode, bool level)
{
config(mode, level); config(mode, level);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -519,7 +529,8 @@ class DigitalPin {
* *
* @return This DigitalPin instance. * @return This DigitalPin instance.
*/ */
inline DigitalPin & operator = (bool value) __attribute__((always_inline)) { inline DigitalPin & operator = (bool value) __attribute__((always_inline))
{
write(value); write(value);
return *this; return *this;
} }
@@ -527,7 +538,8 @@ class DigitalPin {
/** Parenthesis operator /** Parenthesis operator
* @return Pin's level * @return Pin's level
*/ */
inline operator bool () const __attribute__((always_inline)) { inline operator bool () const __attribute__((always_inline))
{
return read(); return read();
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -536,19 +548,26 @@ class DigitalPin {
* @param[in] level If mode is output, set level high/low. * @param[in] level If mode is output, set level high/low.
* If mode is input, enable or disable the pin's 20K pullup. * If mode is input, enable or disable the pin's 20K pullup.
*/ */
ALWAYS_INLINE void config(bool mode, bool level) { ALWAYS_INLINE void config(bool mode, bool level)
{
fastPinConfig(PinNumber, mode, level); fastPinConfig(PinNumber, mode, level);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** /**
* Set pin level high if output mode or enable 20K pullup if input mode. * Set pin level high if output mode or enable 20K pullup if input mode.
*/ */
ALWAYS_INLINE void high() {write(true);} ALWAYS_INLINE void high()
{
write(true);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** /**
* Set pin level low if output mode or disable 20K pullup if input mode. * Set pin level low if output mode or disable 20K pullup if input mode.
*/ */
ALWAYS_INLINE void low() {write(false);} ALWAYS_INLINE void low()
{
write(false);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** /**
* Set pin mode * Set pin mode
@@ -556,12 +575,14 @@ class DigitalPin {
* *
* mode() does not enable or disable the 20K pullup for input mode. * mode() does not enable or disable the 20K pullup for input mode.
*/ */
ALWAYS_INLINE void mode(bool pinMode) { ALWAYS_INLINE void mode(bool pinMode)
{
fastPinMode(PinNumber, pinMode); fastPinMode(PinNumber, pinMode);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** @return Pin's level */ /** @return Pin's level */
ALWAYS_INLINE bool read() const { ALWAYS_INLINE bool read() const
{
return fastDigitalRead(PinNumber); return fastDigitalRead(PinNumber);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -570,7 +591,8 @@ class DigitalPin {
* If the pin is in output mode toggle the pin's level. * If the pin is in output mode toggle the pin's level.
* If the pin is in input mode toggle the state of the 20K pullup. * If the pin is in input mode toggle the state of the 20K pullup.
*/ */
ALWAYS_INLINE void toggle() { ALWAYS_INLINE void toggle()
{
fastDigitalToggle(PinNumber); fastDigitalToggle(PinNumber);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -578,7 +600,8 @@ class DigitalPin {
* @param[in] value If true set the pin's level high else set the * @param[in] value If true set the pin's level high else set the
* pin's level low. * pin's level low.
*/ */
ALWAYS_INLINE void write(bool value) { ALWAYS_INLINE void write(bool value)
{
fastDigitalWrite(PinNumber, value); fastDigitalWrite(PinNumber, value);
} }
}; };
+9 -4
View File
@@ -32,7 +32,8 @@
/** Constructor /** Constructor
* @param[in] pin Pin assigned to this object. * @param[in] pin Pin assigned to this object.
*/ */
PinIO::PinIO(uint8_t pin) { PinIO::PinIO(uint8_t pin)
{
begin(pin); begin(pin);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -40,8 +41,11 @@ PinIO::PinIO(uint8_t pin) {
* @param[in] pin Arduino board pin number. * @param[in] pin Arduino board pin number.
* @return true for success or false if invalid pin number. * @return true for success or false if invalid pin number.
*/ */
bool PinIO::begin(uint8_t pin) { bool PinIO::begin(uint8_t pin)
if (pin >= NUM_DIGITAL_PINS) return false; {
if (pin >= NUM_DIGITAL_PINS) {
return false;
}
uint8_t port = digitalPinToPort(pin); uint8_t port = digitalPinToPort(pin);
pinReg_ = portInputRegister(port); pinReg_ = portInputRegister(port);
bit_ = digitalPinToBitMask(pin); bit_ = digitalPinToBitMask(pin);
@@ -59,7 +63,8 @@ bool PinIO::begin(uint8_t pin) {
* This function may be used with interrupts enabled or disabled. * This function may be used with interrupts enabled or disabled.
* The previous interrupt state will be restored. * The previous interrupt state will be restored.
*/ */
void PinIO::config(bool mode, bool data) { void PinIO::config(bool mode, bool data)
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
modeI(mode); modeI(mode);
writeI(data); writeI(data);
+46 -11
View File
@@ -37,7 +37,8 @@
* @class PinIO * @class PinIO
* @brief AVR port I/O with runtime pin numbers. * @brief AVR port I/O with runtime pin numbers.
*/ */
class PinIO { class PinIO
{
public: public:
/** Create a PinIO object with no assigned pin. */ /** Create a PinIO object with no assigned pin. */
PinIO() : bit_(0), mask_(0XFF) {} PinIO() : bit_(0), mask_(0XFF) {}
@@ -62,14 +63,20 @@ class PinIO {
void config(bool mode, bool data); void config(bool mode, bool data);
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** @return Pin's level */ /** @return Pin's level */
ALWAYS_INLINE bool read() {return *pinReg_ & bit_;} ALWAYS_INLINE bool read()
{
return *pinReg_ & bit_;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** toggle a pin /** toggle a pin
* *
* If the pin is in output mode toggle the pin's level. * If the pin is in output mode toggle the pin's level.
* If the pin is in input mode toggle the state of the 20K pullup. * If the pin is in input mode toggle the state of the 20K pullup.
*/ */
ALWAYS_INLINE void toggle() {*pinReg_ = bit_;} ALWAYS_INLINE void toggle()
{
*pinReg_ = bit_;
}
//============================================================================ //============================================================================
/** /**
* Set pin high if output mode or enable 20K pullup if input mode. * Set pin high if output mode or enable 20K pullup if input mode.
@@ -77,14 +84,20 @@ class PinIO {
* This function must be called with interrupts disabled. * This function must be called with interrupts disabled.
* This function will not change the interrupt state. * This function will not change the interrupt state.
*/ */
ALWAYS_INLINE void highI() {writeI(1);} ALWAYS_INLINE void highI()
{
writeI(1);
}
/** /**
* Set pin low if output mode or disable 20K pullup if input mode. * Set pin low if output mode or disable 20K pullup if input mode.
* *
* This function must be called with interrupts disabled. * This function must be called with interrupts disabled.
* This function will not change the interrupt state. * This function will not change the interrupt state.
*/ */
ALWAYS_INLINE void lowI() {writeI(0);} ALWAYS_INLINE void lowI()
{
writeI(0);
}
/** /**
* Set pin mode * Set pin mode
* @param[in] mode if true set output mode else input mode. * @param[in] mode if true set output mode else input mode.
@@ -94,7 +107,8 @@ class PinIO {
* This function must be called with interrupts disabled. * This function must be called with interrupts disabled.
* This function will not change the interrupt state. * This function will not change the interrupt state.
*/ */
ALWAYS_INLINE void modeI(bool mode) { ALWAYS_INLINE void modeI(bool mode)
{
volatile uint8_t* ddrReg = pinReg_ + 1; volatile uint8_t* ddrReg = pinReg_ + 1;
*ddrReg = mode ? *ddrReg | bit_ : *ddrReg & mask_; *ddrReg = mode ? *ddrReg | bit_ : *ddrReg & mask_;
} }
@@ -106,7 +120,8 @@ class PinIO {
* This function must be called with interrupts disabled. * This function must be called with interrupts disabled.
* This function will not change the interrupt state. * This function will not change the interrupt state.
*/ */
ALWAYS_INLINE void writeI(bool level) { ALWAYS_INLINE void writeI(bool level)
{
*portReg_ = level ? *portReg_ | bit_ : *portReg_ & mask_; *portReg_ = level ? *portReg_ | bit_ : *portReg_ & mask_;
} }
//============================================================================ //============================================================================
@@ -116,14 +131,24 @@ class PinIO {
* This function will enable interrupts. This function should not be * This function will enable interrupts. This function should not be
* called in an ISR or where interrupts are disabled. * called in an ISR or where interrupts are disabled.
*/ */
ALWAYS_INLINE void high() {ATOMIC_BLOCK(ATOMIC_FORCEON) {highI();}} ALWAYS_INLINE void high()
{
ATOMIC_BLOCK(ATOMIC_FORCEON) {
highI();
}
}
/** /**
* Set pin level low if output mode or disable 20K pullup if input mode. * Set pin level low if output mode or disable 20K pullup if input mode.
* *
* This function will enable interrupts. This function should not be * This function will enable interrupts. This function should not be
* called in an ISR or where interrupts are disabled. * called in an ISR or where interrupts are disabled.
*/ */
ALWAYS_INLINE void low() {ATOMIC_BLOCK(ATOMIC_FORCEON) {lowI();}} ALWAYS_INLINE void low()
{
ATOMIC_BLOCK(ATOMIC_FORCEON) {
lowI();
}
}
/** /**
* Set pin mode * Set pin mode
* @param[in] pinMode if true set output mode else input mode. * @param[in] pinMode if true set output mode else input mode.
@@ -133,7 +158,12 @@ class PinIO {
* This function will enable interrupts. This function should not be * This function will enable interrupts. This function should not be
* called in an ISR or where interrupts are disabled. * called in an ISR or where interrupts are disabled.
*/ */
ALWAYS_INLINE void mode(bool pinMode) {ATOMIC_BLOCK(ATOMIC_FORCEON) {modeI(pinMode);}} ALWAYS_INLINE void mode(bool pinMode)
{
ATOMIC_BLOCK(ATOMIC_FORCEON) {
modeI(pinMode);
}
}
/** Write pin. /** Write pin.
* *
* @param[in] level If output mode set pin high if true else low. * @param[in] level If output mode set pin high if true else low.
@@ -142,7 +172,12 @@ class PinIO {
* This function will enable interrupts. This function should not be * This function will enable interrupts. This function should not be
* called in an ISR or where interrupts are disabled. * called in an ISR or where interrupts are disabled.
*/ */
ALWAYS_INLINE void write(bool level) {ATOMIC_BLOCK(ATOMIC_FORCEON) {writeI(level);}} ALWAYS_INLINE void write(bool level)
{
ATOMIC_BLOCK(ATOMIC_FORCEON) {
writeI(level);
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
private: private:
uint8_t bit_; uint8_t bit_;
+19 -9
View File
@@ -49,7 +49,8 @@
* @return true for success else false. * @return true for success else false.
*/ */
bool I2cMasterBase::transfer(uint8_t addrRW, bool I2cMasterBase::transfer(uint8_t addrRW,
void *buf, size_t nbytes, uint8_t option) { void *buf, size_t nbytes, uint8_t option)
{
if (_state != STATE_REP_START) { if (_state != STATE_REP_START) {
start(); start();
} }
@@ -76,7 +77,8 @@ bool I2cMasterBase::transfer(uint8_t addrRW,
* . * .
* @return true for success else false. * @return true for success else false.
*/ */
bool I2cMasterBase::transferContinue(void *buf, size_t nbytes, uint8_t option) { bool I2cMasterBase::transferContinue(void *buf, size_t nbytes, uint8_t option)
{
uint8_t* p = reinterpret_cast<uint8_t*>(buf); uint8_t* p = reinterpret_cast<uint8_t*>(buf);
if (_state == STATE_RX_DATA) { if (_state == STATE_RX_DATA) {
for (size_t i = 0; i < nbytes; i++) { for (size_t i = 0; i < nbytes; i++) {
@@ -111,7 +113,8 @@ bool I2cMasterBase::transferContinue(void *buf, size_t nbytes, uint8_t option) {
* *
* @param[in] sclPin The software SCL pin number. * @param[in] sclPin The software SCL pin number.
*/ */
SoftI2cMaster::SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin) { SoftI2cMaster::SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin)
{
begin(sclPin, sdaPin); begin(sclPin, sdaPin);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -122,7 +125,8 @@ SoftI2cMaster::SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin) {
* *
* @param[in] sclPin The software SCL pin number. * @param[in] sclPin The software SCL pin number.
*/ */
void SoftI2cMaster::begin(uint8_t sclPin, uint8_t sdaPin) { void SoftI2cMaster::begin(uint8_t sclPin, uint8_t sdaPin)
{
uint8_t port; uint8_t port;
// Get bit mask and address of scl registers. // Get bit mask and address of scl registers.
@@ -156,7 +160,8 @@ void SoftI2cMaster::begin(uint8_t sclPin, uint8_t sdaPin) {
* *
* @return The byte read from the I2C bus. * @return The byte read from the I2C bus.
*/ */
uint8_t SoftI2cMaster::read(uint8_t last) { uint8_t SoftI2cMaster::read(uint8_t last)
{
uint8_t b = 0; uint8_t b = 0;
// Set sda to high Z mode for read. // Set sda to high Z mode for read.
@@ -168,7 +173,9 @@ uint8_t SoftI2cMaster::read(uint8_t last) {
sclDelay(16); sclDelay(16);
writeScl(HIGH); writeScl(HIGH);
sclDelay(12); sclDelay(12);
if (readSda()) b |= 1; if (readSda()) {
b |= 1;
}
writeScl(LOW); writeScl(LOW);
} }
// send ACK or NACK // send ACK or NACK
@@ -182,7 +189,8 @@ uint8_t SoftI2cMaster::read(uint8_t last) {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/* Issue a start condition. */ /* Issue a start condition. */
void SoftI2cMaster::start() { void SoftI2cMaster::start()
{
if (!readSda()) { if (!readSda()) {
writeSda(HIGH); writeSda(HIGH);
writeScl(HIGH); writeScl(HIGH);
@@ -194,7 +202,8 @@ void SoftI2cMaster::start() {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/* Issue a stop condition. */ /* Issue a stop condition. */
void SoftI2cMaster::stop(void) { void SoftI2cMaster::stop(void)
{
writeSda(LOW); writeSda(LOW);
sclDelay(20); sclDelay(20);
writeScl(HIGH); writeScl(HIGH);
@@ -210,7 +219,8 @@ void SoftI2cMaster::stop(void) {
* *
* @return The value true, 1, if the slave returned an ACK or false for NACK. * @return The value true, 1, if the slave returned an ACK or false for NACK.
*/ */
bool SoftI2cMaster::write(uint8_t data) { bool SoftI2cMaster::write(uint8_t data)
{
// write byte // write byte
for (uint8_t m = 0X80; m != 0; m >>= 1) { for (uint8_t m = 0X80; m != 0; m >>= 1) {
// don't change this loop unless you verify the change with a scope // don't change this loop unless you verify the change with a scope
+59 -27
View File
@@ -63,7 +63,8 @@ const uint8_t STATE_TX_DATA_NACK = 6;
* @class I2cMasterBase * @class I2cMasterBase
* @brief Base class for FastI2cMaster, SoftI2cMaster * @brief Base class for FastI2cMaster, SoftI2cMaster
*/ */
class I2cMasterBase { class I2cMasterBase
{
public: public:
I2cMasterBase() : _state(STATE_STOP) {} I2cMasterBase() : _state(STATE_STOP) {}
/** Read a byte /** Read a byte
@@ -148,7 +149,8 @@ class I2cMasterBase {
* @class SoftI2cMaster * @class SoftI2cMaster
* @brief Software I2C master class * @brief Software I2C master class
*/ */
class SoftI2cMaster : public I2cMasterBase { class SoftI2cMaster : public I2cMasterBase
{
public: public:
SoftI2cMaster() {} SoftI2cMaster() {}
/** /**
@@ -179,11 +181,18 @@ class SoftI2cMaster : public I2cMasterBase {
volatile uint8_t* _sdaDDR; volatile uint8_t* _sdaDDR;
volatile uint8_t* _sdaInReg; volatile uint8_t* _sdaInReg;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool readSda() {return *_sdaInReg & _sdaBit;} bool readSda()
{
return *_sdaInReg & _sdaBit;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void sclDelay(uint8_t n) {_delay_loop_1(n);} void sclDelay(uint8_t n)
{
_delay_loop_1(n);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void writeScl(bool value) { void writeScl(bool value)
{
uint8_t s = SREG; uint8_t s = SREG;
noInterrupts(); noInterrupts();
if (value == LOW) { if (value == LOW) {
@@ -196,7 +205,8 @@ class SoftI2cMaster : public I2cMasterBase {
SREG = s; SREG = s;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void writeSda(bool value) { void writeSda(bool value)
{
uint8_t s = SREG; uint8_t s = SREG;
noInterrupts(); noInterrupts();
if (value == LOW) { if (value == LOW) {
@@ -217,15 +227,18 @@ class SoftI2cMaster : public I2cMasterBase {
* @brief Fast software I2C master class. * @brief Fast software I2C master class.
*/ */
template<uint8_t sclPin, uint8_t sdaPin> template<uint8_t sclPin, uint8_t sdaPin>
class FastI2cMaster : public I2cMasterBase { class FastI2cMaster : public I2cMasterBase
{
public: public:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
FastI2cMaster() { FastI2cMaster()
{
begin(); begin();
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Initialize I2C bus pins. */ /** Initialize I2C bus pins. */
void begin() { void begin()
{
fastDigitalWrite(sclPin, LOW); fastDigitalWrite(sclPin, LOW);
fastDigitalWrite(sdaPin, LOW); fastDigitalWrite(sdaPin, LOW);
@@ -233,7 +246,8 @@ class FastI2cMaster : public I2cMasterBase {
sdaWrite(HIGH); sdaWrite(HIGH);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
uint8_t read(uint8_t last) { uint8_t read(uint8_t last)
{
uint8_t data = 0; uint8_t data = 0;
sdaWrite(HIGH); sdaWrite(HIGH);
@@ -256,7 +270,8 @@ class FastI2cMaster : public I2cMasterBase {
return data; return data;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void start() { void start()
{
if (!fastDigitalRead(sdaPin)) { if (!fastDigitalRead(sdaPin)) {
// It's a repeat start. // It's a repeat start.
sdaWrite(HIGH); sdaWrite(HIGH);
@@ -270,7 +285,8 @@ class FastI2cMaster : public I2cMasterBase {
sclDelay(8); sclDelay(8);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void stop(void) { void stop(void)
{
sdaWrite(LOW); sdaWrite(LOW);
sclDelay(8); sclDelay(8);
sclWrite(HIGH); sclWrite(HIGH);
@@ -279,7 +295,8 @@ class FastI2cMaster : public I2cMasterBase {
sclDelay(8); sclDelay(8);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool write(uint8_t data) { bool write(uint8_t data)
{
// write byte // write byte
writeBit(7, data); writeBit(7, data);
writeBit(6, data); writeBit(6, data);
@@ -304,24 +321,39 @@ class FastI2cMaster : public I2cMasterBase {
private: private:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void sclWrite(bool value) {fastPinMode(sclPin, !value);} void sclWrite(bool value)
//---------------------------------------------------------------------------- {
inline __attribute__((always_inline)) fastPinMode(sclPin, !value);
void sdaWrite(bool value) {fastPinMode(sdaPin, !value);}
//----------------------------------------------------------------------------
inline __attribute__((always_inline))
void readBit(uint8_t bit, uint8_t* data) {
sclWrite(HIGH);
sclDelay(5);
if (fastDigitalRead(sdaPin)) *data |= 1 << bit;
sclWrite(LOW);
if (bit) sclDelay(6);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void sclDelay(uint8_t n) {_delay_loop_1(n);} inline __attribute__((always_inline))
void sdaWrite(bool value)
{
fastPinMode(sdaPin, !value);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void writeBit(uint8_t bit, uint8_t data) { void readBit(uint8_t bit, uint8_t* data)
{
sclWrite(HIGH);
sclDelay(5);
if (fastDigitalRead(sdaPin)) {
*data |= 1 << bit;
}
sclWrite(LOW);
if (bit) {
sclDelay(6);
}
}
//----------------------------------------------------------------------------
void sclDelay(uint8_t n)
{
_delay_loop_1(n);
}
//----------------------------------------------------------------------------
inline __attribute__((always_inline))
void writeBit(uint8_t bit, uint8_t data)
{
uint8_t mask = 1 << bit; uint8_t mask = 1 << bit;
sdaWrite(data & mask); sdaWrite(data & mask);
sclWrite(HIGH); sclWrite(HIGH);
+30 -12
View File
@@ -48,11 +48,13 @@ const bool SCK_MODE = true;
* @brief Fast software SPI. * @brief Fast software SPI.
*/ */
template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin, uint8_t Mode = 0> template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin, uint8_t Mode = 0>
class SoftSPI { class SoftSPI
{
public: public:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Initialize SoftSPI pins. */ /** Initialize SoftSPI pins. */
void begin() { void begin()
{
fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL); fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL);
fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode)); fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode));
fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode)); fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode));
@@ -61,7 +63,8 @@ class SoftSPI {
/** Soft SPI receive byte. /** Soft SPI receive byte.
* @return Data byte received. * @return Data byte received.
*/ */
ALWAYS_INLINE uint8_t receive() { ALWAYS_INLINE uint8_t receive()
{
uint8_t data = 0; uint8_t data = 0;
receiveBit(7, &data); receiveBit(7, &data);
receiveBit(6, &data); receiveBit(6, &data);
@@ -77,7 +80,8 @@ class SoftSPI {
/** Soft SPI send byte. /** Soft SPI send byte.
* @param[in] data Data byte to send. * @param[in] data Data byte to send.
*/ */
ALWAYS_INLINE void send(uint8_t data) { ALWAYS_INLINE void send(uint8_t data)
{
sendBit(7, data); sendBit(7, data);
sendBit(6, data); sendBit(6, data);
sendBit(5, data); sendBit(5, data);
@@ -92,7 +96,8 @@ class SoftSPI {
* @param[in] txData Data byte to send. * @param[in] txData Data byte to send.
* @return Data byte received. * @return Data byte received.
*/ */
ALWAYS_INLINE uint8_t transfer(uint8_t txData) { ALWAYS_INLINE uint8_t transfer(uint8_t txData)
{
uint8_t rxData = 0; uint8_t rxData = 0;
transferBit(7, &rxData, txData); transferBit(7, &rxData, txData);
transferBit(6, &rxData, txData); transferBit(6, &rxData, txData);
@@ -107,9 +112,16 @@ class SoftSPI {
private: private:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ALWAYS_INLINE bool MODE_CPHA(uint8_t mode) {return (mode & 1) != 0;} ALWAYS_INLINE bool MODE_CPHA(uint8_t mode)
ALWAYS_INLINE bool MODE_CPOL(uint8_t mode) {return (mode & 2) != 0;} {
ALWAYS_INLINE void receiveBit(uint8_t bit, uint8_t* data) { return (mode & 1) != 0;
}
ALWAYS_INLINE bool MODE_CPOL(uint8_t mode)
{
return (mode & 2) != 0;
}
ALWAYS_INLINE void receiveBit(uint8_t bit, uint8_t* data)
{
if (MODE_CPHA(Mode)) { if (MODE_CPHA(Mode)) {
fastDigitalWrite(SckPin, !MODE_CPOL(Mode)); fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
} }
@@ -117,13 +129,16 @@ class SoftSPI {
nop; nop;
fastDigitalWrite(SckPin, fastDigitalWrite(SckPin,
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode)); MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
if (fastDigitalRead(MisoPin)) *data |= 1 << bit; if (fastDigitalRead(MisoPin)) {
*data |= 1 << bit;
}
if (!MODE_CPHA(Mode)) { if (!MODE_CPHA(Mode)) {
fastDigitalWrite(SckPin, MODE_CPOL(Mode)); fastDigitalWrite(SckPin, MODE_CPOL(Mode));
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ALWAYS_INLINE void sendBit(uint8_t bit, uint8_t data) { ALWAYS_INLINE void sendBit(uint8_t bit, uint8_t data)
{
if (MODE_CPHA(Mode)) { if (MODE_CPHA(Mode)) {
fastDigitalWrite(SckPin, !MODE_CPOL(Mode)); fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
} }
@@ -137,14 +152,17 @@ class SoftSPI {
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ALWAYS_INLINE void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData) { ALWAYS_INLINE void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData)
{
if (MODE_CPHA(Mode)) { if (MODE_CPHA(Mode)) {
fastDigitalWrite(SckPin, !MODE_CPOL(Mode)); fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
} }
fastDigitalWrite(MosiPin, txData & (1 << bit)); fastDigitalWrite(MosiPin, txData & (1 << bit));
fastDigitalWrite(SckPin, fastDigitalWrite(SckPin,
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode)); MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
if (fastDigitalRead(MisoPin)) *rxData |= 1 << bit; if (fastDigitalRead(MisoPin)) {
*rxData |= 1 << bit;
}
if (!MODE_CPHA(Mode)) { if (!MODE_CPHA(Mode)) {
fastDigitalWrite(SckPin, MODE_CPOL(Mode)); fastDigitalWrite(SckPin, MODE_CPOL(Mode));
} }
+25 -11
View File
@@ -9,11 +9,13 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<uint8_t ClkPin, uint8_t ConvPin, uint8_t DataPin> template<uint8_t ClkPin, uint8_t ConvPin, uint8_t DataPin>
/** ADS7818 class */ /** ADS7818 class */
class ADS7818 { class ADS7818
{
public: public:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Set pin modes and initial levels. */ /** Set pin modes and initial levels. */
void begin() { void begin()
{
fastPinMode(ClkPin, 1); fastPinMode(ClkPin, 1);
fastDigitalWrite(ClkPin, 0); fastDigitalWrite(ClkPin, 0);
fastPinMode(ConvPin, 1); fastPinMode(ConvPin, 1);
@@ -25,7 +27,8 @@ class ADS7818 {
* \return 16-bit value read. * \return 16-bit value read.
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
uint16_t read() { uint16_t read()
{
uint16_t v = 0; uint16_t v = 0;
fastDigitalWrite(ConvPin, 0); fastDigitalWrite(ConvPin, 0);
fastDigitalWrite(ClkPin, 1); fastDigitalWrite(ClkPin, 1);
@@ -51,15 +54,19 @@ class ADS7818 {
private: private:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void readBitFast16(uint16_t &v, uint8_t b) { void readBitFast16(uint16_t &v, uint8_t b)
{
fastDigitalWrite(ClkPin, 1); fastDigitalWrite(ClkPin, 1);
if (fastDigitalRead(DataPin)) v |= (1 << b); if (fastDigitalRead(DataPin)) {
v |= (1 << b);
}
fastDigitalWrite(ClkPin, 0); fastDigitalWrite(ClkPin, 0);
} }
}; };
#if 0 #if 0
/** initialize I/O ports */ /** initialize I/O ports */
STATIC_ALWAYS_INLINE void adcBegin() { STATIC_ALWAYS_INLINE void adcBegin()
{
fastPinMode(ADC_CLK_PIN, 1); fastPinMode(ADC_CLK_PIN, 1);
fastDigitalWrite(ADC_CLK_PIN, 0); fastDigitalWrite(ADC_CLK_PIN, 0);
fastPinMode(ADC_CONV_PIN, 1); fastPinMode(ADC_CONV_PIN, 1);
@@ -69,8 +76,11 @@ STATIC_ALWAYS_INLINE void adcBegin() {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** clock for don't care bits /** clock for don't care bits
*\param[in] delayBefore if true, delay before raising clock*/ *\param[in] delayBefore if true, delay before raising clock*/
STATIC_ALWAYS_INLINE void fastDummy(bool first) { STATIC_ALWAYS_INLINE void fastDummy(bool first)
if (!first) nop; {
if (!first) {
nop;
}
fastDigitalWrite(ADC_CLK_PIN, 1); fastDigitalWrite(ADC_CLK_PIN, 1);
nop; nop;
fastDigitalWrite(ADC_CLK_PIN, 0); fastDigitalWrite(ADC_CLK_PIN, 0);
@@ -80,16 +90,20 @@ STATIC_ALWAYS_INLINE void fastDummy(bool first) {
* \param[in] v word to receive bit * \param[in] v word to receive bit
* \param[in] b bit number to be set. v |= (1 << b) if next bit is high. * \param[in] b bit number to be set. v |= (1 << b) if next bit is high.
*/ */
STATIC_ALWAYS_INLINE void readBitFast16(uint16_t &v, uint8_t b) { STATIC_ALWAYS_INLINE void readBitFast16(uint16_t &v, uint8_t b)
{
fastDigitalWrite(ADC_CLK_PIN, 1); fastDigitalWrite(ADC_CLK_PIN, 1);
if (fastDigitalRead(ADC_DATA_PIN)) v |= (1 << b); if (fastDigitalRead(ADC_DATA_PIN)) {
v |= (1 << b);
}
fastDigitalWrite(ADC_CLK_PIN, 0); fastDigitalWrite(ADC_CLK_PIN, 0);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Read AD7680 16-bit ADC in less than 8 microseconds /** Read AD7680 16-bit ADC in less than 8 microseconds
* cs is chip select pin * cs is chip select pin
*/ */
STATIC_ALWAYS_INLINE uint16_t adcRead(bool centered = false) { STATIC_ALWAYS_INLINE uint16_t adcRead(bool centered = false)
{
uint16_t v = 0; uint16_t v = 0;
fastDigitalWrite(ADC_CONV_PIN, 0); fastDigitalWrite(ADC_CONV_PIN, 0);
fastDigitalWrite(ADC_CLK_PIN, 1); fastDigitalWrite(ADC_CLK_PIN, 1);
+74 -31
View File
@@ -4,11 +4,13 @@
//============================================================================== //==============================================================================
template<uint8_t CsPin, uint8_t ClkPin, uint8_t DoutPin, uint8_t UsecDelay = 0> template<uint8_t CsPin, uint8_t ClkPin, uint8_t DoutPin, uint8_t UsecDelay = 0>
/** MCP3201 class */ /** MCP3201 class */
class MCP3201 { class MCP3201
{
public: public:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Set pin modes and initial levels. */ /** Set pin modes and initial levels. */
void begin() { void begin()
{
fastPinMode(ClkPin, 1); fastPinMode(ClkPin, 1);
fastDigitalWrite(ClkPin, 0); fastDigitalWrite(ClkPin, 0);
fastPinMode(CsPin, 1); fastPinMode(CsPin, 1);
@@ -20,7 +22,8 @@ class MCP3201 {
* \return 16-bit value read. * \return 16-bit value read.
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
uint16_t read() { uint16_t read()
{
fastDigitalWrite(CsPin, 0); fastDigitalWrite(CsPin, 0);
// Start sample. // Start sample.
mcpAdcDummy(3); mcpAdcDummy(3);
@@ -54,16 +57,24 @@ class MCP3201 {
* \param[in] n nops to delay, must be a constant so compiler optimizes if(). * \param[in] n nops to delay, must be a constant so compiler optimizes if().
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void delayCycles(uint8_t n) { void delayCycles(uint8_t n)
if (n & 1) asm volatile("nop\n\t"); {
if (n & 2) asm volatile("nop\n\t" "nop\n\t"); if (n & 1) {
if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); asm volatile("nop\n\t");
}
if (n & 2) {
asm volatile("nop\n\t" "nop\n\t");
}
if (n & 4) {
asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** clock for don't care bits /** clock for don't care bits
*\param[in] delayBefore if true, delay before raising clock*/ *\param[in] delayBefore if true, delay before raising clock*/
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void mcpAdcDummy(uint8_t delayBefore) { void mcpAdcDummy(uint8_t delayBefore)
{
delayCycles(delayBefore); delayCycles(delayBefore);
fastDigitalWrite(ClkPin, 1); fastDigitalWrite(ClkPin, 1);
delayCycles(3); delayCycles(3);
@@ -71,11 +82,14 @@ class MCP3201 {
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 2) { void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 2)
{
delayCycles(3); delayCycles(3);
fastDigitalWrite(ClkPin, 1); fastDigitalWrite(ClkPin, 1);
delayCycles(delayRead); delayCycles(delayRead);
if (fastDigitalRead(DoutPin)) v |= (1 << b); if (fastDigitalRead(DoutPin)) {
v |= (1 << b);
}
fastDigitalWrite(ClkPin, 0); fastDigitalWrite(ClkPin, 0);
} }
}; };
@@ -83,11 +97,13 @@ class MCP3201 {
template<uint8_t CsPin, uint8_t ClkPin, template<uint8_t CsPin, uint8_t ClkPin,
uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0> uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0>
/** MCP3202 class */ /** MCP3202 class */
class MCP3202 { class MCP3202
{
public: public:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Set pin modes and initial levels. */ /** Set pin modes and initial levels. */
void begin() { void begin()
{
fastPinMode(ClkPin, 1); fastPinMode(ClkPin, 1);
fastDigitalWrite(ClkPin, 0); fastDigitalWrite(ClkPin, 0);
fastPinMode(CsPin, 1); fastPinMode(CsPin, 1);
@@ -100,7 +116,8 @@ class MCP3202 {
* \return 16-bit value read. * \return 16-bit value read.
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
uint16_t read(uint8_t config) { uint16_t read(uint8_t config)
{
uint16_t v = 0; uint16_t v = 0;
fastDigitalWrite(CsPin, 0); fastDigitalWrite(CsPin, 0);
// Start bit. // Start bit.
@@ -139,16 +156,24 @@ class MCP3202 {
* \param[in] n nops to delay, must be a constant so compiler optimizes if(). * \param[in] n nops to delay, must be a constant so compiler optimizes if().
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void delayCycles(uint8_t n) { void delayCycles(uint8_t n)
if (n & 1) asm volatile("nop\n\t"); {
if (n & 2) asm volatile("nop\n\t" "nop\n\t"); if (n & 1) {
if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); asm volatile("nop\n\t");
}
if (n & 2) {
asm volatile("nop\n\t" "nop\n\t");
}
if (n & 4) {
asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** clock for don't care bits /** clock for don't care bits
*\param[in] delayBefore if true, delay before raising clock*/ *\param[in] delayBefore if true, delay before raising clock*/
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void writeBit(bool value) { void writeBit(bool value)
{
fastDigitalWrite(DinPin, value); fastDigitalWrite(DinPin, value);
fastDigitalWrite(ClkPin, 1); fastDigitalWrite(ClkPin, 1);
delayCycles(2); delayCycles(2);
@@ -156,11 +181,14 @@ class MCP3202 {
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1) { void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1)
{
delayCycles(2); delayCycles(2);
fastDigitalWrite(ClkPin, 1); fastDigitalWrite(ClkPin, 1);
delayCycles(delayRead); delayCycles(delayRead);
if (fastDigitalRead(DoutPin)) v |= (1 << b); if (fastDigitalRead(DoutPin)) {
v |= (1 << b);
}
fastDigitalWrite(ClkPin, 0); fastDigitalWrite(ClkPin, 0);
} }
}; };
@@ -168,11 +196,13 @@ class MCP3202 {
template<uint8_t CsPin, uint8_t ClkPin, template<uint8_t CsPin, uint8_t ClkPin,
uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0> uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0>
/** MCP3204 class */ /** MCP3204 class */
class MCP3204 { class MCP3204
{
public: public:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Set pin modes and initial levels. */ /** Set pin modes and initial levels. */
void begin() { void begin()
{
fastPinMode(ClkPin, 1); fastPinMode(ClkPin, 1);
fastDigitalWrite(ClkPin, 0); fastDigitalWrite(ClkPin, 0);
fastPinMode(CsPin, 1); fastPinMode(CsPin, 1);
@@ -185,7 +215,8 @@ class MCP3204 {
* \return 16-bit value read. * \return 16-bit value read.
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
uint16_t read(uint8_t config) { uint16_t read(uint8_t config)
{
uint16_t v = 0; uint16_t v = 0;
fastDigitalWrite(CsPin, 0); fastDigitalWrite(CsPin, 0);
// Start bit. // Start bit.
@@ -228,16 +259,24 @@ class MCP3204 {
* \param[in] n nops to delay, must be a constant so compiler optimizes if(). * \param[in] n nops to delay, must be a constant so compiler optimizes if().
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void delayCycles(uint8_t n) { void delayCycles(uint8_t n)
if (n & 1) asm volatile("nop\n\t"); {
if (n & 2) asm volatile("nop\n\t" "nop\n\t"); if (n & 1) {
if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); asm volatile("nop\n\t");
}
if (n & 2) {
asm volatile("nop\n\t" "nop\n\t");
}
if (n & 4) {
asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** clock for don't care bits /** clock for don't care bits
*\param[in] delayBefore if true, delay before raising clock*/ *\param[in] delayBefore if true, delay before raising clock*/
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void writeBit(bool value) { void writeBit(bool value)
{
fastDigitalWrite(DinPin, value); fastDigitalWrite(DinPin, value);
fastDigitalWrite(ClkPin, 1); fastDigitalWrite(ClkPin, 1);
delayCycles(2); delayCycles(2);
@@ -245,11 +284,14 @@ class MCP3204 {
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1) { void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1)
{
delayCycles(2); delayCycles(2);
fastDigitalWrite(ClkPin, 1); fastDigitalWrite(ClkPin, 1);
delayCycles(delayRead); delayCycles(delayRead);
if (fastDigitalRead(DoutPin)) v |= (1 << b); if (fastDigitalRead(DoutPin)) {
v |= (1 << b);
}
fastDigitalWrite(ClkPin, 0); fastDigitalWrite(ClkPin, 0);
} }
}; };
@@ -257,6 +299,7 @@ class MCP3204 {
// MCP3204 and MCP3208 use the same code. // MCP3204 and MCP3208 use the same code.
template<uint8_t CsPin, uint8_t ClkPin, template<uint8_t CsPin, uint8_t ClkPin,
uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0> uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0>
class MCP3208 : public MCP3204<CsPin, ClkPin, DoutPin, DinPin, UsecDelay> { class MCP3208 : public MCP3204<CsPin, ClkPin, DoutPin, DinPin, UsecDelay>
{
}; };
#endif // MCP320X_h #endif // MCP320X_h
+42 -16
View File
@@ -9,11 +9,13 @@ const uint8_t MCP355X_TO_MS = 100;
//============================================================================== //==============================================================================
template<uint8_t CsPin, uint8_t SckPin, uint8_t SdoPin> template<uint8_t CsPin, uint8_t SckPin, uint8_t SdoPin>
/** MCP355X class */ /** MCP355X class */
class MCP355X { class MCP355X
{
public: public:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Set pin modes and initial levels. */ /** Set pin modes and initial levels. */
void begin(bool singleMode = true) { void begin(bool singleMode = true)
{
m_singleMode = singleMode; m_singleMode = singleMode;
fastPinMode(SdoPin, 0); fastPinMode(SdoPin, 0);
fastPinMode(SckPin, 1); fastPinMode(SckPin, 1);
@@ -32,7 +34,8 @@ class MCP355X {
* \return 22-bit value. * \return 22-bit value.
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
int32_t read() { int32_t read()
{
uint8_t t = 0; uint8_t t = 0;
uint8_t v3 = 0; uint8_t v3 = 0;
if (m_singleMode) { if (m_singleMode) {
@@ -48,15 +51,23 @@ class MCP355X {
fastDigitalWrite(CsPin, 0); fastDigitalWrite(CsPin, 0);
// Delay while RDY settles. // Delay while RDY settles.
delayCycles(4); delayCycles(4);
if (!fastDigitalRead(SdoPin)) break; if (!fastDigitalRead(SdoPin)) {
break;
}
fastDigitalWrite(CsPin, 1); fastDigitalWrite(CsPin, 1);
if (t++ > MCP355X_TO_MS) return MCP355X_ERR; if (t++ > MCP355X_TO_MS) {
return MCP355X_ERR;
}
} }
} else { } else {
while (1) { while (1) {
if (!fastDigitalRead(SdoPin)) break; if (!fastDigitalRead(SdoPin)) {
break;
}
delay(1); delay(1);
if (t++ > MCP355X_TO_MS) return MCP355X_ERR; if (t++ > MCP355X_TO_MS) {
return MCP355X_ERR;
}
} }
} }
uint8_t v2 = readByte(); uint8_t v2 = readByte();
@@ -76,10 +87,14 @@ class MCP355X {
v3 = 0XFF; v3 = 0XFF;
} else if (v2 & 0X40) { } else if (v2 & 0X40) {
// Overflow high. Cause value to be >= MCP355X_OVH. // Overflow high. Cause value to be >= MCP355X_OVH.
if (v2 & 0X20) v2 &= 0X3F; if (v2 & 0X20) {
v2 &= 0X3F;
}
} else if (v2 & 0X80) { } else if (v2 & 0X80) {
// Overflow low. Cause value to be <= MCP355X_OVH. // Overflow low. Cause value to be <= MCP355X_OVH.
if ((v2 & 0X20) == 0) v2 |= 0X40; if ((v2 & 0X20) == 0) {
v2 |= 0X40;
}
v3 = 0XFF; v3 = 0XFF;
} }
uint16_t v_high = (v3 << 8) | v2; uint16_t v_high = (v3 << 8) | v2;
@@ -92,24 +107,35 @@ class MCP355X {
* \param[in] n nops to delay, must be a constant so compiler optimizes if(). * \param[in] n nops to delay, must be a constant so compiler optimizes if().
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void delayCycles(uint8_t n) { void delayCycles(uint8_t n)
if (n & 1) asm volatile("nop\n\t"); {
if (n & 2) asm volatile("nop\n\t" "nop\n\t"); if (n & 1) {
if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); asm volatile("nop\n\t");
}
if (n & 2) {
asm volatile("nop\n\t" "nop\n\t");
}
if (n & 4) {
asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Default delay yields about 2 MHz clock. // Default delay yields about 2 MHz clock.
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void readBit(uint8_t &v, uint8_t b, uint8_t delayRead = 0) { void readBit(uint8_t &v, uint8_t b, uint8_t delayRead = 0)
{
fastDigitalWrite(SckPin, 0); fastDigitalWrite(SckPin, 0);
delayCycles(2 + delayRead); delayCycles(2 + delayRead);
fastDigitalWrite(SckPin, 1); fastDigitalWrite(SckPin, 1);
if (fastDigitalRead(SdoPin)) v |= (1 << b); if (fastDigitalRead(SdoPin)) {
v |= (1 << b);
}
delayCycles(delayRead); delayCycles(delayRead);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline __attribute__((always_inline)) inline __attribute__((always_inline))
uint8_t readByte() { uint8_t readByte()
{
uint8_t v = 0; uint8_t v = 0;
readBit(v, 7); readBit(v, 7);
readBit(v, 6); readBit(v, 6);
@@ -4,7 +4,8 @@ DigitalPin<13> pin13(OUTPUT);
void setup() {} void setup() {}
void loop() { void loop()
{
// toggle is a two byte instruction that executes // toggle is a two byte instruction that executes
// in two cycles or 125 ns on a 16 MHz CPU // in two cycles or 125 ns on a 16 MHz CPU
pin13.toggle(); pin13.toggle();
@@ -4,11 +4,13 @@
// Class with compile time pin number. // Class with compile time pin number.
DigitalPin<13> pin13; DigitalPin<13> pin13;
void setup() { void setup()
{
// Set mode to OUTPUT and level LOW. // Set mode to OUTPUT and level LOW.
pin13.config(OUTPUT, LOW); pin13.config(OUTPUT, LOW);
} }
void loop() { void loop()
{
// toggle is a two byte instruction that executes // toggle is a two byte instruction that executes
// in two cycles or 125 ns on a 16 MHz CPU // in two cycles or 125 ns on a 16 MHz CPU
pin13.toggle(); pin13.toggle();
@@ -6,6 +6,7 @@ DigitalPin<13> pin13(OUTPUT);
void setup() {} void setup() {}
void loop() { void loop()
{
pin13 = pin12; pin13 = pin12;
} }
@@ -10,7 +10,8 @@ DigitalPin<13> dataPin(OUTPUT, HIGH);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Time to send one bit is ten cycles or 625 ns for 16 MHz CPU. // Time to send one bit is ten cycles or 625 ns for 16 MHz CPU.
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void sendBit(uint8_t bit, uint8_t data) { void sendBit(uint8_t bit, uint8_t data)
{
dataPin = data & (1 << bit); dataPin = data & (1 << bit);
clockPin = 1; clockPin = 1;
// may want a nop here - clock pulse is 125 ns wide // may want a nop here - clock pulse is 125 ns wide
@@ -18,7 +19,8 @@ void sendBit(uint8_t bit, uint8_t data) {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Time to send one byte is 5 usec. // Time to send one byte is 5 usec.
void shiftOut(uint8_t bits) { void shiftOut(uint8_t bits)
{
sendBit(7, bits); sendBit(7, bits);
sendBit(6, bits); sendBit(6, bits);
sendBit(5, bits); sendBit(5, bits);
@@ -29,11 +31,13 @@ void shiftOut(uint8_t bits) {
sendBit(0, bits); sendBit(0, bits);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void setup() { void setup()
{
// Not used. // Not used.
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void loop() { void loop()
{
shiftOut(0X55); shiftOut(0X55);
delay(2); delay(2);
} }
@@ -6,7 +6,8 @@
PinIO readPin; PinIO readPin;
PinIO writePin; PinIO writePin;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void setup() { void setup()
{
// Assign pin 12 to readPin. // Assign pin 12 to readPin.
readPin.begin(12); readPin.begin(12);
@@ -18,7 +19,8 @@ void setup() {
writePin.mode(OUTPUT); writePin.mode(OUTPUT);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void loop() { void loop()
{
// Copy the value read from readPin to writePin. // Copy the value read from readPin to writePin.
writePin.write(readPin.read()); writePin.write(readPin.read());
} }
@@ -4,11 +4,13 @@
// Set runtime pin number. // Set runtime pin number.
PinIO pin13(13); PinIO pin13(13);
void setup() { void setup()
{
// set mode to OUTPUT and level LOW // set mode to OUTPUT and level LOW
pin13.config(OUTPUT, LOW); pin13.config(OUTPUT, LOW);
} }
void loop() { void loop()
{
pin13.toggle(); pin13.toggle();
delay(100); delay(100);
pin13.toggle(); pin13.toggle();
@@ -4,13 +4,15 @@
PinIO readPin(12); PinIO readPin(12);
PinIO writePin(13); PinIO writePin(13);
void setup() { void setup()
{
// Set input mode and disable pull-up. // Set input mode and disable pull-up.
readPin.config(INPUT, LOW); readPin.config(INPUT, LOW);
// set output mode // set output mode
writePin.mode(OUTPUT); writePin.mode(OUTPUT);
} }
void loop() { void loop()
{
writePin.write(readPin.read()); writePin.write(readPin.read());
} }
@@ -26,7 +26,8 @@ const uint8_t SCL_PIN = A5;
SoftI2cMaster i2c(SCL_PIN, SDA_PIN); SoftI2cMaster i2c(SCL_PIN, SDA_PIN);
//FastI2cMaster<SCL_PIN, SDA_PIN> i2c; //FastI2cMaster<SCL_PIN, SDA_PIN> i2c;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void setup() { void setup()
{
Serial.begin(9600); Serial.begin(9600);
while (!Serial); while (!Serial);
@@ -55,14 +56,19 @@ void setup() {
Serial.print("Device at address: 0X"); Serial.print("Device at address: 0X");
Serial.print(add, HEX); Serial.print(add, HEX);
Serial.print(" responds to "); Serial.print(" responds to ");
if (rd) Serial.print("Read"); if (rd) {
if (rd && wr) Serial.print(" and "); Serial.print("Read");
if (wr) Serial.print("Write"); }
if (rd && wr) {
Serial.print(" and ");
}
if (wr) {
Serial.print("Write");
}
Serial.println('.'); Serial.println('.');
} }
add += 2; add += 2;
} } while (add);
while (add);
if (!found) { if (!found) {
Serial.println("No devices found."); Serial.println("No devices found.");
@@ -70,7 +76,8 @@ void setup() {
Serial.println("Done"); Serial.println("Done");
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void loop() { void loop()
{
// Not used. // Not used.
} }
@@ -16,10 +16,13 @@ FastI2cMaster<SCL_PIN, SDA_PIN> rtc;
/* /*
* Read 'count' bytes from the DS1307 starting at 'address'. * Read 'count' bytes from the DS1307 starting at 'address'.
*/ */
uint8_t readDS1307(uint8_t address, uint8_t *buf, uint8_t count) { uint8_t readDS1307(uint8_t address, uint8_t *buf, uint8_t count)
{
// Send address of data. // Send address of data.
if (!rtc.transfer(DS1307ADDR | I2C_WRITE, &address, 1)) return false; if (!rtc.transfer(DS1307ADDR | I2C_WRITE, &address, 1)) {
return false;
}
// Read data. // Read data.
return rtc.transfer(DS1307ADDR | I2C_READ, buf, count); return rtc.transfer(DS1307ADDR | I2C_READ, buf, count);
@@ -28,7 +31,8 @@ uint8_t readDS1307(uint8_t address, uint8_t *buf, uint8_t count) {
/* /*
* write 'count' bytes to DS1307 starting at 'address'. * write 'count' bytes to DS1307 starting at 'address'.
*/ */
uint8_t writeDS1307(uint8_t address, uint8_t *buf, uint8_t count) { uint8_t writeDS1307(uint8_t address, uint8_t *buf, uint8_t count)
{
// Write address and continue transfer for write of data. // Write address and continue transfer for write of data.
if (!rtc.transfer(DS1307ADDR | I2C_WRITE, &address, 1, I2C_CONTINUE)) { if (!rtc.transfer(DS1307ADDR | I2C_WRITE, &address, 1, I2C_CONTINUE)) {
@@ -38,7 +42,8 @@ uint8_t writeDS1307(uint8_t address, uint8_t *buf, uint8_t count) {
return rtc.transferContinue(buf, count); return rtc.transferContinue(buf, count);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void setup(void) { void setup(void)
{
Serial.begin(9600); Serial.begin(9600);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -50,18 +55,21 @@ void setup(void) {
// Day of week U.S. convention. // Day of week U.S. convention.
char *Ddd[] = {"Bad", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; char *Ddd[] = {"Bad", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void hexPrint(uint8_t v) { void hexPrint(uint8_t v)
{
Serial.print(v >> 4, HEX); Serial.print(v >> 4, HEX);
Serial.print(v & 0XF, HEX); Serial.print(v & 0XF, HEX);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void hexPrintln(uint8_t v) { void hexPrintln(uint8_t v)
{
hexPrint(v); hexPrint(v);
Serial.println(); Serial.println();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// read hex input // read hex input
uint8_t hexRead(uint16_t* v) { uint8_t hexRead(uint16_t* v)
{
bool valid = false; bool valid = false;
uint16_t n = 0; uint16_t n = 0;
while (!Serial.available()); while (!Serial.available());
@@ -77,14 +85,11 @@ uint8_t hexRead(uint16_t* v) {
n <<= 4; n <<= 4;
if ('a' <= c && c <= 'f') { if ('a' <= c && c <= 'f') {
n += c - ('a' - 10); n += c - ('a' - 10);
} } else if ('A' <= c && c <= 'F') {
else if ('A' <= c && c <= 'F') {
n += c - ('A' - 10); n += c - ('A' - 10);
} } else if ('0' <= c && c <= '9') {
else if ('0' <= c && c <= '9') {
n += c - '0'; n += c - '0';
} } else {
else {
valid = false; valid = false;
break; break;
} }
@@ -99,9 +104,12 @@ uint8_t hexRead(uint16_t* v) {
return true; return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
uint8_t bcdRead(uint8_t min, uint8_t max, uint8_t* n) { uint8_t bcdRead(uint8_t min, uint8_t max, uint8_t* n)
{
uint16_t v; uint16_t v;
if (!hexRead(&v)) return false; if (!hexRead(&v)) {
return false;
}
uint8_t d = 10 * (v >> 4) + (v & 0XF); uint8_t d = 10 * (v >> 4) + (v & 0XF);
if ((v >> 4) > 9 || (v & 0XF) > 9 || d < min || d > max) { if ((v >> 4) > 9 || (v & 0XF) > 9 || d < min || d > max) {
PgmPrintln("Invalid"); PgmPrintln("Invalid");
@@ -111,7 +119,8 @@ uint8_t bcdRead(uint8_t min, uint8_t max, uint8_t* n) {
return true; return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void displayTime(void) { void displayTime(void)
{
uint8_t r[8]; uint8_t r[8];
if (!readDS1307(0, r, 8)) { if (!readDS1307(0, r, 8)) {
PgmPrintln("Read Failed for display time"); PgmPrintln("Read Failed for display time");
@@ -150,7 +159,8 @@ void displayTime(void) {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// dump registers and 56 bytes of RAM // dump registers and 56 bytes of RAM
void dumpAll(void) { void dumpAll(void)
{
uint8_t buf[8]; uint8_t buf[8];
for (uint8_t a = 0; a < 64; a += 8) { for (uint8_t a = 0; a < 64; a += 8) {
hexPrint(a); hexPrint(a);
@@ -167,11 +177,14 @@ void dumpAll(void) {
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void fillNvRam(void) { void fillNvRam(void)
{
uint8_t buf[8]; uint8_t buf[8];
PgmPrint("Enter HEX value for all NV RAM locations (00-FF): "); PgmPrint("Enter HEX value for all NV RAM locations (00-FF): ");
uint16_t v; uint16_t v;
if (!hexRead(&v)) return; if (!hexRead(&v)) {
return;
}
hexPrint(v); hexPrint(v);
for (uint8_t a = 8; a < 64; a ++) { for (uint8_t a = 8; a < 64; a ++) {
if (!writeDS1307(a, (uint8_t *)&v, 1)) { if (!writeDS1307(a, (uint8_t *)&v, 1)) {
@@ -205,7 +218,8 @@ RS1 RS0 FREQUENCY
1 0 8.192kHz 1 0 8.192kHz
1 1 32.768kHz 1 1 32.768kHz
*/ */
void setControl(void) { void setControl(void)
{
PgmPrintln("SQW/OUT pin: "); PgmPrintln("SQW/OUT pin: ");
PgmPrintln("(00) Low"); PgmPrintln("(00) Low");
PgmPrintln("(10) 1Hz"); PgmPrintln("(10) 1Hz");
@@ -215,26 +229,37 @@ void setControl(void) {
PgmPrintln("(80) High"); PgmPrintln("(80) High");
PgmPrint("Enter control: "); PgmPrint("Enter control: ");
uint16_t r; uint16_t r;
if (!hexRead(&r)) return; if (!hexRead(&r)) {
return;
}
hexPrintln(r); hexPrintln(r);
if (!writeDS1307(7, (uint8_t *)&r, 1)) { if (!writeDS1307(7, (uint8_t *)&r, 1)) {
PgmPrint("Write Failed for setControl"); PgmPrint("Write Failed for setControl");
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void setDate(void) { void setDate(void)
{
uint8_t r[4]; uint8_t r[4];
PgmPrint("Enter year (00-99): "); PgmPrint("Enter year (00-99): ");
if (!bcdRead(0, 99, &r[3])) return; if (!bcdRead(0, 99, &r[3])) {
return;
}
hexPrintln(r[3]); hexPrintln(r[3]);
PgmPrint("Enter month (01-12): "); PgmPrint("Enter month (01-12): ");
if (!bcdRead(1, 12, &r[2])) return; if (!bcdRead(1, 12, &r[2])) {
return;
}
hexPrintln(r[2]); hexPrintln(r[2]);
PgmPrint("Enter day (01-31): "); PgmPrint("Enter day (01-31): ");
if (!bcdRead(1, 31, &r[1])) return; if (!bcdRead(1, 31, &r[1])) {
return;
}
hexPrintln(r[1]); hexPrintln(r[1]);
PgmPrint("Enter day of week (01-07, Sun-Sat): "); PgmPrint("Enter day of week (01-07, Sun-Sat): ");
if (!bcdRead(1, 7, &r[0])) return; if (!bcdRead(1, 7, &r[0])) {
return;
}
hexPrintln(r[0]); hexPrintln(r[0]);
if (!writeDS1307(3, r, 4)) { if (!writeDS1307(3, r, 4)) {
@@ -242,12 +267,15 @@ void setDate(void) {
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void setNvRam() { void setNvRam()
{
uint8_t u; uint8_t u;
uint16_t a, v; uint16_t a, v;
while (true) { while (true) {
PgmPrint("Enter zero to quit or Hex address (8-3F):"); PgmPrint("Enter zero to quit or Hex address (8-3F):");
if (!hexRead(&a) || a == 0) return; if (!hexRead(&a) || a == 0) {
return;
}
if (a < 8 || a > 0X3F) { if (a < 8 || a > 0X3F) {
PgmPrintln("Invalid address"); PgmPrintln("Invalid address");
return; return;
@@ -260,7 +288,9 @@ void setNvRam() {
PgmPrint("Current value: "); PgmPrint("Current value: ");
hexPrintln(u); hexPrintln(u);
PgmPrint("Enter new HEX value (00-FF): "); PgmPrint("Enter new HEX value (00-FF): ");
if (!hexRead(&v)) return; if (!hexRead(&v)) {
return;
}
hexPrintln(v); hexPrintln(v);
if (!writeDS1307(a, (uint8_t *)&v, 1)) { if (!writeDS1307(a, (uint8_t *)&v, 1)) {
PgmPrint("Write Failed"); PgmPrint("Write Failed");
@@ -269,16 +299,23 @@ void setNvRam() {
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void setTime(void) { void setTime(void)
{
uint8_t r[3]; uint8_t r[3];
PgmPrint("Enter hours (00-23): "); PgmPrint("Enter hours (00-23): ");
if (!bcdRead(0, 23, &r[2])) return; if (!bcdRead(0, 23, &r[2])) {
return;
}
hexPrintln(r[2]); hexPrintln(r[2]);
PgmPrint("Enter minutes (00-59): "); PgmPrint("Enter minutes (00-59): ");
if (!bcdRead(0, 59, &r[1])) return; if (!bcdRead(0, 59, &r[1])) {
return;
}
hexPrintln(r[1]); hexPrintln(r[1]);
PgmPrint("Enter seconds (00-59): "); PgmPrint("Enter seconds (00-59): ");
if (!bcdRead(0, 59, &r[0])) return; if (!bcdRead(0, 59, &r[0])) {
return;
}
hexPrintln(r[0]); hexPrintln(r[0]);
if (!writeDS1307(0, r, 3)) { if (!writeDS1307(0, r, 3)) {
@@ -287,7 +324,8 @@ void setTime(void) {
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void loop(void) { void loop(void)
{
Serial.println(); Serial.println();
displayTime(); displayTime();
while (Serial.read() >= 0) {} while (Serial.read() >= 0) {}
@@ -302,9 +340,13 @@ void loop(void) {
PgmPrint("Enter option: "); PgmPrint("Enter option: ");
uint16_t n; uint16_t n;
if (!hexRead(&n)) return; if (!hexRead(&n)) {
return;
}
Serial.println(n, DEC); Serial.println(n, DEC);
if (n == 0) return; if (n == 0) {
return;
}
Serial.println(); Serial.println();
if (n == 1) { if (n == 1) {
setTime(); setTime();
@@ -1,11 +1,13 @@
// Scope test for write timing with Arduino digitaWrite(). // Scope test for write timing with Arduino digitaWrite().
const uint8_t PIN13 = 13; const uint8_t PIN13 = 13;
void setup() { void setup()
{
// Set mode to OUTPUT. // Set mode to OUTPUT.
pinMode(PIN13, OUTPUT); pinMode(PIN13, OUTPUT);
} }
void loop() { void loop()
{
digitalWrite(PIN13, HIGH); digitalWrite(PIN13, HIGH);
digitalWrite(PIN13, LOW); digitalWrite(PIN13, LOW);
digitalWrite(PIN13, HIGH); digitalWrite(PIN13, HIGH);
@@ -4,11 +4,13 @@
// Class with compile time pin number. // Class with compile time pin number.
DigitalPin<13> pin13; DigitalPin<13> pin13;
void setup() { void setup()
{
// set mode to OUTPUT // set mode to OUTPUT
pin13.mode(OUTPUT); pin13.mode(OUTPUT);
} }
void loop() { void loop()
{
pin13.high(); pin13.high();
pin13.low(); pin13.low();
pin13.write(1); pin13.write(1);
@@ -1,10 +1,12 @@
// Test fastDigital function timing with a scope. // Test fastDigital function timing with a scope.
#include <DigitalIO.h> #include <DigitalIO.h>
const uint8_t PIN = 13; const uint8_t PIN = 13;
void setup() { void setup()
{
fastPinMode(PIN, OUTPUT); fastPinMode(PIN, OUTPUT);
} }
void loop() { void loop()
{
fastDigitalWrite(PIN, HIGH); fastDigitalWrite(PIN, HIGH);
fastDigitalWrite(PIN, LOW); fastDigitalWrite(PIN, LOW);
fastDigitalToggle(PIN); fastDigitalToggle(PIN);
@@ -4,11 +4,13 @@
// Class with runtime pin numbers. // Class with runtime pin numbers.
PinIO pin(13); PinIO pin(13);
void setup() { void setup()
{
// Set mode to OUTPUT. // Set mode to OUTPUT.
pin.mode(OUTPUT); pin.mode(OUTPUT);
} }
void loop() { void loop()
{
pin.high(); pin.high();
pin.low(); pin.low();
pin.write(1); pin.write(1);
@@ -9,7 +9,8 @@ const uint8_t SPI_MODE = 0;
SoftSPI<SOFT_SPI_MISO_PIN, SOFT_SPI_MOSI_PIN, SOFT_SPI_SCK_PIN, SPI_MODE> spi; SoftSPI<SOFT_SPI_MISO_PIN, SOFT_SPI_MOSI_PIN, SOFT_SPI_SCK_PIN, SPI_MODE> spi;
int test; int test;
void setup() { void setup()
{
Serial.begin(9600); Serial.begin(9600);
spi.begin(); spi.begin();
while(1) { while(1) {
@@ -19,14 +20,19 @@ void setup() {
Serial.println("T - Transfer"); Serial.println("T - Transfer");
while ((test = Serial.read()) <= 0) {} while ((test = Serial.read()) <= 0) {}
test = toupper(test); test = toupper(test);
if (strchr("RST", test)) break; if (strchr("RST", test)) {
break;
}
Serial.println("Invalid entry"); Serial.println("Invalid entry");
}; };
Serial.print("Starting test "); Serial.print("Starting test ");
Serial.println((char)test); Serial.println((char)test);
} }
void loop() { void loop()
if (test == 'S') spi.send(0X55); {
if (test == 'S') {
spi.send(0X55);
}
if (test == 'R') { if (test == 'R') {
Serial.println(spi.receive(), HEX); Serial.println(spi.receive(), HEX);
} }
+43 -10
View File
@@ -44,28 +44,61 @@ class AltSoftSerial : public Stream
{ {
public: public:
AltSoftSerial() { } //!< Constructor AltSoftSerial() { } //!< Constructor
~AltSoftSerial() { end(); } //!< Destructor ~AltSoftSerial()
static void begin(uint32_t baud) { init((ALTSS_BASE_FREQ + baud / 2) / baud); } //!< begin {
end(); //!< Destructor
}
static void begin(uint32_t baud)
{
init((ALTSS_BASE_FREQ + baud / 2) / baud); //!< begin
}
static void end(); //!< end static void end(); //!< end
int peek(); //!< peek int peek(); //!< peek
int read(); //!< read int read(); //!< read
int available(); //!< available int available(); //!< available
#if ARDUINO >= 100 #if ARDUINO >= 100
size_t write(uint8_t byte) { writeByte(byte); return 1; } //!< write size_t write(uint8_t byte)
void flush() { flushOutput(); } //!< flush {
writeByte(byte); //!< write
return 1;
}
void flush()
{
flushOutput(); //!< flush
}
#else #else
void write(uint8_t byte) { writeByte(byte); } //!< write void write(uint8_t byte)
void flush() { flushInput(); } //!< flush {
writeByte(byte); //!< write
}
void flush()
{
flushInput(); //!< flush
}
#endif #endif
using Print::write; using Print::write;
static void flushInput(); //!< flushInput static void flushInput(); //!< flushInput
static void flushOutput(); //!< flushOutput static void flushOutput(); //!< flushOutput
// for drop-in compatibility with NewSoftSerial, rxPin & txPin ignored // for drop-in compatibility with NewSoftSerial, rxPin & txPin ignored
//AltSoftSerial(uint8_t rxPin, uint8_t txPin, bool inverse = false) { } //AltSoftSerial(uint8_t rxPin, uint8_t txPin, bool inverse = false) { }
bool listen() { return false; } //!< listen bool listen()
bool isListening() { return true; } //!< isListening {
bool overflow() { bool r = timing_error; timing_error = false; return r; } //!< overflow return false; //!< listen
static int library_version() { return 1; } //!< library_version }
bool isListening()
{
return true; //!< isListening
}
bool overflow()
{
bool r = timing_error; //!< overflow
timing_error = false;
return r;
}
static int library_version()
{
return 1; //!< library_version
}
static void enable_timer0(bool) { } //!< enable_timer0 static void enable_timer0(bool) { } //!< enable_timer0
static bool timing_error; //!< timing_error static bool timing_error; //!< timing_error
private: private:
+16 -17
View File
@@ -50,8 +50,7 @@ template <class T> class CircularBuffer
*/ */
void clear(void) void clear(void)
{ {
MY_CRITICAL_SECTION MY_CRITICAL_SECTION {
{
m_front = 0; m_front = 0;
m_fill = 0; m_fill = 0;
} }
@@ -64,8 +63,7 @@ template <class T> class CircularBuffer
inline bool empty(void) const inline bool empty(void) const
{ {
bool empty; bool empty;
MY_CRITICAL_SECTION MY_CRITICAL_SECTION {
{
empty = !m_fill; empty = !m_fill;
} }
return empty; return empty;
@@ -78,8 +76,7 @@ template <class T> class CircularBuffer
inline bool full(void) const inline bool full(void) const
{ {
bool full; bool full;
MY_CRITICAL_SECTION MY_CRITICAL_SECTION {
{
full = m_fill == m_size; full = m_fill == m_size;
} }
return full; return full;
@@ -91,8 +88,7 @@ template <class T> class CircularBuffer
*/ */
inline uint8_t available(void) const inline uint8_t available(void) const
{ {
MY_CRITICAL_SECTION MY_CRITICAL_SECTION {
{
return m_fill; return m_fill;
} }
} }
@@ -105,9 +101,11 @@ template <class T> class CircularBuffer
*/ */
T* getFront(void) const T* getFront(void) const
{ {
MY_CRITICAL_SECTION MY_CRITICAL_SECTION {
if (!full())
{ {
if (!full()) return get(m_front); return get(m_front);
}
} }
return static_cast<T*>(NULL); return static_cast<T*>(NULL);
} }
@@ -120,13 +118,13 @@ template <class T> class CircularBuffer
*/ */
bool pushFront(T* record) bool pushFront(T* record)
{ {
MY_CRITICAL_SECTION MY_CRITICAL_SECTION {
{
if (!full()) if (!full())
{ {
T* f = get(m_front); T* f = get(m_front);
if (f != record) if (f != record) {
*f = *record; *f = *record;
}
m_front = (m_front+1) % m_size; m_front = (m_front+1) % m_size;
m_fill++; m_fill++;
return true; return true;
@@ -143,9 +141,11 @@ template <class T> class CircularBuffer
*/ */
T* getBack(void) const T* getBack(void) const
{ {
MY_CRITICAL_SECTION MY_CRITICAL_SECTION {
if (!empty())
{ {
if (!empty()) return get(back()); return get(back());
}
} }
return static_cast<T*>(NULL); return static_cast<T*>(NULL);
} }
@@ -156,8 +156,7 @@ template <class T> class CircularBuffer
*/ */
bool popBack(void) bool popBack(void)
{ {
MY_CRITICAL_SECTION MY_CRITICAL_SECTION {
{
if (!empty()) if (!empty())
{ {
m_fill--; m_fill--;
+6 -2
View File
@@ -26,7 +26,8 @@
#include "IPAddress.h" #include "IPAddress.h"
#if !DOXYGEN #if !DOXYGEN
class Client : public Stream { class Client : public Stream
{
public: public:
virtual int connect(IPAddress ip, uint16_t port) = 0; virtual int connect(IPAddress ip, uint16_t port) = 0;
@@ -43,7 +44,10 @@ public:
virtual operator bool() = 0; virtual operator bool() = 0;
protected: protected:
uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; uint8_t* rawIPAddress(IPAddress& addr)
{
return addr.raw_address();
};
}; };
#endif #endif
+43 -23
View File
@@ -32,13 +32,16 @@
#include "log.h" #include "log.h"
#include "EthernetClient.h" #include "EthernetClient.h"
EthernetClient::EthernetClient() : _sock(-1) { EthernetClient::EthernetClient() : _sock(-1)
{
} }
EthernetClient::EthernetClient(int sock) : _sock(sock) { EthernetClient::EthernetClient(int sock) : _sock(sock)
{
} }
int EthernetClient::connect(const char* host, uint16_t port) { int EthernetClient::connect(const char* host, uint16_t port)
{
int sockfd; int sockfd;
struct addrinfo hints, *servinfo, *p; struct addrinfo hints, *servinfo, *p;
int rv; int rv;
@@ -88,15 +91,18 @@ int EthernetClient::connect(const char* host, uint16_t port) {
return 1; return 1;
} }
int EthernetClient::connect(IPAddress ip, uint16_t port) { int EthernetClient::connect(IPAddress ip, uint16_t port)
{
return connect(ip.toString().c_str(), port); return connect(ip.toString().c_str(), port);
} }
size_t EthernetClient::write(uint8_t b) { size_t EthernetClient::write(uint8_t b)
{
return write(&b, 1); return write(&b, 1);
} }
size_t EthernetClient::write(const uint8_t *buf, size_t size) { size_t EthernetClient::write(const uint8_t *buf, size_t size)
{
int rc = 0; int rc = 0;
int bytes = 0; int bytes = 0;
@@ -119,17 +125,20 @@ size_t EthernetClient::write(const uint8_t *buf, size_t size) {
return bytes; return bytes;
} }
size_t EthernetClient::write(const char *str) { size_t EthernetClient::write(const char *str)
{
if (str == NULL) { if (str == NULL) {
return 0; return 0;
} }
return write((const uint8_t *)str, strlen(str)); return write((const uint8_t *)str, strlen(str));
} }
size_t EthernetClient::write(const char *buffer, size_t size) { size_t EthernetClient::write(const char *buffer, size_t size)
{
return write((const uint8_t *)buffer, size); return write((const uint8_t *)buffer, size);
} }
int EthernetClient::available() { int EthernetClient::available()
{
int count = 0; int count = 0;
if (_sock != -1) { if (_sock != -1) {
@@ -139,10 +148,10 @@ int EthernetClient::available() {
return 0; return 0;
} }
int EthernetClient::read() { int EthernetClient::read()
uint8_t b;
if ( recv(_sock, &b, 1, 0) > 0 )
{ {
uint8_t b;
if ( recv(_sock, &b, 1, 0) > 0 ) {
// recv worked // recv worked
return b; return b;
} else { } else {
@@ -151,22 +160,26 @@ int EthernetClient::read() {
} }
} }
int EthernetClient::read(uint8_t *buf, size_t size) { int EthernetClient::read(uint8_t *buf, size_t size)
{
return recv(_sock, buf, size, 0); return recv(_sock, buf, size, 0);
} }
int EthernetClient::peek() { int EthernetClient::peek()
{
uint8_t b; uint8_t b;
return recv(_sock, &b, 1, MSG_PEEK | MSG_DONTWAIT); return recv(_sock, &b, 1, MSG_PEEK | MSG_DONTWAIT);
} }
void EthernetClient::flush() { void EthernetClient::flush()
{
// There isn't much we can do here // There isn't much we can do here
return; return;
} }
void EthernetClient::stop() { void EthernetClient::stop()
{
if (_sock == -1) { if (_sock == -1) {
return; return;
} }
@@ -186,7 +199,8 @@ void EthernetClient::stop() {
} }
usleep(1000); usleep(1000);
gettimeofday(&curTime, NULL); gettimeofday(&curTime, NULL);
} while (((curTime.tv_sec - startTime.tv_sec) * 1000000) + (curTime.tv_usec - startTime.tv_usec) < 1000000); } while (((curTime.tv_sec - startTime.tv_sec) * 1000000) + (curTime.tv_usec - startTime.tv_usec) <
1000000);
// if it hasn't closed, close it forcefully // if it hasn't closed, close it forcefully
if (s != ETHERNETCLIENT_W5100_CLOSED) { if (s != ETHERNETCLIENT_W5100_CLOSED) {
@@ -195,7 +209,8 @@ void EthernetClient::stop() {
_sock = -1; _sock = -1;
} }
uint8_t EthernetClient::status() { uint8_t EthernetClient::status()
{
if (_sock == -1) { if (_sock == -1) {
return ETHERNETCLIENT_W5100_CLOSED; return ETHERNETCLIENT_W5100_CLOSED;
} }
@@ -203,7 +218,8 @@ uint8_t EthernetClient::status() {
struct tcp_info tcp_info; struct tcp_info tcp_info;
int tcp_info_length = sizeof(tcp_info); int tcp_info_length = sizeof(tcp_info);
if ( getsockopt( _sock, SOL_TCP, TCP_INFO, (void *)&tcp_info, (socklen_t *)&tcp_info_length ) == 0 ) { if ( getsockopt( _sock, SOL_TCP, TCP_INFO, (void *)&tcp_info,
(socklen_t *)&tcp_info_length ) == 0 ) {
switch (tcp_info.tcpi_state) { switch (tcp_info.tcpi_state) {
case TCP_ESTABLISHED: case TCP_ESTABLISHED:
return ETHERNETCLIENT_W5100_ESTABLISHED; return ETHERNETCLIENT_W5100_ESTABLISHED;
@@ -232,7 +248,8 @@ uint8_t EthernetClient::status() {
return ETHERNETCLIENT_W5100_CLOSED; return ETHERNETCLIENT_W5100_CLOSED;
} }
uint8_t EthernetClient::connected() { uint8_t EthernetClient::connected()
{
if (_sock == -1) { if (_sock == -1) {
return 0; return 0;
} }
@@ -246,17 +263,20 @@ uint8_t EthernetClient::connected() {
return 1; return 1;
} }
int EthernetClient::getSocketNumber() { int EthernetClient::getSocketNumber()
{
return _sock; return _sock;
} }
// the next function allows us to use the client returned by // the next function allows us to use the client returned by
// EthernetServer::available() as the condition in an if-statement. // EthernetServer::available() as the condition in an if-statement.
EthernetClient::operator bool() { EthernetClient::operator bool()
{
return _sock != -1; return _sock != -1;
} }
bool EthernetClient::operator==(const EthernetClient& rhs) { bool EthernetClient::operator==(const EthernetClient& rhs)
{
return _sock == rhs._sock && _sock != -1 && rhs._sock != -1; return _sock == rhs._sock && _sock != -1 && rhs._sock != -1;
} }
+14 -4
View File
@@ -40,7 +40,8 @@
/** /**
* EthernetClient class * EthernetClient class
*/ */
class EthernetClient : public Client { class EthernetClient : public Client
{
private: private:
int _sock; //!< @brief Network socket. int _sock; //!< @brief Network socket.
@@ -168,12 +169,18 @@ public:
* @brief Overloaded cast operators. * @brief Overloaded cast operators.
* *
*/ */
virtual bool operator==(const bool value) { return bool() == value; } virtual bool operator==(const bool value)
{
return bool() == value;
}
/** /**
* @brief Overloaded cast operators. * @brief Overloaded cast operators.
* *
*/ */
virtual bool operator!=(const bool value) { return bool() != value; } virtual bool operator!=(const bool value)
{
return bool() != value;
}
/** /**
* @brief Overloaded cast operators. * @brief Overloaded cast operators.
* *
@@ -183,7 +190,10 @@ public:
* @brief Overloaded cast operators. * @brief Overloaded cast operators.
* *
*/ */
virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); }; virtual bool operator!=(const EthernetClient& rhs)
{
return !this->operator==(rhs);
};
friend class EthernetServer; friend class EthernetServer;
}; };
+2 -1
View File
@@ -32,7 +32,8 @@
#include "EthernetClient.h" #include "EthernetClient.h"
#include "EthernetServer.h" #include "EthernetServer.h"
EthernetServer::EthernetServer(uint16_t port, uint16_t max_clients) : port(port), max_clients(max_clients) EthernetServer::EthernetServer(uint16_t port, uint16_t max_clients) : port(port),
max_clients(max_clients)
{ {
clients.reserve(max_clients); clients.reserve(max_clients);
} }
+2 -1
View File
@@ -39,7 +39,8 @@ class EthernetClient;
/** /**
* @brief EthernetServer class * @brief EthernetServer class
*/ */
class EthernetServer : public Server { class EthernetServer : public Server
{
private: private:
uint16_t port; //!< @brief Port number for the network socket. uint16_t port; //!< @brief Port number for the network socket.
+23 -19
View File
@@ -24,53 +24,53 @@
#include <cstring> #include <cstring>
#include "IPAddress.h" #include "IPAddress.h"
IPAddress::IPAddress() { IPAddress::IPAddress()
{
_address.dword = 0; _address.dword = 0;
} }
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) { IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet,
uint8_t fourth_octet)
{
_address.bytes[0] = first_octet; _address.bytes[0] = first_octet;
_address.bytes[1] = second_octet; _address.bytes[1] = second_octet;
_address.bytes[2] = third_octet; _address.bytes[2] = third_octet;
_address.bytes[3] = fourth_octet; _address.bytes[3] = fourth_octet;
} }
IPAddress::IPAddress(uint32_t address) { IPAddress::IPAddress(uint32_t address)
{
_address.dword = address; _address.dword = address;
} }
IPAddress::IPAddress(const uint8_t *address) { IPAddress::IPAddress(const uint8_t *address)
{
memcpy(_address.bytes, address, sizeof(_address.bytes)); memcpy(_address.bytes, address, sizeof(_address.bytes));
} }
bool IPAddress::fromString(const char *address) { bool IPAddress::fromString(const char *address)
{
// TODO: add support for "a", "a.b", "a.b.c" formats // TODO: add support for "a", "a.b", "a.b.c" formats
uint16_t acc = 0; // Accumulator uint16_t acc = 0; // Accumulator
uint8_t dots = 0; uint8_t dots = 0;
while (*address) while (*address) {
{
char c = *address++; char c = *address++;
if (c >= '0' && c <= '9') if (c >= '0' && c <= '9') {
{
acc = acc * 10 + (c - '0'); acc = acc * 10 + (c - '0');
if (acc > 255) { if (acc > 255) {
// Value out of [0..255] range // Value out of [0..255] range
return false; return false;
} }
} } else if (c == '.') {
else if (c == '.')
{
if (dots == 3) { if (dots == 3) {
// Too much dots (there must be 3 dots) // Too much dots (there must be 3 dots)
return false; return false;
} }
_address.bytes[dots++] = acc; _address.bytes[dots++] = acc;
acc = 0; acc = 0;
} } else {
else
{
// Invalid char // Invalid char
return false; return false;
} }
@@ -84,23 +84,27 @@ bool IPAddress::fromString(const char *address) {
return true; return true;
} }
IPAddress& IPAddress::operator=(const uint8_t *address) { IPAddress& IPAddress::operator=(const uint8_t *address)
{
memcpy(_address.bytes, address, sizeof(_address.bytes)); memcpy(_address.bytes, address, sizeof(_address.bytes));
return *this; return *this;
} }
IPAddress& IPAddress::operator=(uint32_t address) { IPAddress& IPAddress::operator=(uint32_t address)
{
_address.dword = address; _address.dword = address;
return *this; return *this;
} }
bool IPAddress::operator==(const uint8_t* addr) const { bool IPAddress::operator==(const uint8_t* addr) const
{
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0; return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
} }
std::string IPAddress::toString() std::string IPAddress::toString()
{ {
char szRet[16]; char szRet[16];
sprintf(szRet,"%u.%u.%u.%u", _address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3]); sprintf(szRet,"%u.%u.%u.%u", _address.bytes[0], _address.bytes[1], _address.bytes[2],
_address.bytes[3]);
return std::string(szRet); return std::string(szRet);
} }
+18 -8
View File
@@ -29,7 +29,8 @@
/** /**
* @brief A class to make it easier to handle and pass around IP addresses * @brief A class to make it easier to handle and pass around IP addresses
*/ */
class IPAddress { class IPAddress
{
private: private:
union { union {
uint8_t bytes[4]; //!< IPv4 address as an array uint8_t bytes[4]; //!< IPv4 address as an array
@@ -45,7 +46,8 @@ class IPAddress {
* *
* @return pointer to the internal structure. * @return pointer to the internal structure.
*/ */
uint8_t* raw_address() { uint8_t* raw_address()
{
return _address.bytes; return _address.bytes;
} }
@@ -86,27 +88,33 @@ class IPAddress {
* *
* @param address to be set. * @param address to be set.
*/ */
bool fromString(const std::string &address) { return fromString(address.c_str()); } bool fromString(const std::string &address)
{
return fromString(address.c_str());
}
/** /**
* @brief Overloaded cast operator * @brief Overloaded cast operator
* *
* Allow IPAddress objects to be used where a pointer to a four-byte uint8_t array is expected * Allow IPAddress objects to be used where a pointer to a four-byte uint8_t array is expected
*/ */
operator uint32_t() const { operator uint32_t() const
{
return _address.dword; return _address.dword;
} }
/** /**
* @brief Overloaded cast operator * @brief Overloaded cast operator
* *
*/ */
bool operator==(const IPAddress& addr) const { bool operator==(const IPAddress& addr) const
{
return _address.dword == addr._address.dword; return _address.dword == addr._address.dword;
} }
/** /**
* @brief Overloaded cast operator * @brief Overloaded cast operator
* *
*/ */
bool operator==(uint32_t addr) const { bool operator==(uint32_t addr) const
{
return _address.dword == addr; return _address.dword == addr;
} }
/** /**
@@ -120,14 +128,16 @@ class IPAddress {
* Allow getting and setting individual octets of the address. * Allow getting and setting individual octets of the address.
* *
*/ */
uint8_t operator[](int index) const { uint8_t operator[](int index) const
{
return _address.bytes[index]; return _address.bytes[index];
} }
/** /**
* @brief Overloaded index operator * @brief Overloaded index operator
* *
*/ */
uint8_t& operator[](int index) { uint8_t& operator[](int index)
{
return _address.bytes[index]; return _address.bytes[index];
} }
/** /**
+47 -25
View File
@@ -30,7 +30,8 @@
// Public Methods ////////////////////////////////////////////////////////////// // Public Methods //////////////////////////////////////////////////////////////
size_t Print::write(const uint8_t *buffer, size_t size) { size_t Print::write(const uint8_t *buffer, size_t size)
{
size_t n = 0; size_t n = 0;
while(size--) { while(size--) {
n += write(*buffer++); n += write(*buffer++);
@@ -42,7 +43,8 @@ size_t
#ifdef __GNUC__ #ifdef __GNUC__
__attribute__((format(printf, 2, 3))) __attribute__((format(printf, 2, 3)))
#endif #endif
Print::printf(const char *format, ...) { Print::printf(const char *format, ...)
{
va_list arg; va_list arg;
va_start(arg, format); va_start(arg, format);
char temp[64]; char temp[64];
@@ -65,31 +67,38 @@ Print::printf(const char *format, ...) {
return len; return len;
} }
size_t Print::print(const std::string &s) { size_t Print::print(const std::string &s)
{
return write(s.c_str(), s.length()); return write(s.c_str(), s.length());
} }
size_t Print::print(const char str[]) { size_t Print::print(const char str[])
{
return write(str); return write(str);
} }
size_t Print::print(char c) { size_t Print::print(char c)
{
return write(c); return write(c);
} }
size_t Print::print(unsigned char b, int base) { size_t Print::print(unsigned char b, int base)
{
return print((unsigned long) b, base); return print((unsigned long) b, base);
} }
size_t Print::print(int n, int base) { size_t Print::print(int n, int base)
{
return print((long) n, base); return print((long) n, base);
} }
size_t Print::print(unsigned int n, int base) { size_t Print::print(unsigned int n, int base)
{
return print((unsigned long) n, base); return print((unsigned long) n, base);
} }
size_t Print::print(long n, int base) { size_t Print::print(long n, int base)
{
if(base == 0) { if(base == 0) {
return write(n); return write(n);
} else if(base == 10) { } else if(base == 10) {
@@ -104,72 +113,83 @@ size_t Print::print(long n, int base) {
} }
} }
size_t Print::print(unsigned long n, int base) { size_t Print::print(unsigned long n, int base)
{
if(base == 0) { if(base == 0) {
return write(n); return write(n);
} } else {
else {
return printNumber(n, base); return printNumber(n, base);
} }
} }
size_t Print::print(double n, int digits) { size_t Print::print(double n, int digits)
{
return printFloat(n, digits); return printFloat(n, digits);
} }
size_t Print::println(void) { size_t Print::println(void)
{
return print("\r\n"); return print("\r\n");
} }
size_t Print::println(const std::string &s) { size_t Print::println(const std::string &s)
{
size_t n = print(s); size_t n = print(s);
n += println(); n += println();
return n; return n;
} }
size_t Print::println(const char c[]) { size_t Print::println(const char c[])
{
size_t n = print(c); size_t n = print(c);
n += println(); n += println();
return n; return n;
} }
size_t Print::println(char c) { size_t Print::println(char c)
{
size_t n = print(c); size_t n = print(c);
n += println(); n += println();
return n; return n;
} }
size_t Print::println(unsigned char b, int base) { size_t Print::println(unsigned char b, int base)
{
size_t n = print(b, base); size_t n = print(b, base);
n += println(); n += println();
return n; return n;
} }
size_t Print::println(int num, int base) { size_t Print::println(int num, int base)
{
size_t n = print(num, base); size_t n = print(num, base);
n += println(); n += println();
return n; return n;
} }
size_t Print::println(unsigned int num, int base) { size_t Print::println(unsigned int num, int base)
{
size_t n = print(num, base); size_t n = print(num, base);
n += println(); n += println();
return n; return n;
} }
size_t Print::println(long num, int base) { size_t Print::println(long num, int base)
{
size_t n = print(num, base); size_t n = print(num, base);
n += println(); n += println();
return n; return n;
} }
size_t Print::println(unsigned long num, int base) { size_t Print::println(unsigned long num, int base)
{
size_t n = print(num, base); size_t n = print(num, base);
n += println(); n += println();
return n; return n;
} }
size_t Print::println(double num, int digits) { size_t Print::println(double num, int digits)
{
size_t n = print(num, digits); size_t n = print(num, digits);
n += println(); n += println();
return n; return n;
@@ -177,7 +197,8 @@ size_t Print::println(double num, int digits) {
// Private Methods ///////////////////////////////////////////////////////////// // Private Methods /////////////////////////////////////////////////////////////
size_t Print::printNumber(unsigned long n, uint8_t base) { size_t Print::printNumber(unsigned long n, uint8_t base)
{
char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
char *str = &buf[sizeof(buf) - 1]; char *str = &buf[sizeof(buf) - 1];
@@ -198,7 +219,8 @@ size_t Print::printNumber(unsigned long n, uint8_t base) {
return write(str); return write(str);
} }
size_t Print::printFloat(double number, uint8_t digits) { size_t Print::printFloat(double number, uint8_t digits)
{
size_t n = 0; size_t n = 0;
if(std::isnan(number)) { if(std::isnan(number)) {
+20 -7
View File
@@ -32,29 +32,42 @@
#define OCT 8 #define OCT 8
#define BIN 2 #define BIN 2
class Print { class Print
{
private: private:
int write_error; int write_error;
size_t printNumber(unsigned long n, uint8_t base); size_t printNumber(unsigned long n, uint8_t base);
size_t printFloat(double number, uint8_t digits); size_t printFloat(double number, uint8_t digits);
protected: protected:
void setWriteError(int err = 1) { write_error = err; } void setWriteError(int err = 1)
{
write_error = err;
}
public: public:
Print() : write_error(0) {} Print() : write_error(0) {}
int getWriteError() { return write_error; } int getWriteError()
void clearWriteError() { setWriteError(0); } {
return write_error;
}
void clearWriteError()
{
setWriteError(0);
}
virtual size_t write(uint8_t) = 0; virtual size_t write(uint8_t) = 0;
size_t write(const char *str) { size_t write(const char *str)
if (str == NULL) {
if (str == NULL) {
return 0; return 0;
}
return write((const uint8_t *) str, strlen(str)); return write((const uint8_t *) str, strlen(str));
} }
virtual size_t write(const uint8_t *buffer, size_t size); virtual size_t write(const uint8_t *buffer, size_t size);
size_t write(const char *buffer, size_t size) { size_t write(const char *buffer, size_t size)
{
return write((const uint8_t *) buffer, size); return write((const uint8_t *) buffer, size);
} }
+53 -18
View File
@@ -69,7 +69,8 @@ bool SerialPort::open(int bauds)
/* create a symlink with predictable name to the PTY device */ /* create a symlink with predictable name to the PTY device */
unlink(serialPort.c_str()); // remove the symlink if it already exists unlink(serialPort.c_str()); // remove the symlink if it already exists
if (symlink(ptsname(sd), serialPort.c_str()) != 0) { if (symlink(ptsname(sd), serialPort.c_str()) != 0) {
logError("Couldn't create a symlink '%s' to PTY! (%d) %s\n", serialPort.c_str(), errno, strerror(errno)); logError("Couldn't create a symlink '%s' to PTY! (%d) %s\n", serialPort.c_str(), errno,
strerror(errno));
return false; return false;
} }
} else { } else {
@@ -83,23 +84,57 @@ bool SerialPort::open(int bauds)
} }
switch (bauds) { switch (bauds) {
case 50: speed = B50 ; break ; case 50:
case 75: speed = B75 ; break ; speed = B50 ;
case 110: speed = B110 ; break ; break ;
case 134: speed = B134 ; break ; case 75:
case 150: speed = B150 ; break ; speed = B75 ;
case 200: speed = B200 ; break ; break ;
case 300: speed = B300 ; break ; case 110:
case 600: speed = B600 ; break ; speed = B110 ;
case 1200: speed = B1200 ; break ; break ;
case 1800: speed = B1800 ; break ; case 134:
case 2400: speed = B2400 ; break ; speed = B134 ;
case 9600: speed = B9600 ; break ; break ;
case 19200: speed = B19200 ; break ; case 150:
case 38400: speed = B38400 ; break ; speed = B150 ;
case 57600: speed = B57600 ; break ; break ;
case 115200: speed = B115200 ; break ; case 200:
default: speed = B115200 ; break ; speed = B200 ;
break ;
case 300:
speed = B300 ;
break ;
case 600:
speed = B600 ;
break ;
case 1200:
speed = B1200 ;
break ;
case 1800:
speed = B1800 ;
break ;
case 2400:
speed = B2400 ;
break ;
case 9600:
speed = B9600 ;
break ;
case 19200:
speed = B19200 ;
break ;
case 38400:
speed = B38400 ;
break ;
case 57600:
speed = B57600 ;
break ;
case 115200:
speed = B115200 ;
break ;
default:
speed = B115200 ;
break ;
} }
// Get the current options of the port // Get the current options of the port
+2 -1
View File
@@ -28,7 +28,8 @@
* SerialPort Class * SerialPort Class
* Class that provides the functionality of arduino Serial library * Class that provides the functionality of arduino Serial library
*/ */
class SerialPort : public Stream { class SerialPort : public Stream
{
private: private:
int sd; //!< @brief file descriptor number. int sd; //!< @brief file descriptor number.
+2 -1
View File
@@ -23,7 +23,8 @@
#include "Print.h" #include "Print.h"
#if !DOXYGEN #if !DOXYGEN
class Server : public Print { class Server : public Print
{
public: public:
virtual void begin() =0; virtual void begin() =0;
}; };
+2 -1
View File
@@ -52,7 +52,8 @@ SoftEeprom::SoftEeprom(const char *fileName, size_t length)
myFile.write((const char*)_values, _length); myFile.write((const char*)_values, _length);
myFile.close(); myFile.close();
} else if (fileInfo.st_size < 0 || (size_t)fileInfo.st_size != _length) { } else if (fileInfo.st_size < 0 || (size_t)fileInfo.st_size != _length) {
logError("Config file %s is not the correct size of %zu. Please remove the file and a new one will be created.\n", _fileName, _length); logError("Config file %s is not the correct size of %zu. Please remove the file and a new one will be created.\n",
_fileName, _length);
exit(1); exit(1);
} else { } else {
//Read config into local memory. //Read config into local memory.
+2 -1
View File
@@ -30,7 +30,8 @@
/** /**
* SoftEeprom class * SoftEeprom class
*/ */
class SoftEeprom { class SoftEeprom
{
private: private:
size_t _length; //!< @brief Eeprom max size. size_t _length; //!< @brief Eeprom max size.
+37 -27
View File
@@ -28,7 +28,8 @@
#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field #define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
// private method to read stream with timeout // private method to read stream with timeout
int Stream::timedRead() { int Stream::timedRead()
{
int c; int c;
_startMillis = millis(); _startMillis = millis();
do { do {
@@ -42,7 +43,8 @@ int Stream::timedRead() {
} }
// private method to peek stream with timeout // private method to peek stream with timeout
int Stream::timedPeek() { int Stream::timedPeek()
{
int c; int c;
_startMillis = millis(); _startMillis = millis();
do { do {
@@ -57,7 +59,8 @@ int Stream::timedPeek() {
// returns peek of the next digit in the stream or -1 if timeout // returns peek of the next digit in the stream or -1 if timeout
// discards non-numeric characters // discards non-numeric characters
int Stream::peekNextDigit() { int Stream::peekNextDigit()
{
int c; int c;
while(1) { while(1) {
c = timedPeek(); c = timedPeek();
@@ -83,25 +86,30 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi
} }
// find returns true if the target string is found // find returns true if the target string is found
bool Stream::find(const char *target) { bool Stream::find(const char *target)
{
return findUntil(target, (char*) ""); return findUntil(target, (char*) "");
} }
// reads data from the stream until the target string of given length is found // reads data from the stream until the target string of given length is found
// returns true if target string is found, false if timed out // returns true if target string is found, false if timed out
bool Stream::find(const char *target, size_t length) { bool Stream::find(const char *target, size_t length)
{
return findUntil(target, length, NULL, 0); return findUntil(target, length, NULL, 0);
} }
// as find but search ends if the terminator string is found // as find but search ends if the terminator string is found
bool Stream::findUntil(const char *target, const char *terminator) { bool Stream::findUntil(const char *target, const char *terminator)
{
return findUntil(target, strlen(target), terminator, strlen(terminator)); return findUntil(target, strlen(target), terminator, strlen(terminator));
} }
// reads data from the stream until the target string of the given length is found // reads data from the stream until the target string of the given length is found
// search terminated if the terminator string is found // search terminated if the terminator string is found
// returns true if target string is found, false if terminated or timed out // returns true if target string is found, false if terminated or timed out
bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen) { bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator,
size_t termLen)
{
size_t index = 0; // maximum target string length is 64k bytes! size_t index = 0; // maximum target string length is 64k bytes!
size_t termIndex = 0; size_t termIndex = 0;
int c; int c;
@@ -135,13 +143,15 @@ bool Stream::findUntil(const char *target, size_t targetLen, const char *termina
// returns the first valid (long) integer value from the current position. // returns the first valid (long) integer value from the current position.
// initial characters that are not digits (or the minus sign) are skipped // initial characters that are not digits (or the minus sign) are skipped
// function is terminated by the first character that is not a digit. // function is terminated by the first character that is not a digit.
long Stream::parseInt() { long Stream::parseInt()
{
return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout) return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
} }
// as above but a given skipChar is ignored // as above but a given skipChar is ignored
// this allows format characters (typically commas) in values to be ignored // this allows format characters (typically commas) in values to be ignored
long Stream::parseInt(char skipChar) { long Stream::parseInt(char skipChar)
{
boolean isNegative = false; boolean isNegative = false;
long value = 0; long value = 0;
int c; int c;
@@ -155,11 +165,9 @@ long Stream::parseInt(char skipChar) {
do { do {
if(c == skipChar) { if(c == skipChar) {
// ignore this charactor // ignore this charactor
} } else if(c == '-') {
else if(c == '-') {
isNegative = true; isNegative = true;
} } else if(c >= '0' && c <= '9') { // is c a digit?
else if(c >= '0' && c <= '9') { // is c a digit?
value = value * 10 + c - '0'; value = value * 10 + c - '0';
} }
read(); // consume the character we got with peek read(); // consume the character we got with peek
@@ -173,13 +181,15 @@ long Stream::parseInt(char skipChar) {
} }
// as parseInt but returns a floating point value // as parseInt but returns a floating point value
float Stream::parseFloat() { float Stream::parseFloat()
{
return parseFloat(NO_SKIP_CHAR); return parseFloat(NO_SKIP_CHAR);
} }
// as above but the given skipChar is ignored // as above but the given skipChar is ignored
// this allows format characters (typically commas) in values to be ignored // this allows format characters (typically commas) in values to be ignored
float Stream::parseFloat(char skipChar) { float Stream::parseFloat(char skipChar)
{
boolean isNegative = false; boolean isNegative = false;
boolean isFraction = false; boolean isFraction = false;
long value = 0; long value = 0;
@@ -195,14 +205,11 @@ float Stream::parseFloat(char skipChar) {
do { do {
if(c == skipChar) { if(c == skipChar) {
// ignore // ignore
} } else if(c == '-') {
else if(c == '-') {
isNegative = true; isNegative = true;
} } else if(c == '.') {
else if(c == '.') {
isFraction = true; isFraction = true;
} } else if(c >= '0' && c <= '9') { // is c a digit?
else if(c >= '0' && c <= '9') { // is c a digit?
value = value * 10 + c - '0'; value = value * 10 + c - '0';
if(isFraction) { if(isFraction) {
fraction *= 0.1; fraction *= 0.1;
@@ -217,8 +224,7 @@ float Stream::parseFloat(char skipChar) {
} }
if(isFraction) { if(isFraction) {
return value * fraction; return value * fraction;
} } else {
else {
return value; return value;
} }
} }
@@ -228,7 +234,8 @@ float Stream::parseFloat(char skipChar) {
// returns the number of characters placed in the buffer // returns the number of characters placed in the buffer
// the buffer is NOT null terminated. // the buffer is NOT null terminated.
// //
size_t Stream::readBytes(char *buffer, size_t length) { size_t Stream::readBytes(char *buffer, size_t length)
{
size_t count = 0; size_t count = 0;
while(count < length) { while(count < length) {
int c = timedRead(); int c = timedRead();
@@ -245,7 +252,8 @@ size_t Stream::readBytes(char *buffer, size_t length) {
// terminates if length characters have been read, timeout, or if the terminator character detected // terminates if length characters have been read, timeout, or if the terminator character detected
// returns the number of characters placed in the buffer (0 means no valid data found) // returns the number of characters placed in the buffer (0 means no valid data found)
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) { size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
{
if(length < 1) { if(length < 1) {
return 0; return 0;
} }
@@ -261,7 +269,8 @@ size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) {
return index; // return number of characters, not including null terminator return index; // return number of characters, not including null terminator
} }
std::string Stream::readString() { std::string Stream::readString()
{
std::string ret; std::string ret;
int c = timedRead(); int c = timedRead();
while(c >= 0) { while(c >= 0) {
@@ -271,7 +280,8 @@ std::string Stream::readString() {
return ret; return ret;
} }
std::string Stream::readStringUntil(char terminator) { std::string Stream::readStringUntil(char terminator)
{
std::string ret; std::string ret;
int c = timedRead(); int c = timedRead();
while(c >= 0 && c != terminator) { while(c >= 0 && c != terminator) {
+32 -15
View File
@@ -38,9 +38,11 @@
*/ */
#if !DOXYGEN #if !DOXYGEN
class Stream: public Print { class Stream: public Print
{
protected: protected:
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read unsigned long
_timeout; // number of milliseconds to wait for the next char before aborting timed read
unsigned long _startMillis; // used for timeout measurement unsigned long _startMillis; // used for timeout measurement
int timedRead(); // private method to read stream with timeout int timedRead(); // private method to read stream with timeout
int timedPeek(); // private method to peek stream with timeout int timedPeek(); // private method to peek stream with timeout
@@ -52,35 +54,47 @@ class Stream: public Print {
virtual int peek() = 0; virtual int peek() = 0;
virtual void flush() = 0; virtual void flush() = 0;
Stream() { Stream()
{
_timeout = 1000; _timeout = 1000;
} }
// parsing methods // parsing methods
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second void setTimeout(unsigned long
timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
bool find(const char *target); // reads data from the stream until the target string is found bool find(const char *target); // reads data from the stream until the target string is found
bool find(uint8_t *target) { bool find(uint8_t *target)
{
return find((char *) target); return find((char *) target);
} }
// returns true if target string is found, false if timed out (see setTimeout) // returns true if target string is found, false if timed out (see setTimeout)
bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found bool find(const char *target, size_t
bool find(const uint8_t *target, size_t length) { length); // reads data from the stream until the target string of given length is found
bool find(const uint8_t *target, size_t length)
{
return find((char *) target, length); return find((char *) target, length);
} }
// returns true if target string is found, false if timed out // returns true if target string is found, false if timed out
bool find(char target) { return find (&target, 1); } bool find(char target)
{
return find (&target, 1);
}
bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found bool findUntil(const char *target,
bool findUntil(const uint8_t *target, const char *terminator) { const char *terminator); // as find but search ends if the terminator string is found
bool findUntil(const uint8_t *target, const char *terminator)
{
return findUntil((char *) target, terminator); return findUntil((char *) target, terminator);
} }
bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found bool findUntil(const char *target, size_t targetLen, const char *terminate,
bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) { size_t termLen); // as above but search ends if the terminate string is found
bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen)
{
return findUntil((char *) target, targetLen, terminate, termLen); return findUntil((char *) target, targetLen, terminate, termLen);
} }
@@ -91,14 +105,17 @@ class Stream: public Print {
float parseFloat(); // float version of parseInt float parseFloat(); // float version of parseInt
virtual size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer virtual size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer
virtual size_t readBytes(uint8_t *buffer, size_t length) { virtual size_t readBytes(uint8_t *buffer, size_t length)
{
return readBytes((char *) buffer, length); return readBytes((char *) buffer, length);
} }
// terminates if length characters have been read or timeout (see setTimeout) // terminates if length characters have been read or timeout (see setTimeout)
// returns the number of characters placed in the buffer (0 means no valid data found) // returns the number of characters placed in the buffer (0 means no valid data found)
size_t readBytesUntil(char terminator, char *buffer, size_t length); // as readBytes with terminator character size_t readBytesUntil(char terminator, char *buffer,
size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) { size_t length); // as readBytes with terminator character
size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length)
{
return readBytesUntil(terminator, (char *) buffer, length); return readBytesUntil(terminator, (char *) buffer, length);
} }
// terminates if length characters have been read, timeout, or if the terminator character detected // terminates if length characters have been read, timeout, or if the terminator character detected
+18 -9
View File
@@ -23,7 +23,8 @@
#include <math.h> #include <math.h>
#include "stdlib_noniso.h" #include "stdlib_noniso.h"
char* utoa(unsigned value, char* result, int base) { char* utoa(unsigned value, char* result, int base)
{
if(base < 2 || base > 16) { if(base < 2 || base > 16) {
*result = 0; *result = 0;
return result; return result;
@@ -44,7 +45,8 @@ char* utoa(unsigned value, char* result, int base) {
return result; return result;
} }
char* itoa(int value, char* result, int base) { char* itoa(int value, char* result, int base)
{
if(base < 2 || base > 16) { if(base < 2 || base > 16) {
*result = 0; *result = 0;
return result; return result;
@@ -70,21 +72,25 @@ char* itoa(int value, char* result, int base) {
return result; return result;
} }
int atoi(const char* s) { int atoi(const char* s)
{
return (int) atol(s); return (int) atol(s);
} }
long atol(const char* s) { long atol(const char* s)
{
char * tmp; char * tmp;
return strtol(s, &tmp, 10); return strtol(s, &tmp, 10);
} }
double atof(const char* s) { double atof(const char* s)
{
char * tmp; char * tmp;
return strtod(s, &tmp); return strtod(s, &tmp);
} }
void reverse(char* begin, char* end) { void reverse(char* begin, char* end)
{
char *is = begin; char *is = begin;
char *ie = end - 1; char *ie = end - 1;
while(is < ie) { while(is < ie) {
@@ -96,7 +102,8 @@ void reverse(char* begin, char* end) {
} }
} }
char* ltoa(long value, char* result, int base) { char* ltoa(long value, char* result, int base)
{
if(base < 2 || base > 16) { if(base < 2 || base > 16) {
*result = 0; *result = 0;
return result; return result;
@@ -122,7 +129,8 @@ char* ltoa(long value, char* result, int base) {
return result; return result;
} }
char* ultoa(unsigned long value, char* result, int base) { char* ultoa(unsigned long value, char* result, int base)
{
if(base < 2 || base > 16) { if(base < 2 || base > 16) {
*result = 0; *result = 0;
return result; return result;
@@ -143,7 +151,8 @@ char* ultoa(unsigned long value, char* result, int base) {
return result; return result;
} }
char* dtostrf (double val, signed char width, unsigned char prec, char *s) { char* dtostrf (double val, signed char width, unsigned char prec, char *s)
{
sprintf(s,"%*.*f", width, prec, val); sprintf(s,"%*.*f", width, prec, val);
return s; return s;
} }
+90 -41
View File
@@ -7,39 +7,46 @@
#include "PubSubClient.h" #include "PubSubClient.h"
#include "Arduino.h" #include "Arduino.h"
PubSubClient::PubSubClient() { PubSubClient::PubSubClient()
{
this->_state = MQTT_DISCONNECTED; this->_state = MQTT_DISCONNECTED;
this->_client = NULL; this->_client = NULL;
this->stream = NULL; this->stream = NULL;
setCallback(NULL); setCallback(NULL);
} }
PubSubClient::PubSubClient(Client& client) { PubSubClient::PubSubClient(Client& client)
{
this->_state = MQTT_DISCONNECTED; this->_state = MQTT_DISCONNECTED;
setClient(client); setClient(client);
this->stream = NULL; this->stream = NULL;
} }
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) { PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client)
{
this->_state = MQTT_DISCONNECTED; this->_state = MQTT_DISCONNECTED;
setServer(addr, port); setServer(addr, port);
setClient(client); setClient(client);
this->stream = NULL; this->stream = NULL;
} }
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client, Stream& stream) { PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client, Stream& stream)
{
this->_state = MQTT_DISCONNECTED; this->_state = MQTT_DISCONNECTED;
setServer(addr,port); setServer(addr,port);
setClient(client); setClient(client);
setStream(stream); setStream(stream);
} }
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client)
{
this->_state = MQTT_DISCONNECTED; this->_state = MQTT_DISCONNECTED;
setServer(addr, port); setServer(addr, port);
setCallback(callback); setCallback(callback);
setClient(client); setClient(client);
this->stream = NULL; this->stream = NULL;
} }
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client,
Stream& stream)
{
this->_state = MQTT_DISCONNECTED; this->_state = MQTT_DISCONNECTED;
setServer(addr,port); setServer(addr,port);
setCallback(callback); setCallback(callback);
@@ -47,26 +54,31 @@ PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATUR
setStream(stream); setStream(stream);
} }
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client) { PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client)
{
this->_state = MQTT_DISCONNECTED; this->_state = MQTT_DISCONNECTED;
setServer(ip, port); setServer(ip, port);
setClient(client); setClient(client);
this->stream = NULL; this->stream = NULL;
} }
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client, Stream& stream) { PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client, Stream& stream)
{
this->_state = MQTT_DISCONNECTED; this->_state = MQTT_DISCONNECTED;
setServer(ip,port); setServer(ip,port);
setClient(client); setClient(client);
setStream(stream); setStream(stream);
} }
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client)
{
this->_state = MQTT_DISCONNECTED; this->_state = MQTT_DISCONNECTED;
setServer(ip, port); setServer(ip, port);
setCallback(callback); setCallback(callback);
setClient(client); setClient(client);
this->stream = NULL; this->stream = NULL;
} }
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client,
Stream& stream)
{
this->_state = MQTT_DISCONNECTED; this->_state = MQTT_DISCONNECTED;
setServer(ip,port); setServer(ip,port);
setCallback(callback); setCallback(callback);
@@ -74,26 +86,32 @@ PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE,
setStream(stream); setStream(stream);
} }
PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client) { PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client)
{
this->_state = MQTT_DISCONNECTED; this->_state = MQTT_DISCONNECTED;
setServer(domain,port); setServer(domain,port);
setClient(client); setClient(client);
this->stream = NULL; this->stream = NULL;
} }
PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client, Stream& stream) { PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client, Stream& stream)
{
this->_state = MQTT_DISCONNECTED; this->_state = MQTT_DISCONNECTED;
setServer(domain,port); setServer(domain,port);
setClient(client); setClient(client);
setStream(stream); setStream(stream);
} }
PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE,
Client& client)
{
this->_state = MQTT_DISCONNECTED; this->_state = MQTT_DISCONNECTED;
setServer(domain,port); setServer(domain,port);
setCallback(callback); setCallback(callback);
setClient(client); setClient(client);
this->stream = NULL; this->stream = NULL;
} }
PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE,
Client& client, Stream& stream)
{
this->_state = MQTT_DISCONNECTED; this->_state = MQTT_DISCONNECTED;
setServer(domain,port); setServer(domain,port);
setCallback(callback); setCallback(callback);
@@ -101,19 +119,25 @@ PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGN
setStream(stream); setStream(stream);
} }
boolean PubSubClient::connect(const char *id) { boolean PubSubClient::connect(const char *id)
{
return connect(id,NULL,NULL,0,0,0,0); return connect(id,NULL,NULL,0,0,0,0);
} }
boolean PubSubClient::connect(const char *id, const char *user, const char *pass) { boolean PubSubClient::connect(const char *id, const char *user, const char *pass)
{
return connect(id,user,pass,0,0,0,0); return connect(id,user,pass,0,0,0,0);
} }
boolean PubSubClient::connect(const char *id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) { boolean PubSubClient::connect(const char *id, const char* willTopic, uint8_t willQos,
boolean willRetain, const char* willMessage)
{
return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage); return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage);
} }
boolean PubSubClient::connect(const char *id, const char *user, const char *pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) { boolean PubSubClient::connect(const char *id, const char *user, const char *pass,
const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage)
{
if (!connected()) { if (!connected()) {
int result = 0; int result = 0;
@@ -206,7 +230,8 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass
} }
// reads a byte into result // reads a byte into result
boolean PubSubClient::readByte(uint8_t * result) { boolean PubSubClient::readByte(uint8_t * result)
{
uint32_t previousMillis = millis(); uint32_t previousMillis = millis();
while(!_client->available()) { while(!_client->available()) {
uint32_t currentMillis = millis(); uint32_t currentMillis = millis();
@@ -219,7 +244,8 @@ boolean PubSubClient::readByte(uint8_t * result) {
} }
// reads a byte into result[*index] and increments index // reads a byte into result[*index] and increments index
boolean PubSubClient::readByte(uint8_t * result, uint16_t * index){ boolean PubSubClient::readByte(uint8_t * result, uint16_t * index)
{
uint16_t current_index = *index; uint16_t current_index = *index;
uint8_t * write_address = &(result[current_index]); uint8_t * write_address = &(result[current_index]);
if(readByte(write_address)) { if(readByte(write_address)) {
@@ -229,7 +255,8 @@ boolean PubSubClient::readByte(uint8_t * result, uint16_t * index){
return false; return false;
} }
uint16_t PubSubClient::readPacket(uint8_t* lengthLength) { uint16_t PubSubClient::readPacket(uint8_t* lengthLength)
{
uint16_t len = 0; uint16_t len = 0;
if(!readByte(buffer, &len)) { if(!readByte(buffer, &len)) {
return 0; return 0;
@@ -289,7 +316,8 @@ uint16_t PubSubClient::readPacket(uint8_t* lengthLength) {
return len; return len;
} }
boolean PubSubClient::loop() { boolean PubSubClient::loop()
{
if (connected()) { if (connected()) {
unsigned long t = millis(); unsigned long t = millis();
if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) { if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) {
@@ -354,19 +382,24 @@ boolean PubSubClient::loop() {
return false; return false;
} }
boolean PubSubClient::publish(const char* topic, const char* payload) { boolean PubSubClient::publish(const char* topic, const char* payload)
{
return publish(topic,(const uint8_t*)payload,strlen(payload),false); return publish(topic,(const uint8_t*)payload,strlen(payload),false);
} }
boolean PubSubClient::publish(const char* topic, const char* payload, boolean retained) { boolean PubSubClient::publish(const char* topic, const char* payload, boolean retained)
{
return publish(topic,(const uint8_t*)payload,strlen(payload),retained); return publish(topic,(const uint8_t*)payload,strlen(payload),retained);
} }
boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength) { boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength)
{
return publish(topic, payload, plength, false); return publish(topic, payload, plength, false);
} }
boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) { boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength,
boolean retained)
{
if (connected()) { if (connected()) {
if (MQTT_MAX_PACKET_SIZE < 5 + 2+strlen(topic) + plength) { if (MQTT_MAX_PACKET_SIZE < 5 + 2+strlen(topic) + plength) {
// Too long // Too long
@@ -388,7 +421,9 @@ boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigne
return false; return false;
} }
boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) { boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsigned int plength,
boolean retained)
{
uint8_t llen = 0; uint8_t llen = 0;
uint8_t digit; uint8_t digit;
unsigned int rc = 0; unsigned int rc = 0;
@@ -433,7 +468,8 @@ boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsig
return rc == tlen + 4 + plength; return rc == tlen + 4 + plength;
} }
boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) { boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length)
{
uint8_t lenBuf[4]; uint8_t lenBuf[4];
uint8_t llen = 0; uint8_t llen = 0;
uint8_t digit; uint8_t digit;
@@ -475,11 +511,13 @@ boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) {
#endif #endif
} }
boolean PubSubClient::subscribe(const char* topic) { boolean PubSubClient::subscribe(const char* topic)
{
return subscribe(topic, 0); return subscribe(topic, 0);
} }
boolean PubSubClient::subscribe(const char* topic, uint8_t qos) { boolean PubSubClient::subscribe(const char* topic, uint8_t qos)
{
// original: if (qos < 0 || qos > 1) { (qos is uint8_t, hence qos < 0 impossible, tekka) // original: if (qos < 0 || qos > 1) { (qos is uint8_t, hence qos < 0 impossible, tekka)
if (qos > 1) { if (qos > 1) {
return false; return false;
@@ -504,7 +542,8 @@ boolean PubSubClient::subscribe(const char* topic, uint8_t qos) {
return false; return false;
} }
boolean PubSubClient::unsubscribe(const char* topic) { boolean PubSubClient::unsubscribe(const char* topic)
{
if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) {
// Too long // Too long
return false; return false;
@@ -523,7 +562,8 @@ boolean PubSubClient::unsubscribe(const char* topic) {
return false; return false;
} }
void PubSubClient::disconnect() { void PubSubClient::disconnect()
{
buffer[0] = MQTTDISCONNECT; buffer[0] = MQTTDISCONNECT;
buffer[1] = 0; buffer[1] = 0;
_client->write(buffer,2); _client->write(buffer,2);
@@ -532,7 +572,8 @@ void PubSubClient::disconnect() {
lastInActivity = lastOutActivity = millis(); lastInActivity = lastOutActivity = millis();
} }
uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t pos) { uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t pos)
{
const char* idp = string; const char* idp = string;
uint16_t i = 0; uint16_t i = 0;
pos += 2; pos += 2;
@@ -546,7 +587,8 @@ uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t po
} }
boolean PubSubClient::connected() { boolean PubSubClient::connected()
{
boolean rc; boolean rc;
if (_client == NULL ) { if (_client == NULL ) {
rc = false; rc = false;
@@ -563,39 +605,46 @@ boolean PubSubClient::connected() {
return rc; return rc;
} }
PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port) { PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port)
{
IPAddress addr(ip[0],ip[1],ip[2],ip[3]); IPAddress addr(ip[0],ip[1],ip[2],ip[3]);
return setServer(addr,port); return setServer(addr,port);
} }
PubSubClient& PubSubClient::setServer(IPAddress ip, uint16_t port) { PubSubClient& PubSubClient::setServer(IPAddress ip, uint16_t port)
{
this->ip = ip; this->ip = ip;
this->port = port; this->port = port;
this->domain = NULL; this->domain = NULL;
return *this; return *this;
} }
PubSubClient& PubSubClient::setServer(const char * domain, uint16_t port) { PubSubClient& PubSubClient::setServer(const char * domain, uint16_t port)
{
this->domain = domain; this->domain = domain;
this->port = port; this->port = port;
return *this; return *this;
} }
PubSubClient& PubSubClient::setCallback(MQTT_CALLBACK_SIGNATURE) { PubSubClient& PubSubClient::setCallback(MQTT_CALLBACK_SIGNATURE)
{
this->callback = callback; this->callback = callback;
return *this; return *this;
} }
PubSubClient& PubSubClient::setClient(Client& client){ PubSubClient& PubSubClient::setClient(Client& client)
{
this->_client = &client; this->_client = &client;
return *this; return *this;
} }
PubSubClient& PubSubClient::setStream(Stream& stream){ PubSubClient& PubSubClient::setStream(Stream& stream)
{
this->stream = &stream; this->stream = &stream;
return *this; return *this;
} }
int PubSubClient::state() { int PubSubClient::state()
{
return this->_state; return this->_state;
} }
+16 -8
View File
@@ -81,7 +81,8 @@
#endif #endif
/** PubSubClient class */ /** PubSubClient class */
class PubSubClient { class PubSubClient
{
private: private:
Client* _client; Client* _client;
uint8_t buffer[MQTT_MAX_PACKET_SIZE]; uint8_t buffer[MQTT_MAX_PACKET_SIZE];
@@ -106,15 +107,18 @@ public:
PubSubClient(IPAddress, uint16_t, Client& client); //!< PubSubClient PubSubClient(IPAddress, uint16_t, Client& client); //!< PubSubClient
PubSubClient(IPAddress, uint16_t, Client& client, Stream&); //!< PubSubClient PubSubClient(IPAddress, uint16_t, Client& client, Stream&); //!< PubSubClient
PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient
PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); //!< PubSubClient PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client,
Stream&); //!< PubSubClient
PubSubClient(uint8_t *, uint16_t, Client& client); //!< PubSubClient PubSubClient(uint8_t *, uint16_t, Client& client); //!< PubSubClient
PubSubClient(uint8_t *, uint16_t, Client& client, Stream&); //!< PubSubClient PubSubClient(uint8_t *, uint16_t, Client& client, Stream&); //!< PubSubClient
PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient
PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); //!< PubSubClient PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client,
Stream&); //!< PubSubClient
PubSubClient(const char*, uint16_t, Client& client); //!< PubSubClient PubSubClient(const char*, uint16_t, Client& client); //!< PubSubClient
PubSubClient(const char*, uint16_t, Client& client, Stream&); //!< PubSubClient PubSubClient(const char*, uint16_t, Client& client, Stream&); //!< PubSubClient
PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient
PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); //!< PubSubClient PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client,
Stream&); //!< PubSubClient
PubSubClient& setServer(IPAddress ip, uint16_t port); //!< setServer PubSubClient& setServer(IPAddress ip, uint16_t port); //!< setServer
PubSubClient& setServer(uint8_t * ip, uint16_t port); //!< setServer PubSubClient& setServer(uint8_t * ip, uint16_t port); //!< setServer
@@ -125,14 +129,18 @@ public:
boolean connect(const char* id); //!< connect boolean connect(const char* id); //!< connect
boolean connect(const char* id, const char* user, const char* pass); //!< connect boolean connect(const char* id, const char* user, const char* pass); //!< connect
boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); //!< connect boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain,
boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); //!< connect const char* willMessage); //!< connect
boolean connect(const char* id, const char* user, const char* pass, const char* willTopic,
uint8_t willQos, boolean willRetain, const char* willMessage); //!< connect
void disconnect(); //!< disconnect void disconnect(); //!< disconnect
boolean publish(const char* topic, const char* payload); //!< publish boolean publish(const char* topic, const char* payload); //!< publish
boolean publish(const char* topic, const char* payload, boolean retained); //!< publish boolean publish(const char* topic, const char* payload, boolean retained); //!< publish
boolean publish(const char* topic, const uint8_t * payload, unsigned int plength); //!< publish boolean publish(const char* topic, const uint8_t * payload, unsigned int plength); //!< publish
boolean publish(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained); //!< publish boolean publish(const char* topic, const uint8_t * payload, unsigned int plength,
boolean publish_P(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained); //!< publish_P boolean retained); //!< publish
boolean publish_P(const char* topic, const uint8_t * payload, unsigned int plength,
boolean retained); //!< publish_P
boolean subscribe(const char* topic); //!< subscribe boolean subscribe(const char* topic); //!< subscribe
boolean subscribe(const char* topic, uint8_t qos); //!< subscribe boolean subscribe(const char* topic, uint8_t qos); //!< subscribe
boolean unsubscribe(const char* topic); //!< unsubscribe boolean unsubscribe(const char* topic); //!< unsubscribe
+10 -5
View File
@@ -44,12 +44,14 @@ LOCAL void RF24_ce(const bool level)
hwDigitalWrite(MY_RF24_CE_PIN, level); hwDigitalWrite(MY_RF24_CE_PIN, level);
} }
LOCAL uint8_t RF24_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_t len, const bool aReadMode) LOCAL uint8_t RF24_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_t len,
const bool aReadMode)
{ {
uint8_t status; uint8_t status;
uint8_t* current = buf; uint8_t* current = buf;
#if !defined(MY_SOFTSPI) #if !defined(MY_SOFTSPI)
_SPI.beginTransaction(SPISettings(MY_RF24_SPI_MAX_SPEED, MY_RF24_SPI_DATA_ORDER, MY_RF24_SPI_DATA_MODE)); _SPI.beginTransaction(SPISettings(MY_RF24_SPI_MAX_SPEED, MY_RF24_SPI_DATA_ORDER,
MY_RF24_SPI_DATA_MODE));
#endif #endif
RF24_csn(LOW); RF24_csn(LOW);
// timing // timing
@@ -261,7 +263,8 @@ LOCAL bool RF24_sendMessage(const uint8_t recipient, const void* buf, const uint
RF24_flushTX(); RF24_flushTX();
// this command is affected in clones (e.g. Si24R1): flipped NoACK bit when using W_TX_PAYLOAD_NO_ACK / W_TX_PAYLOAD // this command is affected in clones (e.g. Si24R1): flipped NoACK bit when using W_TX_PAYLOAD_NO_ACK / W_TX_PAYLOAD
// AutoACK is disabled on the broadcasting pipe - NO_ACK prevents resending // AutoACK is disabled on the broadcasting pipe - NO_ACK prevents resending
RF24_spiMultiByteTransfer(recipient == BROADCAST_ADDRESS ? RF24_WRITE_TX_PAYLOAD_NO_ACK : RF24_WRITE_TX_PAYLOAD, (uint8_t*)buf, len, false ); RF24_spiMultiByteTransfer(recipient == BROADCAST_ADDRESS ? RF24_WRITE_TX_PAYLOAD_NO_ACK :
RF24_WRITE_TX_PAYLOAD, (uint8_t*)buf, len, false );
// go, TX starts after ~10us // go, TX starts after ~10us
RF24_ce(HIGH); RF24_ce(HIGH);
// timeout counter to detect HW issues // timeout counter to detect HW issues
@@ -331,7 +334,8 @@ LOCAL uint8_t RF24_getNodeID(void)
LOCAL bool RF24_sanityCheck(void) LOCAL bool RF24_sanityCheck(void)
{ {
// detect HW defect, configuration errors or interrupted SPI line, CE disconnect cannot be detected // detect HW defect, configuration errors or interrupted SPI line, CE disconnect cannot be detected
return (RF24_readByteRegister(RF24_RF_SETUP) == MY_RF24_RF_SETUP) & (RF24_readByteRegister(RF24_RF_CH) == MY_RF24_CHANNEL); return (RF24_readByteRegister(RF24_RF_SETUP) == MY_RF24_RF_SETUP) & (RF24_readByteRegister(
RF24_RF_CH) == MY_RF24_CHANNEL);
} }
#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) #if defined(MY_RX_MESSAGE_BUFFER_FEATURE)
@@ -427,7 +431,8 @@ LOCAL bool RF24_initialize(void)
RF24_setDynamicPayload(_BV(RF24_DPL_P0 + RF24_BROADCAST_PIPE) | _BV(RF24_DPL_P0)); RF24_setDynamicPayload(_BV(RF24_DPL_P0 + RF24_BROADCAST_PIPE) | _BV(RF24_DPL_P0));
// listen to broadcast pipe // listen to broadcast pipe
MY_RF24_BASE_ADDR[0] = BROADCAST_ADDRESS; MY_RF24_BASE_ADDR[0] = BROADCAST_ADDRESS;
RF24_setPipeAddress(RF24_RX_ADDR_P0 + RF24_BROADCAST_PIPE, (uint8_t*)&MY_RF24_BASE_ADDR, RF24_BROADCAST_PIPE > 1 ? 1 : MY_RF24_ADDR_WIDTH); RF24_setPipeAddress(RF24_RX_ADDR_P0 + RF24_BROADCAST_PIPE, (uint8_t*)&MY_RF24_BASE_ADDR,
RF24_BROADCAST_PIPE > 1 ? 1 : MY_RF24_ADDR_WIDTH);
// pipe 0, set full address, later only LSB is updated // pipe 0, set full address, later only LSB is updated
RF24_setPipeAddress(RF24_RX_ADDR_P0, (uint8_t*)&MY_RF24_BASE_ADDR, MY_RF24_ADDR_WIDTH); RF24_setPipeAddress(RF24_RX_ADDR_P0, (uint8_t*)&MY_RF24_BASE_ADDR, MY_RF24_ADDR_WIDTH);
RF24_setPipeAddress(RF24_TX_ADDR, (uint8_t*)&MY_RF24_BASE_ADDR, MY_RF24_ADDR_WIDTH); RF24_setPipeAddress(RF24_TX_ADDR, (uint8_t*)&MY_RF24_BASE_ADDR, MY_RF24_ADDR_WIDTH);
+4 -2
View File
@@ -36,7 +36,8 @@
#if defined (ARDUINO) && !defined (__arm__) && !defined (_SPI) #if defined (ARDUINO) && !defined (__arm__) && !defined (_SPI)
#include <SPI.h> #include <SPI.h>
#if defined(MY_SOFTSPI) #if defined(MY_SOFTSPI)
SoftSPI<MY_SOFT_SPI_MISO_PIN, MY_SOFT_SPI_MOSI_PIN, MY_SOFT_SPI_SCK_PIN, MY_RF24_SPI_DATA_MODE> _SPI; SoftSPI<MY_SOFT_SPI_MISO_PIN, MY_SOFT_SPI_MOSI_PIN, MY_SOFT_SPI_SCK_PIN, MY_RF24_SPI_DATA_MODE>
_SPI;
#else #else
#define _SPI SPI #define _SPI SPI
#endif #endif
@@ -234,7 +235,8 @@
LOCAL void RF24_csn(const bool level); LOCAL void RF24_csn(const bool level);
LOCAL void RF24_ce(const bool level); LOCAL void RF24_ce(const bool level);
LOCAL uint8_t RF24_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, const uint8_t len, const bool aReadMode); LOCAL uint8_t RF24_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, const uint8_t len,
const bool aReadMode);
LOCAL uint8_t RF24_spiByteTransfer(const uint8_t cmd); LOCAL uint8_t RF24_spiByteTransfer(const uint8_t cmd);
LOCAL uint8_t RF24_RAW_readByteRegister(const uint8_t cmd); LOCAL uint8_t RF24_RAW_readByteRegister(const uint8_t cmd);
LOCAL uint8_t RF24_RAW_writeByteRegister(const uint8_t cmd, const uint8_t value); LOCAL uint8_t RF24_RAW_writeByteRegister(const uint8_t cmd, const uint8_t value);
+91 -68
View File
@@ -39,14 +39,15 @@ volatile uint8_t RFM69::SENDERID;
volatile uint8_t RFM69::TARGETID; // should match _address volatile uint8_t RFM69::TARGETID; // should match _address
volatile uint8_t RFM69::PAYLOADLEN; volatile uint8_t RFM69::PAYLOADLEN;
volatile uint8_t RFM69::ACK_REQUESTED; volatile uint8_t RFM69::ACK_REQUESTED;
volatile uint8_t RFM69::ACK_RECEIVED; // should be polled immediately after sending a packet with ACK request volatile uint8_t
volatile int16_t RFM69::RSSI; // most accurate RSSI during reception (closest to the reception) RFM69::ACK_RECEIVED; // should be polled immediately after sending a packet with ACK request
volatile int16_t
RFM69::RSSI; // most accurate RSSI during reception (closest to the reception)
RFM69* RFM69::selfPointer; RFM69* RFM69::selfPointer;
bool RFM69::initialize(uint8_t freqBand, uint8_t nodeID, uint8_t networkID) bool RFM69::initialize(uint8_t freqBand, uint8_t nodeID, uint8_t networkID)
{ {
const uint8_t CONFIG[][2] = const uint8_t CONFIG[][2] = {
{
/* 0x01 */ { REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF | RF_OPMODE_STANDBY }, /* 0x01 */ { REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF | RF_OPMODE_STANDBY },
/* 0x02 */ { REG_DATAMODUL, RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_00 }, // no shaping /* 0x02 */ { REG_DATAMODUL, RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_00 }, // no shaping
/* 0x03 */ { REG_BITRATEMSB, RF_BITRATEMSB_55555}, // default: 4.8 KBPS /* 0x03 */ { REG_BITRATEMSB, RF_BITRATEMSB_55555}, // default: 4.8 KBPS
@@ -129,7 +130,8 @@ bool RFM69::initialize(uint8_t freqBand, uint8_t nodeID, uint8_t networkID)
// return the frequency (in Hz) // return the frequency (in Hz)
uint32_t RFM69::getFrequency() uint32_t RFM69::getFrequency()
{ {
return RF69_FSTEP * (((uint32_t) readReg(REG_FRFMSB) << 16) + ((uint16_t) readReg(REG_FRFMID) << 8) + readReg(REG_FRFLSB)); return RF69_FSTEP * (((uint32_t) readReg(REG_FRFMSB) << 16) + ((uint16_t) readReg(
REG_FRFMID) << 8) + readReg(REG_FRFLSB));
} }
// set the frequency (in Hz) // set the frequency (in Hz)
@@ -183,13 +185,15 @@ void RFM69::setMode(uint8_t newMode)
// we are using packet mode, so this check is not really needed // we are using packet mode, so this check is not really needed
// but waiting for mode ready is necessary when going from sleep because the FIFO may not be immediately available from previous mode // but waiting for mode ready is necessary when going from sleep because the FIFO may not be immediately available from previous mode
while (_mode == RF69_MODE_SLEEP && (readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // wait for ModeReady while (_mode == RF69_MODE_SLEEP &&
(readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // wait for ModeReady
_mode = newMode; _mode = newMode;
} }
//put transceiver in sleep mode to save battery - to wake or resume receiving just call receiveDone() //put transceiver in sleep mode to save battery - to wake or resume receiving just call receiveDone()
void RFM69::sleep() { void RFM69::sleep()
{
setMode(RF69_MODE_SLEEP); setMode(RF69_MODE_SLEEP);
} }
@@ -224,8 +228,8 @@ void RFM69::setPowerLevel(uint8_t powerLevel)
bool RFM69::canSend() bool RFM69::canSend()
{ {
if (_mode == RF69_MODE_RX && PAYLOADLEN == 0 && readRSSI() < CSMA_LIMIT) // if signal stronger than -100dBm is detected assume channel activity if (_mode == RF69_MODE_RX && PAYLOADLEN == 0 &&
{ readRSSI() < CSMA_LIMIT) { // if signal stronger than -100dBm is detected assume channel activity
setMode(RF69_MODE_STANDBY); setMode(RF69_MODE_STANDBY);
return true; return true;
} }
@@ -234,7 +238,8 @@ bool RFM69::canSend()
void RFM69::send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK) void RFM69::send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK)
{ {
writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART); // avoid RX deadlocks writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) |
RF_PACKET2_RXRESTART); // avoid RX deadlocks
uint32_t now = millis(); uint32_t now = millis();
while (!canSend() && millis() - now < RF69_CSMA_LIMIT_MS) { while (!canSend() && millis() - now < RF69_CSMA_LIMIT_MS) {
receiveDone(); receiveDone();
@@ -248,16 +253,15 @@ void RFM69::send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool
// The reason for the semi-automaton is that the lib is interrupt driven and // The reason for the semi-automaton is that the lib is interrupt driven and
// requires user action to read the received data and decide what to do with it // requires user action to read the received data and decide what to do with it
// replies usually take only 5..8ms at 50kbps@915MHz // replies usually take only 5..8ms at 50kbps@915MHz
bool RFM69::sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize, uint8_t retries, uint8_t retryWaitTime) { bool RFM69::sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize,
uint32_t sentTime; uint8_t retries, uint8_t retryWaitTime)
for (uint8_t i = 0; i <= retries; i++)
{ {
uint32_t sentTime;
for (uint8_t i = 0; i <= retries; i++) {
send(toAddress, buffer, bufferSize, true); send(toAddress, buffer, bufferSize, true);
sentTime = millis(); sentTime = millis();
while (millis() - sentTime < retryWaitTime) while (millis() - sentTime < retryWaitTime) {
{ if (ACKReceived(toAddress)) {
if (ACKReceived(toAddress))
{
//Serial.print(" ~ms:"); Serial.print(millis() - sentTime); //Serial.print(" ~ms:"); Serial.print(millis() - sentTime);
return true; return true;
} }
@@ -268,7 +272,8 @@ bool RFM69::sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferS
} }
// should be polled immediately after sending a packet with ACK request // should be polled immediately after sending a packet with ACK request
bool RFM69::ACKReceived(uint8_t fromNodeID) { bool RFM69::ACKReceived(uint8_t fromNodeID)
{
if (receiveDone()) { if (receiveDone()) {
return (SENDERID == fromNodeID || fromNodeID == RF69_BROADCAST_ADDR) && ACK_RECEIVED; return (SENDERID == fromNodeID || fromNodeID == RF69_BROADCAST_ADDR) && ACK_RECEIVED;
} }
@@ -276,16 +281,20 @@ bool RFM69::ACKReceived(uint8_t fromNodeID) {
} }
// check whether an ACK was requested in the last received packet (non-broadcasted packet) // check whether an ACK was requested in the last received packet (non-broadcasted packet)
bool RFM69::ACKRequested() { bool RFM69::ACKRequested()
{
return ACK_REQUESTED && (TARGETID != RF69_BROADCAST_ADDR); return ACK_REQUESTED && (TARGETID != RF69_BROADCAST_ADDR);
} }
// should be called immediately after reception in case sender wants ACK // should be called immediately after reception in case sender wants ACK
void RFM69::sendACK(const void* buffer, uint8_t bufferSize) { void RFM69::sendACK(const void* buffer, uint8_t bufferSize)
ACK_REQUESTED = 0; // TWS added to make sure we don't end up in a timing race and infinite loop sending Acks {
ACK_REQUESTED =
0; // TWS added to make sure we don't end up in a timing race and infinite loop sending Acks
uint8_t sender = SENDERID; uint8_t sender = SENDERID;
int16_t _RSSI = RSSI; // save payload received RSSI value int16_t _RSSI = RSSI; // save payload received RSSI value
writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART); // avoid RX deadlocks writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) |
RF_PACKET2_RXRESTART); // avoid RX deadlocks
uint32_t now = millis(); uint32_t now = millis();
while (!canSend() && millis() - now < RF69_CSMA_LIMIT_MS) { while (!canSend() && millis() - now < RF69_CSMA_LIMIT_MS) {
receiveDone(); receiveDone();
@@ -296,12 +305,14 @@ void RFM69::sendACK(const void* buffer, uint8_t bufferSize) {
RSSI = _RSSI; // restore payload RSSI RSSI = _RSSI; // restore payload RSSI
} }
void RFM69::interruptHook(uint8_t CTLbyte) { void RFM69::interruptHook(uint8_t CTLbyte)
{
(void)CTLbyte; (void)CTLbyte;
}; };
// internal function // internal function
void RFM69::sendFrame(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK, bool sendACK) void RFM69::sendFrame(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK,
bool sendACK)
{ {
setMode(RF69_MODE_STANDBY); // turn off receiver to prevent reception while filling fifo setMode(RF69_MODE_STANDBY); // turn off receiver to prevent reception while filling fifo
while ((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) {} // wait for ModeReady while ((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) {} // wait for ModeReady
@@ -314,8 +325,7 @@ void RFM69::sendFrame(uint8_t toAddress, const void* buffer, uint8_t bufferSize,
uint8_t CTLbyte = 0x00; uint8_t CTLbyte = 0x00;
if (sendACK) { if (sendACK) {
CTLbyte = RFM69_CTL_SENDACK; CTLbyte = RFM69_CTL_SENDACK;
} } else if (requestACK) {
else if (requestACK) {
CTLbyte = RFM69_CTL_REQACK; CTLbyte = RFM69_CTL_REQACK;
} }
@@ -335,17 +345,18 @@ void RFM69::sendFrame(uint8_t toAddress, const void* buffer, uint8_t bufferSize,
// no need to wait for transmit mode to be ready since its handled by the radio // no need to wait for transmit mode to be ready since its handled by the radio
setMode(RF69_MODE_TX); setMode(RF69_MODE_TX);
uint32_t txStart = millis(); uint32_t txStart = millis();
while (hwDigitalRead(_interruptPin) == 0 && millis() - txStart < RF69_TX_LIMIT_MS) {} // wait for DIO0 to turn HIGH signalling transmission finish while (hwDigitalRead(_interruptPin) == 0 &&
millis() - txStart < RF69_TX_LIMIT_MS) {} // wait for DIO0 to turn HIGH signalling transmission finish
//while (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PACKETSENT == 0x00); // wait for ModeReady //while (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PACKETSENT == 0x00); // wait for ModeReady
setMode(RF69_MODE_STANDBY); setMode(RF69_MODE_STANDBY);
} }
// internal function - interrupt gets called when a packet is received // internal function - interrupt gets called when a packet is received
void RFM69::interruptHandler() { void RFM69::interruptHandler()
{
//hwPinMode(4, OUTPUT); //hwPinMode(4, OUTPUT);
//hwDigitalWrite(4, 1); //hwDigitalWrite(4, 1);
if (_mode == RF69_MODE_RX && (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY)) if (_mode == RF69_MODE_RX && (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY)) {
{
//RSSI = readRSSI(); //RSSI = readRSSI();
setMode(RF69_MODE_STANDBY); setMode(RF69_MODE_STANDBY);
select(); select();
@@ -353,9 +364,10 @@ void RFM69::interruptHandler() {
PAYLOADLEN = SPI.transfer(0); PAYLOADLEN = SPI.transfer(0);
PAYLOADLEN = PAYLOADLEN > 66 ? 66 : PAYLOADLEN; // precaution PAYLOADLEN = PAYLOADLEN > 66 ? 66 : PAYLOADLEN; // precaution
TARGETID = SPI.transfer(0); TARGETID = SPI.transfer(0);
if(!(_promiscuousMode || TARGETID == _address || TARGETID == RF69_BROADCAST_ADDR) // match this node's address, or broadcast address or anything in promiscuous mode if(!(_promiscuousMode || TARGETID == _address ||
|| PAYLOADLEN < 3) // address situation could receive packets that are malformed and don't fit this libraries extra fields TARGETID == RF69_BROADCAST_ADDR) // match this node's address, or broadcast address or anything in promiscuous mode
{ || PAYLOADLEN <
3) { // address situation could receive packets that are malformed and don't fit this libraries extra fields
PAYLOADLEN = 0; PAYLOADLEN = 0;
unselect(); unselect();
receiveBegin(); receiveBegin();
@@ -372,8 +384,7 @@ void RFM69::interruptHandler() {
interruptHook(CTLbyte); // TWS: hook to derived class interrupt function interruptHook(CTLbyte); // TWS: hook to derived class interrupt function
for (uint8_t i = 0; i < DATALEN; i++) for (uint8_t i = 0; i < DATALEN; i++) {
{
DATA[i] = SPI.transfer(0); DATA[i] = SPI.transfer(0);
} }
if (DATALEN < RF69_MAX_DATA_LEN) { if (DATALEN < RF69_MAX_DATA_LEN) {
@@ -387,10 +398,14 @@ void RFM69::interruptHandler() {
} }
// internal function // internal function
void RFM69::isr0() { selfPointer->interruptHandler(); } void RFM69::isr0()
{
selfPointer->interruptHandler();
}
// internal function // internal function
void RFM69::receiveBegin() { void RFM69::receiveBegin()
{
DATALEN = 0; DATALEN = 0;
SENDERID = 0; SENDERID = 0;
TARGETID = 0; TARGETID = 0;
@@ -399,24 +414,23 @@ void RFM69::receiveBegin() {
ACK_RECEIVED = 0; ACK_RECEIVED = 0;
RSSI = 0; RSSI = 0;
if (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY) { if (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY) {
writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART); // avoid RX deadlocks writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) |
RF_PACKET2_RXRESTART); // avoid RX deadlocks
} }
writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01); // set DIO0 to "PAYLOADREADY" in receive mode writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01); // set DIO0 to "PAYLOADREADY" in receive mode
setMode(RF69_MODE_RX); setMode(RF69_MODE_RX);
} }
// checks if a packet was received and/or puts transceiver in receive (ie RX or listen) mode // checks if a packet was received and/or puts transceiver in receive (ie RX or listen) mode
bool RFM69::receiveDone() { bool RFM69::receiveDone()
{
//ATOMIC_BLOCK(ATOMIC_FORCEON) //ATOMIC_BLOCK(ATOMIC_FORCEON)
//{ //{
noInterrupts(); // re-enabled in unselect() via setMode() or via receiveBegin() noInterrupts(); // re-enabled in unselect() via setMode() or via receiveBegin()
if (_mode == RF69_MODE_RX && PAYLOADLEN > 0) if (_mode == RF69_MODE_RX && PAYLOADLEN > 0) {
{
setMode(RF69_MODE_STANDBY); // enables interrupts setMode(RF69_MODE_STANDBY); // enables interrupts
return true; return true;
} } else if (_mode == RF69_MODE_RX) { // already in RX no payload yet
else if (_mode == RF69_MODE_RX) // already in RX no payload yet
{
interrupts(); // explicitly re-enable interrupts interrupts(); // explicitly re-enable interrupts
return false; return false;
} }
@@ -428,10 +442,10 @@ bool RFM69::receiveDone() {
// To enable encryption: radio.encrypt("ABCDEFGHIJKLMNOP"); // To enable encryption: radio.encrypt("ABCDEFGHIJKLMNOP");
// To disable encryption: radio.encrypt(null) or radio.encrypt(0) // To disable encryption: radio.encrypt(null) or radio.encrypt(0)
// KEY HAS TO BE 16 bytes !!! // KEY HAS TO BE 16 bytes !!!
void RFM69::encrypt(const char* key) { void RFM69::encrypt(const char* key)
setMode(RF69_MODE_STANDBY);
if (key != 0)
{ {
setMode(RF69_MODE_STANDBY);
if (key != 0) {
select(); select();
SPI.transfer(REG_AESKEY1 | 0x80); SPI.transfer(REG_AESKEY1 | 0x80);
for (uint8_t i = 0; i < 16; i++) { for (uint8_t i = 0; i < 16; i++) {
@@ -443,10 +457,10 @@ void RFM69::encrypt(const char* key) {
} }
// get the received signal strength indicator (RSSI) // get the received signal strength indicator (RSSI)
int16_t RFM69::readRSSI(bool forceTrigger) { int16_t RFM69::readRSSI(bool forceTrigger)
int16_t rssi = 0;
if (forceTrigger)
{ {
int16_t rssi = 0;
if (forceTrigger) {
// RSSI trigger not needed if DAGC is in continuous mode // RSSI trigger not needed if DAGC is in continuous mode
writeReg(REG_RSSICONFIG, RF_RSSI_START); writeReg(REG_RSSICONFIG, RF_RSSI_START);
while ((readReg(REG_RSSICONFIG) & RF_RSSI_DONE) == 0x00) {} // wait for RSSI_Ready while ((readReg(REG_RSSICONFIG) & RF_RSSI_DONE) == 0x00) {} // wait for RSSI_Ready
@@ -474,7 +488,8 @@ void RFM69::writeReg(uint8_t addr, uint8_t value)
} }
// select the RFM69 transceiver (save SPI settings, set CS low) // select the RFM69 transceiver (save SPI settings, set CS low)
void RFM69::select() { void RFM69::select()
{
noInterrupts(); noInterrupts();
#if defined (SPCR) && defined (SPSR) #if defined (SPCR) && defined (SPSR)
// save current SPI settings // save current SPI settings
@@ -484,12 +499,14 @@ void RFM69::select() {
// set RFM69 SPI settings // set RFM69 SPI settings
SPI.setDataMode(SPI_MODE0); SPI.setDataMode(SPI_MODE0);
SPI.setBitOrder(MSBFIRST); SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV4); // decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present SPI.setClockDivider(
SPI_CLOCK_DIV4); // decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present
hwDigitalWrite(_slaveSelectPin, LOW); hwDigitalWrite(_slaveSelectPin, LOW);
} }
// unselect the RFM69 transceiver (set CS high, restore SPI settings) // unselect the RFM69 transceiver (set CS high, restore SPI settings)
void RFM69::unselect() { void RFM69::unselect()
{
hwDigitalWrite(_slaveSelectPin, HIGH); hwDigitalWrite(_slaveSelectPin, HIGH);
// restore SPI settings to what they were before talking to RFM69 // restore SPI settings to what they were before talking to RFM69
#if defined (SPCR) && defined (SPSR) #if defined (SPCR) && defined (SPSR)
@@ -501,31 +518,36 @@ void RFM69::unselect() {
// true = disable filtering to capture all frames on network // true = disable filtering to capture all frames on network
// false = enable node/broadcast filtering to capture only frames sent to this/broadcast address // false = enable node/broadcast filtering to capture only frames sent to this/broadcast address
void RFM69::promiscuous(bool onOff) { void RFM69::promiscuous(bool onOff)
{
_promiscuousMode = onOff; _promiscuousMode = onOff;
//writeReg(REG_PACKETCONFIG1, (readReg(REG_PACKETCONFIG1) & 0xF9) | (onOff ? RF_PACKET1_ADRSFILTERING_OFF : RF_PACKET1_ADRSFILTERING_NODEBROADCAST)); //writeReg(REG_PACKETCONFIG1, (readReg(REG_PACKETCONFIG1) & 0xF9) | (onOff ? RF_PACKET1_ADRSFILTERING_OFF : RF_PACKET1_ADRSFILTERING_NODEBROADCAST));
} }
// for RFM69HW only: you must call setHighPower(true) after initialize() or else transmission won't work // for RFM69HW only: you must call setHighPower(true) after initialize() or else transmission won't work
void RFM69::setHighPower(bool onOff) { void RFM69::setHighPower(bool onOff)
{
_isRFM69HW = onOff; _isRFM69HW = onOff;
writeReg(REG_OCP, _isRFM69HW ? RF_OCP_OFF : RF_OCP_ON); writeReg(REG_OCP, _isRFM69HW ? RF_OCP_OFF : RF_OCP_ON);
if (_isRFM69HW) { // turning ON if (_isRFM69HW) { // turning ON
writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0x1F) | RF_PALEVEL_PA1_ON | RF_PALEVEL_PA2_ON); // enable P1 & P2 amplifier stages writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0x1F) | RF_PALEVEL_PA1_ON |
} RF_PALEVEL_PA2_ON); // enable P1 & P2 amplifier stages
else { } else {
writeReg(REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | _powerLevel); // enable P0 only writeReg(REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF |
_powerLevel); // enable P0 only
} }
} }
// internal function // internal function
void RFM69::setHighPowerRegs(bool onOff) { void RFM69::setHighPowerRegs(bool onOff)
{
writeReg(REG_TESTPA1, onOff ? 0x5D : 0x55); writeReg(REG_TESTPA1, onOff ? 0x5D : 0x55);
writeReg(REG_TESTPA2, onOff ? 0x7C : 0x70); writeReg(REG_TESTPA2, onOff ? 0x7C : 0x70);
} }
// set the slave select (CS) pin // set the slave select (CS) pin
void RFM69::setCS(uint8_t newSPISlaveSelect) { void RFM69::setCS(uint8_t newSPISlaveSelect)
{
_slaveSelectPin = newSPISlaveSelect; _slaveSelectPin = newSPISlaveSelect;
hwDigitalWrite(_slaveSelectPin, HIGH); hwDigitalWrite(_slaveSelectPin, HIGH);
hwPinMode(_slaveSelectPin, OUTPUT); hwPinMode(_slaveSelectPin, OUTPUT);
@@ -537,11 +559,13 @@ void RFM69::setCS(uint8_t newSPISlaveSelect) {
// SERIAL PRINT // SERIAL PRINT
// replace Serial.print("string") with SerialPrint("string") // replace Serial.print("string") with SerialPrint("string")
#define SerialPrint(x) SerialPrint_P(PSTR(x)) #define SerialPrint(x) SerialPrint_P(PSTR(x))
void SerialWrite ( uint8_t c ) { void SerialWrite ( uint8_t c )
{
Serial.write ( c ); Serial.write ( c );
} }
void SerialPrint_P(PGM_P str, void (*f)(uint8_t) = SerialWrite ) { void SerialPrint_P(PGM_P str, void (*f)(uint8_t) = SerialWrite )
{
for (uint8_t c; (c = pgm_read_byte(str)); str++) { for (uint8_t c; (c = pgm_read_byte(str)); str++) {
(*f)(c); (*f)(c);
} }
@@ -563,8 +587,7 @@ void RFM69::readAllRegs()
#endif #endif
Serial.println("Address - HEX - BIN"); Serial.println("Address - HEX - BIN");
for (uint8_t regAddr = 1; regAddr <= 0x4F; regAddr++) for (uint8_t regAddr = 1; regAddr <= 0x4F; regAddr++) {
{
select(); select();
SPI.transfer(regAddr & 0x7F); // send address + r/w bit SPI.transfer(regAddr & 0x7F); // send address + r/w bit
regVal = SPI.transfer(0); regVal = SPI.transfer(0);
@@ -577,8 +600,7 @@ void RFM69::readAllRegs()
Serial.println(regVal,BIN); Serial.println(regVal,BIN);
#if REGISTER_DETAIL #if REGISTER_DETAIL
switch ( regAddr ) switch ( regAddr ) {
{
case 0x1 : { case 0x1 : {
SerialPrint ( "Controls the automatic Sequencer ( see section 4.2 )\nSequencerOff : " ); SerialPrint ( "Controls the automatic Sequencer ( see section 4.2 )\nSequencerOff : " );
if ( 0x80 & regVal ) { if ( 0x80 & regVal ) {
@@ -820,7 +842,8 @@ uint8_t RFM69::readTemperature(uint8_t calFactor) // returns centigrade
setMode(RF69_MODE_STANDBY); setMode(RF69_MODE_STANDBY);
writeReg(REG_TEMP1, RF_TEMP1_MEAS_START); writeReg(REG_TEMP1, RF_TEMP1_MEAS_START);
while ((readReg(REG_TEMP1) & RF_TEMP1_MEAS_RUNNING)) {} while ((readReg(REG_TEMP1) & RF_TEMP1_MEAS_RUNNING)) {}
return ~readReg(REG_TEMP2) + COURSE_TEMP_COEF + calFactor; // 'complement' corrects the slope, rising temp = rising val return ~readReg(REG_TEMP2) + COURSE_TEMP_COEF +
calFactor; // 'complement' corrects the slope, rising temp = rising val
} // COURSE_TEMP_COEF puts reading in the ballpark, user can add additional correction } // COURSE_TEMP_COEF puts reading in the ballpark, user can add additional correction
void RFM69::rcCalibration() void RFM69::rcCalibration()
+24 -7
View File
@@ -79,7 +79,8 @@
#define RFM69_CTL_REQACK 0x40 #define RFM69_CTL_REQACK 0x40
/** RFM69 class */ /** RFM69 class */
class RFM69 { class RFM69
{
public: public:
static volatile uint8_t DATA[RF69_MAX_DATA_LEN]; //!< recv/xmit buf, including hdr & crc bytes static volatile uint8_t DATA[RF69_MAX_DATA_LEN]; //!< recv/xmit buf, including hdr & crc bytes
static volatile uint8_t DATALEN; //!< DATALEN static volatile uint8_t DATALEN; //!< DATALEN
@@ -87,11 +88,22 @@ class RFM69 {
static volatile uint8_t TARGETID; //!< should match _address static volatile uint8_t TARGETID; //!< should match _address
static volatile uint8_t PAYLOADLEN; //!< PAYLOADLEN static volatile uint8_t PAYLOADLEN; //!< PAYLOADLEN
static volatile uint8_t ACK_REQUESTED; //!< ACK_REQUESTED static volatile uint8_t ACK_REQUESTED; //!< ACK_REQUESTED
static volatile uint8_t ACK_RECEIVED; //!< Should be polled immediately after sending a packet with ACK requestwith ACK request static volatile uint8_t
ACK_RECEIVED; //!< Should be polled immediately after sending a packet with ACK requestwith ACK request
static volatile int16_t RSSI; //!< most accurate RSSI during reception (closest to the reception) static volatile int16_t RSSI; //!< most accurate RSSI during reception (closest to the reception)
static volatile uint8_t _mode; //!< should be protected? static volatile uint8_t _mode; //!< should be protected?
RFM69(uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false, uint8_t interruptNum=RF69_IRQ_NUM) { //!< Constructor /**
* @brief Constructor
*
* @param slaveSelectPin ChipSelect pin.
* @param interruptPin Interrupt pin.
* @param isRFM69HW Set to @c true to indicate RFM69HW variant.
* @param interruptNum Interrupt number.
*/
RFM69(uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false,
uint8_t interruptNum=RF69_IRQ_NUM)
{
_slaveSelectPin = slaveSelectPin; _slaveSelectPin = slaveSelectPin;
_interruptPin = interruptPin; _interruptPin = interruptPin;
_interruptNum = interruptNum; _interruptNum = interruptNum;
@@ -105,8 +117,11 @@ class RFM69 {
void setAddress(uint8_t addr); //!< setAddress void setAddress(uint8_t addr); //!< setAddress
void setNetwork(uint8_t networkID); //!< setNetwork void setNetwork(uint8_t networkID); //!< setNetwork
bool canSend(); //!< canSend bool canSend(); //!< canSend
virtual void send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK=false); //!< send virtual void send(uint8_t toAddress, const void* buffer, uint8_t bufferSize,
virtual bool sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize, uint8_t retries=2, uint8_t retryWaitTime=40); //!< sendWithRetry (40ms roundtrip req for 61byte packets) bool requestACK=false); //!< send
virtual bool sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize,
uint8_t retries=2, uint8_t retryWaitTime=
40); //!< sendWithRetry (40ms roundtrip req for 61byte packets)
virtual bool receiveDone(); //!< receiveDone virtual bool receiveDone(); //!< receiveDone
bool ACKReceived(uint8_t fromNodeID); //!< ACKReceived bool ACKReceived(uint8_t fromNodeID); //!< ACKReceived
bool ACKRequested(); //!< ACKRequested bool ACKRequested(); //!< ACKRequested
@@ -117,7 +132,8 @@ class RFM69 {
void setCS(uint8_t newSPISlaveSelect); //!< setCS void setCS(uint8_t newSPISlaveSelect); //!< setCS
int16_t readRSSI(bool forceTrigger=false); //!< readRSSI int16_t readRSSI(bool forceTrigger=false); //!< readRSSI
void promiscuous(bool onOff=true); //!< promiscuous void promiscuous(bool onOff=true); //!< promiscuous
virtual void setHighPower(bool onOFF=true); //!< setHighPower (have to call it after initialize for RFM69HW) virtual void setHighPower(bool onOFF=
true); //!< setHighPower (have to call it after initialize for RFM69HW)
virtual void setPowerLevel(uint8_t level); //!< setPowerLevel (reduce/increase transmit power level) virtual void setPowerLevel(uint8_t level); //!< setPowerLevel (reduce/increase transmit power level)
void sleep(); //!< sleep void sleep(); //!< sleep
uint8_t readTemperature(uint8_t calFactor=0); //!< readTemperature (get CMOS temperature (8bit)) uint8_t readTemperature(uint8_t calFactor=0); //!< readTemperature (get CMOS temperature (8bit))
@@ -132,7 +148,8 @@ class RFM69 {
static void isr0(); //!< isr0 static void isr0(); //!< isr0
void virtual interruptHandler(); //!< interruptHandler void virtual interruptHandler(); //!< interruptHandler
virtual void interruptHook(uint8_t CTLbyte); //!< interruptHook virtual void interruptHook(uint8_t CTLbyte); //!< interruptHook
virtual void sendFrame(uint8_t toAddress, const void* buffer, uint8_t size, bool requestACK=false, bool sendACK=false); //!< sendFrame virtual void sendFrame(uint8_t toAddress, const void* buffer, uint8_t size, bool requestACK=false,
bool sendACK=false); //!< sendFrame
static RFM69* selfPointer; //!< selfPointer static RFM69* selfPointer; //!< selfPointer
uint8_t _slaveSelectPin; //!< _slaveSelectPin uint8_t _slaveSelectPin; //!< _slaveSelectPin
+90 -63
View File
@@ -26,18 +26,23 @@
#if defined(LINUX_ARCH_RASPBERRYPI) #if defined(LINUX_ARCH_RASPBERRYPI)
uint8_t spi_rxbuff[32 + 1]; //SPI receive buffer (payload max 32 bytes, MYS protocol limitation) uint8_t spi_rxbuff[32 + 1]; //SPI receive buffer (payload max 32 bytes, MYS protocol limitation)
uint8_t spi_txbuff[32 + 1]; //SPI transmit buffer (payload max 32 bytes + 1 byte for the command, MYS protocol limitation) uint8_t spi_txbuff[32 +
1]; //SPI transmit buffer (payload max 32 bytes + 1 byte for the command, MYS protocol limitation)
#endif #endif
LOCAL void RFM95_csn(const bool level) { LOCAL void RFM95_csn(const bool level)
{
hwDigitalWrite(MY_RFM95_SPI_CS, level); hwDigitalWrite(MY_RFM95_SPI_CS, level);
} }
LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_t len, const bool aReadMode) { LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_t len,
const bool aReadMode)
{
uint8_t status; uint8_t status;
uint8_t* current = buf; uint8_t* current = buf;
#if !defined(MY_SOFTSPI) #if !defined(MY_SOFTSPI)
_SPI.beginTransaction(SPISettings(MY_RFM95_SPI_MAX_SPEED, MY_RFM95_SPI_DATA_ORDER, MY_RFM95_SPI_DATA_MODE)); _SPI.beginTransaction(SPISettings(MY_RFM95_SPI_MAX_SPEED, MY_RFM95_SPI_DATA_ORDER,
MY_RFM95_SPI_DATA_MODE));
#endif #endif
RFM95_csn(LOW); RFM95_csn(LOW);
#if defined(LINUX_ARCH_RASPBERRYPI) #if defined(LINUX_ARCH_RASPBERRYPI)
@@ -49,8 +54,7 @@ LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_
while (len--) { while (len--) {
if (aReadMode) { if (aReadMode) {
*ptx++ = RF24_NOP; *ptx++ = RF24_NOP;
} } else {
else {
*ptx++ = *current++; *ptx++ = *current++;
} }
} }
@@ -58,16 +62,14 @@ LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_
if (aReadMode) { if (aReadMode) {
if (size == 2) { if (size == 2) {
status = *++prx; // result is 2nd byte of receive buffer status = *++prx; // result is 2nd byte of receive buffer
} } else {
else {
status = *prx++; // status is 1st byte of receive buffer status = *prx++; // status is 1st byte of receive buffer
// decrement before to skip status byte // decrement before to skip status byte
while (--size) { while (--size) {
*buf++ = *prx++; *buf++ = *prx++;
} }
} }
} } else {
else {
status = *prx; // status is 1st byte of receive buffer status = *prx; // status is 1st byte of receive buffer
} }
#else #else
@@ -78,8 +80,9 @@ LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_
if (buf != NULL) { if (buf != NULL) {
*current++ = status; *current++ = status;
} }
} else {
status = _SPI.transfer(*current++);
} }
else status = _SPI.transfer(*current++);
} }
#endif #endif
RFM95_csn(HIGH); RFM95_csn(HIGH);
@@ -90,12 +93,14 @@ LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_
} }
// low level register access // low level register access
LOCAL uint8_t RFM95_RAW_readByteRegister(const uint8_t address) { LOCAL uint8_t RFM95_RAW_readByteRegister(const uint8_t address)
{
return RFM95_spiMultiByteTransfer(address, NULL, 1, true); return RFM95_spiMultiByteTransfer(address, NULL, 1, true);
} }
// low level register access // low level register access
LOCAL uint8_t RFM95_RAW_writeByteRegister(const uint8_t address, uint8_t value) { LOCAL uint8_t RFM95_RAW_writeByteRegister(const uint8_t address, uint8_t value)
{
return RFM95_spiMultiByteTransfer(address, &value, 1, false); return RFM95_spiMultiByteTransfer(address, &value, 1, false);
} }
@@ -109,7 +114,8 @@ LOCAL uint8_t RFM95_RAW_writeByteRegister(const uint8_t address, uint8_t value)
// check RegPktRssiValue (0x1A) vs. RegRssiValue (0x1B) // check RegPktRssiValue (0x1A) vs. RegRssiValue (0x1B)
LOCAL bool RFM95_initialise(const float frequency) { LOCAL bool RFM95_initialise(const float frequency)
{
RFM95_DEBUG(PSTR("RFM95:INIT\n")); RFM95_DEBUG(PSTR("RFM95:INIT\n"));
// reset radio module if rst pin defined // reset radio module if rst pin defined
#if defined(MY_RFM95_RST_PIN) #if defined(MY_RFM95_RST_PIN)
@@ -167,14 +173,15 @@ LOCAL bool RFM95_initialise(const float frequency) {
} }
// RxDone, TxDone, CADDone is mapped to DI0 // RxDone, TxDone, CADDone is mapped to DI0
LOCAL void RFM95_interruptHandler(void) { LOCAL void RFM95_interruptHandler(void)
{
// Read the interrupt register // Read the interrupt register
const uint8_t irqFlags = RFM95_readReg(RFM95_REG_12_IRQ_FLAGS); const uint8_t irqFlags = RFM95_readReg(RFM95_REG_12_IRQ_FLAGS);
if (RFM95.radioMode == RFM95_RADIO_MODE_RX && (irqFlags & (RFM95_RX_TIMEOUT | RFM95_PAYLOAD_CRC_ERROR)) ) { if (RFM95.radioMode == RFM95_RADIO_MODE_RX &&
(irqFlags & (RFM95_RX_TIMEOUT | RFM95_PAYLOAD_CRC_ERROR)) ) {
// CRC error or timeout // CRC error or timeout
// RXcontinuous mode: radio stays in RX mode, clearing IRQ needed // RXcontinuous mode: radio stays in RX mode, clearing IRQ needed
} } else if (RFM95.radioMode == RFM95_RADIO_MODE_RX && (irqFlags & RFM95_RX_DONE)) {
else if (RFM95.radioMode == RFM95_RADIO_MODE_RX && (irqFlags & RFM95_RX_DONE)) {
// set radio to STDBY (we are in RXcontinuous mode) // set radio to STDBY (we are in RXcontinuous mode)
(void)RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY); (void)RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY);
// Have received a packet // Have received a packet
@@ -189,16 +196,15 @@ LOCAL void RFM95_interruptHandler(void) {
RFM95.currentPacket.payloadLen = bufLen - RFM95_HEADER_LEN; RFM95.currentPacket.payloadLen = bufLen - RFM95_HEADER_LEN;
// Message for us // Message for us
if ((RFM95.currentPacket.header.version >= RFM95_MIN_PACKET_HEADER_VERSION) && if ((RFM95.currentPacket.header.version >= RFM95_MIN_PACKET_HEADER_VERSION) &&
(RFM95_PROMISCUOUS || RFM95.currentPacket.header.recipient == RFM95.address || RFM95.currentPacket.header.recipient == RFM95_BROADCAST_ADDRESS)) { (RFM95_PROMISCUOUS || RFM95.currentPacket.header.recipient == RFM95.address ||
RFM95.currentPacket.header.recipient == RFM95_BROADCAST_ADDRESS)) {
RFM95.rxBufferValid = true; RFM95.rxBufferValid = true;
} }
} }
} } else if (RFM95.radioMode == RFM95_RADIO_MODE_TX && (irqFlags & RFM95_TX_DONE) ) {
else if (RFM95.radioMode == RFM95_RADIO_MODE_TX && (irqFlags & RFM95_TX_DONE) ) {
(void)RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY); (void)RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY);
} } else if (RFM95.radioMode == RFM95_RADIO_MODE_CAD && (irqFlags & RFM95_CAD_DONE) ) {
else if (RFM95.radioMode == RFM95_RADIO_MODE_CAD && (irqFlags & RFM95_CAD_DONE) ) {
RFM95.cad = irqFlags & RFM95_CAD_DETECTED; RFM95.cad = irqFlags & RFM95_CAD_DETECTED;
(void)RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY); (void)RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY);
} }
@@ -207,7 +213,8 @@ LOCAL void RFM95_interruptHandler(void) {
RFM95_writeReg(RFM95_REG_12_IRQ_FLAGS, 0xFF); RFM95_writeReg(RFM95_REG_12_IRQ_FLAGS, 0xFF);
} }
LOCAL bool RFM95_available(void) { LOCAL bool RFM95_available(void)
{
if (RFM95.radioMode == RFM95_RADIO_MODE_TX) { if (RFM95.radioMode == RFM95_RADIO_MODE_TX) {
return false; return false;
} }
@@ -215,13 +222,15 @@ LOCAL bool RFM95_available(void) {
return RFM95.rxBufferValid; return RFM95.rxBufferValid;
} }
LOCAL void RFM95_clearRxBuffer(void) { LOCAL void RFM95_clearRxBuffer(void)
{
noInterrupts(); noInterrupts();
RFM95.rxBufferValid = false; RFM95.rxBufferValid = false;
interrupts(); interrupts();
} }
LOCAL uint8_t RFM95_recv(uint8_t* buf) { LOCAL uint8_t RFM95_recv(uint8_t* buf)
{
if (!RFM95_available()) { if (!RFM95_available()) {
return false; return false;
} }
@@ -249,7 +258,8 @@ LOCAL uint8_t RFM95_recv(uint8_t* buf) {
return payloadLen; return payloadLen;
} }
LOCAL bool RFM95_send(rfm95_packet_t &packet) { LOCAL bool RFM95_send(rfm95_packet_t &packet)
{
const uint8_t finalLen = packet.payloadLen + RFM95_HEADER_LEN; const uint8_t finalLen = packet.payloadLen + RFM95_HEADER_LEN;
// Make sure we dont interrupt an outgoing message // Make sure we dont interrupt an outgoing message
RFM95_waitPacketSent(); RFM95_waitPacketSent();
@@ -271,7 +281,9 @@ LOCAL bool RFM95_send(rfm95_packet_t &packet) {
return true; return true;
} }
LOCAL bool RFM95_sendFrame(const uint8_t recipient, uint8_t* data, const uint8_t len, const rfm95_flag_t flags) { LOCAL bool RFM95_sendFrame(const uint8_t recipient, uint8_t* data, const uint8_t len,
const rfm95_flag_t flags)
{
rfm95_packet_t packet; rfm95_packet_t packet;
packet.header.version = RFM95_PACKET_HEADER_VERSION; packet.header.version = RFM95_PACKET_HEADER_VERSION;
packet.header.sender = RFM95.address; packet.header.sender = RFM95.address;
@@ -283,14 +295,16 @@ LOCAL bool RFM95_sendFrame(const uint8_t recipient, uint8_t* data, const uint8_t
return RFM95_send(packet); return RFM95_send(packet);
} }
LOCAL void RFM95_setFrequency(const float centre) { LOCAL void RFM95_setFrequency(const float centre)
{
const uint32_t freq = (centre * 1000000.0) / RFM95_FSTEP; const uint32_t freq = (centre * 1000000.0) / RFM95_FSTEP;
RFM95_writeReg(RFM95_REG_06_FRF_MSB, (freq >> 16) & 0xff); RFM95_writeReg(RFM95_REG_06_FRF_MSB, (freq >> 16) & 0xff);
RFM95_writeReg(RFM95_REG_07_FRF_MID, (freq >> 8) & 0xff); RFM95_writeReg(RFM95_REG_07_FRF_MID, (freq >> 8) & 0xff);
RFM95_writeReg(RFM95_REG_08_FRF_LSB, freq & 0xff); RFM95_writeReg(RFM95_REG_08_FRF_LSB, freq & 0xff);
} }
LOCAL bool RFM95_setTxPower(uint8_t powerLevel) { LOCAL bool RFM95_setTxPower(uint8_t powerLevel)
{
// RFM95/96/97/98 does not have RFO pins connected to anything. Only PA_BOOST // RFM95/96/97/98 does not have RFO pins connected to anything. Only PA_BOOST
powerLevel = max((uint8_t)RFM95_MIN_POWER_LEVEL_DBM, powerLevel); powerLevel = max((uint8_t)RFM95_MIN_POWER_LEVEL_DBM, powerLevel);
powerLevel = min((uint8_t)RFM95_MAX_POWER_LEVEL_DBM, powerLevel); powerLevel = min((uint8_t)RFM95_MAX_POWER_LEVEL_DBM, powerLevel);
@@ -304,8 +318,7 @@ LOCAL bool RFM95_setTxPower(uint8_t powerLevel) {
// My measurements show 20dBm is correct // My measurements show 20dBm is correct
RFM95_writeReg(RFM95_REG_4D_PA_DAC, RFM95_PA_DAC_ENABLE); RFM95_writeReg(RFM95_REG_4D_PA_DAC, RFM95_PA_DAC_ENABLE);
val = powerLevel - 8; val = powerLevel - 8;
} } else {
else {
RFM95_writeReg(RFM95_REG_4D_PA_DAC, RFM95_PA_DAC_DISABLE); RFM95_writeReg(RFM95_REG_4D_PA_DAC, RFM95_PA_DAC_DISABLE);
val = powerLevel - 5; val = powerLevel - 5;
} }
@@ -318,27 +331,32 @@ LOCAL bool RFM95_setTxPower(uint8_t powerLevel) {
} }
// Sets registers from a canned modem configuration structure // Sets registers from a canned modem configuration structure
LOCAL void RFM95_setModemRegisters(const rfm95_modemConfig_t config) { LOCAL void RFM95_setModemRegisters(const rfm95_modemConfig_t config)
{
RFM95_writeReg(RFM95_REG_1D_MODEM_CONFIG1, config.reg_1d); RFM95_writeReg(RFM95_REG_1D_MODEM_CONFIG1, config.reg_1d);
RFM95_writeReg(RFM95_REG_1E_MODEM_CONFIG2, config.reg_1e); RFM95_writeReg(RFM95_REG_1E_MODEM_CONFIG2, config.reg_1e);
RFM95_writeReg(RFM95_REG_26_MODEM_CONFIG3, config.reg_26); RFM95_writeReg(RFM95_REG_26_MODEM_CONFIG3, config.reg_26);
} }
LOCAL void RFM95_setPreambleLength(const uint16_t preambleLength) { LOCAL void RFM95_setPreambleLength(const uint16_t preambleLength)
{
RFM95_writeReg(RFM95_REG_20_PREAMBLE_MSB, preambleLength >> 8); RFM95_writeReg(RFM95_REG_20_PREAMBLE_MSB, preambleLength >> 8);
RFM95_writeReg(RFM95_REG_21_PREAMBLE_LSB, preambleLength & 0xff); RFM95_writeReg(RFM95_REG_21_PREAMBLE_LSB, preambleLength & 0xff);
} }
LOCAL void RFM95_setAddress(const uint8_t addr) { LOCAL void RFM95_setAddress(const uint8_t addr)
{
RFM95.address = addr; RFM95.address = addr;
} }
LOCAL uint8_t RFM95_getAddress(void) { LOCAL uint8_t RFM95_getAddress(void)
{
return RFM95.address; return RFM95.address;
} }
LOCAL bool RFM95_isChannelActive(void) { LOCAL bool RFM95_isChannelActive(void)
{
(void)RFM95_setRadioMode(RFM95_RADIO_MODE_CAD); (void)RFM95_setRadioMode(RFM95_RADIO_MODE_CAD);
while (RFM95.radioMode == RFM95_RADIO_MODE_CAD) { while (RFM95.radioMode == RFM95_RADIO_MODE_CAD) {
doYield(); doYield();
@@ -347,7 +365,8 @@ LOCAL bool RFM95_isChannelActive(void) {
return RFM95.cad; return RFM95.cad;
} }
LOCAL bool RFM95_setRadioMode(const rfm95_radioMode_t newRadioMode) { LOCAL bool RFM95_setRadioMode(const rfm95_radioMode_t newRadioMode)
{
if (RFM95.radioMode == newRadioMode) { if (RFM95.radioMode == newRadioMode) {
return false; return false;
} }
@@ -355,35 +374,35 @@ LOCAL bool RFM95_setRadioMode(const rfm95_radioMode_t newRadioMode) {
if (newRadioMode == RFM95_RADIO_MODE_STDBY) { if (newRadioMode == RFM95_RADIO_MODE_STDBY) {
regMode = RFM95_MODE_STDBY; regMode = RFM95_MODE_STDBY;
} } else if (newRadioMode == RFM95_RADIO_MODE_SLEEP) {
else if (newRadioMode == RFM95_RADIO_MODE_SLEEP) {
regMode = RFM95_MODE_SLEEP; regMode = RFM95_MODE_SLEEP;
} } else if (newRadioMode == RFM95_RADIO_MODE_CAD) {
else if (newRadioMode == RFM95_RADIO_MODE_CAD) {
regMode = RFM95_MODE_CAD; regMode = RFM95_MODE_CAD;
RFM95_writeReg(RFM95_REG_40_DIO_MAPPING1, 0x80); // Interrupt on CadDone, DIO0 RFM95_writeReg(RFM95_REG_40_DIO_MAPPING1, 0x80); // Interrupt on CadDone, DIO0
} } else if (newRadioMode == RFM95_RADIO_MODE_RX) {
else if (newRadioMode == RFM95_RADIO_MODE_RX) {
regMode = RFM95_MODE_RXCONTINUOUS; regMode = RFM95_MODE_RXCONTINUOUS;
RFM95_writeReg(RFM95_REG_40_DIO_MAPPING1, 0x00); // Interrupt on RxDone, DIO0 RFM95_writeReg(RFM95_REG_40_DIO_MAPPING1, 0x00); // Interrupt on RxDone, DIO0
} } else if (newRadioMode == RFM95_RADIO_MODE_TX) {
else if (newRadioMode == RFM95_RADIO_MODE_TX) {
regMode = RFM95_MODE_TX; regMode = RFM95_MODE_TX;
RFM95_writeReg(RFM95_REG_40_DIO_MAPPING1, 0x40); // Interrupt on TxDone, DIO0 RFM95_writeReg(RFM95_REG_40_DIO_MAPPING1, 0x40); // Interrupt on TxDone, DIO0
} else {
return false;
} }
else return false;
RFM95_writeReg(RFM95_REG_01_OP_MODE, regMode); RFM95_writeReg(RFM95_REG_01_OP_MODE, regMode);
RFM95.radioMode = newRadioMode; RFM95.radioMode = newRadioMode;
return true; return true;
} }
LOCAL bool RFM95_sleep(void) { LOCAL bool RFM95_sleep(void)
{
return RFM95_setRadioMode(RFM95_RADIO_MODE_SLEEP); return RFM95_setRadioMode(RFM95_RADIO_MODE_SLEEP);
} }
// should be called immediately after reception in case sender wants ACK // should be called immediately after reception in case sender wants ACK
LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t sequenceNumber, const rfm95_RSSI_t RSSI, const rfm95_RSSI_t SNR) { LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t sequenceNumber,
const rfm95_RSSI_t RSSI, const rfm95_RSSI_t SNR)
{
RFM95_DEBUG(PSTR("RFM95:SAC:SEND ACK to=%d,RSSI=%d\n"),recipient,RSSI); RFM95_DEBUG(PSTR("RFM95:SAC:SEND ACK to=%d,RSSI=%d\n"),recipient,RSSI);
rfm95_ack_t ACK; rfm95_ack_t ACK;
ACK.sequenceNumber = sequenceNumber; ACK.sequenceNumber = sequenceNumber;
@@ -395,25 +414,26 @@ LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t s
(void)RFM95_sendFrame(recipient, (uint8_t*)&ACK, sizeof(rfm95_ack_t), flags); (void)RFM95_sendFrame(recipient, (uint8_t*)&ACK, sizeof(rfm95_ack_t), flags);
} }
LOCAL bool RFM95_executeATC(const rfm95_RSSI_t currentRSSI, const rfm95_RSSI_t targetRSSI) { LOCAL bool RFM95_executeATC(const rfm95_RSSI_t currentRSSI, const rfm95_RSSI_t targetRSSI)
{
// allow +-5% // allow +-5%
if (currentRSSI < (targetRSSI*1.05) && RFM95.powerLevel < RFM95_MAX_POWER_LEVEL_DBM) { if (currentRSSI < (targetRSSI*1.05) && RFM95.powerLevel < RFM95_MAX_POWER_LEVEL_DBM) {
// increase transmitter power // increase transmitter power
RFM95.powerLevel++; RFM95.powerLevel++;
} } else if (currentRSSI > (targetRSSI*0.95) && RFM95.powerLevel > RFM95_MIN_POWER_LEVEL_DBM) {
else if (currentRSSI > (targetRSSI*0.95) && RFM95.powerLevel > RFM95_MIN_POWER_LEVEL_DBM) {
// decrease transmitter power // decrease transmitter power
RFM95.powerLevel--; RFM95.powerLevel--;
} } else {
else {
// nothing to adjust // nothing to adjust
return false; return false;
} }
RFM95_DEBUG(PSTR("RFM95:ATC:ADJ TXL,cR=%d,tR=%d,TXL=%d\n"), currentRSSI - RFM95_RSSI_OFFSET, targetRSSI - RFM95_RSSI_OFFSET, RFM95.powerLevel); RFM95_DEBUG(PSTR("RFM95:ATC:ADJ TXL,cR=%d,tR=%d,TXL=%d\n"), currentRSSI - RFM95_RSSI_OFFSET,
targetRSSI - RFM95_RSSI_OFFSET, RFM95.powerLevel);
return RFM95_setTxPower(RFM95.powerLevel);; return RFM95_setTxPower(RFM95.powerLevel);;
} }
LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer, const uint8_t bufferSize, const uint8_t retries, const uint32_t retryWaitTime) LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer,
const uint8_t bufferSize, const uint8_t retries, const uint32_t retryWaitTime)
{ {
for (uint8_t retry = 0; retry < retries; retry++) { for (uint8_t retry = 0; retry < retries; retry++) {
RFM95_DEBUG(PSTR("RFM95:SWR:SEND TO=%d,RETRY=%d\n"), recipient, retry); RFM95_DEBUG(PSTR("RFM95:SWR:SEND TO=%d,RETRY=%d\n"), recipient, retry);
@@ -431,8 +451,10 @@ LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer, cons
const uint8_t sender = RFM95.currentPacket.header.sender; const uint8_t sender = RFM95.currentPacket.header.sender;
const rfm95_sequenceNumber_t ACKsequenceNumber = RFM95.currentPacket.ACK.sequenceNumber; const rfm95_sequenceNumber_t ACKsequenceNumber = RFM95.currentPacket.ACK.sequenceNumber;
const rfm95_flag_t flag = RFM95.currentPacket.header.controlFlags; const rfm95_flag_t flag = RFM95.currentPacket.header.controlFlags;
if (sender == recipient && RFM95_getACKReceived(flag) && (ACKsequenceNumber == RFM95.txSequenceNumber - 1)) { if (sender == recipient && RFM95_getACKReceived(flag) &&
RFM95_DEBUG(PSTR("RFM95:SWR:ACK FROM=%d,SEQ=%d,RSSI=%d,SNR=%d\n"),sender,ACKsequenceNumber, RFM95.currentPacket.ACK.RSSI-RFM95_RSSI_OFFSET, (int8_t)RFM95.currentPacket.ACK.SNR / 4); (ACKsequenceNumber == RFM95.txSequenceNumber - 1)) {
RFM95_DEBUG(PSTR("RFM95:SWR:ACK FROM=%d,SEQ=%d,RSSI=%d,SNR=%d\n"),sender,ACKsequenceNumber,
RFM95.currentPacket.ACK.RSSI-RFM95_RSSI_OFFSET, (int8_t)RFM95.currentPacket.ACK.SNR / 4);
RFM95_clearRxBuffer(); RFM95_clearRxBuffer();
// ATC // ATC
@@ -455,7 +477,8 @@ LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer, cons
// Wait until no channel activity detected or timeout // Wait until no channel activity detected or timeout
LOCAL bool RFM95_waitCAD(void) { LOCAL bool RFM95_waitCAD(void)
{
const uint32_t enterMS = hwMillis(); const uint32_t enterMS = hwMillis();
while (RFM95_isChannelActive()) { while (RFM95_isChannelActive()) {
if (hwMillis() - enterMS > RFM95_CAD_TIMEOUT_MS) { if (hwMillis() - enterMS > RFM95_CAD_TIMEOUT_MS) {
@@ -467,23 +490,27 @@ LOCAL bool RFM95_waitCAD(void) {
} }
// Wait for any previous transmission to finish // Wait for any previous transmission to finish
LOCAL bool RFM95_waitPacketSent(void) { LOCAL bool RFM95_waitPacketSent(void)
{
while (RFM95.radioMode == RFM95_RADIO_MODE_TX) { while (RFM95.radioMode == RFM95_RADIO_MODE_TX) {
doYield(); doYield();
} }
return true; return true;
} }
LOCAL int16_t RFM95_getRSSI(void) { LOCAL int16_t RFM95_getRSSI(void)
{
return (int16_t)(RFM95.currentPacket.RSSI - RFM95_RSSI_OFFSET); return (int16_t)(RFM95.currentPacket.RSSI - RFM95_RSSI_OFFSET);
} }
LOCAL void RFM95_ATCmode(const bool OnOff, const int16_t targetRSSI) { LOCAL void RFM95_ATCmode(const bool OnOff, const int16_t targetRSSI)
{
RFM95.ATCenabled = OnOff; RFM95.ATCenabled = OnOff;
RFM95.ATCtargetRSSI = (uint8_t)(targetRSSI + RFM95_RSSI_OFFSET); RFM95.ATCtargetRSSI = (uint8_t)(targetRSSI + RFM95_RSSI_OFFSET);
} }
LOCAL bool RFM95_sanityCheck(void) { LOCAL bool RFM95_sanityCheck(void)
{
// not implemented yet // not implemented yet
return true; return true;
} }
+9 -4
View File
@@ -106,7 +106,8 @@
#if defined (ARDUINO) && !defined (__arm__) && !defined (_SPI) #if defined (ARDUINO) && !defined (__arm__) && !defined (_SPI)
#include <SPI.h> #include <SPI.h>
#if defined(MY_SOFTSPI) #if defined(MY_SOFTSPI)
SoftSPI<MY_SOFT_SPI_MISO_PIN, MY_SOFT_SPI_MOSI_PIN, MY_SOFT_SPI_SCK_PIN, MY_RF24_SPI_DATA_MODE> _SPI; SoftSPI<MY_SOFT_SPI_MISO_PIN, MY_SOFT_SPI_MOSI_PIN, MY_SOFT_SPI_SCK_PIN, MY_RF24_SPI_DATA_MODE>
_SPI;
#else #else
#define _SPI SPI #define _SPI SPI
#endif #endif
@@ -316,7 +317,8 @@ LOCAL bool RFM95_send(rfm95_packet_t &packet);
* @param flags * @param flags
* @return True if frame sent * @return True if frame sent
*/ */
LOCAL bool RFM95_sendFrame(const uint8_t recipient, uint8_t* data, const uint8_t len, const rfm95_flag_t flags); LOCAL bool RFM95_sendFrame(const uint8_t recipient, uint8_t* data, const uint8_t len,
const rfm95_flag_t flags);
/** /**
* @brief RFM95_setPreambleLength * @brief RFM95_setPreambleLength
* @param preambleLength * @param preambleLength
@@ -350,7 +352,8 @@ LOCAL bool RFM95_isChannelActive(void);
* @param RSSI (rfm95_RSSI_t) * @param RSSI (rfm95_RSSI_t)
* @param SNR (rfm95_RSSI_t) * @param SNR (rfm95_RSSI_t)
*/ */
LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t sequenceNumber, const rfm95_RSSI_t RSSI, const rfm95_RSSI_t SNR); LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t sequenceNumber,
const rfm95_RSSI_t RSSI, const rfm95_RSSI_t SNR);
/** /**
* @brief RFM95_sendWithRetry * @brief RFM95_sendWithRetry
* @param recipient * @param recipient
@@ -360,7 +363,9 @@ LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t s
* @param retryWaitTime * @param retryWaitTime
* @return True if packet successfully sent * @return True if packet successfully sent
*/ */
LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer, const uint8_t bufferSize, const uint8_t retries = RFM95_RETRIES, const uint32_t retryWaitTime = RFM95_RETRY_TIMEOUT_MS); LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer,
const uint8_t bufferSize, const uint8_t retries = RFM95_RETRIES,
const uint32_t retryWaitTime = RFM95_RETRY_TIMEOUT_MS);
/** /**
* @brief RFM95_waitCAD * @brief RFM95_waitCAD
* @return True if no channel activity detected * @return True if no channel activity detected
+24 -15
View File
@@ -31,11 +31,13 @@ SPIClass SPI = SPIClass();
uint8_t SPIClass::initialized = 0; uint8_t SPIClass::initialized = 0;
uint8_t SPIClass::is_initialized() { uint8_t SPIClass::is_initialized()
{
return initialized; return initialized;
} }
void SPIClass::begin() { void SPIClass::begin()
{
if (!initialized) { if (!initialized) {
if (!bcm2835_spi_begin()) { if (!bcm2835_spi_begin()) {
logError("You need root privilege to use SPI.\n"); logError("You need root privilege to use SPI.\n");
@@ -46,7 +48,8 @@ void SPIClass::begin() {
initialized++; // reference count initialized++; // reference count
} }
void SPIClass::end() { void SPIClass::end()
{
if (initialized) { if (initialized) {
initialized--; initialized--;
} }
@@ -57,47 +60,53 @@ void SPIClass::end() {
} }
} }
void SPIClass::setBitOrder(uint8_t bit_order) { void SPIClass::setBitOrder(uint8_t bit_order)
{
bcm2835_spi_setBitOrder(bit_order); bcm2835_spi_setBitOrder(bit_order);
} }
void SPIClass::setDataMode(uint8_t data_mode) { void SPIClass::setDataMode(uint8_t data_mode)
{
bcm2835_spi_setDataMode(data_mode); bcm2835_spi_setDataMode(data_mode);
} }
void SPIClass::setClockDivider(uint16_t divider) { void SPIClass::setClockDivider(uint16_t divider)
{
bcm2835_spi_setClockDivider(divider); bcm2835_spi_setClockDivider(divider);
} }
void SPIClass::chipSelect(int csn_pin) { void SPIClass::chipSelect(int csn_pin)
{
if (csn_pin == RPI_GPIO_P1_26) { if (csn_pin == RPI_GPIO_P1_26) {
csn_pin = BCM2835_SPI_CS1; csn_pin = BCM2835_SPI_CS1;
} } else if (csn_pin == RPI_GPIO_P1_24) {
else if (csn_pin == RPI_GPIO_P1_24) {
csn_pin = BCM2835_SPI_CS0; csn_pin = BCM2835_SPI_CS0;
} } else {
else {
csn_pin = BCM2835_SPI_CS0; csn_pin = BCM2835_SPI_CS0;
} }
bcm2835_spi_chipSelect(csn_pin); bcm2835_spi_chipSelect(csn_pin);
delayMicroseconds(5); delayMicroseconds(5);
} }
void SPIClass::beginTransaction(SPISettings settings) { void SPIClass::beginTransaction(SPISettings settings)
{
pthread_mutex_lock(&spiMutex); pthread_mutex_lock(&spiMutex);
setBitOrder(settings.border); setBitOrder(settings.border);
setDataMode(settings.dmode); setDataMode(settings.dmode);
setClockDivider(settings.cdiv); setClockDivider(settings.cdiv);
} }
void SPIClass::endTransaction() { void SPIClass::endTransaction()
{
pthread_mutex_unlock(&spiMutex); pthread_mutex_unlock(&spiMutex);
} }
void SPIClass::usingInterrupt(uint8_t interruptNumber) { void SPIClass::usingInterrupt(uint8_t interruptNumber)
{
(void)interruptNumber; (void)interruptNumber;
} }
void SPIClass::notUsingInterrupt(uint8_t interruptNumber) { void SPIClass::notUsingInterrupt(uint8_t interruptNumber)
{
(void)interruptNumber; (void)interruptNumber;
} }
+16 -8
View File
@@ -45,7 +45,8 @@
/** /**
* SPISettings class * SPISettings class
*/ */
class SPISettings { class SPISettings
{
public: public:
/** /**
@@ -53,7 +54,8 @@ public:
* *
* Default clock speed is 8Mhz. * Default clock speed is 8Mhz.
*/ */
SPISettings() { SPISettings()
{
init(BCM2835_SPI_CLOCK_DIVIDER_32, BCM2835_SPI_BIT_ORDER_MSBFIRST, BCM2835_SPI_MODE0); init(BCM2835_SPI_CLOCK_DIVIDER_32, BCM2835_SPI_BIT_ORDER_MSBFIRST, BCM2835_SPI_MODE0);
} }
/** /**
@@ -63,7 +65,8 @@ public:
* @param bitOrder SPI bit order. * @param bitOrder SPI bit order.
* @param dataMode SPI data mode. * @param dataMode SPI data mode.
*/ */
SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
{
uint16_t divider; uint16_t divider;
switch (clock) { switch (clock) {
@@ -105,7 +108,8 @@ private:
* @param bitOrder SPI bit order. * @param bitOrder SPI bit order.
* @param dataMode SPI data mode. * @param dataMode SPI data mode.
*/ */
void init(uint16_t divider, uint8_t bitOrder, uint8_t dataMode) { void init(uint16_t divider, uint8_t bitOrder, uint8_t dataMode)
{
cdiv = divider; cdiv = divider;
border = bitOrder; border = bitOrder;
dmode = dataMode; dmode = dataMode;
@@ -117,7 +121,8 @@ private:
/** /**
* SPIClass class * SPIClass class
*/ */
class SPIClass { class SPIClass
{
private: private:
static uint8_t initialized; //!< @brief SPI initialized flag. static uint8_t initialized; //!< @brief SPI initialized flag.
@@ -207,15 +212,18 @@ public:
static void notUsingInterrupt(uint8_t interruptNumber); static void notUsingInterrupt(uint8_t interruptNumber);
}; };
uint8_t SPIClass::transfer(uint8_t data) { uint8_t SPIClass::transfer(uint8_t data)
{
return bcm2835_spi_transfer(data); return bcm2835_spi_transfer(data);
} }
void SPIClass::transfernb(char* tbuf, char* rbuf, uint32_t len) { void SPIClass::transfernb(char* tbuf, char* rbuf, uint32_t len)
{
bcm2835_spi_transfernb( tbuf, rbuf, len); bcm2835_spi_transfernb( tbuf, rbuf, len);
} }
void SPIClass::transfern(char* buf, uint32_t len) { void SPIClass::transfern(char* buf, uint32_t len)
{
transfernb(buf, buf, len); transfernb(buf, buf, len);
} }
+18 -5
View File
@@ -31,7 +31,8 @@
#define BUFFER_LENGTH 32 #define BUFFER_LENGTH 32
class TwoWire : public Stream { class TwoWire : public Stream
{
private: private:
static uint8_t rxBuffer[]; static uint8_t rxBuffer[];
@@ -67,10 +68,22 @@ public:
int peek(); int peek();
void flush(); void flush();
inline size_t write(unsigned long n) { return write((uint8_t)n); } inline size_t write(unsigned long n)
inline size_t write(long n) { return write((uint8_t)n); } {
inline size_t write(unsigned int n) { return write((uint8_t)n); } return write((uint8_t)n);
inline size_t write(int n) { return write((uint8_t)n); } }
inline size_t write(long n)
{
return write((uint8_t)n);
}
inline size_t write(unsigned int n)
{
return write((uint8_t)n);
}
inline size_t write(int n)
{
return write((uint8_t)n);
}
using Print::write; using Print::write;
}; };
+135 -160
View File
@@ -77,8 +77,7 @@ static int i2c_byte_wait_us = 0;
/* Function to return the pointers to the hardware register bases */ /* Function to return the pointers to the hardware register bases */
uint32_t* bcm2835_regbase(uint8_t regbase) uint32_t* bcm2835_regbase(uint8_t regbase)
{ {
switch (regbase) switch (regbase) {
{
case BCM2835_REGBASE_ST: case BCM2835_REGBASE_ST:
return (uint32_t *)bcm2835_st; return (uint32_t *)bcm2835_st;
case BCM2835_REGBASE_GPIO: case BCM2835_REGBASE_GPIO:
@@ -115,13 +114,10 @@ unsigned int bcm2835_version(void)
uint32_t bcm2835_peri_read(volatile uint32_t* paddr) uint32_t bcm2835_peri_read(volatile uint32_t* paddr)
{ {
uint32_t ret; uint32_t ret;
if (debug) if (debug) {
{
printf("bcm2835_peri_read paddr %08X\n", (unsigned) paddr); printf("bcm2835_peri_read paddr %08X\n", (unsigned) paddr);
return 0; return 0;
} } else {
else
{
__sync_synchronize(); __sync_synchronize();
ret = *paddr; ret = *paddr;
__sync_synchronize(); __sync_synchronize();
@@ -137,13 +133,10 @@ uint32_t bcm2835_peri_read(volatile uint32_t* paddr)
*/ */
uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr) uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr)
{ {
if (debug) if (debug) {
{
printf("bcm2835_peri_read_nb paddr %08X\n", (unsigned) paddr); printf("bcm2835_peri_read_nb paddr %08X\n", (unsigned) paddr);
return 0; return 0;
} } else {
else
{
return *paddr; return *paddr;
} }
} }
@@ -153,12 +146,9 @@ uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr)
void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value) void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value)
{ {
if (debug) if (debug) {
{
printf("bcm2835_peri_write paddr %08X, value %08X\n", (unsigned) paddr, value); printf("bcm2835_peri_write paddr %08X, value %08X\n", (unsigned) paddr, value);
} } else {
else
{
__sync_synchronize(); __sync_synchronize();
*paddr = value; *paddr = value;
__sync_synchronize(); __sync_synchronize();
@@ -168,13 +158,10 @@ void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value)
/* write to peripheral without the write barrier */ /* write to peripheral without the write barrier */
void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value) void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value)
{ {
if (debug) if (debug) {
{
printf("bcm2835_peri_write_nb paddr %08X, value %08X\n", printf("bcm2835_peri_write_nb paddr %08X, value %08X\n",
(unsigned) paddr, value); (unsigned) paddr, value);
} } else {
else
{
*paddr = value; *paddr = value;
} }
} }
@@ -449,8 +436,7 @@ void bcm2835_delayMicroseconds(uint64_t micros)
struct timespec t1; struct timespec t1;
uint64_t start; uint64_t start;
if (debug) if (debug) {
{
/* Cant access sytem timers in debug mode */ /* Cant access sytem timers in debug mode */
printf("bcm2835_delayMicroseconds %lld\n", micros); printf("bcm2835_delayMicroseconds %lld\n", micros);
return; return;
@@ -461,8 +447,7 @@ void bcm2835_delayMicroseconds(uint64_t micros)
*/ */
start = bcm2835_st_read(); start = bcm2835_st_read();
if (micros > 450) if (micros > 450) {
{
t1.tv_sec = 0; t1.tv_sec = 0;
t1.tv_nsec = 1000 * (long)(micros - 200); t1.tv_nsec = 1000 * (long)(micros - 200);
nanosleep(&t1, NULL); nanosleep(&t1, NULL);
@@ -478,20 +463,22 @@ void bcm2835_delayMicroseconds(uint64_t micros)
/* Set the state of an output */ /* Set the state of an output */
void bcm2835_gpio_write(uint8_t pin, uint8_t on) void bcm2835_gpio_write(uint8_t pin, uint8_t on)
{ {
if (on) if (on) {
bcm2835_gpio_set(pin); bcm2835_gpio_set(pin);
else } else {
bcm2835_gpio_clr(pin); bcm2835_gpio_clr(pin);
} }
}
/* Set the state of a all 32 outputs in the mask to on or off */ /* Set the state of a all 32 outputs in the mask to on or off */
void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on) void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on)
{ {
if (on) if (on) {
bcm2835_gpio_set_multi(mask); bcm2835_gpio_set_multi(mask);
else } else {
bcm2835_gpio_clr_multi(mask); bcm2835_gpio_clr_multi(mask);
} }
}
/* Set the state of a all 32 outputs in the mask to the values in value */ /* Set the state of a all 32 outputs in the mask to the values in value */
void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask) void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask)
@@ -532,8 +519,9 @@ int bcm2835_spi_begin(void)
{ {
volatile uint32_t* paddr; volatile uint32_t* paddr;
if (bcm2835_spi0 == MAP_FAILED) if (bcm2835_spi0 == MAP_FAILED) {
return 0; /* bcm2835_init() failed, or not root */ return 0; /* bcm2835_init() failed, or not root */
}
/* Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them */ /* Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them */
bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); /* CE1 */ bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); /* CE1 */
@@ -642,17 +630,14 @@ void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len)
bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA);
/* Use the FIFO's to reduce the interbyte times */ /* Use the FIFO's to reduce the interbyte times */
while((TXCnt < len)||(RXCnt < len)) while((TXCnt < len)||(RXCnt < len)) {
{
/* TX fifo not full, so add some more bytes */ /* TX fifo not full, so add some more bytes */
while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD))&&(TXCnt < len )) while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD))&&(TXCnt < len )) {
{
bcm2835_peri_write_nb(fifo, tbuf[TXCnt]); bcm2835_peri_write_nb(fifo, tbuf[TXCnt]);
TXCnt++; TXCnt++;
} }
/* Rx fifo not empty, so get the next received bytes */ /* Rx fifo not empty, so get the next received bytes */
while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD))&&( RXCnt < len )) while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD))&&( RXCnt < len )) {
{
rbuf[RXCnt] = bcm2835_peri_read_nb(fifo); rbuf[RXCnt] = bcm2835_peri_read_nb(fifo);
RXCnt++; RXCnt++;
} }
@@ -684,8 +669,7 @@ void bcm2835_spi_writenb(char* tbuf, uint32_t len)
/* Set TA = 1 */ /* Set TA = 1 */
bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA);
for (i = 0; i < len; i++) for (i = 0; i < len; i++) {
{
/* Maybe wait for TXD */ /* Maybe wait for TXD */
while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD))
; ;
@@ -694,14 +678,16 @@ void bcm2835_spi_writenb(char* tbuf, uint32_t len)
bcm2835_peri_write_nb(fifo, tbuf[i]); bcm2835_peri_write_nb(fifo, tbuf[i]);
/* Read from FIFO to prevent stalling */ /* Read from FIFO to prevent stalling */
while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) {
(void) bcm2835_peri_read_nb(fifo); (void) bcm2835_peri_read_nb(fifo);
} }
}
/* Wait for DONE to be set */ /* Wait for DONE to be set */
while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) { while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) {
while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) {
(void) bcm2835_peri_read_nb(fifo); (void) bcm2835_peri_read_nb(fifo);
}
}; };
/* Set TA = 0, and also set the barrier */ /* Set TA = 0, and also set the barrier */
@@ -736,8 +722,9 @@ int bcm2835_i2c_begin(void)
uint16_t cdiv; uint16_t cdiv;
if ( bcm2835_bsc0 == MAP_FAILED if ( bcm2835_bsc0 == MAP_FAILED
|| bcm2835_bsc1 == MAP_FAILED) || bcm2835_bsc1 == MAP_FAILED) {
return 0; /* bcm2835_init() failed, or not root */ return 0; /* bcm2835_init() failed, or not root */
}
#ifdef I2C_V1 #ifdef I2C_V1
volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4; volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4;
@@ -840,8 +827,7 @@ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len)
/* Set Data Length */ /* Set Data Length */
bcm2835_peri_write(dlen, len); bcm2835_peri_write(dlen, len);
/* pre populate FIFO with max buffer */ /* pre populate FIFO with max buffer */
while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) {
{
bcm2835_peri_write_nb(fifo, buf[i]); bcm2835_peri_write_nb(fifo, buf[i]);
i++; i++;
remaining--; remaining--;
@@ -851,10 +837,8 @@ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len)
bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
/* Transfer is over when BCM2835_BSC_S_DONE */ /* Transfer is over when BCM2835_BSC_S_DONE */
while(!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE )) while(!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE )) {
{ while ( remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_TXD )) {
while ( remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_TXD ))
{
/* Write to FIFO */ /* Write to FIFO */
bcm2835_peri_write(fifo, buf[i]); bcm2835_peri_write(fifo, buf[i]);
i++; i++;
@@ -863,20 +847,17 @@ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len)
} }
/* Received a NACK */ /* Received a NACK */
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) {
{
reason = BCM2835_I2C_REASON_ERROR_NACK; reason = BCM2835_I2C_REASON_ERROR_NACK;
} }
/* Received Clock Stretch Timeout */ /* Received Clock Stretch Timeout */
else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) {
{
reason = BCM2835_I2C_REASON_ERROR_CLKT; reason = BCM2835_I2C_REASON_ERROR_CLKT;
} }
/* Not all data is sent */ /* Not all data is sent */
else if (remaining) else if (remaining) {
{
reason = BCM2835_I2C_REASON_ERROR_DATA; reason = BCM2835_I2C_REASON_ERROR_DATA;
} }
@@ -914,11 +895,9 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ); bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ);
/* wait for transfer to complete */ /* wait for transfer to complete */
while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) {
{
/* we must empty the FIFO as it is populated and not use any delay */ /* we must empty the FIFO as it is populated and not use any delay */
while (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD) while (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD) {
{
/* Read from FIFO, no barrier */ /* Read from FIFO, no barrier */
buf[i] = bcm2835_peri_read_nb(fifo); buf[i] = bcm2835_peri_read_nb(fifo);
i++; i++;
@@ -927,8 +906,7 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
} }
/* transfer has finished - grab any remaining stuff in FIFO */ /* transfer has finished - grab any remaining stuff in FIFO */
while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD)) while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD)) {
{
/* Read from FIFO, no barrier */ /* Read from FIFO, no barrier */
buf[i] = bcm2835_peri_read_nb(fifo); buf[i] = bcm2835_peri_read_nb(fifo);
i++; i++;
@@ -936,20 +914,17 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
} }
/* Received a NACK */ /* Received a NACK */
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) {
{
reason = BCM2835_I2C_REASON_ERROR_NACK; reason = BCM2835_I2C_REASON_ERROR_NACK;
} }
/* Received Clock Stretch Timeout */ /* Received Clock Stretch Timeout */
else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) {
{
reason = BCM2835_I2C_REASON_ERROR_CLKT; reason = BCM2835_I2C_REASON_ERROR_CLKT;
} }
/* Not all data is received */ /* Not all data is received */
else if (remaining) else if (remaining) {
{
reason = BCM2835_I2C_REASON_ERROR_DATA; reason = BCM2835_I2C_REASON_ERROR_DATA;
} }
@@ -990,12 +965,12 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
/* poll for transfer has started */ /* poll for transfer has started */
while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) {
{
/* Linux may cause us to miss entire transfer stage */ /* Linux may cause us to miss entire transfer stage */
if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE) if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE) {
break; break;
} }
}
/* Send a repeated start with read bit set in address */ /* Send a repeated start with read bit set in address */
bcm2835_peri_write(dlen, len); bcm2835_peri_write(dlen, len);
@@ -1005,11 +980,9 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
bcm2835_delayMicroseconds(i2c_byte_wait_us * 3); bcm2835_delayMicroseconds(i2c_byte_wait_us * 3);
/* wait for transfer to complete */ /* wait for transfer to complete */
while (!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE)) while (!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE)) {
{
/* we must empty the FIFO as it is populated and not use any delay */ /* we must empty the FIFO as it is populated and not use any delay */
while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) {
{
/* Read from FIFO */ /* Read from FIFO */
buf[i] = bcm2835_peri_read(fifo); buf[i] = bcm2835_peri_read(fifo);
i++; i++;
@@ -1018,8 +991,7 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
} }
/* transfer has finished - grab any remaining stuff in FIFO */ /* transfer has finished - grab any remaining stuff in FIFO */
while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) {
{
/* Read from FIFO */ /* Read from FIFO */
buf[i] = bcm2835_peri_read(fifo); buf[i] = bcm2835_peri_read(fifo);
i++; i++;
@@ -1027,20 +999,17 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
} }
/* Received a NACK */ /* Received a NACK */
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) {
{
reason = BCM2835_I2C_REASON_ERROR_NACK; reason = BCM2835_I2C_REASON_ERROR_NACK;
} }
/* Received Clock Stretch Timeout */ /* Received Clock Stretch Timeout */
else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) {
{
reason = BCM2835_I2C_REASON_ERROR_CLKT; reason = BCM2835_I2C_REASON_ERROR_CLKT;
} }
/* Not all data is sent */ /* Not all data is sent */
else if (remaining) else if (remaining) {
{
reason = BCM2835_I2C_REASON_ERROR_DATA; reason = BCM2835_I2C_REASON_ERROR_DATA;
} }
@@ -1080,8 +1049,7 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
bcm2835_peri_write(dlen, cmds_len); bcm2835_peri_write(dlen, cmds_len);
/* pre populate FIFO with max buffer */ /* pre populate FIFO with max buffer */
while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) {
{
bcm2835_peri_write_nb(fifo, cmds[i]); bcm2835_peri_write_nb(fifo, cmds[i]);
i++; i++;
remaining--; remaining--;
@@ -1091,12 +1059,12 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
/* poll for transfer has started (way to do repeated start, from BCM2835 datasheet) */ /* poll for transfer has started (way to do repeated start, from BCM2835 datasheet) */
while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) {
{
/* Linux may cause us to miss entire transfer stage */ /* Linux may cause us to miss entire transfer stage */
if(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE) if(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE) {
break; break;
} }
}
remaining = buf_len; remaining = buf_len;
i = 0; i = 0;
@@ -1109,11 +1077,9 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
bcm2835_delayMicroseconds(i2c_byte_wait_us * (cmds_len + 1)); bcm2835_delayMicroseconds(i2c_byte_wait_us * (cmds_len + 1));
/* wait for transfer to complete */ /* wait for transfer to complete */
while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) {
{
/* we must empty the FIFO as it is populated and not use any delay */ /* we must empty the FIFO as it is populated and not use any delay */
while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) {
{
/* Read from FIFO, no barrier */ /* Read from FIFO, no barrier */
buf[i] = bcm2835_peri_read_nb(fifo); buf[i] = bcm2835_peri_read_nb(fifo);
i++; i++;
@@ -1122,8 +1088,7 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
} }
/* transfer has finished - grab any remaining stuff in FIFO */ /* transfer has finished - grab any remaining stuff in FIFO */
while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) {
{
/* Read from FIFO */ /* Read from FIFO */
buf[i] = bcm2835_peri_read(fifo); buf[i] = bcm2835_peri_read(fifo);
i++; i++;
@@ -1131,20 +1096,17 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
} }
/* Received a NACK */ /* Received a NACK */
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) {
{
reason = BCM2835_I2C_REASON_ERROR_NACK; reason = BCM2835_I2C_REASON_ERROR_NACK;
} }
/* Received Clock Stretch Timeout */ /* Received Clock Stretch Timeout */
else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) {
{
reason = BCM2835_I2C_REASON_ERROR_CLKT; reason = BCM2835_I2C_REASON_ERROR_CLKT;
} }
/* Not all data is sent */ /* Not all data is sent */
else if (remaining) else if (remaining) {
{
reason = BCM2835_I2C_REASON_ERROR_DATA; reason = BCM2835_I2C_REASON_ERROR_DATA;
} }
@@ -1169,13 +1131,10 @@ uint64_t bcm2835_st_read(void)
st = bcm2835_peri_read(paddr); st = bcm2835_peri_read(paddr);
/* Test for overflow */ /* Test for overflow */
if (st == hi) if (st == hi) {
{
st <<= 32; st <<= 32;
st += lo; st += lo;
} } else {
else
{
st <<= 32; st <<= 32;
paddr = bcm2835_st + BCM2835_ST_CLO/4; paddr = bcm2835_st + BCM2835_ST_CLO/4;
st += bcm2835_peri_read(paddr); st += bcm2835_peri_read(paddr);
@@ -1197,8 +1156,9 @@ void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros)
void bcm2835_pwm_set_clock(uint32_t divisor) void bcm2835_pwm_set_clock(uint32_t divisor)
{ {
if ( bcm2835_clk == MAP_FAILED if ( bcm2835_clk == MAP_FAILED
|| bcm2835_pwm == MAP_FAILED) || bcm2835_pwm == MAP_FAILED) {
return; /* bcm2835_init() failed or not root */ return; /* bcm2835_init() failed or not root */
}
/* From Gerts code */ /* From Gerts code */
divisor &= 0xfff; divisor &= 0xfff;
@@ -1206,43 +1166,47 @@ void bcm2835_pwm_set_clock(uint32_t divisor)
bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x01); bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x01);
bcm2835_delay(110); /* Prevents clock going slow */ bcm2835_delay(110); /* Prevents clock going slow */
/* Wait for the clock to be not busy */ /* Wait for the clock to be not busy */
while ((bcm2835_peri_read(bcm2835_clk + BCM2835_PWMCLK_CNTL) & 0x80) != 0) while ((bcm2835_peri_read(bcm2835_clk + BCM2835_PWMCLK_CNTL) & 0x80) != 0) {
bcm2835_delay(1); bcm2835_delay(1);
}
/* set the clock divider and enable PWM clock */ /* set the clock divider and enable PWM clock */
bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_DIV, BCM2835_PWM_PASSWRD | (divisor << 12)); bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_DIV, BCM2835_PWM_PASSWRD | (divisor << 12));
bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x11); /* Source=osc and enable */ bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL,
BCM2835_PWM_PASSWRD | 0x11); /* Source=osc and enable */
} }
void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled) void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled)
{ {
if ( bcm2835_clk == MAP_FAILED if ( bcm2835_clk == MAP_FAILED
|| bcm2835_pwm == MAP_FAILED) || bcm2835_pwm == MAP_FAILED) {
return; /* bcm2835_init() failed or not root */ return; /* bcm2835_init() failed or not root */
}
uint32_t control = bcm2835_peri_read(bcm2835_pwm + BCM2835_PWM_CONTROL); uint32_t control = bcm2835_peri_read(bcm2835_pwm + BCM2835_PWM_CONTROL);
if (channel == 0) if (channel == 0) {
{ if (markspace) {
if (markspace)
control |= BCM2835_PWM0_MS_MODE; control |= BCM2835_PWM0_MS_MODE;
else } else {
control &= ~BCM2835_PWM0_MS_MODE; control &= ~BCM2835_PWM0_MS_MODE;
if (enabled) }
if (enabled) {
control |= BCM2835_PWM0_ENABLE; control |= BCM2835_PWM0_ENABLE;
else } else {
control &= ~BCM2835_PWM0_ENABLE; control &= ~BCM2835_PWM0_ENABLE;
} }
else if (channel == 1) } else if (channel == 1) {
{ if (markspace) {
if (markspace)
control |= BCM2835_PWM1_MS_MODE; control |= BCM2835_PWM1_MS_MODE;
else } else {
control &= ~BCM2835_PWM1_MS_MODE; control &= ~BCM2835_PWM1_MS_MODE;
if (enabled) }
if (enabled) {
control |= BCM2835_PWM1_ENABLE; control |= BCM2835_PWM1_ENABLE;
else } else {
control &= ~BCM2835_PWM1_ENABLE; control &= ~BCM2835_PWM1_ENABLE;
} }
}
/* If you use the barrier here, wierd things happen, and the commands dont work */ /* If you use the barrier here, wierd things happen, and the commands dont work */
bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, control); bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, control);
@@ -1253,26 +1217,30 @@ void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled)
void bcm2835_pwm_set_range(uint8_t channel, uint32_t range) void bcm2835_pwm_set_range(uint8_t channel, uint32_t range)
{ {
if ( bcm2835_clk == MAP_FAILED if ( bcm2835_clk == MAP_FAILED
|| bcm2835_pwm == MAP_FAILED) || bcm2835_pwm == MAP_FAILED) {
return; /* bcm2835_init() failed or not root */ return; /* bcm2835_init() failed or not root */
}
if (channel == 0) if (channel == 0) {
bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_RANGE, range); bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_RANGE, range);
else if (channel == 1) } else if (channel == 1) {
bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_RANGE, range); bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_RANGE, range);
} }
}
void bcm2835_pwm_set_data(uint8_t channel, uint32_t data) void bcm2835_pwm_set_data(uint8_t channel, uint32_t data)
{ {
if ( bcm2835_clk == MAP_FAILED if ( bcm2835_clk == MAP_FAILED
|| bcm2835_pwm == MAP_FAILED) || bcm2835_pwm == MAP_FAILED) {
return; /* bcm2835_init() failed or not root */ return; /* bcm2835_init() failed or not root */
}
if (channel == 0) if (channel == 0) {
bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_DATA, data); bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_DATA, data);
else if (channel == 1) } else if (channel == 1) {
bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_DATA, data); bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_DATA, data);
} }
}
/* Allocate page-aligned memory. */ /* Allocate page-aligned memory. */
void *malloc_aligned(size_t size) void *malloc_aligned(size_t size)
@@ -1289,14 +1257,17 @@ void *malloc_aligned(size_t size)
static void *mapmem(const char *msg, size_t size, int fd, off_t off) static void *mapmem(const char *msg, size_t size, int fd, off_t off)
{ {
void *map = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, off); void *map = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, off);
if (map == MAP_FAILED) if (map == MAP_FAILED) {
logError("bcm2835_init: %s mmap failed: %s\n", msg, strerror(errno)); logError("bcm2835_init: %s mmap failed: %s\n", msg, strerror(errno));
}
return map; return map;
} }
static void unmapmem(void **pmem, size_t size) static void unmapmem(void **pmem, size_t size)
{ {
if (*pmem == MAP_FAILED) return; if (*pmem == MAP_FAILED) {
return;
}
munmap(*pmem, size); munmap(*pmem, size);
*pmem = MAP_FAILED; *pmem = MAP_FAILED;
} }
@@ -1308,8 +1279,7 @@ int bcm2835_init(void)
int ok; int ok;
FILE *fp; FILE *fp;
if (debug) if (debug) {
{
bcm2835_peripherals = (uint32_t*)BCM2835_PERI_BASE; bcm2835_peripherals = (uint32_t*)BCM2835_PERI_BASE;
bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4; bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4;
@@ -1326,15 +1296,16 @@ int bcm2835_init(void)
/* Figure out the base and size of the peripheral address block /* Figure out the base and size of the peripheral address block
// using the device-tree. Required for RPi2, optional for RPi 1 // using the device-tree. Required for RPi2, optional for RPi 1
*/ */
if ((fp = fopen(BMC2835_RPI2_DT_FILENAME , "rb"))) if ((fp = fopen(BMC2835_RPI2_DT_FILENAME , "rb"))) {
{
unsigned char buf[4]; unsigned char buf[4];
fseek(fp, BMC2835_RPI2_DT_PERI_BASE_ADDRESS_OFFSET, SEEK_SET); fseek(fp, BMC2835_RPI2_DT_PERI_BASE_ADDRESS_OFFSET, SEEK_SET);
if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf)) if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf)) {
bcm2835_peripherals_base = (uint32_t *)(buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0); bcm2835_peripherals_base = (uint32_t *)(buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0);
}
fseek(fp, BMC2835_RPI2_DT_PERI_SIZE_OFFSET, SEEK_SET); fseek(fp, BMC2835_RPI2_DT_PERI_SIZE_OFFSET, SEEK_SET);
if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf)) if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf)) {
bcm2835_peripherals_size = (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0); bcm2835_peripherals_size = (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0);
}
fclose(fp); fclose(fp);
} }
/* else we are prob on RPi 1 with BCM2835, and use the hardwired defaults */ /* else we are prob on RPi 1 with BCM2835, and use the hardwired defaults */
@@ -1346,19 +1317,20 @@ int bcm2835_init(void)
*/ */
memfd = -1; memfd = -1;
ok = 0; ok = 0;
if (geteuid() == 0) if (geteuid() == 0) {
{
/* Open the master /dev/mem device */ /* Open the master /dev/mem device */
if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) {
{
logError("bcm2835_init: Unable to open /dev/mem: %s\n", logError("bcm2835_init: Unable to open /dev/mem: %s\n",
strerror(errno)) ; strerror(errno)) ;
goto exit; goto exit;
} }
/* Base of the peripherals block is mapped to VM */ /* Base of the peripherals block is mapped to VM */
bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, (uint32_t)bcm2835_peripherals_base); bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd,
if (bcm2835_peripherals == MAP_FAILED) goto exit; (uint32_t)bcm2835_peripherals_base);
if (bcm2835_peripherals == MAP_FAILED) {
goto exit;
}
/* Now compute the base addresses of various peripherals, /* Now compute the base addresses of various peripherals,
// which are at fixed offsets within the mapped peripherals block // which are at fixed offsets within the mapped peripherals block
@@ -1374,13 +1346,10 @@ int bcm2835_init(void)
bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4; bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4;
ok = 1; ok = 1;
} } else {
else
{
/* Not root, try /dev/gpiomem */ /* Not root, try /dev/gpiomem */
/* Open the master /dev/mem device */ /* Open the master /dev/mem device */
if ((memfd = open("/dev/gpiomem", O_RDWR | O_SYNC) ) < 0) if ((memfd = open("/dev/gpiomem", O_RDWR | O_SYNC) ) < 0) {
{
logError("bcm2835_init: Unable to open /dev/gpiomem: %s\n", logError("bcm2835_init: Unable to open /dev/gpiomem: %s\n",
strerror(errno)) ; strerror(errno)) ;
goto exit; goto exit;
@@ -1388,18 +1357,23 @@ int bcm2835_init(void)
/* Base of the peripherals block is mapped to VM */ /* Base of the peripherals block is mapped to VM */
bcm2835_peripherals_base = 0; bcm2835_peripherals_base = 0;
bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, (uint32_t)bcm2835_peripherals_base); bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd,
if (bcm2835_peripherals == MAP_FAILED) goto exit; (uint32_t)bcm2835_peripherals_base);
if (bcm2835_peripherals == MAP_FAILED) {
goto exit;
}
bcm2835_gpio = bcm2835_peripherals; bcm2835_gpio = bcm2835_peripherals;
ok = 1; ok = 1;
} }
exit: exit:
if (memfd >= 0) if (memfd >= 0) {
close(memfd); close(memfd);
}
if (!ok) if (!ok) {
bcm2835_close(); bcm2835_close();
}
return ok; return ok;
} }
@@ -1407,7 +1381,9 @@ exit:
/* Close this library and deallocate everything */ /* Close this library and deallocate everything */
int bcm2835_close(void) int bcm2835_close(void)
{ {
if (debug) return 1; /* Success */ if (debug) {
return 1; /* Success */
}
unmapmem((void**) &bcm2835_peripherals, bcm2835_peripherals_size); unmapmem((void**) &bcm2835_peripherals, bcm2835_peripherals_size);
bcm2835_peripherals = MAP_FAILED; bcm2835_peripherals = MAP_FAILED;
@@ -1431,8 +1407,9 @@ int main(int argc, char **argv)
/* Be non-destructive */ /* Be non-destructive */
bcm2835_set_debug(1); bcm2835_set_debug(1);
if (!bcm2835_init()) if (!bcm2835_init()) {
return 1; return 1;
}
/* Configure some GPIO pins fo some testing /* Configure some GPIO pins fo some testing
// Set RPI pin P1-11 to be an output // Set RPI pin P1-11 to be an output
@@ -1445,12 +1422,12 @@ int main(int argc, char **argv)
/* And a low detect enable */ /* And a low detect enable */
bcm2835_gpio_len(RPI_GPIO_P1_15); bcm2835_gpio_len(RPI_GPIO_P1_15);
/* and input hysteresis disabled on GPIOs 0 to 27 */ /* and input hysteresis disabled on GPIOs 0 to 27 */
bcm2835_gpio_set_pad(BCM2835_PAD_GROUP_GPIO_0_27, BCM2835_PAD_SLEW_RATE_UNLIMITED|BCM2835_PAD_DRIVE_8mA); bcm2835_gpio_set_pad(BCM2835_PAD_GROUP_GPIO_0_27,
BCM2835_PAD_SLEW_RATE_UNLIMITED|BCM2835_PAD_DRIVE_8mA);
#if 1 #if 1
/* Blink */ /* Blink */
while (1) while (1) {
{
/* Turn it on */ /* Turn it on */
bcm2835_gpio_write(RPI_GPIO_P1_11, HIGH); bcm2835_gpio_write(RPI_GPIO_P1_11, HIGH);
@@ -1467,8 +1444,7 @@ int main(int argc, char **argv)
#if 0 #if 0
/* Read input */ /* Read input */
while (1) while (1) {
{
/* Read some data */ /* Read some data */
uint8_t value = bcm2835_gpio_lev(RPI_GPIO_P1_15); uint8_t value = bcm2835_gpio_lev(RPI_GPIO_P1_15);
printf("read from pin 15: %d\n", value); printf("read from pin 15: %d\n", value);
@@ -1482,10 +1458,8 @@ int main(int argc, char **argv)
/* Look for a low event detection /* Look for a low event detection
// eds will be set whenever pin 15 goes low // eds will be set whenever pin 15 goes low
*/ */
while (1) while (1) {
{ if (bcm2835_gpio_eds(RPI_GPIO_P1_15)) {
if (bcm2835_gpio_eds(RPI_GPIO_P1_15))
{
/* Now clear the eds flag by setting it to 1 */ /* Now clear the eds flag by setting it to 1 */
bcm2835_gpio_set_eds(RPI_GPIO_P1_15); bcm2835_gpio_set_eds(RPI_GPIO_P1_15);
printf("low event detect for pin 15\n"); printf("low event detect for pin 15\n");
@@ -1496,8 +1470,9 @@ int main(int argc, char **argv)
} }
#endif #endif
if (!bcm2835_close()) if (!bcm2835_close()) {
return 1; return 1;
}
return 0; return 0;
} }
+14 -25
View File
@@ -577,8 +577,7 @@ extern volatile uint32_t *bcm2835_bsc1;
/*! \brief bcm2835RegisterBase /*! \brief bcm2835RegisterBase
Register bases for bcm2835_regbase() Register bases for bcm2835_regbase()
*/ */
typedef enum typedef enum {
{
BCM2835_REGBASE_ST = 1, /*!< Base of the ST (System Timer) registers. */ BCM2835_REGBASE_ST = 1, /*!< Base of the ST (System Timer) registers. */
BCM2835_REGBASE_GPIO = 2, /*!< Base of the GPIO registers. */ BCM2835_REGBASE_GPIO = 2, /*!< Base of the GPIO registers. */
BCM2835_REGBASE_PWM = 3, /*!< Base of the PWM registers. */ BCM2835_REGBASE_PWM = 3, /*!< Base of the PWM registers. */
@@ -635,8 +634,7 @@ typedef enum
/*! \brief bcm2835PortFunction /*! \brief bcm2835PortFunction
Port function select modes for bcm2835_gpio_fsel() Port function select modes for bcm2835_gpio_fsel()
*/ */
typedef enum typedef enum {
{
BCM2835_GPIO_FSEL_INPT = 0x00, /*!< Input 0b000 */ BCM2835_GPIO_FSEL_INPT = 0x00, /*!< Input 0b000 */
BCM2835_GPIO_FSEL_OUTP = 0x01, /*!< Output 0b001 */ BCM2835_GPIO_FSEL_OUTP = 0x01, /*!< Output 0b001 */
BCM2835_GPIO_FSEL_ALT0 = 0x04, /*!< Alternate function 0 0b100 */ BCM2835_GPIO_FSEL_ALT0 = 0x04, /*!< Alternate function 0 0b100 */
@@ -651,8 +649,7 @@ typedef enum
/*! \brief bcm2835PUDControl /*! \brief bcm2835PUDControl
Pullup/Pulldown defines for bcm2835_gpio_pud() Pullup/Pulldown defines for bcm2835_gpio_pud()
*/ */
typedef enum typedef enum {
{
BCM2835_GPIO_PUD_OFF = 0x00, /*!< Off ? disable pull-up/down 0b00 */ BCM2835_GPIO_PUD_OFF = 0x00, /*!< Off ? disable pull-up/down 0b00 */
BCM2835_GPIO_PUD_DOWN = 0x01, /*!< Enable Pull Down control 0b01 */ BCM2835_GPIO_PUD_DOWN = 0x01, /*!< Enable Pull Down control 0b01 */
BCM2835_GPIO_PUD_UP = 0x02 /*!< Enable Pull Up control 0b10 */ BCM2835_GPIO_PUD_UP = 0x02 /*!< Enable Pull Up control 0b10 */
@@ -679,8 +676,7 @@ typedef enum
/*! \brief bcm2835PadGroup /*! \brief bcm2835PadGroup
Pad group specification for bcm2835_gpio_pad() Pad group specification for bcm2835_gpio_pad()
*/ */
typedef enum typedef enum {
{
BCM2835_PAD_GROUP_GPIO_0_27 = 0, /*!< Pad group for GPIO pads 0 to 27 */ BCM2835_PAD_GROUP_GPIO_0_27 = 0, /*!< Pad group for GPIO pads 0 to 27 */
BCM2835_PAD_GROUP_GPIO_28_45 = 1, /*!< Pad group for GPIO pads 28 to 45 */ BCM2835_PAD_GROUP_GPIO_28_45 = 1, /*!< Pad group for GPIO pads 28 to 45 */
BCM2835_PAD_GROUP_GPIO_46_53 = 2 /*!< Pad group for GPIO pads 46 to 53 */ BCM2835_PAD_GROUP_GPIO_46_53 = 2 /*!< Pad group for GPIO pads 46 to 53 */
@@ -700,8 +696,7 @@ typedef enum
If you are using the RPi Compute Module, just use the GPIO number: there is no need to use one of these If you are using the RPi Compute Module, just use the GPIO number: there is no need to use one of these
symbolic names symbolic names
*/ */
typedef enum typedef enum {
{
RPI_GPIO_P1_03 = 0, /*!< Version 1, Pin P1-03 */ RPI_GPIO_P1_03 = 0, /*!< Version 1, Pin P1-03 */
RPI_GPIO_P1_05 = 1, /*!< Version 1, Pin P1-05 */ RPI_GPIO_P1_05 = 1, /*!< Version 1, Pin P1-05 */
RPI_GPIO_P1_07 = 4, /*!< Version 1, Pin P1-07 */ RPI_GPIO_P1_07 = 4, /*!< Version 1, Pin P1-07 */
@@ -825,8 +820,7 @@ typedef enum
/*! \brief bcm2835SPIBitOrder SPI Bit order /*! \brief bcm2835SPIBitOrder SPI Bit order
Specifies the SPI data bit ordering for bcm2835_spi_setBitOrder() Specifies the SPI data bit ordering for bcm2835_spi_setBitOrder()
*/ */
typedef enum typedef enum {
{
BCM2835_SPI_BIT_ORDER_LSBFIRST = 0, /*!< LSB First */ BCM2835_SPI_BIT_ORDER_LSBFIRST = 0, /*!< LSB First */
BCM2835_SPI_BIT_ORDER_MSBFIRST = 1 /*!< MSB First */ BCM2835_SPI_BIT_ORDER_MSBFIRST = 1 /*!< MSB First */
} bcm2835SPIBitOrder; } bcm2835SPIBitOrder;
@@ -834,8 +828,7 @@ typedef enum
/*! \brief SPI Data mode /*! \brief SPI Data mode
Specify the SPI data mode to be passed to bcm2835_spi_setDataMode() Specify the SPI data mode to be passed to bcm2835_spi_setDataMode()
*/ */
typedef enum typedef enum {
{
BCM2835_SPI_MODE0 = 0, /*!< CPOL = 0, CPHA = 0 */ BCM2835_SPI_MODE0 = 0, /*!< CPOL = 0, CPHA = 0 */
BCM2835_SPI_MODE1 = 1, /*!< CPOL = 0, CPHA = 1 */ BCM2835_SPI_MODE1 = 1, /*!< CPOL = 0, CPHA = 1 */
BCM2835_SPI_MODE2 = 2, /*!< CPOL = 1, CPHA = 0 */ BCM2835_SPI_MODE2 = 2, /*!< CPOL = 1, CPHA = 0 */
@@ -845,8 +838,7 @@ typedef enum
/*! \brief bcm2835SPIChipSelect /*! \brief bcm2835SPIChipSelect
Specify the SPI chip select pin(s) Specify the SPI chip select pin(s)
*/ */
typedef enum typedef enum {
{
BCM2835_SPI_CS0 = 0, /*!< Chip Select 0 */ BCM2835_SPI_CS0 = 0, /*!< Chip Select 0 */
BCM2835_SPI_CS1 = 1, /*!< Chip Select 1 */ BCM2835_SPI_CS1 = 1, /*!< Chip Select 1 */
BCM2835_SPI_CS2 = 2, /*!< Chip Select 2 (ie pins CS1 and CS2 are asserted) */ BCM2835_SPI_CS2 = 2, /*!< Chip Select 2 (ie pins CS1 and CS2 are asserted) */
@@ -860,8 +852,7 @@ typedef enum
It is reported that (contrary to the documentation) any even divider may used. It is reported that (contrary to the documentation) any even divider may used.
The frequencies shown for each divider have been confirmed by measurement. The frequencies shown for each divider have been confirmed by measurement.
*/ */
typedef enum typedef enum {
{
BCM2835_SPI_CLOCK_DIVIDER_65536 = 0, /*!< 65536 = 262.144us = 3.814697260kHz */ BCM2835_SPI_CLOCK_DIVIDER_65536 = 0, /*!< 65536 = 262.144us = 3.814697260kHz */
BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768, /*!< 32768 = 131.072us = 7.629394531kHz */ BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768, /*!< 32768 = 131.072us = 7.629394531kHz */
BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384, /*!< 16384 = 65.536us = 15.25878906kHz */ BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384, /*!< 16384 = 65.536us = 15.25878906kHz */
@@ -922,8 +913,7 @@ typedef enum
Specifies the divider used to generate the I2C clock from the system clock. Specifies the divider used to generate the I2C clock from the system clock.
Clock divided is based on nominal base clock rate of 250MHz Clock divided is based on nominal base clock rate of 250MHz
*/ */
typedef enum typedef enum {
{
BCM2835_I2C_CLOCK_DIVIDER_2500 = 2500, /*!< 2500 = 10us = 100 kHz */ BCM2835_I2C_CLOCK_DIVIDER_2500 = 2500, /*!< 2500 = 10us = 100 kHz */
BCM2835_I2C_CLOCK_DIVIDER_626 = 626, /*!< 622 = 2.504us = 399.3610 kHz */ BCM2835_I2C_CLOCK_DIVIDER_626 = 626, /*!< 622 = 2.504us = 399.3610 kHz */
BCM2835_I2C_CLOCK_DIVIDER_150 = 150, /*!< 150 = 60ns = 1.666 MHz (default at reset) */ BCM2835_I2C_CLOCK_DIVIDER_150 = 150, /*!< 150 = 60ns = 1.666 MHz (default at reset) */
@@ -933,8 +923,7 @@ typedef enum
/*! \brief bcm2835I2CReasonCodes /*! \brief bcm2835I2CReasonCodes
Specifies the reason codes for the bcm2835_i2c_write and bcm2835_i2c_read functions. Specifies the reason codes for the bcm2835_i2c_write and bcm2835_i2c_read functions.
*/ */
typedef enum typedef enum {
{
BCM2835_I2C_REASON_OK = 0x00, /*!< Success */ BCM2835_I2C_REASON_OK = 0x00, /*!< Success */
BCM2835_I2C_REASON_ERROR_NACK = 0x01, /*!< Received a NACK */ BCM2835_I2C_REASON_ERROR_NACK = 0x01, /*!< Received a NACK */
BCM2835_I2C_REASON_ERROR_CLKT = 0x02, /*!< Received Clock Stretch Timeout */ BCM2835_I2C_REASON_ERROR_CLKT = 0x02, /*!< Received Clock Stretch Timeout */
@@ -994,8 +983,7 @@ typedef enum
Clock divided is based on nominal PWM base clock rate of 19.2MHz Clock divided is based on nominal PWM base clock rate of 19.2MHz
The frequencies shown for each divider have been confirmed by measurement The frequencies shown for each divider have been confirmed by measurement
*/ */
typedef enum typedef enum {
{
BCM2835_PWM_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 9.375kHz */ BCM2835_PWM_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 9.375kHz */
BCM2835_PWM_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 18.75kHz */ BCM2835_PWM_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 18.75kHz */
BCM2835_PWM_CLOCK_DIVIDER_512 = 512, /*!< 512 = 37.5kHz */ BCM2835_PWM_CLOCK_DIVIDER_512 = 512, /*!< 512 = 37.5kHz */
@@ -1578,7 +1566,8 @@ extern "C" {
\param[in] buf_len Number of bytes to receive in the buf buffer. \param[in] buf_len Number of bytes to receive in the buf buffer.
\return reason see \ref bcm2835I2CReasonCodes \return reason see \ref bcm2835I2CReasonCodes
*/ */
extern uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint32_t buf_len); extern uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf,
uint32_t buf_len);
/*! @} */ /*! @} */
+96 -31
View File
@@ -35,8 +35,9 @@ int get_rpi_info(rpi_info *info)
int found = 0; int found = 0;
int len; int len;
if ((fp = fopen("/proc/cpuinfo", "r")) == NULL) if ((fp = fopen("/proc/cpuinfo", "r")) == NULL) {
return -1; return -1;
}
while(!feof(fp)) { while(!feof(fp)) {
fgets(buffer, sizeof(buffer), fp); fgets(buffer, sizeof(buffer), fp);
sscanf(buffer, "Hardware : %s", hardware); sscanf(buffer, "Hardware : %s", hardware);
@@ -51,48 +52,111 @@ int get_rpi_info(rpi_info *info)
} }
fclose(fp); fclose(fp);
if (!found) if (!found) {
return -1; return -1;
}
if ((len = strlen(revision)) == 0) if ((len = strlen(revision)) == 0) {
return -1; return -1;
}
if (len >= 6 && strtol((char[]){revision[len-6],0}, NULL, 16) & 8) { if (len >= 6 && strtol((char[]) {
revision[len-6],0
}, NULL, 16) & 8) {
// new scheme // new scheme
//info->rev = revision[len-1]-'0'; //info->rev = revision[len-1]-'0';
strcpy(info->revision, revision); strcpy(info->revision, revision);
switch (revision[len-2]) { switch (revision[len-2]) {
case '0': info->type = "Model A"; info->p1_revision = 2; break; case '0':
case '1': info->type = "Model B"; info->p1_revision = 2; break; info->type = "Model A";
case '2': info->type = "Model A+"; info->p1_revision = 3; break; info->p1_revision = 2;
case '3': info->type = "Model B+"; info->p1_revision = 3; break; break;
case '4': info->type = "Pi 2 Model B"; info->p1_revision = 3; break; case '1':
case '5': info->type = "Alpha"; info->p1_revision = 3; break; info->type = "Model B";
case '6': info->type = "Compute"; info->p1_revision = 0; break; info->p1_revision = 2;
case '8': info->type = "Pi 3 Model B"; info->p1_revision = 3; break; break;
case '9': info->type = "Zero"; info->p1_revision = 3; break; case '2':
default : info->type = "Unknown"; info->p1_revision = 3; break; info->type = "Model A+";
info->p1_revision = 3;
break;
case '3':
info->type = "Model B+";
info->p1_revision = 3;
break;
case '4':
info->type = "Pi 2 Model B";
info->p1_revision = 3;
break;
case '5':
info->type = "Alpha";
info->p1_revision = 3;
break;
case '6':
info->type = "Compute";
info->p1_revision = 0;
break;
case '8':
info->type = "Pi 3 Model B";
info->p1_revision = 3;
break;
case '9':
info->type = "Zero";
info->p1_revision = 3;
break;
default :
info->type = "Unknown";
info->p1_revision = 3;
break;
} }
switch (revision[len-4]) { switch (revision[len-4]) {
case '0': info->processor = "BCM2835"; break; case '0':
case '1': info->processor = "BCM2836"; break; info->processor = "BCM2835";
case '2': info->processor = "BCM2837"; break; break;
default : info->processor = "Unknown"; break; case '1':
info->processor = "BCM2836";
break;
case '2':
info->processor = "BCM2837";
break;
default :
info->processor = "Unknown";
break;
} }
switch (revision[len-5]) { switch (revision[len-5]) {
case '0': info->manufacturer = "Sony"; break; case '0':
case '1': info->manufacturer = "Egoman"; break; info->manufacturer = "Sony";
case '2': info->manufacturer = "Embest"; break; break;
case '4': info->manufacturer = "Embest"; break; case '1':
default : info->manufacturer = "Unknown"; break; info->manufacturer = "Egoman";
break;
case '2':
info->manufacturer = "Embest";
break;
case '4':
info->manufacturer = "Embest";
break;
default :
info->manufacturer = "Unknown";
break;
} }
switch (strtol((char[]){revision[len-6],0}, NULL, 16) & 7) { switch (strtol((char[]) {
case 0: info->ram = "256M"; break; revision[len-6],0
case 1: info->ram = "512M"; break; }, NULL, 16) & 7) {
case 2: info->ram = "1024M"; break; case 0:
default: info->ram = "Unknown"; break; info->ram = "256M";
break;
case 1:
info->ram = "512M";
break;
case 2:
info->ram = "1024M";
break;
default:
info->ram = "Unknown";
break;
} }
} else { }
else {
// old scheme // old scheme
info->ram = "Unknown"; info->ram = "Unknown";
info->manufacturer = "Unknown"; info->manufacturer = "Unknown";
@@ -101,10 +165,11 @@ int get_rpi_info(rpi_info *info)
strcpy(info->revision, revision); strcpy(info->revision, revision);
// get last four characters (ignore preceeding 1000 for overvolt) // get last four characters (ignore preceeding 1000 for overvolt)
if (len > 4) if (len > 4) {
rev = (char *)&revision+len-4; rev = (char *)&revision+len-4;
else } else {
rev = revision; rev = revision;
}
if ((strcmp(rev, "0002") == 0) || if ((strcmp(rev, "0002") == 0) ||
(strcmp(rev, "0003") == 0)) { (strcmp(rev, "0003") == 0)) {
+1 -2
View File
@@ -28,8 +28,7 @@ SOFTWARE.
extern "C" { extern "C" {
#endif #endif
typedef struct typedef struct {
{
int p1_revision; int p1_revision;
char *ram; char *ram;
char *manufacturer; char *manufacturer;
+3 -2
View File
@@ -39,10 +39,11 @@ int piHiPri (const int pri)
memset (&sched, 0, sizeof(sched)) ; memset (&sched, 0, sizeof(sched)) ;
if (pri > sched_get_priority_max (SCHED_RR)) if (pri > sched_get_priority_max (SCHED_RR)) {
sched.sched_priority = sched_get_priority_max (SCHED_RR) ; sched.sched_priority = sched_get_priority_max (SCHED_RR) ;
else } else {
sched.sched_priority = pri ; sched.sched_priority = pri ;
}
return sched_setscheduler (0, SCHED_RR, &sched) ; return sched_setscheduler (0, SCHED_RR, &sched) ;
} }
+35 -17
View File
@@ -55,8 +55,7 @@ static pthread_t *threadIds[64] = {NULL};
// sysFds: // sysFds:
// Map a file descriptor from the /sys/class/gpio/gpioX/value // Map a file descriptor from the /sys/class/gpio/gpioX/value
static int sysFds[64] = static int sysFds[64] = {
{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
@@ -95,7 +94,8 @@ int get_gpio_number(uint8_t physPin, uint8_t *gpio)
return 0; return 0;
} }
void *interruptHandler(void *args) { void *interruptHandler(void *args)
{
int fd, ret; int fd, ret;
struct pollfd polls; struct pollfd polls;
char c; char c;
@@ -142,7 +142,8 @@ void *interruptHandler(void *args) {
return NULL; return NULL;
} }
void rpi_util::pinMode(uint8_t physPin, uint8_t mode) { void rpi_util::pinMode(uint8_t physPin, uint8_t mode)
{
uint8_t gpioPin; uint8_t gpioPin;
if (get_gpio_number(physPin, &gpioPin)) { if (get_gpio_number(physPin, &gpioPin)) {
@@ -158,7 +159,8 @@ void rpi_util::pinMode(uint8_t physPin, uint8_t mode) {
} }
} }
void rpi_util::digitalWrite(uint8_t physPin, uint8_t value) { void rpi_util::digitalWrite(uint8_t physPin, uint8_t value)
{
uint8_t gpioPin; uint8_t gpioPin;
if (get_gpio_number(physPin, &gpioPin)) { if (get_gpio_number(physPin, &gpioPin)) {
@@ -178,7 +180,8 @@ void rpi_util::digitalWrite(uint8_t physPin, uint8_t value) {
} }
} }
uint8_t rpi_util::digitalRead(uint8_t physPin) { uint8_t rpi_util::digitalRead(uint8_t physPin)
{
uint8_t gpioPin; uint8_t gpioPin;
if (get_gpio_number(physPin, &gpioPin)) { if (get_gpio_number(physPin, &gpioPin)) {
@@ -194,7 +197,8 @@ uint8_t rpi_util::digitalRead(uint8_t physPin) {
} }
} }
void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode) { void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode)
{
FILE *fd; FILE *fd;
char fName[40]; char fName[40];
char c; char c;
@@ -228,7 +232,8 @@ void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode) {
snprintf(fName, sizeof(fName), "/sys/class/gpio/gpio%d/direction", gpioPin) ; snprintf(fName, sizeof(fName), "/sys/class/gpio/gpio%d/direction", gpioPin) ;
if ((fd = fopen (fName, "w")) == NULL) { if ((fd = fopen (fName, "w")) == NULL) {
fprintf (stderr, "attachInterrupt: Unable to open GPIO direction interface for pin %d: %s\n", physPin, strerror(errno)); fprintf (stderr, "attachInterrupt: Unable to open GPIO direction interface for pin %d: %s\n",
physPin, strerror(errno));
exit(1) ; exit(1) ;
} }
fprintf(fd, "in\n") ; fprintf(fd, "in\n") ;
@@ -236,14 +241,23 @@ void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode) {
snprintf(fName, sizeof(fName), "/sys/class/gpio/gpio%d/edge", gpioPin) ; snprintf(fName, sizeof(fName), "/sys/class/gpio/gpio%d/edge", gpioPin) ;
if ((fd = fopen(fName, "w")) == NULL) { if ((fd = fopen(fName, "w")) == NULL) {
fprintf (stderr, "attachInterrupt: Unable to open GPIO edge interface for pin %d: %s\n", physPin, strerror(errno)); fprintf (stderr, "attachInterrupt: Unable to open GPIO edge interface for pin %d: %s\n", physPin,
strerror(errno));
exit(1) ; exit(1) ;
} }
switch (mode) { switch (mode) {
case CHANGE: fprintf(fd, "both\n"); break; case CHANGE:
case FALLING: fprintf(fd, "falling\n"); break; fprintf(fd, "both\n");
case RISING: fprintf(fd, "rising\n"); break; break;
case NONE: fprintf(fd, "none\n"); break; case FALLING:
fprintf(fd, "falling\n");
break;
case RISING:
fprintf(fd, "rising\n");
break;
case NONE:
fprintf(fd, "none\n");
break;
default: default:
logError("attachInterrupt: Invalid mode\n"); logError("attachInterrupt: Invalid mode\n");
fclose(fd); fclose(fd);
@@ -275,7 +289,8 @@ void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode) {
pthread_create(threadIds[gpioPin], NULL, interruptHandler, (void *)threadArgs); pthread_create(threadIds[gpioPin], NULL, interruptHandler, (void *)threadArgs);
} }
void rpi_util::detachInterrupt(uint8_t physPin) { void rpi_util::detachInterrupt(uint8_t physPin)
{
uint8_t gpioPin; uint8_t gpioPin;
if (get_gpio_number(physPin, &gpioPin)) { if (get_gpio_number(physPin, &gpioPin)) {
@@ -305,18 +320,21 @@ void rpi_util::detachInterrupt(uint8_t physPin) {
fclose(fp); fclose(fp);
} }
uint8_t rpi_util::digitalPinToInterrupt(uint8_t physPin) { uint8_t rpi_util::digitalPinToInterrupt(uint8_t physPin)
{
// No need to convert the pin to gpio, we do it in attachInterrupt(). // No need to convert the pin to gpio, we do it in attachInterrupt().
return physPin; return physPin;
} }
void rpi_util::interrupts() { void rpi_util::interrupts()
{
pthread_mutex_lock(&intMutex); pthread_mutex_lock(&intMutex);
interruptsEnabled = true; interruptsEnabled = true;
pthread_mutex_unlock(&intMutex); pthread_mutex_unlock(&intMutex);
} }
void rpi_util::noInterrupts() { void rpi_util::noInterrupts()
{
pthread_mutex_lock(&intMutex); pthread_mutex_lock(&intMutex);
interruptsEnabled = false; interruptsEnabled = false;
pthread_mutex_unlock(&intMutex); pthread_mutex_unlock(&intMutex);
+2 -1
View File
@@ -29,7 +29,8 @@ const int pin_to_gpio_rev1[41] = {-1, -1, -1, 0, -1, 1, -1, 4, 14, -1, 15, 17, 1
const int pin_to_gpio_rev2[41] = {-1, -1, -1, 2, -1, 3, -1, 4, 14, -1, 15, 17, 18, 27, -1, 22, 23, -1, 24, 10, -1, 9, 25, 11, 8, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; const int pin_to_gpio_rev2[41] = {-1, -1, -1, 2, -1, 3, -1, 4, 14, -1, 15, 17, 18, 27, -1, 22, 23, -1, 24, 10, -1, 9, 25, 11, 8, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
const int pin_to_gpio_rev3[41] = {-1, -1, -1, 2, -1, 3, -1, 4, 14, -1, 15, 17, 18, 27, -1, 22, 23, -1, 24, 10, -1, 9, 25, 11, 8, -1, 7, -1, -1, 5, -1, 6, 12, 13, -1, 19, 16, 26, 20, -1, 21 }; const int pin_to_gpio_rev3[41] = {-1, -1, -1, 2, -1, 3, -1, 4, 14, -1, 15, 17, 18, 27, -1, 22, 23, -1, 24, 10, -1, 9, 25, 11, 8, -1, 7, -1, -1, 5, -1, 6, 12, 13, -1, 19, 16, 26, 20, -1, 21 };
namespace rpi_util { namespace rpi_util
{
typedef enum { typedef enum {
LSBFIRST = BCM2835_SPI_BIT_ORDER_LSBFIRST, LSBFIRST = BCM2835_SPI_BIT_ORDER_LSBFIRST,
+32 -19
View File
@@ -47,13 +47,15 @@ uint8_t SPIFlash::UNIQUEID[8];
/// get this from the datasheet of your flash chip /// get this from the datasheet of your flash chip
/// Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf) /// Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf)
/// Example for Winbond 4Mbit W25X40CL: 0xEF30 (page 14: http://www.winbond.com/NR/rdonlyres/6E25084C-0BFE-4B25-903D-AE10221A0929/0/W25X40CL.pdf) /// Example for Winbond 4Mbit W25X40CL: 0xEF30 (page 14: http://www.winbond.com/NR/rdonlyres/6E25084C-0BFE-4B25-903D-AE10221A0929/0/W25X40CL.pdf)
SPIFlash::SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID) { SPIFlash::SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID)
{
_slaveSelectPin = slaveSelectPin; _slaveSelectPin = slaveSelectPin;
_jedecID = jedecID; _jedecID = jedecID;
} }
/// Select the flash chip /// Select the flash chip
void SPIFlash::select() { void SPIFlash::select()
{
//save current SPI settings //save current SPI settings
#ifndef SPI_HAS_TRANSACTION #ifndef SPI_HAS_TRANSACTION
noInterrupts(); noInterrupts();
@@ -69,14 +71,16 @@ void SPIFlash::select() {
// set FLASH SPI settings // set FLASH SPI settings
SPI.setDataMode(SPI_MODE0); SPI.setDataMode(SPI_MODE0);
SPI.setBitOrder(MSBFIRST); SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV4); //decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present SPI.setClockDivider(
SPI_CLOCK_DIV4); //decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present
SPI.begin(); SPI.begin();
#endif #endif
hwDigitalWrite(_slaveSelectPin, LOW); hwDigitalWrite(_slaveSelectPin, LOW);
} }
/// UNselect the flash chip /// UNselect the flash chip
void SPIFlash::unselect() { void SPIFlash::unselect()
{
hwDigitalWrite(_slaveSelectPin, HIGH); hwDigitalWrite(_slaveSelectPin, HIGH);
//restore SPI settings to what they were before talking to the FLASH chip //restore SPI settings to what they were before talking to the FLASH chip
#ifdef SPI_HAS_TRANSACTION #ifdef SPI_HAS_TRANSACTION
@@ -150,7 +154,8 @@ uint8_t* SPIFlash::readUniqueId()
} }
/// read 1 byte from flash memory /// read 1 byte from flash memory
uint8_t SPIFlash::readByte(uint32_t addr) { uint8_t SPIFlash::readByte(uint32_t addr)
{
command(SPIFLASH_ARRAYREADLOWFREQ); command(SPIFLASH_ARRAYREADLOWFREQ);
SPI.transfer(addr >> 16); SPI.transfer(addr >> 16);
SPI.transfer(addr >> 8); SPI.transfer(addr >> 8);
@@ -161,7 +166,8 @@ uint8_t SPIFlash::readByte(uint32_t addr) {
} }
/// read unlimited # of bytes /// read unlimited # of bytes
void SPIFlash::readBytes(uint32_t addr, void* buf, uint16_t len) { void SPIFlash::readBytes(uint32_t addr, void* buf, uint16_t len)
{
command(SPIFLASH_ARRAYREAD); command(SPIFLASH_ARRAYREAD);
SPI.transfer(addr >> 16); SPI.transfer(addr >> 16);
SPI.transfer(addr >> 8); SPI.transfer(addr >> 8);
@@ -174,13 +180,13 @@ void SPIFlash::readBytes(uint32_t addr, void* buf, uint16_t len) {
} }
/// Send a command to the flash chip, pass TRUE for isWrite when its a write command /// Send a command to the flash chip, pass TRUE for isWrite when its a write command
void SPIFlash::command(uint8_t cmd, boolean isWrite){ void SPIFlash::command(uint8_t cmd, boolean isWrite)
{
#if defined(__AVR_ATmega32U4__) // Arduino Leonardo, MoteinoLeo #if defined(__AVR_ATmega32U4__) // Arduino Leonardo, MoteinoLeo
DDRB |= B00000001; // Make sure the SS pin (PB0 - used by RFM12B on MoteinoLeo R1) is set as output HIGH! DDRB |= B00000001; // Make sure the SS pin (PB0 - used by RFM12B on MoteinoLeo R1) is set as output HIGH!
PORTB |= B00000001; PORTB |= B00000001;
#endif #endif
if (isWrite) if (isWrite) {
{
command(SPIFLASH_WRITEENABLE); // Write Enable command(SPIFLASH_WRITEENABLE); // Write Enable
unselect(); unselect();
} }
@@ -221,7 +227,8 @@ uint8_t SPIFlash::readStatus()
/// Write 1 byte to flash memory /// Write 1 byte to flash memory
/// WARNING: you can only write to previously erased memory locations (see datasheet) /// WARNING: you can only write to previously erased memory locations (see datasheet)
/// use the block erase commands to first clear memory (write 0xFFs) /// use the block erase commands to first clear memory (write 0xFFs)
void SPIFlash::writeByte(uint32_t addr, uint8_t byt) { void SPIFlash::writeByte(uint32_t addr, uint8_t byt)
{
command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program
SPI.transfer(addr >> 16); SPI.transfer(addr >> 16);
SPI.transfer(addr >> 8); SPI.transfer(addr >> 8);
@@ -235,7 +242,8 @@ void SPIFlash::writeByte(uint32_t addr, uint8_t byt) {
/// use the block erase commands to first clear memory (write 0xFFs) /// use the block erase commands to first clear memory (write 0xFFs)
/// This version handles both page alignment and data blocks larger than 256 bytes. /// This version handles both page alignment and data blocks larger than 256 bytes.
/// See documentation of #MY_SPIFLASH_SST25TYPE define for more information /// See documentation of #MY_SPIFLASH_SST25TYPE define for more information
void SPIFlash::writeBytes(uint32_t addr, const void* buf, uint16_t len) { void SPIFlash::writeBytes(uint32_t addr, const void* buf, uint16_t len)
{
#ifdef MY_SPIFLASH_SST25TYPE #ifdef MY_SPIFLASH_SST25TYPE
//SST25 Type of Flash does not support Page Programming but AAI Word Programming //SST25 Type of Flash does not support Page Programming but AAI Word Programming
uint16_t i=0; uint16_t i=0;
@@ -285,8 +293,7 @@ void SPIFlash::writeBytes(uint32_t addr, const void* buf, uint16_t len) {
uint16_t n; uint16_t n;
uint16_t maxBytes = 256-(addr%256); // force the first set of bytes to stay within the first page uint16_t maxBytes = 256-(addr%256); // force the first set of bytes to stay within the first page
uint16_t offset = 0; uint16_t offset = 0;
while (len>0) while (len>0) {
{
n = (len<=maxBytes) ? len : maxBytes; n = (len<=maxBytes) ? len : maxBytes;
command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program
SPI.transfer(addr >> 16); SPI.transfer(addr >> 16);
@@ -312,13 +319,15 @@ void SPIFlash::writeBytes(uint32_t addr, const void* buf, uint16_t len) {
/// other things and later check if the chip is done with busy() /// other things and later check if the chip is done with busy()
/// note that any command will first wait for chip to become available using busy() /// note that any command will first wait for chip to become available using busy()
/// so no need to do that twice /// so no need to do that twice
void SPIFlash::chipErase() { void SPIFlash::chipErase()
{
command(SPIFLASH_CHIPERASE, true); command(SPIFLASH_CHIPERASE, true);
unselect(); unselect();
} }
/// erase a 4Kbyte block /// erase a 4Kbyte block
void SPIFlash::blockErase4K(uint32_t addr) { void SPIFlash::blockErase4K(uint32_t addr)
{
command(SPIFLASH_BLOCKERASE_4K, true); // Block Erase command(SPIFLASH_BLOCKERASE_4K, true); // Block Erase
SPI.transfer(addr >> 16); SPI.transfer(addr >> 16);
SPI.transfer(addr >> 8); SPI.transfer(addr >> 8);
@@ -327,7 +336,8 @@ void SPIFlash::blockErase4K(uint32_t addr) {
} }
/// erase a 32Kbyte block /// erase a 32Kbyte block
void SPIFlash::blockErase32K(uint32_t addr) { void SPIFlash::blockErase32K(uint32_t addr)
{
command(SPIFLASH_BLOCKERASE_32K, true); // Block Erase command(SPIFLASH_BLOCKERASE_32K, true); // Block Erase
SPI.transfer(addr >> 16); SPI.transfer(addr >> 16);
SPI.transfer(addr >> 8); SPI.transfer(addr >> 8);
@@ -335,17 +345,20 @@ void SPIFlash::blockErase32K(uint32_t addr) {
unselect(); unselect();
} }
void SPIFlash::sleep() { void SPIFlash::sleep()
{
command(SPIFLASH_SLEEP); command(SPIFLASH_SLEEP);
unselect(); unselect();
} }
void SPIFlash::wakeup() { void SPIFlash::wakeup()
{
command(SPIFLASH_WAKE); command(SPIFLASH_WAKE);
unselect(); unselect();
} }
/// cleanup /// cleanup
void SPIFlash::end() { void SPIFlash::end()
{
SPI.end(); SPI.end();
} }
+6 -3
View File
@@ -112,17 +112,20 @@
#endif #endif
/** SPIFlash class */ /** SPIFlash class */
class SPIFlash { class SPIFlash
{
public: public:
static uint8_t UNIQUEID[8]; //!< Storage for unique identifier static uint8_t UNIQUEID[8]; //!< Storage for unique identifier
SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID=0); //!< Constructor SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID=0); //!< Constructor
boolean initialize(); //!< setup SPI, read device ID etc... boolean initialize(); //!< setup SPI, read device ID etc...
void command(uint8_t cmd, boolean isWrite=false); //!< Send a command to the flash chip, pass TRUE for isWrite when its a write command void command(uint8_t cmd, boolean isWrite=
false); //!< Send a command to the flash chip, pass TRUE for isWrite when its a write command
uint8_t readStatus(); //!< return the STATUS register uint8_t readStatus(); //!< return the STATUS register
uint8_t readByte(uint32_t addr); //!< read 1 byte from flash memory uint8_t readByte(uint32_t addr); //!< read 1 byte from flash memory
void readBytes(uint32_t addr, void* buf, uint16_t len); //!< read unlimited # of bytes void readBytes(uint32_t addr, void* buf, uint16_t len); //!< read unlimited # of bytes
void writeByte(uint32_t addr, uint8_t byt); //!< Write 1 byte to flash memory void writeByte(uint32_t addr, uint8_t byt); //!< Write 1 byte to flash memory
void writeBytes(uint32_t addr, const void* buf, uint16_t len); //!< write multiple bytes to flash memory (up to 64K), if define SPIFLASH_SST25TYPE is set AAI Word Programming will be used void writeBytes(uint32_t addr, const void* buf,
uint16_t len); //!< write multiple bytes to flash memory (up to 64K), if define SPIFLASH_SST25TYPE is set AAI Word Programming will be used
boolean busy(); //!< check if the chip is busy erasing/writing boolean busy(); //!< check if the chip is busy erasing/writing
void chipErase(); //!< erase entire flash memory array void chipErase(); //!< erase entire flash memory array
void blockErase4K(uint32_t address); //!< erase a 4Kbyte block void blockErase4K(uint32_t address); //!< erase a 4Kbyte block

Some files were not shown because too many files have changed in this diff Show More