Added {} to control structures for clarity (#600)
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
* network topology allowing messages to be routed to nodes.
|
* network topology allowing messages to be routed to nodes.
|
||||||
*
|
*
|
||||||
* Created by Tomas Hozza <thozza@gmail.com>
|
* Created by Tomas Hozza <thozza@gmail.com>
|
||||||
* Copyright (C) 2015 Tomas Hozza
|
* Copyright (C) 2015 Tomas Hozza
|
||||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||||
*
|
*
|
||||||
* Documentation: http://www.mysensors.org
|
* Documentation: http://www.mysensors.org
|
||||||
@@ -135,7 +135,7 @@ bool gatewayTransportInit() {
|
|||||||
_w5100_spi_en(false);
|
_w5100_spi_en(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
MY_SERIALDEVICE.print(F("IP: "));
|
MY_SERIALDEVICE.print(F("IP: "));
|
||||||
MY_SERIALDEVICE.println(Ethernet.localIP());
|
MY_SERIALDEVICE.println(Ethernet.localIP());
|
||||||
// give the Ethernet interface a second to initialize
|
// give the Ethernet interface a second to initialize
|
||||||
@@ -437,8 +437,9 @@ void gatewayTransportRenewIP()
|
|||||||
unsigned long now = hwMillis();
|
unsigned long now = hwMillis();
|
||||||
|
|
||||||
// http://playground.arduino.cc/Code/TimingRollover
|
// http://playground.arduino.cc/Code/TimingRollover
|
||||||
if ((long)(now - next_time) < 0)
|
if ((long)(now - next_time) < 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (Ethernet.maintain() & ~(0x06)) {
|
if (Ethernet.maintain() & ~(0x06)) {
|
||||||
debug(PSTR("IP was not renewed correctly\n"));
|
debug(PSTR("IP was not renewed correctly\n"));
|
||||||
/* Error occured -> IP was not renewed */
|
/* Error occured -> IP was not renewed */
|
||||||
|
|||||||
@@ -49,8 +49,9 @@ 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;
|
||||||
|
}
|
||||||
setIndication(INDICATION_GW_TX);
|
setIndication(INDICATION_GW_TX);
|
||||||
char *topic = protocolFormatMQTTTopic(MY_MQTT_PUBLISH_TOPIC_PREFIX, message);
|
char *topic = protocolFormatMQTTTopic(MY_MQTT_PUBLISH_TOPIC_PREFIX, message);
|
||||||
debug(PSTR("Sending message on topic: %s\n"), topic);
|
debug(PSTR("Sending message on topic: %s\n"), topic);
|
||||||
@@ -134,7 +135,7 @@ bool gatewayTransportInit() {
|
|||||||
(void)WiFi.begin(MY_ESP8266_SSID, MY_ESP8266_PASSWORD);
|
(void)WiFi.begin(MY_ESP8266_SSID, MY_ESP8266_PASSWORD);
|
||||||
#ifdef MY_IP_ADDRESS
|
#ifdef MY_IP_ADDRESS
|
||||||
WiFi.config(_MQTT_clientIp, _gatewayIp, _subnetIp);
|
WiFi.config(_MQTT_clientIp, _gatewayIp, _subnetIp);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gatewayTransportConnect();
|
gatewayTransportConnect();
|
||||||
@@ -144,15 +145,16 @@ bool gatewayTransportInit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool gatewayTransportAvailable() {
|
bool gatewayTransportAvailable() {
|
||||||
if (_MQTT_connecting)
|
if (_MQTT_connecting) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
//keep lease on dhcp address
|
//keep lease on dhcp address
|
||||||
//Ethernet.maintain();
|
//Ethernet.maintain();
|
||||||
if (!_MQTT_client.connected()) {
|
if (!_MQTT_client.connected()) {
|
||||||
//reinitialise client
|
//reinitialise client
|
||||||
if (gatewayTransportConnect())
|
if (gatewayTransportConnect()) {
|
||||||
reconnectMQTT();
|
reconnectMQTT();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_MQTT_client.loop();
|
_MQTT_client.loop();
|
||||||
|
|||||||
+32
-23
@@ -81,7 +81,7 @@ void hwPowerDown(period_t period) {
|
|||||||
sei();
|
sei();
|
||||||
// Directly sleep CPU, to prevent race conditions! (see chapter 7.7 of ATMega328P datasheet)
|
// Directly sleep CPU, to prevent race conditions! (see chapter 7.7 of ATMega328P datasheet)
|
||||||
sleep_cpu();
|
sleep_cpu();
|
||||||
sleep_disable();
|
sleep_disable();
|
||||||
// restore previous WDT settings
|
// restore previous WDT settings
|
||||||
cli();
|
cli();
|
||||||
wdt_reset();
|
wdt_reset();
|
||||||
@@ -124,12 +124,16 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo
|
|||||||
// 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();
|
||||||
// attach interrupts
|
// attach interrupts
|
||||||
_wakeUp1Interrupt = interrupt1;
|
_wakeUp1Interrupt = interrupt1;
|
||||||
_wakeUp2Interrupt = interrupt2;
|
_wakeUp2Interrupt = interrupt2;
|
||||||
if (interrupt1 != INVALID_INTERRUPT_NUM) attachInterrupt(interrupt1, wakeUp1, mode1);
|
if (interrupt1 != INVALID_INTERRUPT_NUM) {
|
||||||
if (interrupt2 != INVALID_INTERRUPT_NUM) attachInterrupt(interrupt2, wakeUp2, mode2);
|
attachInterrupt(interrupt1, wakeUp1, mode1);
|
||||||
|
}
|
||||||
|
if (interrupt2 != INVALID_INTERRUPT_NUM) {
|
||||||
|
attachInterrupt(interrupt2, wakeUp2, mode2);
|
||||||
|
}
|
||||||
|
|
||||||
if (ms>0) {
|
if (ms>0) {
|
||||||
// sleep for defined time
|
// sleep for defined time
|
||||||
hwInternalSleep(ms);
|
hwInternalSleep(ms);
|
||||||
@@ -137,15 +141,20 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo
|
|||||||
// sleep until ext interrupt triggered
|
// sleep until ext interrupt triggered
|
||||||
hwPowerDown(SLEEP_FOREVER);
|
hwPowerDown(SLEEP_FOREVER);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assure any interrupts attached, will get detached when they did not occur.
|
// Assure any interrupts attached, will get detached when they did not occur.
|
||||||
if (interrupt1 != INVALID_INTERRUPT_NUM) detachInterrupt(interrupt1);
|
if (interrupt1 != INVALID_INTERRUPT_NUM) {
|
||||||
if (interrupt2 != INVALID_INTERRUPT_NUM) detachInterrupt(interrupt2);
|
detachInterrupt(interrupt1);
|
||||||
|
}
|
||||||
|
if (interrupt2 != INVALID_INTERRUPT_NUM) {
|
||||||
|
detachInterrupt(interrupt2);
|
||||||
|
}
|
||||||
|
|
||||||
// Return what woke the mcu.
|
// Return what woke the mcu.
|
||||||
int8_t ret = MY_WAKE_UP_BY_TIMER; // default: no interrupt triggered, timer wake up
|
int8_t ret = MY_WAKE_UP_BY_TIMER; // default: no interrupt triggered, timer wake up
|
||||||
if (interruptWakeUp()) ret = static_cast<int8_t>(_wokeUpByInterrupt);
|
if (interruptWakeUp()) {
|
||||||
|
ret = static_cast<int8_t>(_wokeUpByInterrupt);
|
||||||
|
}
|
||||||
// Clear woke-up-by-interrupt flag, so next sleeps won't return immediately.
|
// Clear woke-up-by-interrupt flag, so next sleeps won't return immediately.
|
||||||
_wokeUpByInterrupt = INVALID_INTERRUPT_NUM;
|
_wokeUpByInterrupt = INVALID_INTERRUPT_NUM;
|
||||||
|
|
||||||
@@ -153,7 +162,7 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo
|
|||||||
}
|
}
|
||||||
|
|
||||||
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));
|
||||||
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||||
@@ -162,12 +171,12 @@ uint16_t hwCPUVoltage() {
|
|||||||
ADMUX = (_BV(MUX3) | _BV(MUX2));
|
ADMUX = (_BV(MUX3) | _BV(MUX2));
|
||||||
#else
|
#else
|
||||||
ADMUX = (_BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1));
|
ADMUX = (_BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1));
|
||||||
#endif
|
#endif
|
||||||
// Vref settle
|
// Vref settle
|
||||||
delay(70);
|
delay(70);
|
||||||
// Do conversion
|
// Do conversion
|
||||||
ADCSRA |= _BV(ADSC);
|
ADCSRA |= _BV(ADSC);
|
||||||
while (bit_is_set(ADCSRA,ADSC));
|
while (bit_is_set(ADCSRA,ADSC)) {};
|
||||||
// return Vcc in mV
|
// return Vcc in mV
|
||||||
return (1125300UL) / ADC;
|
return (1125300UL) / ADC;
|
||||||
}
|
}
|
||||||
@@ -175,8 +184,8 @@ uint16_t hwCPUVoltage() {
|
|||||||
uint16_t hwCPUFrequency() {
|
uint16_t hwCPUFrequency() {
|
||||||
cli();
|
cli();
|
||||||
// setup timer1
|
// setup timer1
|
||||||
TIFR1 = 0xFF;
|
TIFR1 = 0xFF;
|
||||||
TCNT1 = 0;
|
TCNT1 = 0;
|
||||||
TCCR1A = 0;
|
TCCR1A = 0;
|
||||||
TCCR1C = 0;
|
TCCR1C = 0;
|
||||||
// save WDT settings
|
// save WDT settings
|
||||||
@@ -186,24 +195,24 @@ uint16_t hwCPUFrequency() {
|
|||||||
WDTCSR |= (1 << WDIE);
|
WDTCSR |= (1 << WDIE);
|
||||||
wdt_reset();
|
wdt_reset();
|
||||||
// start timer1 with 1024 prescaling
|
// start timer1 with 1024 prescaling
|
||||||
TCCR1B = _BV(CS12) | _BV(CS10);
|
TCCR1B = _BV(CS12) | _BV(CS10);
|
||||||
// wait until wdt interrupt
|
// wait until wdt interrupt
|
||||||
while (bit_is_clear(WDTCSR,WDIF));
|
while (bit_is_clear(WDTCSR,WDIF)) {};
|
||||||
// stop timer
|
// stop timer
|
||||||
TCCR1B = 0;
|
TCCR1B = 0;
|
||||||
// restore WDT settings
|
// restore WDT settings
|
||||||
wdt_reset();
|
wdt_reset();
|
||||||
WDTCSR |= (1 << WDCE) | (1 << WDE);
|
WDTCSR |= (1 << WDCE) | (1 << WDE);
|
||||||
WDTCSR = WDTsave;
|
WDTCSR = WDTsave;
|
||||||
sei();
|
sei();
|
||||||
// return frequency in 1/10MHz (accuracy +- 10%)
|
// return frequency in 1/10MHz (accuracy +- 10%)
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -58,7 +58,9 @@ byte i2c_eeprom_read_byte(unsigned int eeaddress ) {
|
|||||||
Wire.write((int)(eeaddress & 0xFF)); // LSB
|
Wire.write((int)(eeaddress & 0xFF)); // LSB
|
||||||
Wire.endTransmission();
|
Wire.endTransmission();
|
||||||
Wire.requestFrom(I2C_EEP_ADDRESS,1);
|
Wire.requestFrom(I2C_EEP_ADDRESS,1);
|
||||||
if (Wire.available()) rdata = Wire.read();
|
if (Wire.available()) {
|
||||||
|
rdata = Wire.read();
|
||||||
|
}
|
||||||
return rdata;
|
return rdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ void setIndication( const indication_t ind )
|
|||||||
ledsBlinkErr(ind-INDICATION_ERR_START);
|
ledsBlinkErr(ind-INDICATION_ERR_START);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (indication)
|
if (indication) {
|
||||||
indication(ind);
|
indication(ind);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-4
@@ -51,8 +51,9 @@ inline void ledsInit()
|
|||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
prevTime += LED_PROCESS_INTERVAL_MS;
|
prevTime += LED_PROCESS_INTERVAL_MS;
|
||||||
|
|
||||||
@@ -63,19 +64,25 @@ void ledsProcess() {
|
|||||||
#if defined(MY_DEFAULT_RX_LED_PIN)
|
#if defined(MY_DEFAULT_RX_LED_PIN)
|
||||||
state = (countRx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF;
|
state = (countRx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF;
|
||||||
hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, state);
|
hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, state);
|
||||||
if (countRx) --countRx;
|
if (countRx) {
|
||||||
|
--countRx;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MY_DEFAULT_TX_LED_PIN)
|
#if defined(MY_DEFAULT_TX_LED_PIN)
|
||||||
state = (countTx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF;
|
state = (countTx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF;
|
||||||
hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, state);
|
hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, state);
|
||||||
if (countTx) --countTx;
|
if (countTx) {
|
||||||
|
--countTx;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MY_DEFAULT_ERR_LED_PIN)
|
#if defined(MY_DEFAULT_ERR_LED_PIN)
|
||||||
state = (countErr & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF;
|
state = (countErr & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF;
|
||||||
hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, state);
|
hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, state);
|
||||||
if (countErr) --countErr;
|
if (countErr) {
|
||||||
|
--countErr;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+25
-2
@@ -1,3 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||||
|
* between your home built sensors/actuators and HA controller of choice.
|
||||||
|
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||||
|
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||||
|
* network topology allowing messages to be routed to nodes.
|
||||||
|
*
|
||||||
|
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||||
|
* Copyright (C) 2013-2015 Sensnology AB
|
||||||
|
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||||
|
*
|
||||||
|
* Documentation: http://www.mysensors.org
|
||||||
|
* Support Forum: http://forum.mysensors.org
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* version 2 as published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
// Initialize library and handle sketch functions like we want to
|
// Initialize library and handle sketch functions like we want to
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
@@ -12,8 +31,12 @@ int main(void) {
|
|||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
_process(); // Process incoming data
|
_process(); // Process incoming data
|
||||||
if (loop) loop(); // Call sketch loop
|
if (loop) {
|
||||||
if (serialEventRun) serialEventRun();
|
loop(); // Call sketch loop
|
||||||
|
}
|
||||||
|
if (serialEventRun) {
|
||||||
|
serialEventRun();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-3
@@ -1,4 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||||
|
* between your home built sensors/actuators and HA controller of choice.
|
||||||
|
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||||
|
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||||
|
* network topology allowing messages to be routed to nodes.
|
||||||
|
*
|
||||||
|
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||||
|
* Copyright (C) 2013-2015 Sensnology AB
|
||||||
|
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||||
|
*
|
||||||
|
* Documentation: http://www.mysensors.org
|
||||||
|
* Support Forum: http://forum.mysensors.org
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* version 2 as published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
//This may be used to change user task stack size:
|
//This may be used to change user task stack size:
|
||||||
//#define CONT_STACKSIZE 4096
|
//#define CONT_STACKSIZE 4096
|
||||||
#include "Schedule.h"
|
#include "Schedule.h"
|
||||||
@@ -109,8 +127,9 @@ 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)();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void __gdb_init() {}
|
extern "C" void __gdb_init() {}
|
||||||
@@ -144,4 +163,4 @@ extern "C" void user_init(void) {
|
|||||||
LOOP_QUEUE_SIZE);
|
LOOP_QUEUE_SIZE);
|
||||||
|
|
||||||
system_init_done_cb(&init_done);
|
system_init_done_cb(&init_done);
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-2
@@ -1,4 +1,22 @@
|
|||||||
// Initialize library and handle sketch functions like we want to
|
/**
|
||||||
|
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||||
|
* between your home built sensors/actuators and HA controller of choice.
|
||||||
|
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||||
|
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||||
|
* network topology allowing messages to be routed to nodes.
|
||||||
|
*
|
||||||
|
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||||
|
* Copyright (C) 2013-2015 Sensnology AB
|
||||||
|
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||||
|
*
|
||||||
|
* Documentation: http://www.mysensors.org
|
||||||
|
* Support Forum: http://forum.mysensors.org
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* version 2 as published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
// Initialize library and handle sketch functions like we want to
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
@@ -129,7 +147,9 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
_process(); // Process incoming data
|
_process(); // Process incoming data
|
||||||
if (loop) loop(); // Call sketch loop
|
if (loop) {
|
||||||
|
loop(); // Call sketch loop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-6
@@ -75,10 +75,12 @@ 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 {
|
||||||
@@ -173,7 +175,7 @@ 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) {
|
||||||
return atoi(data);
|
return atoi(data);
|
||||||
@@ -183,7 +185,7 @@ 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) {
|
||||||
return atoi(data);
|
return atoi(data);
|
||||||
@@ -211,7 +213,7 @@ MyMessage& MyMessage::setDestination(uint8_t _destination) {
|
|||||||
// 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);
|
||||||
memcpy(data, value, payloadLength);
|
memcpy(data, value, payloadLength);
|
||||||
return *this;
|
return *this;
|
||||||
@@ -221,7 +223,7 @@ 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);
|
||||||
if (length) {
|
if (length) {
|
||||||
strncpy(data, value, length);
|
strncpy(data, value, length);
|
||||||
}
|
}
|
||||||
// null terminate string
|
// null terminate string
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
* version 2 as published by the Free Software Foundation.
|
* version 2 as published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MyOTAFirmwareUpdate.h"
|
#include "MyOTAFirmwareUpdate.h"
|
||||||
|
|
||||||
// global variables
|
// global variables
|
||||||
@@ -76,7 +76,7 @@ bool firmwareOTAUpdateProcess() {
|
|||||||
// erase lower 32K -> max flash size for ATMEGA328
|
// erase lower 32K -> max flash size for ATMEGA328
|
||||||
_flash.blockErase32K(0);
|
_flash.blockErase32K(0);
|
||||||
// wait until flash erased
|
// wait until flash erased
|
||||||
while ( _flash.busy() );
|
while ( _flash.busy() ) {}
|
||||||
_fwBlock = _fc.blocks;
|
_fwBlock = _fc.blocks;
|
||||||
_fwUpdateOngoing = true;
|
_fwUpdateOngoing = true;
|
||||||
// reset flags
|
// reset flags
|
||||||
@@ -96,7 +96,7 @@ bool firmwareOTAUpdateProcess() {
|
|||||||
// write to flash
|
// write to flash
|
||||||
_flash.writeBytes( ((_fwBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET, firmwareResponse->data, FIRMWARE_BLOCK_SIZE);
|
_flash.writeBytes( ((_fwBlock - 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() ) {}
|
||||||
_fwBlock--;
|
_fwBlock--;
|
||||||
if (!_fwBlock) {
|
if (!_fwBlock) {
|
||||||
// We're finished! Do a checksum and reboot.
|
// We're finished! Do a checksum and reboot.
|
||||||
@@ -137,7 +137,7 @@ void presentBootloaderInformation(){
|
|||||||
// add bootloader information
|
// add bootloader information
|
||||||
reqFWConfig->BLVersion = MY_OTA_BOOTLOADER_VERSION;
|
reqFWConfig->BLVersion = MY_OTA_BOOTLOADER_VERSION;
|
||||||
_fwUpdateOngoing = false;
|
_fwUpdateOngoing = false;
|
||||||
_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_CONFIG_REQUEST, false));
|
_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_CONFIG_REQUEST, false));
|
||||||
}
|
}
|
||||||
// do a crc16 on the whole received firmware
|
// do a crc16 on the whole received firmware
|
||||||
bool transportIsValidFirmware() {
|
bool transportIsValidFirmware() {
|
||||||
@@ -146,10 +146,12 @@ bool transportIsValidFirmware() {
|
|||||||
for (uint16_t i = 0; i < _fc.blocks * FIRMWARE_BLOCK_SIZE; ++i) {
|
for (uint16_t i = 0; i < _fc.blocks * FIRMWARE_BLOCK_SIZE; ++i) {
|
||||||
crc ^= _flash.readByte(i + FIRMWARE_START_OFFSET);
|
crc ^= _flash.readByte(i + FIRMWARE_START_OFFSET);
|
||||||
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
|
}
|
||||||
crc = (crc >> 1);
|
else {
|
||||||
|
crc = (crc >> 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return crc == _fc.crc;
|
return crc == _fc.crc;
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
*
|
*
|
||||||
* |E| SYS | SUB | Message | Comment
|
* |E| SYS | SUB | Message | Comment
|
||||||
* |-|------|-------|-------------------------------------------|----------------------------------------------------------------------------
|
* |-|------|-------|-------------------------------------------|----------------------------------------------------------------------------
|
||||||
* | | OTA | FWP | UPDATE | FW update initiated
|
* | | OTA | FWP | UPDATE | FW update initiated
|
||||||
* |!| OTA | FWP | FLASH INIT FAIL | Failed to initialise flash
|
* |!| OTA | FWP | FLASH INIT FAIL | Failed to initialise flash
|
||||||
* | | OTA | FWP | UPDATE SKIPPED | FW update skipped, no newer version available
|
* | | OTA | FWP | UPDATE SKIPPED | FW update skipped, no newer version available
|
||||||
* | | OTA | FWP | RECV B=%04X | Received FW block (B)
|
* | | OTA | FWP | RECV B=%04X | Received FW block (B)
|
||||||
@@ -132,10 +132,10 @@ bool firmwareOTAUpdateProcess();
|
|||||||
*/
|
*/
|
||||||
bool transportIsValidFirmware();
|
bool transportIsValidFirmware();
|
||||||
/**
|
/**
|
||||||
* @brief Present bootloader/FW information upon startup
|
* @brief Present bootloader/FW information upon startup
|
||||||
*/
|
*/
|
||||||
void presentBootloaderInformation();
|
void presentBootloaderInformation();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** @}*/
|
/** @}*/
|
||||||
|
|||||||
@@ -70,10 +70,12 @@ bool protocolParse(MyMessage &message, char *inputString) {
|
|||||||
value = str;
|
value = str;
|
||||||
// Remove trailing carriage return and newline character (if it exists)
|
// Remove trailing carriage return and newline character (if it exists)
|
||||||
uint8_t lastCharacter = strlen(value)-1;
|
uint8_t lastCharacter = strlen(value)-1;
|
||||||
if (value[lastCharacter] == '\r')
|
if (value[lastCharacter] == '\r') {
|
||||||
value[lastCharacter] = 0;
|
value[lastCharacter] = 0;
|
||||||
if (value[lastCharacter] == '\n')
|
}
|
||||||
|
if (value[lastCharacter] == '\n') {
|
||||||
value[lastCharacter] = 0;
|
value[lastCharacter] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -81,16 +83,18 @@ bool protocolParse(MyMessage &message, char *inputString) {
|
|||||||
}
|
}
|
||||||
//debug(PSTR("Received %d"), i);
|
//debug(PSTR("Received %d"), i);
|
||||||
// Check for invalid input
|
// Check for invalid input
|
||||||
if (i < 5)
|
if (i < 5) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
message.sender = GATEWAY_ADDRESS;
|
message.sender = GATEWAY_ADDRESS;
|
||||||
message.last = GATEWAY_ADDRESS;
|
message.last = GATEWAY_ADDRESS;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,8 +162,9 @@ bool protocolMQTTParse(MyMessage &message, char* topic, uint8_t* payload, unsign
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i != 6)
|
if (i != 6) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
message.sender = GATEWAY_ADDRESS;
|
message.sender = GATEWAY_ADDRESS;
|
||||||
message.last = GATEWAY_ADDRESS;
|
message.last = GATEWAY_ADDRESS;
|
||||||
@@ -190,11 +195,14 @@ bool protocolMQTTParse(MyMessage &message, char* topic, uint8_t* payload, unsign
|
|||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-9
@@ -72,8 +72,9 @@ void _infiniteLoop(void) {
|
|||||||
void _begin(void) {
|
void _begin(void) {
|
||||||
hwWatchdogReset();
|
hwWatchdogReset();
|
||||||
|
|
||||||
if (preHwInit)
|
if (preHwInit) {
|
||||||
preHwInit();
|
preHwInit();
|
||||||
|
}
|
||||||
|
|
||||||
hwInit();
|
hwInit();
|
||||||
|
|
||||||
@@ -120,7 +121,7 @@ void _begin(void) {
|
|||||||
pinMode(MY_NODE_UNLOCK_PIN, INPUT_PULLUP);
|
pinMode(MY_NODE_UNLOCK_PIN, INPUT_PULLUP);
|
||||||
// Make a short delay so we are sure any large external nets are fully pulled
|
// Make a short delay so we are sure any large external nets are fully pulled
|
||||||
unsigned long enter = hwMillis();
|
unsigned long enter = hwMillis();
|
||||||
while (hwMillis() - enter < 2);
|
while (hwMillis() - enter < 2) {}
|
||||||
if (digitalRead(MY_NODE_UNLOCK_PIN) == 0) {
|
if (digitalRead(MY_NODE_UNLOCK_PIN) == 0) {
|
||||||
// Pin is grounded, reset lock counter
|
// Pin is grounded, reset lock counter
|
||||||
hwWriteConfig(EEPROM_NODE_LOCK_COUNTER, MY_NODE_LOCK_COUNTER_MAX);
|
hwWriteConfig(EEPROM_NODE_LOCK_COUNTER, MY_NODE_LOCK_COUNTER_MAX);
|
||||||
@@ -224,9 +225,9 @@ void presentNode(void) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (presentation)
|
if (presentation) {
|
||||||
presentation();
|
presentation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -299,8 +300,12 @@ bool present(const uint8_t childSensorId, const uint8_t sensorType, const char *
|
|||||||
|
|
||||||
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) result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME, ack).set(name));
|
if (name) {
|
||||||
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_NAME, ack).set(name));
|
||||||
|
}
|
||||||
|
if (version) {
|
||||||
|
result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION, ack).set(version));
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,8 +350,9 @@ bool _processInternalMessages(void) {
|
|||||||
}
|
}
|
||||||
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)
|
||||||
@@ -385,7 +391,9 @@ bool _processInternalMessages(void) {
|
|||||||
}
|
}
|
||||||
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++) hwWriteConfig(i, 0xFF);
|
for (int i = EEPROM_START; i<EEPROM_LOCAL_CONFIG_ADDRESS; i++) {
|
||||||
|
hwWriteConfig(i, 0xFF);
|
||||||
|
}
|
||||||
setIndication(INDICATION_REBOOT);
|
setIndication(INDICATION_REBOOT);
|
||||||
hwReboot();
|
hwReboot();
|
||||||
}
|
}
|
||||||
@@ -405,7 +413,7 @@ bool _processInternalMessages(void) {
|
|||||||
#if defined(MY_CORE_COMPATIBILITY_CHECK)
|
#if defined(MY_CORE_COMPATIBILITY_CHECK)
|
||||||
approveRegistration = (_msg.getByte() >= MY_CORE_MIN_VERSION);
|
approveRegistration = (_msg.getByte() >= MY_CORE_MIN_VERSION);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (F_CPU>16000000)
|
#if (F_CPU>16000000)
|
||||||
// delay for fast GW and slow nodes
|
// delay for fast GW and slow nodes
|
||||||
delay(5);
|
delay(5);
|
||||||
|
|||||||
@@ -52,10 +52,12 @@ static uint8_t* signerSha256(const uint8_t* data, size_t sz);
|
|||||||
static char i2h(uint8_t i)
|
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) {
|
||||||
@@ -98,7 +100,7 @@ bool signerAtsha204CheckTimer(void) {
|
|||||||
memset(_signing_signing_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH);
|
memset(_signing_signing_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH);
|
||||||
memset(_signing_verifying_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH);
|
memset(_signing_verifying_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH);
|
||||||
_signing_verification_ongoing = false;
|
_signing_verification_ongoing = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -132,7 +134,9 @@ bool signerAtsha204GetNonce(MyMessage &msg) {
|
|||||||
// Be a little fancy to handle turnover (prolong the time allowed to timeout after turnover)
|
// Be a little fancy to handle turnover (prolong the time allowed to timeout after turnover)
|
||||||
// Note that if message is "too" quick, and arrives before turnover, it will be rejected
|
// Note that if message is "too" quick, and arrives before turnover, it will be rejected
|
||||||
// but this is consider such a rare case that it is accepted and rejects are 'safe'
|
// but this is consider such a rare case that it is accepted and rejects are 'safe'
|
||||||
if (_signing_timestamp + MY_VERIFICATION_TIMEOUT_MS < hwMillis()) _signing_timestamp = 0;
|
if (_signing_timestamp + MY_VERIFICATION_TIMEOUT_MS < hwMillis()) {
|
||||||
|
_signing_timestamp = 0;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +152,7 @@ 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);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate signature of message
|
// Calculate signature of message
|
||||||
@@ -180,18 +184,18 @@ bool signerAtsha204SignMsg(MyMessage &msg) {
|
|||||||
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;
|
||||||
} else {
|
} else {
|
||||||
// Make sure we have not expired
|
// Make sure we have not expired
|
||||||
if (!signerCheckTimer()) {
|
if (!signerCheckTimer()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_signing_verification_ongoing = false;
|
_signing_verification_ongoing = false;
|
||||||
|
|
||||||
if (msg.data[mGetLength(msg)] != SIGNING_IDENTIFIER) {
|
if (msg.data[mGetLength(msg)] != SIGNING_IDENTIFIER) {
|
||||||
DEBUG_SIGNING_PRINTBUF(F("Incorrect signing identifier"), NULL, 0);
|
DEBUG_SIGNING_PRINTBUF(F("Incorrect signing identifier"), NULL, 0);
|
||||||
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));
|
||||||
@@ -230,7 +234,7 @@ bool signerAtsha204VerifyMsg(MyMessage &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
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
DEBUG_SIGNING_PRINTBUF(F("Signature OK"), NULL, 0);
|
DEBUG_SIGNING_PRINTBUF(F("Signature OK"), NULL, 0);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -56,10 +56,12 @@ static void signerCalculateSignature(MyMessage &msg, bool signing);
|
|||||||
static char i2h(uint8_t i)
|
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) {
|
||||||
@@ -106,7 +108,7 @@ bool signerAtsha204SoftCheckTimer(void) {
|
|||||||
memset(_signing_signing_nonce, 0xAA, 32);
|
memset(_signing_signing_nonce, 0xAA, 32);
|
||||||
memset(_signing_verifying_nonce, 0xAA, 32);
|
memset(_signing_verifying_nonce, 0xAA, 32);
|
||||||
_signing_verification_ongoing = false;
|
_signing_verification_ongoing = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -115,7 +117,7 @@ bool signerAtsha204SoftCheckTimer(void) {
|
|||||||
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
|
||||||
// hashed (SHA256) to produce the resulting nonce
|
// hashed (SHA256) to produce the resulting nonce
|
||||||
_signing_sha256.init();
|
_signing_sha256.init();
|
||||||
for (int i = 0; i < 32; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
@@ -134,7 +136,9 @@ bool signerAtsha204SoftGetNonce(MyMessage &msg) {
|
|||||||
// Be a little fancy to handle turnover (prolong the time allowed to timeout after turnover)
|
// Be a little fancy to handle turnover (prolong the time allowed to timeout after turnover)
|
||||||
// Note that if message is "too" quick, and arrives before turnover, it will be rejected
|
// Note that if message is "too" quick, and arrives before turnover, it will be rejected
|
||||||
// but this is consider such a rare case that it is accepted and rejects are 'safe'
|
// but this is consider such a rare case that it is accepted and rejects are 'safe'
|
||||||
if (_signing_timestamp + MY_VERIFICATION_TIMEOUT_MS < hwMillis()) _signing_timestamp = 0;
|
if (_signing_timestamp + MY_VERIFICATION_TIMEOUT_MS < hwMillis()) {
|
||||||
|
_signing_timestamp = 0;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +154,7 @@ 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);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate signature of message
|
// Calculate signature of message
|
||||||
@@ -160,9 +164,13 @@ bool signerAtsha204SoftSignMsg(MyMessage &msg) {
|
|||||||
if (DO_WHITELIST(msg.destination)) {
|
if (DO_WHITELIST(msg.destination)) {
|
||||||
// Salt the signature with the senders nodeId and the (hopefully) unique serial The Creator has provided
|
// Salt the signature with the senders nodeId and the (hopefully) unique serial The Creator has provided
|
||||||
_signing_sha256.init();
|
_signing_sha256.init();
|
||||||
for (int i=0; i<32; i++) _signing_sha256.write(_signing_hmac[i]);
|
for (int i=0; i<32; i++) {
|
||||||
|
_signing_sha256.write(_signing_hmac[i]);
|
||||||
|
}
|
||||||
_signing_sha256.write(msg.sender);
|
_signing_sha256.write(msg.sender);
|
||||||
for (int i=0; i<SHA204_SERIAL_SZ; i++) _signing_sha256.write(_signing_node_serial_info[i]);
|
for (int i=0; i<SHA204_SERIAL_SZ; i++) {
|
||||||
|
_signing_sha256.write(_signing_node_serial_info[i]);
|
||||||
|
}
|
||||||
memcpy(_signing_hmac, _signing_sha256.result(), 32);
|
memcpy(_signing_hmac, _signing_sha256.result(), 32);
|
||||||
DEBUG_SIGNING_PRINTBUF(F("SHA256: "), _signing_hmac, 32);
|
DEBUG_SIGNING_PRINTBUF(F("SHA256: "), _signing_hmac, 32);
|
||||||
DEBUG_SIGNING_PRINTBUF(F("Signature salted with serial"), NULL, 0);
|
DEBUG_SIGNING_PRINTBUF(F("Signature salted with serial"), NULL, 0);
|
||||||
@@ -181,18 +189,18 @@ bool signerAtsha204SoftSignMsg(MyMessage &msg) {
|
|||||||
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;
|
||||||
} else {
|
} else {
|
||||||
// Make sure we have not expired
|
// Make sure we have not expired
|
||||||
if (!signerCheckTimer()) {
|
if (!signerCheckTimer()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_signing_verification_ongoing = false;
|
_signing_verification_ongoing = false;
|
||||||
|
|
||||||
if (msg.data[mGetLength(msg)] != SIGNING_IDENTIFIER) {
|
if (msg.data[mGetLength(msg)] != SIGNING_IDENTIFIER) {
|
||||||
DEBUG_SIGNING_PRINTBUF(F("Incorrect signing identifier"), NULL, 0);
|
DEBUG_SIGNING_PRINTBUF(F("Incorrect signing identifier"), NULL, 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get signature of message
|
// Get signature of message
|
||||||
@@ -206,9 +214,13 @@ bool signerAtsha204SoftVerifyMsg(MyMessage &msg) {
|
|||||||
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);
|
||||||
_signing_sha256.init();
|
_signing_sha256.init();
|
||||||
for (int i=0; i<32; i++) _signing_sha256.write(_signing_hmac[i]);
|
for (int i=0; i<32; i++) {
|
||||||
|
_signing_sha256.write(_signing_hmac[i]);
|
||||||
|
}
|
||||||
_signing_sha256.write(msg.sender);
|
_signing_sha256.write(msg.sender);
|
||||||
for (int i=0; i<SHA204_SERIAL_SZ; i++) _signing_sha256.write(_signing_whitelist[j].serial[i]);
|
for (int i=0; i<SHA204_SERIAL_SZ; i++) {
|
||||||
|
_signing_sha256.write(_signing_whitelist[j].serial[i]);
|
||||||
|
}
|
||||||
memcpy(_signing_hmac, _signing_sha256.result(), 32);
|
memcpy(_signing_hmac, _signing_sha256.result(), 32);
|
||||||
DEBUG_SIGNING_PRINTBUF(F("SHA256: "), _signing_hmac, 32);
|
DEBUG_SIGNING_PRINTBUF(F("SHA256: "), _signing_hmac, 32);
|
||||||
break;
|
break;
|
||||||
@@ -229,7 +241,7 @@ bool signerAtsha204SoftVerifyMsg(MyMessage &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
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
DEBUG_SIGNING_PRINTBUF(F("Signature OK"), NULL, 0);
|
DEBUG_SIGNING_PRINTBUF(F("Signature OK"), NULL, 0);
|
||||||
return true;
|
return true;
|
||||||
@@ -268,7 +280,9 @@ static void signerCalculateSignature(MyMessage &msg, bool signing) {
|
|||||||
|
|
||||||
// Calculate message digest first
|
// Calculate message digest first
|
||||||
_signing_sha256.init();
|
_signing_sha256.init();
|
||||||
for (int i=0; i<32; i++) _signing_sha256.write(_signing_temp_message[i]);
|
for (int i=0; i<32; i++) {
|
||||||
|
_signing_sha256.write(_signing_temp_message[i]);
|
||||||
|
}
|
||||||
_signing_sha256.write(0x15); // OPCODE
|
_signing_sha256.write(0x15); // OPCODE
|
||||||
_signing_sha256.write(0x02); // param1
|
_signing_sha256.write(0x02); // param1
|
||||||
_signing_sha256.write(0x08); // param2(1)
|
_signing_sha256.write(0x08); // param2(1)
|
||||||
@@ -276,26 +290,40 @@ static void signerCalculateSignature(MyMessage &msg, bool signing) {
|
|||||||
_signing_sha256.write(0xEE); // SN[8]
|
_signing_sha256.write(0xEE); // SN[8]
|
||||||
_signing_sha256.write(0x01); // SN[0]
|
_signing_sha256.write(0x01); // SN[0]
|
||||||
_signing_sha256.write(0x23); // SN[1]
|
_signing_sha256.write(0x23); // SN[1]
|
||||||
for (int i=0; i<25; i++) _signing_sha256.write(0x00);
|
for (int i=0; i<25; i++) {
|
||||||
for (int i=0; i<32; i++) _signing_sha256.write(signing ? _signing_signing_nonce[i] : _signing_verifying_nonce[i]);
|
_signing_sha256.write(0x00);
|
||||||
|
}
|
||||||
|
for (int i=0; i<32; i++) {
|
||||||
|
_signing_sha256.write(signing ? _signing_signing_nonce[i] : _signing_verifying_nonce[i]);
|
||||||
|
}
|
||||||
// Purge nonce when used
|
// Purge nonce when used
|
||||||
memset(signing ? _signing_signing_nonce : _signing_verifying_nonce, 0xAA, 32);
|
memset(signing ? _signing_signing_nonce : _signing_verifying_nonce, 0xAA, 32);
|
||||||
memcpy(_signing_temp_message, _signing_sha256.result(), 32);
|
memcpy(_signing_temp_message, _signing_sha256.result(), 32);
|
||||||
|
|
||||||
// Feed "message" to HMAC calculator
|
// Feed "message" to HMAC calculator
|
||||||
_signing_sha256.initHmac(_signing_hmac_key,32); // Set the key to use
|
_signing_sha256.initHmac(_signing_hmac_key,32); // Set the key to use
|
||||||
for (int i=0; i<32; i++) _signing_sha256.write(0x00); // 32 bytes zeroes
|
for (int i=0; i<32; i++) {
|
||||||
for (int i=0; i<32; i++) _signing_sha256.write(_signing_temp_message[i]); // 32 bytes digest
|
_signing_sha256.write(0x00); // 32 bytes zeroes
|
||||||
|
}
|
||||||
|
for (int i=0; i<32; i++) {
|
||||||
|
_signing_sha256.write(_signing_temp_message[i]); // 32 bytes digest
|
||||||
|
}
|
||||||
_signing_sha256.write(0x11); // OPCODE
|
_signing_sha256.write(0x11); // OPCODE
|
||||||
_signing_sha256.write(0x04); // Mode
|
_signing_sha256.write(0x04); // Mode
|
||||||
_signing_sha256.write(0x00); // SlotID(1)
|
_signing_sha256.write(0x00); // SlotID(1)
|
||||||
_signing_sha256.write(0x00); // SlotID(2)
|
_signing_sha256.write(0x00); // SlotID(2)
|
||||||
for (int i=0; i<11; i++) _signing_sha256.write(0x00); // 11 bytes zeroes
|
for (int i=0; i<11; i++) {
|
||||||
|
_signing_sha256.write(0x00); // 11 bytes zeroes
|
||||||
|
}
|
||||||
_signing_sha256.write(0xEE); // SN[8]
|
_signing_sha256.write(0xEE); // SN[8]
|
||||||
for (int i=0; i<4; i++) _signing_sha256.write(0x00); // 4 bytes zeroes
|
for (int i=0; i<4; i++) {
|
||||||
|
_signing_sha256.write(0x00); // 4 bytes zeroes
|
||||||
|
}
|
||||||
_signing_sha256.write(0x01); // SN[0]
|
_signing_sha256.write(0x01); // SN[0]
|
||||||
_signing_sha256.write(0x23); // SN[1]
|
_signing_sha256.write(0x23); // SN[1]
|
||||||
for (int i=0; i<2; i++) _signing_sha256.write(0x00); // 2 bytes zeroes
|
for (int i=0; i<2; i++) {
|
||||||
|
_signing_sha256.write(0x00); // 2 bytes zeroes
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(_signing_hmac, _signing_sha256.resultHmac(), 32);
|
memcpy(_signing_hmac, _signing_sha256.resultHmac(), 32);
|
||||||
|
|
||||||
|
|||||||
+31
-26
@@ -112,7 +112,7 @@ void stInitUpdate(void) {
|
|||||||
// ID invalid (0 or 255)
|
// ID invalid (0 or 255)
|
||||||
transportSwitchSM(stFailure);
|
transportSwitchSM(stFailure);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +191,7 @@ void stIDUpdate(void) {
|
|||||||
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
|
||||||
@@ -261,7 +261,7 @@ 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
|
||||||
@@ -319,7 +319,9 @@ void transportSwitchSM(transportState& newState) {
|
|||||||
else {
|
else {
|
||||||
_transportSM.stateRetries++; // increment retries
|
_transportSM.stateRetries++; // increment retries
|
||||||
}
|
}
|
||||||
if (_transportSM.currentState->Transition) _transportSM.currentState->Transition(); // State transition
|
if (_transportSM.currentState->Transition) {
|
||||||
|
_transportSM.currentState->Transition(); // State transition
|
||||||
|
}
|
||||||
_transportSM.stateEnter = hwMillis(); // save time
|
_transportSM.stateEnter = hwMillis(); // save time
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,7 +330,9 @@ uint32_t transportTimeInState(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void transportUpdateSM(void) {
|
void transportUpdateSM(void) {
|
||||||
if (_transportSM.currentState->Update) _transportSM.currentState->Update();
|
if (_transportSM.currentState->Update) {
|
||||||
|
_transportSM.currentState->Update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isTransportReady(void) {
|
bool isTransportReady(void) {
|
||||||
@@ -363,7 +367,7 @@ void transportInitialise(void) {
|
|||||||
// 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
|
||||||
transportProcessFIFO();
|
transportProcessFIFO();
|
||||||
}
|
}
|
||||||
@@ -415,7 +419,7 @@ 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 = _nc.parentNodeId; // by default, all traffic is routed via parent node
|
uint8_t route = _nc.parentNodeId; // by default, all traffic is routed via parent node
|
||||||
|
|
||||||
if (_transportSM.findingParentNode && destination != BROADCAST_ADDRESS) {
|
if (_transportSM.findingParentNode && destination != BROADCAST_ADDRESS) {
|
||||||
TRANSPORT_DEBUG(PSTR("!TSF:RTE:FPAR ACTIVE\n")); // find parent active, message not sent
|
TRANSPORT_DEBUG(PSTR("!TSF:RTE:FPAR ACTIVE\n")); // find parent active, message not sent
|
||||||
// request to send a non-BC message while finding parent active, abort
|
// request to send a non-BC message while finding parent active, abort
|
||||||
@@ -438,7 +442,7 @@ bool transportRouteMessage(MyMessage &message) {
|
|||||||
if (message.last != _nc.parentNodeId) {
|
if (message.last != _nc.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 = _nc.parentNodeId;
|
route = _nc.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;
|
||||||
@@ -464,7 +468,9 @@ bool transportRouteMessage(MyMessage &message) {
|
|||||||
else _transportSM.failedUplinkTransmissions = 0u;
|
else _transportSM.failedUplinkTransmissions = 0u;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if(!result) setIndication(INDICATION_ERR_TX);
|
if(!result) {
|
||||||
|
setIndication(INDICATION_ERR_TX);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -532,7 +538,7 @@ void transportProcessMessage(void) {
|
|||||||
setIndication(INDICATION_RX);
|
setIndication(INDICATION_RX);
|
||||||
const uint8_t payloadLength = transportReceive((uint8_t *)&_msg);
|
const uint8_t payloadLength = transportReceive((uint8_t *)&_msg);
|
||||||
// get message length and limit size
|
// get message length and limit size
|
||||||
const uint8_t msgLength = min(mGetLength(_msg), (uint8_t)MAX_PAYLOAD);
|
const uint8_t msgLength = min(mGetLength(_msg), (uint8_t)MAX_PAYLOAD);
|
||||||
// calculate expected length
|
// calculate expected length
|
||||||
const uint8_t expectedMessageLength = HEADER_SIZE + (mGetSigned(_msg) ? MAX_PAYLOAD : msgLength);
|
const uint8_t expectedMessageLength = HEADER_SIZE + (mGetSigned(_msg) ? MAX_PAYLOAD : msgLength);
|
||||||
const uint8_t command = mGetCommand(_msg);
|
const uint8_t command = mGetCommand(_msg);
|
||||||
@@ -557,12 +563,12 @@ void transportProcessMessage(void) {
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reject messages that do not pass verification
|
// Reject messages that do not pass verification
|
||||||
if (!signerVerifyMsg(_msg)) {
|
if (!signerVerifyMsg(_msg)) {
|
||||||
setIndication(INDICATION_ERR_SIGN);
|
setIndication(INDICATION_ERR_SIGN);
|
||||||
TRANSPORT_DEBUG(PSTR("!TSF:MSG:SIGN VERIFY FAIL\n"));
|
TRANSPORT_DEBUG(PSTR("!TSF:MSG:SIGN VERIFY FAIL\n"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update routing table if msg not from parent
|
// update routing table if msg not from parent
|
||||||
@@ -580,7 +586,7 @@ void transportProcessMessage(void) {
|
|||||||
|
|
||||||
// set message received flag
|
// set message received flag
|
||||||
_transportSM.msgReceived = true;
|
_transportSM.msgReceived = true;
|
||||||
|
|
||||||
// Is message addressed to this node?
|
// Is message addressed to this node?
|
||||||
if (destination == _nc.nodeId) {
|
if (destination == _nc.nodeId) {
|
||||||
// prevent buffer overflow by limiting max. possible message length (5 bits=31 bytes max) to MAX_PAYLOAD (25 bytes)
|
// prevent buffer overflow by limiting max. possible message length (5 bits=31 bytes max) to MAX_PAYLOAD (25 bytes)
|
||||||
@@ -590,14 +596,14 @@ void transportProcessMessage(void) {
|
|||||||
// Check if sender requests an ack back.
|
// Check if sender requests an ack back.
|
||||||
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 = _nc.nodeId;
|
_msgTmp.sender = _nc.nodeId;
|
||||||
_msgTmp.destination = sender;
|
_msgTmp.destination = sender;
|
||||||
// send ACK, use transportSendRoute since ACK reply is not internal, i.e. if !transportOK do not reply
|
// send ACK, use transportSendRoute since ACK reply is not internal, i.e. if !transportOK do not reply
|
||||||
(void)transportSendRoute(_msgTmp);
|
(void)transportSendRoute(_msgTmp);
|
||||||
}
|
}
|
||||||
if(!mGetAck(_msg)) {
|
if(!mGetAck(_msg)) {
|
||||||
// only process if not ACK
|
// only process if not ACK
|
||||||
if (command == C_INTERNAL) {
|
if (command == C_INTERNAL) {
|
||||||
@@ -683,7 +689,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) {
|
||||||
@@ -707,7 +713,7 @@ void transportProcessMessage(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return; // no further processing required, do not forward
|
return; // no further processing required, do not forward
|
||||||
}
|
}
|
||||||
} // isTransportReady
|
} // isTransportReady
|
||||||
if (type == I_FIND_PARENT_RESPONSE) {
|
if (type == I_FIND_PARENT_RESPONSE) {
|
||||||
@@ -732,12 +738,14 @@ void transportProcessMessage(void) {
|
|||||||
(void)transportRouteMessage(_msg);
|
(void)transportRouteMessage(_msg);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Callback for BC, only for non-internal messages
|
// Callback for BC, only for non-internal messages
|
||||||
if (command != C_INTERNAL) {
|
if (command != C_INTERNAL) {
|
||||||
#if !defined(MY_GATEWAY_FEATURE)
|
#if !defined(MY_GATEWAY_FEATURE)
|
||||||
// only proceed if message received from parent
|
// only proceed if message received from parent
|
||||||
if (last != _nc.parentNodeId) return;
|
if (last != _nc.parentNodeId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(MY_GATEWAY_FEATURE)
|
#if defined(MY_GATEWAY_FEATURE)
|
||||||
// Hand over message to controller
|
// Hand over message to controller
|
||||||
@@ -747,10 +755,10 @@ void transportProcessMessage(void) {
|
|||||||
receive(_msg);
|
receive(_msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
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()) {
|
||||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:REL MSG\n")); // relay msg
|
TRANSPORT_DEBUG(PSTR("TSF:MSG:REL MSG\n")); // relay msg
|
||||||
@@ -817,7 +825,7 @@ bool transportSendWrite(const uint8_t to, MyMessage &message) {
|
|||||||
setIndication(INDICATION_ERR_SIGN);
|
setIndication(INDICATION_ERR_SIGN);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) );
|
||||||
|
|
||||||
@@ -873,6 +881,3 @@ uint8_t transportGetRoute(const uint8_t node) {
|
|||||||
#endif
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// EOF MyTransport.cpp
|
|
||||||
@@ -125,7 +125,9 @@ bool _serialProcess()
|
|||||||
{
|
{
|
||||||
char inch;
|
char inch;
|
||||||
unsigned char i;
|
unsigned char i;
|
||||||
if (!_dev.available()) return false;
|
if (!_dev.available()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
while(_dev.available()) {
|
while(_dev.available()) {
|
||||||
inch = _dev.read();
|
inch = _dev.read();
|
||||||
@@ -263,7 +265,9 @@ bool transportSend(uint8_t to, const void* data, uint8_t len)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Start of header by writing multiple SOH
|
// Start of header by writing multiple SOH
|
||||||
for(byte w=0;w<1;w++) _dev.write(SOH);
|
for(byte w=0;w<1;w++) {
|
||||||
|
_dev.write(SOH);
|
||||||
|
}
|
||||||
_dev.write(to); // Destination address
|
_dev.write(to); // Destination address
|
||||||
cs += to;
|
cs += to;
|
||||||
_dev.write(_nodeId); // Source address
|
_dev.write(_nodeId); // Source address
|
||||||
@@ -351,5 +355,3 @@ uint8_t transportReceive(void* data) {
|
|||||||
void transportPowerDown() {
|
void transportPowerDown() {
|
||||||
// Nothing to shut down here
|
// Nothing to shut down here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||||
|
* between your home built sensors/actuators and HA controller of choice.
|
||||||
|
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||||
|
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||||
|
* network topology allowing messages to be routed to nodes.
|
||||||
|
*
|
||||||
|
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||||
|
* Copyright (C) 2013-2015 Sensnology AB
|
||||||
|
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||||
|
*
|
||||||
|
* Documentation: http://www.mysensors.org
|
||||||
|
* Support Forum: http://forum.mysensors.org
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* version 2 as published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
/***
|
/***
|
||||||
* This file defines the Sensor library version number
|
* This file defines the Sensor library version number
|
||||||
* Normally, contributors should not modify this directly
|
* Normally, contributors should not modify this directly
|
||||||
|
|||||||
+30
-22
@@ -36,13 +36,13 @@
|
|||||||
/* This version derived by Mark Tillotson 2012-01-23, tidied up, slimmed down
|
/* This version derived by Mark Tillotson 2012-01-23, tidied up, slimmed down
|
||||||
and tailored to 8-bit microcontroller abilities and Arduino datatypes.
|
and tailored to 8-bit microcontroller abilities and Arduino datatypes.
|
||||||
|
|
||||||
The s-box and inverse s-box were retained as tables (0.5kB PROGMEM) but all
|
The s-box and inverse s-box were retained as tables (0.5kB PROGMEM) but all
|
||||||
the other transformations are coded to save table space. Many efficiency
|
the other transformations are coded to save table space. Many efficiency
|
||||||
improvments to the routines mix_sub_columns() and inv_mix_sub_columns()
|
improvments to the routines mix_sub_columns() and inv_mix_sub_columns()
|
||||||
(mainly common sub-expression elimination).
|
(mainly common sub-expression elimination).
|
||||||
|
|
||||||
Only the routines with precalculated subkey schedule are retained (together
|
Only the routines with precalculated subkey schedule are retained (together
|
||||||
with set_key() - this does however mean each AES object takes 240 bytes of
|
with set_key() - this does however mean each AES object takes 240 bytes of
|
||||||
RAM, alas)
|
RAM, alas)
|
||||||
|
|
||||||
The CBC routines side-effect the iv argument (so that successive calls work
|
The CBC routines side-effect the iv argument (so that successive calls work
|
||||||
@@ -218,7 +218,7 @@ static void inv_mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
|
|||||||
byte a8 = f2(a4), b8 = f2(b4), c8 = f2(c4), d8 = f2(d4) ;
|
byte a8 = f2(a4), b8 = f2(b4), c8 = f2(c4), d8 = f2(d4) ;
|
||||||
byte a9 = a8 ^ a1,b9 = b8 ^ b1,c9 = c8 ^ c1,d9 = d8 ^ d1 ;
|
byte a9 = a8 ^ a1,b9 = b8 ^ b1,c9 = c8 ^ c1,d9 = d8 ^ d1 ;
|
||||||
byte ac = a8 ^ a4,bc = b8 ^ b4,cc = c8 ^ c4,dc = d8 ^ d4 ;
|
byte ac = a8 ^ a4,bc = b8 ^ b4,cc = c8 ^ c4,dc = d8 ^ d4 ;
|
||||||
|
|
||||||
dt[i] = is_box (ac^a2 ^ b9^b2 ^ cc^c1 ^ d9) ;
|
dt[i] = is_box (ac^a2 ^ b9^b2 ^ cc^c1 ^ d9) ;
|
||||||
dt[(i+5)&15] = is_box (a9 ^ bc^b2 ^ c9^c2 ^ dc^d1) ;
|
dt[(i+5)&15] = is_box (a9 ^ bc^b2 ^ c9^c2 ^ dc^d1) ;
|
||||||
dt[(i+10)&15] = is_box (ac^a1 ^ b9 ^ cc^c2 ^ d9^d2) ;
|
dt[(i+10)&15] = is_box (ac^a1 ^ b9 ^ cc^c2 ^ d9^d2) ;
|
||||||
@@ -257,32 +257,33 @@ byte AES::set_key (byte key [], int keylen)
|
|||||||
switch (keylen)
|
switch (keylen)
|
||||||
{
|
{
|
||||||
case 16:
|
case 16:
|
||||||
case 128:
|
case 128:
|
||||||
keylen = 16; // 10 rounds
|
keylen = 16; // 10 rounds
|
||||||
round = 10 ;
|
round = 10 ;
|
||||||
break;
|
break;
|
||||||
case 24:
|
case 24:
|
||||||
case 192:
|
case 192:
|
||||||
keylen = 24; // 12 rounds
|
keylen = 24; // 12 rounds
|
||||||
round = 12 ;
|
round = 12 ;
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
case 256:
|
case 256:
|
||||||
keylen = 32; // 14 rounds
|
keylen = 32; // 14 rounds
|
||||||
round = 14 ;
|
round = 14 ;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
round = 0;
|
round = 0;
|
||||||
return AES_FAILURE;
|
return AES_FAILURE;
|
||||||
}
|
}
|
||||||
hi = (round + 1) << 4 ;
|
hi = (round + 1) << 4 ;
|
||||||
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 ;
|
||||||
@@ -295,12 +296,14 @@ byte AES::set_key (byte key [], int keylen)
|
|||||||
}
|
}
|
||||||
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]) ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
byte tt = cc - keylen ;
|
byte tt = cc - keylen ;
|
||||||
for (byte i = 0 ; i < N_COL ; i++)
|
for (byte i = 0 ; i < N_COL ; i++) {
|
||||||
key_sched [cc + i] = key_sched [tt + i] ^ t[i] ;
|
key_sched [cc + i] = key_sched [tt + i] ^ t[i] ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return AES_SUCCESS ;
|
return AES_SUCCESS ;
|
||||||
}
|
}
|
||||||
@@ -309,8 +312,9 @@ byte AES::set_key (byte key [], int keylen)
|
|||||||
|
|
||||||
void AES::clean ()
|
void AES::clean ()
|
||||||
{
|
{
|
||||||
for (byte i = 0 ; i < KEY_SCHEDULE_BYTES ; i++)
|
for (byte i = 0 ; i < KEY_SCHEDULE_BYTES ; i++) {
|
||||||
key_sched [i] = 0 ;
|
key_sched [i] = 0 ;
|
||||||
|
}
|
||||||
round = 0 ;
|
round = 0 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,7 +344,7 @@ byte AES::encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
|
|||||||
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)) ;
|
||||||
@@ -360,8 +364,9 @@ byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOC
|
|||||||
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 ;
|
||||||
|
}
|
||||||
copy_n_bytes (cipher, iv, N_BLOCK) ;
|
copy_n_bytes (cipher, iv, N_BLOCK) ;
|
||||||
plain += N_BLOCK ;
|
plain += N_BLOCK ;
|
||||||
cipher += N_BLOCK ;
|
cipher += N_BLOCK ;
|
||||||
@@ -376,8 +381,9 @@ 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 ;
|
||||||
|
}
|
||||||
copy_n_bytes (cipher, iv, N_BLOCK) ;
|
copy_n_bytes (cipher, iv, N_BLOCK) ;
|
||||||
plain += N_BLOCK ;
|
plain += N_BLOCK ;
|
||||||
cipher += N_BLOCK ;
|
cipher += N_BLOCK ;
|
||||||
@@ -411,13 +417,14 @@ 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) {
|
||||||
return AES_FAILURE ;
|
return AES_FAILURE ;
|
||||||
|
}
|
||||||
xor_block (plain, iv) ;
|
xor_block (plain, iv) ;
|
||||||
copy_n_bytes (iv, tmp, N_BLOCK) ;
|
copy_n_bytes (iv, tmp, N_BLOCK) ;
|
||||||
plain += N_BLOCK ;
|
plain += N_BLOCK ;
|
||||||
@@ -429,13 +436,14 @@ 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) {
|
||||||
return AES_FAILURE ;
|
return AES_FAILURE ;
|
||||||
|
}
|
||||||
xor_block (plain, iv) ;
|
xor_block (plain, iv) ;
|
||||||
copy_n_bytes (iv, tmp, N_BLOCK) ;
|
copy_n_bytes (iv, tmp, N_BLOCK) ;
|
||||||
plain += N_BLOCK ;
|
plain += N_BLOCK ;
|
||||||
@@ -505,7 +513,7 @@ void AES::padPlaintext(void* in,byte* out)
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
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--){
|
||||||
if (arr_pad[lpad - 1] != in[i]){
|
if (arr_pad[lpad - 1] != in[i]){
|
||||||
|
|||||||
@@ -24,10 +24,12 @@ static void swi_set_signal_pin(uint8_t is_high)
|
|||||||
{
|
{
|
||||||
SHA204_SET_OUTPUT();
|
SHA204_SET_OUTPUT();
|
||||||
|
|
||||||
if (is_high)
|
if (is_high) {
|
||||||
SHA204_POUT_HIGH();
|
SHA204_POUT_HIGH();
|
||||||
else
|
}
|
||||||
SHA204_POUT_LOW();
|
else {
|
||||||
|
SHA204_POUT_LOW();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t swi_send_bytes(uint8_t count, uint8_t *buffer)
|
static uint8_t swi_send_bytes(uint8_t count, uint8_t *buffer)
|
||||||
@@ -109,8 +111,9 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
|
|||||||
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)
|
||||||
@@ -159,8 +162,9 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
|
|||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (SHA204_PIN_READ() != 0)
|
if (SHA204_PIN_READ() != 0) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
} while (timeout_count-- > 0);
|
} while (timeout_count-- > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,16 +173,18 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
|
|||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -191,8 +197,9 @@ static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response)
|
|||||||
uint8_t i;
|
uint8_t i;
|
||||||
uint8_t ret_code;
|
uint8_t ret_code;
|
||||||
|
|
||||||
for (i = 0; i < size; i++)
|
for (i = 0; i < size; i++) {
|
||||||
response[i] = 0;
|
response[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
(void) swi_send_byte(SHA204_SWI_FLAG_TX);
|
(void) swi_send_byte(SHA204_SWI_FLAG_TX);
|
||||||
|
|
||||||
@@ -200,8 +207,9 @@ static uint8_t sha204p_receive_response(uint8_t size, uint8_t *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;
|
||||||
|
}
|
||||||
|
|
||||||
return SHA204_SUCCESS;
|
return SHA204_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -209,10 +217,12 @@ static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response)
|
|||||||
// Translate error so that the Communication layer
|
// Translate error so that the Communication layer
|
||||||
// can distinguish between a real error or the
|
// can distinguish between a real error or the
|
||||||
// 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Communication functions */
|
/* Communication functions */
|
||||||
@@ -223,8 +233,9 @@ static uint8_t sha204c_resync(uint8_t size, uint8_t *response)
|
|||||||
// (step 1 of the re-synchronization process).
|
// (step 1 of the re-synchronization process).
|
||||||
delay(SHA204_SYNC_TIMEOUT);
|
delay(SHA204_SYNC_TIMEOUT);
|
||||||
uint8_t ret_code = sha204p_receive_response(size, response);
|
uint8_t ret_code = sha204p_receive_response(size, response);
|
||||||
if (ret_code == SHA204_SUCCESS)
|
if (ret_code == SHA204_SUCCESS) {
|
||||||
return ret_code;
|
return ret_code;
|
||||||
|
}
|
||||||
|
|
||||||
// We lost communication. Send a Wake pulse and try
|
// We lost communication. Send a Wake pulse and try
|
||||||
// to receive a response (steps 2 and 3 of the
|
// to receive a response (steps 2 and 3 of the
|
||||||
@@ -261,17 +272,21 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
|
|||||||
{
|
{
|
||||||
// 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait minimum command execution time and then start polling for a response.
|
// Wait minimum command execution time and then start polling for a response.
|
||||||
@@ -282,8 +297,9 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
|
|||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
// Poll for response.
|
// Poll for response.
|
||||||
timeout_countdown = execution_timeout_us;
|
timeout_countdown = execution_timeout_us;
|
||||||
@@ -297,11 +313,13 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
|
|||||||
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.
|
||||||
@@ -309,16 +327,19 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
|
|||||||
{
|
{
|
||||||
// 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) {
|
||||||
// We did not have to wake up the device. Try receiving response again.
|
// We did not have to wake up the device. Try receiving response again.
|
||||||
continue;
|
continue;
|
||||||
if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP)
|
}
|
||||||
|
if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) {
|
||||||
// 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We received a response of valid size.
|
// We received a response of valid size.
|
||||||
@@ -327,19 +348,22 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
|
|||||||
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.
|
||||||
return ret_code;
|
return ret_code;
|
||||||
|
}
|
||||||
|
|
||||||
// Received status response.
|
// Received status response.
|
||||||
status_byte = rx_buffer[SHA204_BUFFER_POS_STATUS];
|
status_byte = rx_buffer[SHA204_BUFFER_POS_STATUS];
|
||||||
|
|
||||||
// Translate the three possible device status error codes
|
// Translate the three possible device status error codes
|
||||||
// into library return codes.
|
// into library return codes.
|
||||||
if (status_byte == SHA204_STATUS_BYTE_PARSE)
|
if (status_byte == SHA204_STATUS_BYTE_PARSE) {
|
||||||
return SHA204_PARSE_ERROR;
|
return SHA204_PARSE_ERROR;
|
||||||
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
|
||||||
@@ -359,16 +383,19 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
|
|||||||
{
|
{
|
||||||
// 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) {
|
||||||
// We did not have to wake up the device. Try receiving response again.
|
// We did not have to wake up the device. Try receiving response again.
|
||||||
continue;
|
continue;
|
||||||
if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP)
|
}
|
||||||
|
if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) {
|
||||||
// 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;
|
||||||
|
}
|
||||||
} // block end of check response consistency
|
} // block end of check response consistency
|
||||||
|
|
||||||
} // block end of receive retry loop
|
} // block end of receive retry loop
|
||||||
@@ -418,8 +445,9 @@ static void sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc)
|
|||||||
// Shift CRC to the left by 1.
|
// Shift CRC to the left by 1.
|
||||||
crc_register <<= 1;
|
crc_register <<= 1;
|
||||||
|
|
||||||
if ((data_bit ^ crc_bit) != 0)
|
if ((data_bit ^ crc_bit) != 0) {
|
||||||
crc_register ^= polynom;
|
crc_register ^= polynom;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
crc[0] = (uint8_t) (crc_register & 0x00FF);
|
crc[0] = (uint8_t) (crc_register & 0x00FF);
|
||||||
@@ -475,22 +503,27 @@ uint8_t atsha204_wakeup(uint8_t *response)
|
|||||||
delay(SHA204_WAKEUP_DELAY);
|
delay(SHA204_WAKEUP_DELAY);
|
||||||
|
|
||||||
uint8_t ret_code = sha204p_receive_response(SHA204_RSP_SIZE_MIN, response);
|
uint8_t ret_code = sha204p_receive_response(SHA204_RSP_SIZE_MIN, response);
|
||||||
if (ret_code != SHA204_SUCCESS)
|
if (ret_code != SHA204_SUCCESS) {
|
||||||
return ret_code;
|
return ret_code;
|
||||||
|
}
|
||||||
|
|
||||||
// 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ret_code != SHA204_SUCCESS)
|
if (ret_code != SHA204_SUCCESS) {
|
||||||
delay(SHA204_COMMAND_EXEC_MAX);
|
delay(SHA204_COMMAND_EXEC_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
return ret_code;
|
return ret_code;
|
||||||
}
|
}
|
||||||
@@ -580,14 +613,16 @@ uint8_t atsha204_getSerialNumber(uint8_t * response)
|
|||||||
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];
|
||||||
|
}
|
||||||
|
|
||||||
/* read from bytes 8->11 of config zone */
|
/* read from bytes 8->11 of config zone */
|
||||||
returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN47);
|
returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN47);
|
||||||
|
|
||||||
for (int i=4; i<8; i++) // store bytes 4-7 of SN into response array
|
for (int i=4; i<8; i++) {// store bytes 4-7 of SN into response array
|
||||||
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 */
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ void Sha256Class::hashBlock() {
|
|||||||
f=state.w[5];
|
f=state.w[5];
|
||||||
g=state.w[6];
|
g=state.w[6];
|
||||||
h=state.w[7];
|
h=state.w[7];
|
||||||
|
|
||||||
for (i=0; i<64; i++) {
|
for (i=0; i<64; i++) {
|
||||||
if (i>=16) {
|
if (i>=16) {
|
||||||
t1 = buffer.w[i&15] + buffer.w[(i-7)&15];
|
t1 = buffer.w[i&15] + buffer.w[(i-7)&15];
|
||||||
@@ -102,7 +102,9 @@ void Sha256Class::pad() {
|
|||||||
|
|
||||||
// Pad with 0x80 followed by 0x00 until the end of the block
|
// Pad with 0x80 followed by 0x00 until the end of the block
|
||||||
addUncounted(0x80);
|
addUncounted(0x80);
|
||||||
while (bufferOffset != 56) addUncounted(0x00);
|
while (bufferOffset != 56) {
|
||||||
|
addUncounted(0x00);
|
||||||
|
}
|
||||||
|
|
||||||
// Append length in the last 8 bytes
|
// Append length in the last 8 bytes
|
||||||
addUncounted(0); // We're only using 32 bit lengths
|
addUncounted(0); // We're only using 32 bit lengths
|
||||||
@@ -119,7 +121,7 @@ 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();
|
||||||
|
|
||||||
// Swap byte order back
|
// Swap byte order back
|
||||||
for (int i=0; i<8; i++) {
|
for (int i=0; i<8; i++) {
|
||||||
uint32_t a,b;
|
uint32_t a,b;
|
||||||
@@ -130,7 +132,7 @@ uint8_t* Sha256Class::result(void) {
|
|||||||
b|=a>>24;
|
b|=a>>24;
|
||||||
state.w[i]=b;
|
state.w[i]=b;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return pointer to hash (20 characters)
|
// Return pointer to hash (20 characters)
|
||||||
return state.b;
|
return state.b;
|
||||||
}
|
}
|
||||||
@@ -147,7 +149,9 @@ void Sha256Class::initHmac(const uint8_t* key, int keyLength) {
|
|||||||
if (keyLength > BLOCK_LENGTH) {
|
if (keyLength > BLOCK_LENGTH) {
|
||||||
// Hash long keys
|
// Hash long keys
|
||||||
init();
|
init();
|
||||||
for (;keyLength--;) write(*key++);
|
for (;keyLength--;) {
|
||||||
|
write(*key++);
|
||||||
|
}
|
||||||
memcpy(keyBuffer,result(),HASH_LENGTH);
|
memcpy(keyBuffer,result(),HASH_LENGTH);
|
||||||
} else {
|
} else {
|
||||||
// Block length keys are used as is
|
// Block length keys are used as is
|
||||||
@@ -166,7 +170,11 @@ uint8_t* Sha256Class::resultHmac(void) {
|
|||||||
memcpy(innerHash,result(),HASH_LENGTH);
|
memcpy(innerHash,result(),HASH_LENGTH);
|
||||||
// Calculate outer hash
|
// Calculate outer hash
|
||||||
init();
|
init();
|
||||||
for (i=0; i<BLOCK_LENGTH; i++) write(keyBuffer[i] ^ HMAC_OPAD);
|
for (i=0; i<BLOCK_LENGTH; i++) {
|
||||||
for (i=0; i<HASH_LENGTH; i++) write(innerHash[i]);
|
write(keyBuffer[i] ^ HMAC_OPAD);
|
||||||
|
}
|
||||||
|
for (i=0; i<HASH_LENGTH; i++) {
|
||||||
|
write(innerHash[i]);
|
||||||
|
}
|
||||||
return result();
|
return result();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
/* An Alternative Software Serial Library
|
/* An Alternative Software Serial Library
|
||||||
* http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html
|
* http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html
|
||||||
* Copyright (c) 2014 PJRC.COM, LLC, Paul Stoffregen, paul@pjrc.com
|
* Copyright (c) 2014 PJRC.COM, LLC, Paul Stoffregen, paul@pjrc.com
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
@@ -108,8 +108,10 @@ void AltSoftSerial::writeByte(uint8_t b)
|
|||||||
uint8_t intr_state, head;
|
uint8_t intr_state, head;
|
||||||
|
|
||||||
head = tx_buffer_head + 1;
|
head = tx_buffer_head + 1;
|
||||||
if (head >= TX_BUFFER_SIZE) head = 0;
|
if (head >= TX_BUFFER_SIZE) {
|
||||||
while (tx_buffer_tail == head) ; // wait until space in buffer
|
head = 0;
|
||||||
|
}
|
||||||
|
while (tx_buffer_tail == head) {} // wait until space in buffer
|
||||||
intr_state = SREG;
|
intr_state = SREG;
|
||||||
cli();
|
cli();
|
||||||
if (tx_state) {
|
if (tx_state) {
|
||||||
@@ -168,7 +170,9 @@ ISR(COMPARE_A_INTERRUPT)
|
|||||||
DISABLE_INT_COMPARE_A();
|
DISABLE_INT_COMPARE_A();
|
||||||
} else {
|
} else {
|
||||||
tx_state = 1;
|
tx_state = 1;
|
||||||
if (++tail >= TX_BUFFER_SIZE) tail = 0;
|
if (++tail >= TX_BUFFER_SIZE) {
|
||||||
|
tail = 0;
|
||||||
|
}
|
||||||
tx_buffer_tail = tail;
|
tx_buffer_tail = tail;
|
||||||
tx_byte = tx_buffer[tail];
|
tx_byte = tx_buffer[tail];
|
||||||
tx_bit = 0;
|
tx_bit = 0;
|
||||||
@@ -180,7 +184,7 @@ ISR(COMPARE_A_INTERRUPT)
|
|||||||
|
|
||||||
void AltSoftSerial::flushOutput(void)
|
void AltSoftSerial::flushOutput(void)
|
||||||
{
|
{
|
||||||
while (tx_state) /* wait */ ;
|
while (tx_state) {}/* wait */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -216,14 +220,18 @@ ISR(CAPTURE_INTERRUPT)
|
|||||||
target = rx_target;
|
target = rx_target;
|
||||||
while (1) {
|
while (1) {
|
||||||
offset = capture - target;
|
offset = capture - target;
|
||||||
if (offset < 0) break;
|
if (offset < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
rx_byte = (rx_byte >> 1) | rx_bit;
|
rx_byte = (rx_byte >> 1) | rx_bit;
|
||||||
target += ticks_per_bit;
|
target += ticks_per_bit;
|
||||||
state++;
|
state++;
|
||||||
if (state >= 9) {
|
if (state >= 9) {
|
||||||
DISABLE_INT_COMPARE_B();
|
DISABLE_INT_COMPARE_B();
|
||||||
head = rx_buffer_head + 1;
|
head = rx_buffer_head + 1;
|
||||||
if (head >= RX_BUFFER_SIZE) head = 0;
|
if (head >= RX_BUFFER_SIZE) {
|
||||||
|
head = 0;
|
||||||
|
}
|
||||||
if (head != rx_buffer_tail) {
|
if (head != rx_buffer_tail) {
|
||||||
rx_buffer[head] = rx_byte;
|
rx_buffer[head] = rx_byte;
|
||||||
rx_buffer_head = head;
|
rx_buffer_head = head;
|
||||||
@@ -253,7 +261,9 @@ ISR(COMPARE_B_INTERRUPT)
|
|||||||
state++;
|
state++;
|
||||||
}
|
}
|
||||||
head = rx_buffer_head + 1;
|
head = rx_buffer_head + 1;
|
||||||
if (head >= RX_BUFFER_SIZE) head = 0;
|
if (head >= RX_BUFFER_SIZE) {
|
||||||
|
head = 0;
|
||||||
|
}
|
||||||
if (head != rx_buffer_tail) {
|
if (head != rx_buffer_tail) {
|
||||||
rx_buffer[head] = rx_byte;
|
rx_buffer[head] = rx_byte;
|
||||||
rx_buffer_head = head;
|
rx_buffer_head = head;
|
||||||
@@ -271,8 +281,12 @@ int AltSoftSerial::read(void)
|
|||||||
|
|
||||||
head = rx_buffer_head;
|
head = rx_buffer_head;
|
||||||
tail = rx_buffer_tail;
|
tail = rx_buffer_tail;
|
||||||
if (head == tail) return -1;
|
if (head == tail) {
|
||||||
if (++tail >= RX_BUFFER_SIZE) tail = 0;
|
return -1;
|
||||||
|
}
|
||||||
|
if (++tail >= RX_BUFFER_SIZE) {
|
||||||
|
tail = 0;
|
||||||
|
}
|
||||||
out = rx_buffer[tail];
|
out = rx_buffer[tail];
|
||||||
rx_buffer_tail = tail;
|
rx_buffer_tail = tail;
|
||||||
return out;
|
return out;
|
||||||
@@ -284,7 +298,9 @@ int AltSoftSerial::peek(void)
|
|||||||
|
|
||||||
head = rx_buffer_head;
|
head = rx_buffer_head;
|
||||||
tail = rx_buffer_tail;
|
tail = rx_buffer_tail;
|
||||||
if (head == tail) return -1;
|
if (head == tail) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return rx_buffer[tail];
|
return rx_buffer[tail];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,7 +310,9 @@ int AltSoftSerial::available(void)
|
|||||||
|
|
||||||
head = rx_buffer_head;
|
head = rx_buffer_head;
|
||||||
tail = rx_buffer_tail;
|
tail = rx_buffer_tail;
|
||||||
if (head >= tail) return head - tail;
|
if (head >= tail) {
|
||||||
|
return head - tail;
|
||||||
|
}
|
||||||
return RX_BUFFER_SIZE + head - tail;
|
return RX_BUFFER_SIZE + head - tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,9 +327,14 @@ void ftm0_isr(void)
|
|||||||
{
|
{
|
||||||
uint32_t flags = FTM0_STATUS;
|
uint32_t flags = FTM0_STATUS;
|
||||||
FTM0_STATUS = 0;
|
FTM0_STATUS = 0;
|
||||||
if (flags & (1<<5)) altss_capture_interrupt();
|
if (flags & (1<<5)) {
|
||||||
if (flags & (1<<6)) altss_compare_a_interrupt();
|
altss_capture_interrupt();
|
||||||
if (flags & (1<<0)) altss_compare_b_interrupt();
|
}
|
||||||
|
if (flags & (1<<6)) {
|
||||||
|
altss_compare_a_interrupt();
|
||||||
|
}
|
||||||
|
if (flags & (1<<0)) {
|
||||||
|
altss_compare_b_interrupt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -120,7 +120,9 @@ size_t EthernetClient::write(const uint8_t *buf, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t EthernetClient::write(const char *str) {
|
size_t EthernetClient::write(const char *str) {
|
||||||
if (str == NULL) return 0;
|
if (str == NULL) {
|
||||||
|
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) {
|
||||||
@@ -165,8 +167,9 @@ void EthernetClient::flush() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EthernetClient::stop() {
|
void EthernetClient::stop() {
|
||||||
if (_sock == -1)
|
if (_sock == -1) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// attempt to close the connection gracefully (send a FIN to other side)
|
// attempt to close the connection gracefully (send a FIN to other side)
|
||||||
shutdown(_sock, SHUT_RDWR);
|
shutdown(_sock, SHUT_RDWR);
|
||||||
@@ -178,21 +181,24 @@ void EthernetClient::stop() {
|
|||||||
uint8_t s;
|
uint8_t s;
|
||||||
do {
|
do {
|
||||||
s = status();
|
s = status();
|
||||||
if (s == ETHERNETCLIENT_W5100_CLOSED)
|
if (s == ETHERNETCLIENT_W5100_CLOSED) {
|
||||||
break; // exit the loop
|
break; // exit the loop
|
||||||
|
}
|
||||||
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) {
|
||||||
close(_sock);
|
close(_sock);
|
||||||
|
}
|
||||||
_sock = -1;
|
_sock = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t EthernetClient::status() {
|
uint8_t EthernetClient::status() {
|
||||||
if (_sock == -1) return ETHERNETCLIENT_W5100_CLOSED;
|
if (_sock == -1) {
|
||||||
|
return ETHERNETCLIENT_W5100_CLOSED;
|
||||||
|
}
|
||||||
|
|
||||||
struct tcp_info tcp_info;
|
struct tcp_info tcp_info;
|
||||||
int tcp_info_length = sizeof(tcp_info);
|
int tcp_info_length = sizeof(tcp_info);
|
||||||
@@ -227,8 +233,10 @@ uint8_t EthernetClient::status() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t EthernetClient::connected() {
|
uint8_t EthernetClient::connected() {
|
||||||
if (_sock == -1) return 0;
|
if (_sock == -1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (peek() < 0) {
|
if (peek() < 0) {
|
||||||
if (errno == EAGAIN) {
|
if (errno == EAGAIN) {
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -151,7 +151,9 @@ size_t EthernetServer::write(const uint8_t *buffer, size_t size)
|
|||||||
|
|
||||||
size_t EthernetServer::write(const char *str)
|
size_t EthernetServer::write(const char *str)
|
||||||
{
|
{
|
||||||
if (str == NULL) return 0;
|
if (str == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return write((const uint8_t *)str, strlen(str));
|
return write((const uint8_t *)str, strlen(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-8
@@ -105,10 +105,12 @@ 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) {
|
||||||
@@ -182,8 +184,9 @@ size_t Print::printNumber(unsigned long n, uint8_t base) {
|
|||||||
*str = '\0';
|
*str = '\0';
|
||||||
|
|
||||||
// prevent crash if called with base == 1
|
// prevent crash if called with base == 1
|
||||||
if(base < 2)
|
if(base < 2) {
|
||||||
base = 10;
|
base = 10;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
unsigned long m = n;
|
unsigned long m = n;
|
||||||
@@ -198,14 +201,18 @@ size_t Print::printNumber(unsigned long n, uint8_t base) {
|
|||||||
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)) {
|
||||||
return print("nan");
|
return print("nan");
|
||||||
if(std::isinf(number))
|
}
|
||||||
|
if(std::isinf(number)) {
|
||||||
return print("inf");
|
return print("inf");
|
||||||
if(number > 4294967040.0)
|
}
|
||||||
|
if(number > 4294967040.0) {
|
||||||
return print("ovf"); // constant determined empirically
|
return print("ovf"); // constant determined empirically
|
||||||
if(number < -4294967040.0)
|
}
|
||||||
|
if(number < -4294967040.0) {
|
||||||
return print("ovf"); // constant determined empirically
|
return print("ovf"); // constant determined empirically
|
||||||
|
}
|
||||||
|
|
||||||
// Handle negative numbers
|
// Handle negative numbers
|
||||||
if(number < 0.0) {
|
if(number < 0.0) {
|
||||||
@@ -215,8 +222,9 @@ size_t Print::printFloat(double number, uint8_t digits) {
|
|||||||
|
|
||||||
// Round correctly so that print(1.999, 2) prints as "2.00"
|
// Round correctly so that print(1.999, 2) prints as "2.00"
|
||||||
double rounding = 0.5;
|
double rounding = 0.5;
|
||||||
for(uint8_t i = 0; i < digits; ++i)
|
for(uint8_t i = 0; i < digits; ++i) {
|
||||||
rounding /= 10.0;
|
rounding /= 10.0;
|
||||||
|
}
|
||||||
|
|
||||||
number += rounding;
|
number += rounding;
|
||||||
|
|
||||||
|
|||||||
@@ -212,7 +212,9 @@ int SerialPort::peek()
|
|||||||
{
|
{
|
||||||
FILE * f = fdopen(sd, "r+");
|
FILE * f = fdopen(sd, "r+");
|
||||||
int c = getc(f);
|
int c = getc(f);
|
||||||
if (c == EOF) return -1;
|
if (c == EOF) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
ungetc(c, f);
|
ungetc(c, f);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|||||||
+53
-29
@@ -33,8 +33,9 @@ int Stream::timedRead() {
|
|||||||
_startMillis = millis();
|
_startMillis = millis();
|
||||||
do {
|
do {
|
||||||
c = read();
|
c = read();
|
||||||
if(c >= 0)
|
if(c >= 0) {
|
||||||
return c;
|
return c;
|
||||||
|
}
|
||||||
yield();
|
yield();
|
||||||
} while(millis() - _startMillis < _timeout);
|
} while(millis() - _startMillis < _timeout);
|
||||||
return -1; // -1 indicates timeout
|
return -1; // -1 indicates timeout
|
||||||
@@ -46,8 +47,9 @@ int Stream::timedPeek() {
|
|||||||
_startMillis = millis();
|
_startMillis = millis();
|
||||||
do {
|
do {
|
||||||
c = peek();
|
c = peek();
|
||||||
if(c >= 0)
|
if(c >= 0) {
|
||||||
return c;
|
return c;
|
||||||
|
}
|
||||||
yield();
|
yield();
|
||||||
} while(millis() - _startMillis < _timeout);
|
} while(millis() - _startMillis < _timeout);
|
||||||
return -1; // -1 indicates timeout
|
return -1; // -1 indicates timeout
|
||||||
@@ -59,12 +61,15 @@ int Stream::peekNextDigit() {
|
|||||||
int c;
|
int c;
|
||||||
while(1) {
|
while(1) {
|
||||||
c = timedPeek();
|
c = timedPeek();
|
||||||
if(c < 0)
|
if(c < 0) {
|
||||||
return c; // timeout
|
return c; // timeout
|
||||||
if(c == '-')
|
}
|
||||||
|
if(c == '-') {
|
||||||
return c;
|
return c;
|
||||||
if(c >= '0' && c <= '9')
|
}
|
||||||
|
if(c >= '0' && c <= '9') {
|
||||||
return c;
|
return c;
|
||||||
|
}
|
||||||
read(); // discard non-numeric
|
read(); // discard non-numeric
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,13 +106,14 @@ bool Stream::findUntil(const char *target, size_t targetLen, const char *termina
|
|||||||
size_t termIndex = 0;
|
size_t termIndex = 0;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
if(*target == 0)
|
if(*target == 0) {
|
||||||
return true; // return true if target is a null string
|
return true; // return true if target is a null string
|
||||||
|
}
|
||||||
while((c = timedRead()) > 0) {
|
while((c = timedRead()) > 0) {
|
||||||
|
|
||||||
if(c != target[index])
|
if(c != target[index]) {
|
||||||
index = 0; // reset index if any char does not match
|
index = 0; // reset index if any char does not match
|
||||||
|
}
|
||||||
if(c == target[index]) {
|
if(c == target[index]) {
|
||||||
//////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
|
//////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
|
||||||
if(++index >= targetLen) { // return true if all chars in the target match
|
if(++index >= targetLen) { // return true if all chars in the target match
|
||||||
@@ -116,10 +122,12 @@ bool Stream::findUntil(const char *target, size_t targetLen, const char *termina
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(termLen > 0 && c == terminator[termIndex]) {
|
if(termLen > 0 && c == terminator[termIndex]) {
|
||||||
if(++termIndex >= termLen)
|
if(++termIndex >= termLen) {
|
||||||
return false; // return false if terminate string found before target string
|
return false; // return false if terminate string found before target string
|
||||||
} else
|
}
|
||||||
|
} else {
|
||||||
termIndex = 0;
|
termIndex = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -140,22 +148,27 @@ long Stream::parseInt(char skipChar) {
|
|||||||
|
|
||||||
c = peekNextDigit();
|
c = peekNextDigit();
|
||||||
// ignore non numeric leading characters
|
// ignore non numeric leading characters
|
||||||
if(c < 0)
|
if(c < 0) {
|
||||||
return 0; // zero returned if timeout
|
return 0; // zero returned if timeout
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
c = timedPeek();
|
c = timedPeek();
|
||||||
} while((c >= '0' && c <= '9') || c == skipChar);
|
} while((c >= '0' && c <= '9') || c == skipChar);
|
||||||
|
|
||||||
if(isNegative)
|
if(isNegative) {
|
||||||
value = -value;
|
value = -value;
|
||||||
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,31 +188,39 @@ float Stream::parseFloat(char skipChar) {
|
|||||||
|
|
||||||
c = peekNextDigit();
|
c = peekNextDigit();
|
||||||
// ignore non numeric leading characters
|
// ignore non numeric leading characters
|
||||||
if(c < 0)
|
if(c < 0) {
|
||||||
return 0; // zero returned if timeout
|
return 0; // zero returned if timeout
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
read(); // consume the character we got with peek
|
read(); // consume the character we got with peek
|
||||||
c = timedPeek();
|
c = timedPeek();
|
||||||
} while((c >= '0' && c <= '9') || c == '.' || c == skipChar);
|
} while((c >= '0' && c <= '9') || c == '.' || c == skipChar);
|
||||||
|
|
||||||
if(isNegative)
|
if(isNegative) {
|
||||||
value = -value;
|
value = -value;
|
||||||
if(isFraction)
|
}
|
||||||
|
if(isFraction) {
|
||||||
return value * fraction;
|
return value * fraction;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
return value;
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// read characters from stream into buffer
|
// read characters from stream into buffer
|
||||||
@@ -211,8 +232,9 @@ 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();
|
||||||
if(c < 0)
|
if(c < 0) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
*buffer++ = (char) c;
|
*buffer++ = (char) c;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@@ -224,13 +246,15 @@ size_t Stream::readBytes(char *buffer, size_t length) {
|
|||||||
// 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;
|
||||||
|
}
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
while(index < length) {
|
while(index < length) {
|
||||||
int c = timedRead();
|
int c = timedRead();
|
||||||
if(c < 0 || c == terminator)
|
if(c < 0 || c == terminator) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
*buffer++ = (char) c;
|
*buffer++ = (char) c;
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
noniso.cpp - replacements for non-ISO functions used by Arduino core
|
noniso.cpp - replacements for non-ISO functions used by Arduino core
|
||||||
Copyright © 2016 Ivan Grokhotkov
|
Copyright © 2016 Ivan Grokhotkov
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
The above copyright notice and this permission notice shall be included in
|
||||||
all copies or substantial portions of the Software.
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
@@ -61,8 +61,9 @@ char* itoa(int value, char* result, int base) {
|
|||||||
} while(quotient);
|
} while(quotient);
|
||||||
|
|
||||||
// Apply negative sign
|
// Apply negative sign
|
||||||
if(value < 0)
|
if(value < 0) {
|
||||||
*out++ = '-';
|
*out++ = '-';
|
||||||
|
}
|
||||||
|
|
||||||
reverse(result, out);
|
reverse(result, out);
|
||||||
*out = 0;
|
*out = 0;
|
||||||
@@ -112,8 +113,9 @@ char* ltoa(long value, char* result, int base) {
|
|||||||
} while(quotient);
|
} while(quotient);
|
||||||
|
|
||||||
// Apply negative sign
|
// Apply negative sign
|
||||||
if(value < 0)
|
if(value < 0) {
|
||||||
*out++ = '-';
|
*out++ = '-';
|
||||||
|
}
|
||||||
|
|
||||||
reverse(result, out);
|
reverse(result, out);
|
||||||
*out = 0;
|
*out = 0;
|
||||||
|
|||||||
@@ -231,7 +231,9 @@ boolean PubSubClient::readByte(uint8_t * result, uint16_t * index){
|
|||||||
|
|
||||||
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)) return 0;
|
if(!readByte(buffer, &len)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
bool isPublish = (buffer[0]&0xF0) == MQTTPUBLISH;
|
bool isPublish = (buffer[0]&0xF0) == MQTTPUBLISH;
|
||||||
uint32_t multiplier = 1;
|
uint32_t multiplier = 1;
|
||||||
uint16_t length = 0;
|
uint16_t length = 0;
|
||||||
@@ -240,7 +242,9 @@ uint16_t PubSubClient::readPacket(uint8_t* lengthLength) {
|
|||||||
uint8_t start = 0;
|
uint8_t start = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(!readByte(&digit)) return 0;
|
if(!readByte(&digit)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
buffer[len++] = digit;
|
buffer[len++] = digit;
|
||||||
length += (digit & 127) * multiplier;
|
length += (digit & 127) * multiplier;
|
||||||
multiplier *= 128;
|
multiplier *= 128;
|
||||||
@@ -249,8 +253,12 @@ uint16_t PubSubClient::readPacket(uint8_t* lengthLength) {
|
|||||||
|
|
||||||
if (isPublish) {
|
if (isPublish) {
|
||||||
// Read in topic length to calculate bytes to skip over for Stream writing
|
// Read in topic length to calculate bytes to skip over for Stream writing
|
||||||
if(!readByte(buffer, &len)) return 0;
|
if(!readByte(buffer, &len)) {
|
||||||
if(!readByte(buffer, &len)) return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
if(!readByte(buffer, &len)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
skip = (buffer[*lengthLength+1]<<8)+buffer[*lengthLength+2];
|
skip = (buffer[*lengthLength+1]<<8)+buffer[*lengthLength+2];
|
||||||
start = 2;
|
start = 2;
|
||||||
if (buffer[0]&MQTTQOS1) {
|
if (buffer[0]&MQTTQOS1) {
|
||||||
@@ -260,7 +268,9 @@ uint16_t PubSubClient::readPacket(uint8_t* lengthLength) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (uint16_t i = start;i<length;i++) {
|
for (uint16_t i = start;i<length;i++) {
|
||||||
if(!readByte(&digit)) return 0;
|
if(!readByte(&digit)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (this->stream) {
|
if (this->stream) {
|
||||||
if (isPublish && len-*lengthLength-2>skip) {
|
if (isPublish && len-*lengthLength-2>skip) {
|
||||||
this->stream->write(digit);
|
this->stream->write(digit);
|
||||||
|
|||||||
+18
-15
@@ -71,7 +71,7 @@ LOCAL uint8_t RF24_spiMultiByteTransfer(uint8_t cmd, uint8_t* buf, uint8_t len,
|
|||||||
} 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) { *buf++ = *prx++; }
|
while (--size) { *buf++ = *prx++; }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
status = *prx; // status is 1st byte of receive buffer
|
status = *prx; // status is 1st byte of receive buffer
|
||||||
@@ -79,9 +79,11 @@ LOCAL uint8_t RF24_spiMultiByteTransfer(uint8_t cmd, uint8_t* buf, uint8_t len,
|
|||||||
#else
|
#else
|
||||||
status = _SPI.transfer( cmd );
|
status = _SPI.transfer( cmd );
|
||||||
while ( len-- ) {
|
while ( len-- ) {
|
||||||
if (aReadMode) {
|
if (aReadMode) {
|
||||||
status = _SPI.transfer( NOP );
|
status = _SPI.transfer( NOP );
|
||||||
if (buf != NULL) *current++ = status;
|
if (buf != NULL) {
|
||||||
|
*current++ = status;
|
||||||
|
}
|
||||||
} else status = _SPI.transfer(*current++);
|
} else status = _SPI.transfer(*current++);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -92,7 +94,7 @@ LOCAL uint8_t RF24_spiMultiByteTransfer(uint8_t cmd, uint8_t* buf, uint8_t len,
|
|||||||
// timing
|
// timing
|
||||||
delayMicroseconds(10);
|
delayMicroseconds(10);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCAL uint8_t RF24_spiByteTransfer(uint8_t cmd) {
|
LOCAL uint8_t RF24_spiByteTransfer(uint8_t cmd) {
|
||||||
return RF24_spiMultiByteTransfer( cmd, NULL, 0, false);
|
return RF24_spiMultiByteTransfer( cmd, NULL, 0, false);
|
||||||
@@ -182,8 +184,8 @@ LOCAL void RF24_enableFeatures(void) {
|
|||||||
RF24_RAW_writeByteRegister(ACTIVATE, 0x73);
|
RF24_RAW_writeByteRegister(ACTIVATE, 0x73);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCAL void RF24_openWritingPipe(uint8_t recipient) {
|
LOCAL void RF24_openWritingPipe(uint8_t recipient) {
|
||||||
RF24_DEBUG(PSTR("RF24:open writing pipe, recipient=%d\n"), recipient);
|
RF24_DEBUG(PSTR("RF24:open writing pipe, recipient=%d\n"), recipient);
|
||||||
// only write LSB of RX0 and TX pipe
|
// only write LSB of RX0 and TX pipe
|
||||||
RF24_setPipeLSB(RX_ADDR_P0, recipient);
|
RF24_setPipeLSB(RX_ADDR_P0, recipient);
|
||||||
RF24_setPipeLSB(TX_ADDR, recipient);
|
RF24_setPipeLSB(TX_ADDR, recipient);
|
||||||
@@ -191,10 +193,12 @@ LOCAL void RF24_openWritingPipe(uint8_t recipient) {
|
|||||||
|
|
||||||
LOCAL void RF24_startListening(void) {
|
LOCAL void RF24_startListening(void) {
|
||||||
RF24_DEBUG(PSTR("RF24:start listening\n"));
|
RF24_DEBUG(PSTR("RF24:start listening\n"));
|
||||||
// toggle PRX
|
// toggle PRX
|
||||||
RF24_setRFConfiguration(MY_RF24_CONFIGURATION | _BV(PWR_UP) | _BV(PRIM_RX) );
|
RF24_setRFConfiguration(MY_RF24_CONFIGURATION | _BV(PWR_UP) | _BV(PRIM_RX) );
|
||||||
// all RX pipe addresses must be unique, therefore skip if node ID is 0xFF
|
// all RX pipe addresses must be unique, therefore skip if node ID is 0xFF
|
||||||
if(MY_RF24_NODE_ADDRESS!=AUTO) RF24_setPipeLSB(RX_ADDR_P0, MY_RF24_NODE_ADDRESS);
|
if(MY_RF24_NODE_ADDRESS!=AUTO) {
|
||||||
|
RF24_setPipeLSB(RX_ADDR_P0, MY_RF24_NODE_ADDRESS);
|
||||||
|
}
|
||||||
// start listening
|
// start listening
|
||||||
RF24_ce(HIGH);
|
RF24_ce(HIGH);
|
||||||
}
|
}
|
||||||
@@ -219,7 +223,7 @@ LOCAL bool RF24_sendMessage( uint8_t recipient, const void* buf, uint8_t len ) {
|
|||||||
uint8_t status;
|
uint8_t status;
|
||||||
|
|
||||||
RF24_stopListening();
|
RF24_stopListening();
|
||||||
RF24_openWritingPipe( recipient );
|
RF24_openWritingPipe( recipient );
|
||||||
RF24_DEBUG(PSTR("RF24:send message to %d, len=%d\n"),recipient,len);
|
RF24_DEBUG(PSTR("RF24:send message to %d, len=%d\n"),recipient,len);
|
||||||
// flush TX FIFO
|
// flush TX FIFO
|
||||||
RF24_flushTX();
|
RF24_flushTX();
|
||||||
@@ -251,10 +255,10 @@ LOCAL bool RF24_sendMessage( uint8_t recipient, const void* buf, uint8_t len ) {
|
|||||||
LOCAL uint8_t RF24_getDynamicPayloadSize(void) {
|
LOCAL uint8_t RF24_getDynamicPayloadSize(void) {
|
||||||
uint8_t result = RF24_spiMultiByteTransfer(R_RX_PL_WID, NULL, 1, true);
|
uint8_t result = RF24_spiMultiByteTransfer(R_RX_PL_WID, NULL, 1, true);
|
||||||
// check if payload size invalid
|
// check if payload size invalid
|
||||||
if(result > 32) {
|
if(result > 32) {
|
||||||
RF24_DEBUG(PSTR("RF24:invalid payload length = %d\n"),result);
|
RF24_DEBUG(PSTR("RF24:invalid payload length = %d\n"),result);
|
||||||
RF24_flushRX();
|
RF24_flushRX();
|
||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -267,7 +271,7 @@ LOCAL bool RF24_isDataAvailable() {
|
|||||||
LOCAL uint8_t RF24_readMessage( void* buf) {
|
LOCAL uint8_t RF24_readMessage( void* buf) {
|
||||||
const uint8_t len = RF24_getDynamicPayloadSize();
|
const uint8_t len = RF24_getDynamicPayloadSize();
|
||||||
RF24_DEBUG(PSTR("RF24:read message, len=%d\n"), len);
|
RF24_DEBUG(PSTR("RF24:read message, len=%d\n"), len);
|
||||||
RF24_spiMultiByteTransfer( R_RX_PAYLOAD , (uint8_t*)buf, len, true );
|
RF24_spiMultiByteTransfer( R_RX_PAYLOAD , (uint8_t*)buf, len, true );
|
||||||
// clear RX interrupt
|
// clear RX interrupt
|
||||||
RF24_setStatus(_BV(RX_DR) );
|
RF24_setStatus(_BV(RX_DR) );
|
||||||
return len;
|
return len;
|
||||||
@@ -314,7 +318,7 @@ LOCAL void RF24_irqHandler( void )
|
|||||||
// for a message we've already read.
|
// for a message we've already read.
|
||||||
while (RF24_isDataAvailable()) {
|
while (RF24_isDataAvailable()) {
|
||||||
RF24_receiveCallback(); // Must call RF24_readMessage(), which will clear RX_DR IRQ !
|
RF24_receiveCallback(); // Must call RF24_readMessage(), which will clear RX_DR IRQ !
|
||||||
}
|
}
|
||||||
// Restore our interrupt handler.
|
// Restore our interrupt handler.
|
||||||
#if defined(MY_GATEWAY_SERIAL) && !defined(__linux__)
|
#if defined(MY_GATEWAY_SERIAL) && !defined(__linux__)
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
@@ -395,4 +399,3 @@ LOCAL bool RF24_initialize(void) {
|
|||||||
RF24_setStatus(_BV(TX_DS) | _BV(MAX_RT) | _BV(RX_DR));
|
RF24_setStatus(_BV(TX_DS) | _BV(MAX_RT) | _BV(RX_DR));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+96
-71
@@ -6,23 +6,23 @@
|
|||||||
// **********************************************************************************
|
// **********************************************************************************
|
||||||
// License
|
// License
|
||||||
// **********************************************************************************
|
// **********************************************************************************
|
||||||
// This program is free software; you can redistribute it
|
// This program is free software; you can redistribute it
|
||||||
// and/or modify it under the terms of the GNU General
|
// and/or modify it under the terms of the GNU General
|
||||||
// Public License as published by the Free Software
|
// Public License as published by the Free Software
|
||||||
// Foundation; either version 3 of the License, or
|
// Foundation; either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
//
|
//
|
||||||
// This program is distributed in the hope that it will
|
// This program is distributed in the hope that it will
|
||||||
// be useful, but WITHOUT ANY WARRANTY; without even the
|
// be useful, but WITHOUT ANY WARRANTY; without even the
|
||||||
// implied warranty of MERCHANTABILITY or FITNESS FOR A
|
// implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
// PARTICULAR PURPOSE. See the GNU General Public
|
// PARTICULAR PURPOSE. See the GNU General Public
|
||||||
// License for more details.
|
// License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General
|
// You should have received a copy of the GNU General
|
||||||
// Public License along with this program.
|
// Public License along with this program.
|
||||||
// If not, see <http://www.gnu.org/licenses/>.
|
// If not, see <http://www.gnu.org/licenses/>.
|
||||||
//
|
//
|
||||||
// Licence can be viewed at
|
// Licence can be viewed at
|
||||||
// http://www.gnu.org/licenses/gpl-3.0.txt
|
// http://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
//
|
//
|
||||||
// Please maintain this license information along with authorship
|
// Please maintain this license information along with authorship
|
||||||
@@ -93,17 +93,18 @@ bool RFM69::initialize(uint8_t freqBand, uint8_t nodeID, uint8_t networkID)
|
|||||||
unsigned long start = millis();
|
unsigned long start = millis();
|
||||||
uint8_t timeout = 50;
|
uint8_t timeout = 50;
|
||||||
do {
|
do {
|
||||||
writeReg(REG_SYNCVALUE1, 0xAA);
|
writeReg(REG_SYNCVALUE1, 0xAA);
|
||||||
yield();
|
yield();
|
||||||
} while (readReg(REG_SYNCVALUE1) != 0xaa && millis()-start < timeout);
|
} while (readReg(REG_SYNCVALUE1) != 0xaa && millis()-start < timeout);
|
||||||
start = millis();
|
start = millis();
|
||||||
do {
|
do {
|
||||||
writeReg(REG_SYNCVALUE1, 0x55);
|
writeReg(REG_SYNCVALUE1, 0x55);
|
||||||
yield();
|
yield();
|
||||||
} while (readReg(REG_SYNCVALUE1) != 0x55 && millis()-start < timeout);
|
} while (readReg(REG_SYNCVALUE1) != 0x55 && millis()-start < timeout);
|
||||||
|
|
||||||
for (uint8_t i = 0; CONFIG[i][0] != 255; i++)
|
for (uint8_t i = 0; CONFIG[i][0] != 255; i++) {
|
||||||
writeReg(CONFIG[i][0], CONFIG[i][1]);
|
writeReg(CONFIG[i][0], CONFIG[i][1]);
|
||||||
|
}
|
||||||
|
|
||||||
// Encryption is persistent between resets and can trip you up during debugging.
|
// Encryption is persistent between resets and can trip you up during debugging.
|
||||||
// Disable it during initialization so we always start from a known state.
|
// Disable it during initialization so we always start from a known state.
|
||||||
@@ -113,10 +114,11 @@ bool RFM69::initialize(uint8_t freqBand, uint8_t nodeID, uint8_t networkID)
|
|||||||
setMode(RF69_MODE_STANDBY);
|
setMode(RF69_MODE_STANDBY);
|
||||||
start = millis();
|
start = millis();
|
||||||
while (((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) && millis()-start < timeout) {
|
while (((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) && millis()-start < timeout) {
|
||||||
yield();
|
yield();
|
||||||
} // wait for ModeReady
|
} // wait for ModeReady
|
||||||
if (millis()-start >= timeout)
|
if (millis()-start >= timeout) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
attachInterrupt(_interruptNum, RFM69::isr0, RISING);
|
attachInterrupt(_interruptNum, RFM69::isr0, RISING);
|
||||||
|
|
||||||
selfPointer = this;
|
selfPointer = this;
|
||||||
@@ -149,17 +151,22 @@ void RFM69::setFrequency(uint32_t freqHz)
|
|||||||
|
|
||||||
void RFM69::setMode(uint8_t newMode)
|
void RFM69::setMode(uint8_t newMode)
|
||||||
{
|
{
|
||||||
if (newMode == _mode)
|
if (newMode == _mode) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (newMode) {
|
switch (newMode) {
|
||||||
case RF69_MODE_TX:
|
case RF69_MODE_TX:
|
||||||
writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_TRANSMITTER);
|
writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_TRANSMITTER);
|
||||||
if (_isRFM69HW) setHighPowerRegs(true);
|
if (_isRFM69HW) {
|
||||||
|
setHighPowerRegs(true);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case RF69_MODE_RX:
|
case RF69_MODE_RX:
|
||||||
writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_RECEIVER);
|
writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_RECEIVER);
|
||||||
if (_isRFM69HW) setHighPowerRegs(false);
|
if (_isRFM69HW) {
|
||||||
|
setHighPowerRegs(false);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case RF69_MODE_SYNTH:
|
case RF69_MODE_SYNTH:
|
||||||
writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_SYNTHESIZER);
|
writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_SYNTHESIZER);
|
||||||
@@ -209,7 +216,9 @@ void RFM69::setNetwork(uint8_t networkID)
|
|||||||
void RFM69::setPowerLevel(uint8_t powerLevel)
|
void RFM69::setPowerLevel(uint8_t powerLevel)
|
||||||
{
|
{
|
||||||
_powerLevel = (powerLevel > 31 ? 31 : powerLevel);
|
_powerLevel = (powerLevel > 31 ? 31 : powerLevel);
|
||||||
if (_isRFM69HW) _powerLevel /= 2;
|
if (_isRFM69HW) {
|
||||||
|
_powerLevel /= 2;
|
||||||
|
}
|
||||||
writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0xE0) | _powerLevel);
|
writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0xE0) | _powerLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +236,9 @@ void RFM69::send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool
|
|||||||
{
|
{
|
||||||
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) receiveDone();
|
while (!canSend() && millis() - now < RF69_CSMA_LIMIT_MS) {
|
||||||
|
receiveDone();
|
||||||
|
}
|
||||||
sendFrame(toAddress, buffer, bufferSize, requestACK, false);
|
sendFrame(toAddress, buffer, bufferSize, requestACK, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,8 +269,9 @@ 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;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,21 +299,25 @@ void RFM69::sendACK(const void* buffer, uint8_t bufferSize) {
|
|||||||
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
|
||||||
writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_00); // DIO0 is "Packet Sent"
|
writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_00); // DIO0 is "Packet Sent"
|
||||||
if (bufferSize > RF69_MAX_DATA_LEN) bufferSize = RF69_MAX_DATA_LEN;
|
if (bufferSize > RF69_MAX_DATA_LEN) {
|
||||||
|
bufferSize = RF69_MAX_DATA_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
// control byte
|
// control byte
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
// write to FIFO
|
// write to FIFO
|
||||||
select();
|
select();
|
||||||
@@ -311,14 +327,15 @@ void RFM69::sendFrame(uint8_t toAddress, const void* buffer, uint8_t bufferSize,
|
|||||||
SPI.transfer(_address);
|
SPI.transfer(_address);
|
||||||
SPI.transfer(CTLbyte);
|
SPI.transfer(CTLbyte);
|
||||||
|
|
||||||
for (uint8_t i = 0; i < bufferSize; i++)
|
for (uint8_t i = 0; i < bufferSize; i++) {
|
||||||
SPI.transfer(((uint8_t*) buffer)[i]);
|
SPI.transfer(((uint8_t*) buffer)[i]);
|
||||||
|
}
|
||||||
unselect();
|
unselect();
|
||||||
|
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
@@ -352,14 +369,16 @@ void RFM69::interruptHandler() {
|
|||||||
|
|
||||||
ACK_RECEIVED = CTLbyte & RFM69_CTL_SENDACK; // extract ACK-received flag
|
ACK_RECEIVED = CTLbyte & RFM69_CTL_SENDACK; // extract ACK-received flag
|
||||||
ACK_REQUESTED = CTLbyte & RFM69_CTL_REQACK; // extract ACK-requested flag
|
ACK_REQUESTED = CTLbyte & RFM69_CTL_REQACK; // extract ACK-requested flag
|
||||||
|
|
||||||
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) DATA[DATALEN] = 0; // add null at end of string
|
if (DATALEN < RF69_MAX_DATA_LEN) {
|
||||||
|
DATA[DATALEN] = 0; // add null at end of string
|
||||||
|
}
|
||||||
unselect();
|
unselect();
|
||||||
setMode(RF69_MODE_RX);
|
setMode(RF69_MODE_RX);
|
||||||
}
|
}
|
||||||
@@ -379,8 +398,9 @@ void RFM69::receiveBegin() {
|
|||||||
ACK_REQUESTED = 0;
|
ACK_REQUESTED = 0;
|
||||||
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);
|
||||||
}
|
}
|
||||||
@@ -414,8 +434,9 @@ void RFM69::encrypt(const char* key) {
|
|||||||
{
|
{
|
||||||
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++) {
|
||||||
SPI.transfer(key[i]);
|
SPI.transfer(key[i]);
|
||||||
|
}
|
||||||
unselect();
|
unselect();
|
||||||
}
|
}
|
||||||
writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFE) | (key ? 1 : 0));
|
writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFE) | (key ? 1 : 0));
|
||||||
@@ -428,7 +449,7 @@ int16_t RFM69::readRSSI(bool 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
|
||||||
}
|
}
|
||||||
rssi = -readReg(REG_RSSIVALUE);
|
rssi = -readReg(REG_RSSIVALUE);
|
||||||
rssi >>= 1;
|
rssi >>= 1;
|
||||||
@@ -489,10 +510,12 @@ void RFM69::promiscuous(bool onOff) {
|
|||||||
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
|
||||||
@@ -501,7 +524,7 @@ void RFM69::setHighPowerRegs(bool onOff) {
|
|||||||
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);
|
||||||
@@ -519,7 +542,9 @@ void SerialWrite ( uint8_t 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++) (*f)(c);
|
for (uint8_t c; (c = pgm_read_byte(str)); str++) {
|
||||||
|
(*f)(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -527,7 +552,7 @@ void RFM69::readAllRegs()
|
|||||||
{
|
{
|
||||||
uint8_t regVal;
|
uint8_t regVal;
|
||||||
|
|
||||||
#if REGISTER_DETAIL
|
#if REGISTER_DETAIL
|
||||||
int capVal;
|
int capVal;
|
||||||
|
|
||||||
//... State Variables for intelligent decoding
|
//... State Variables for intelligent decoding
|
||||||
@@ -536,7 +561,7 @@ void RFM69::readAllRegs()
|
|||||||
int freqDev = 0;
|
int freqDev = 0;
|
||||||
long freqCenter = 0;
|
long freqCenter = 0;
|
||||||
#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++)
|
||||||
{
|
{
|
||||||
@@ -551,8 +576,8 @@ void RFM69::readAllRegs()
|
|||||||
Serial.print(" - ");
|
Serial.print(" - ");
|
||||||
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 : " );
|
||||||
@@ -561,19 +586,19 @@ void RFM69::readAllRegs()
|
|||||||
} else {
|
} else {
|
||||||
SerialPrint ( "0 -> Operating mode as selected with Mode bits in RegOpMode is automatically reached with the Sequencer\n" );
|
SerialPrint ( "0 -> Operating mode as selected with Mode bits in RegOpMode is automatically reached with the Sequencer\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
SerialPrint( "\nEnables Listen mode, should be enabled whilst in Standby mode:\nListenOn : " );
|
SerialPrint( "\nEnables Listen mode, should be enabled whilst in Standby mode:\nListenOn : " );
|
||||||
if ( 0x40 & regVal ) {
|
if ( 0x40 & regVal ) {
|
||||||
SerialPrint ( "1 -> On\n" );
|
SerialPrint ( "1 -> On\n" );
|
||||||
} else {
|
} else {
|
||||||
SerialPrint ( "0 -> Off ( see section 4.3)\n" );
|
SerialPrint ( "0 -> Off ( see section 4.3)\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
SerialPrint( "\nAborts Listen mode when set together with ListenOn=0 See section 4.3.4 for details (Always reads 0.)\n" );
|
SerialPrint( "\nAborts Listen mode when set together with ListenOn=0 See section 4.3.4 for details (Always reads 0.)\n" );
|
||||||
if ( 0x20 & regVal ) {
|
if ( 0x20 & regVal ) {
|
||||||
SerialPrint ( "ERROR - ListenAbort should NEVER return 1 this is a write only register\n" );
|
SerialPrint ( "ERROR - ListenAbort should NEVER return 1 this is a write only register\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
SerialPrint("\nTransceiver's operating modes:\nMode : ");
|
SerialPrint("\nTransceiver's operating modes:\nMode : ");
|
||||||
capVal = (regVal >> 2) & 0x7;
|
capVal = (regVal >> 2) & 0x7;
|
||||||
if ( capVal == 0b000 ) {
|
if ( capVal == 0b000 ) {
|
||||||
@@ -593,9 +618,9 @@ void RFM69::readAllRegs()
|
|||||||
SerialPrint ( "\n" );
|
SerialPrint ( "\n" );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x2 : {
|
case 0x2 : {
|
||||||
|
|
||||||
SerialPrint("Data Processing mode:\nDataMode : ");
|
SerialPrint("Data Processing mode:\nDataMode : ");
|
||||||
capVal = (regVal >> 5) & 0x3;
|
capVal = (regVal >> 5) & 0x3;
|
||||||
if ( capVal == 0b00 ) {
|
if ( capVal == 0b00 ) {
|
||||||
@@ -607,7 +632,7 @@ void RFM69::readAllRegs()
|
|||||||
} else if ( capVal == 0b11 ) {
|
} else if ( capVal == 0b11 ) {
|
||||||
SerialPrint ( "11 -> Continuous mode without bit synchronizer\n" );
|
SerialPrint ( "11 -> Continuous mode without bit synchronizer\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
SerialPrint("\nModulation scheme:\nModulation Type : ");
|
SerialPrint("\nModulation scheme:\nModulation Type : ");
|
||||||
capVal = (regVal >> 3) & 0x3;
|
capVal = (regVal >> 3) & 0x3;
|
||||||
if ( capVal == 0b00 ) {
|
if ( capVal == 0b00 ) {
|
||||||
@@ -620,7 +645,7 @@ void RFM69::readAllRegs()
|
|||||||
} else if ( capVal == 0b11 ) {
|
} else if ( capVal == 0b11 ) {
|
||||||
SerialPrint ( "11 -> reserved\n" );
|
SerialPrint ( "11 -> reserved\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
SerialPrint("\nData shaping: ");
|
SerialPrint("\nData shaping: ");
|
||||||
if ( modeFSK ) {
|
if ( modeFSK ) {
|
||||||
SerialPrint( "in FSK:\n" );
|
SerialPrint( "in FSK:\n" );
|
||||||
@@ -650,16 +675,16 @@ void RFM69::readAllRegs()
|
|||||||
SerialPrint ( "ERROR - 11 is reserved\n" );
|
SerialPrint ( "ERROR - 11 is reserved\n" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SerialPrint ( "\n" );
|
SerialPrint ( "\n" );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x3 : {
|
case 0x3 : {
|
||||||
bitRate = (regVal << 8);
|
bitRate = (regVal << 8);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x4 : {
|
case 0x4 : {
|
||||||
bitRate |= regVal;
|
bitRate |= regVal;
|
||||||
SerialPrint ( "Bit Rate (Chip Rate when Manchester encoding is enabled)\nBitRate : ");
|
SerialPrint ( "Bit Rate (Chip Rate when Manchester encoding is enabled)\nBitRate : ");
|
||||||
@@ -668,12 +693,12 @@ void RFM69::readAllRegs()
|
|||||||
SerialPrint( "\n" );
|
SerialPrint( "\n" );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x5 : {
|
case 0x5 : {
|
||||||
freqDev = ( (regVal & 0x3f) << 8 );
|
freqDev = ( (regVal & 0x3f) << 8 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x6 : {
|
case 0x6 : {
|
||||||
freqDev |= regVal;
|
freqDev |= regVal;
|
||||||
SerialPrint( "Frequency deviation\nFdev : " );
|
SerialPrint( "Frequency deviation\nFdev : " );
|
||||||
@@ -682,20 +707,20 @@ void RFM69::readAllRegs()
|
|||||||
SerialPrint ( "\n" );
|
SerialPrint ( "\n" );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x7 : {
|
case 0x7 : {
|
||||||
unsigned long tempVal = regVal;
|
unsigned long tempVal = regVal;
|
||||||
freqCenter = ( tempVal << 16 );
|
freqCenter = ( tempVal << 16 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x8 : {
|
case 0x8 : {
|
||||||
unsigned long tempVal = regVal;
|
unsigned long tempVal = regVal;
|
||||||
freqCenter = freqCenter | ( tempVal << 8 );
|
freqCenter = freqCenter | ( tempVal << 8 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x9 : {
|
case 0x9 : {
|
||||||
freqCenter = freqCenter | regVal;
|
freqCenter = freqCenter | regVal;
|
||||||
SerialPrint ( "RF Carrier frequency\nFRF : " );
|
SerialPrint ( "RF Carrier frequency\nFRF : " );
|
||||||
unsigned long val = 61UL * freqCenter;
|
unsigned long val = 61UL * freqCenter;
|
||||||
@@ -711,7 +736,7 @@ void RFM69::readAllRegs()
|
|||||||
} else {
|
} else {
|
||||||
SerialPrint ( "0 -> RC calibration is in progress\n" );
|
SerialPrint ( "0 -> RC calibration is in progress\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
SerialPrint ( "\n" );
|
SerialPrint ( "\n" );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -726,7 +751,7 @@ void RFM69::readAllRegs()
|
|||||||
SerialPrint ( "\n" );
|
SerialPrint ( "\n" );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0xc : {
|
case 0xc : {
|
||||||
SerialPrint ( "Reserved\n\n" );
|
SerialPrint ( "Reserved\n\n" );
|
||||||
break;
|
break;
|
||||||
@@ -745,7 +770,7 @@ void RFM69::readAllRegs()
|
|||||||
} else if ( val == 0b11 ) {
|
} else if ( val == 0b11 ) {
|
||||||
SerialPrint ( "11 -> 262 ms\n" );
|
SerialPrint ( "11 -> 262 ms\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
SerialPrint ( "\nResolution of Listen mode Rx time (calibrated RC osc):\nListenResolRx : " );
|
SerialPrint ( "\nResolution of Listen mode Rx time (calibrated RC osc):\nListenResolRx : " );
|
||||||
val = (regVal >> 4) & 0x3;
|
val = (regVal >> 4) & 0x3;
|
||||||
if ( val == 0b00 ) {
|
if ( val == 0b00 ) {
|
||||||
@@ -764,7 +789,7 @@ void RFM69::readAllRegs()
|
|||||||
} else {
|
} else {
|
||||||
SerialPrint ( "0 -> signal strength is above RssiThreshold\n" );
|
SerialPrint ( "0 -> signal strength is above RssiThreshold\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
SerialPrint ( "\nAction taken after acceptance of a packet in Listen mode:\nListenEnd : " );
|
SerialPrint ( "\nAction taken after acceptance of a packet in Listen mode:\nListenEnd : " );
|
||||||
val = (regVal >> 1 ) & 0x3;
|
val = (regVal >> 1 ) & 0x3;
|
||||||
if ( val == 0b00 ) {
|
if ( val == 0b00 ) {
|
||||||
@@ -776,12 +801,12 @@ void RFM69::readAllRegs()
|
|||||||
} else if ( val == 0b11 ) {
|
} else if ( val == 0b11 ) {
|
||||||
SerialPrint ( "11 -> Reserved\n" );
|
SerialPrint ( "11 -> Reserved\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SerialPrint ( "\n" );
|
SerialPrint ( "\n" );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default : {
|
default : {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -794,12 +819,12 @@ 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()
|
||||||
{
|
{
|
||||||
writeReg(REG_OSC1, RF_OSC1_RCCAL_START);
|
writeReg(REG_OSC1, RF_OSC1_RCCAL_START);
|
||||||
while ((readReg(REG_OSC1) & RF_OSC1_RCCAL_DONE) == 0x00);
|
while ((readReg(REG_OSC1) & RF_OSC1_RCCAL_DONE) == 0x00) {}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-3
@@ -79,9 +79,15 @@ void SPIClass::setClockDivider(uint16_t divider) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SPIClass::chipSelect(int csn_pin) {
|
void SPIClass::chipSelect(int csn_pin) {
|
||||||
if (csn_pin == RPI_GPIO_P1_26) csn_pin = BCM2835_SPI_CS1;
|
if (csn_pin == RPI_GPIO_P1_26) {
|
||||||
else if (csn_pin == RPI_GPIO_P1_24) csn_pin = BCM2835_SPI_CS0;
|
csn_pin = BCM2835_SPI_CS1;
|
||||||
else csn_pin = BCM2835_SPI_CS0;
|
}
|
||||||
|
else if (csn_pin == RPI_GPIO_P1_24) {
|
||||||
|
csn_pin = BCM2835_SPI_CS0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
csn_pin = BCM2835_SPI_CS0;
|
||||||
|
}
|
||||||
bcm2835_spi_chipSelect(csn_pin);
|
bcm2835_spi_chipSelect(csn_pin);
|
||||||
delayMicroseconds(5);
|
delayMicroseconds(5);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,28 +7,28 @@
|
|||||||
// > Updated Jan. 5, 2015, TomWS1, modified writeBytes to allow blocks > 256 bytes and handle page misalignment.
|
// > Updated Jan. 5, 2015, TomWS1, modified writeBytes to allow blocks > 256 bytes and handle page misalignment.
|
||||||
// > Updated Feb. 26, 2015 TomWS1, added support for SPI Transactions (Arduino 1.5.8 and above)
|
// > Updated Feb. 26, 2015 TomWS1, added support for SPI Transactions (Arduino 1.5.8 and above)
|
||||||
// > Selective merge by Felix after testing in IDE 1.0.6, 1.6.4
|
// > Selective merge by Felix after testing in IDE 1.0.6, 1.6.4
|
||||||
// > Updated May 19, 2016 D-H-R, added support for SST25/Microchip Flash which does not support Page programming with OPCode 0x02,
|
// > Updated May 19, 2016 D-H-R, added support for SST25/Microchip Flash which does not support Page programming with OPCode 0x02,
|
||||||
// > use define MY_SPIFLASH_SST25TYPE for SST25 Type Flash Memory
|
// > use define MY_SPIFLASH_SST25TYPE for SST25 Type Flash Memory
|
||||||
// **********************************************************************************
|
// **********************************************************************************
|
||||||
// License
|
// License
|
||||||
// **********************************************************************************
|
// **********************************************************************************
|
||||||
// This program is free software; you can redistribute it
|
// This program is free software; you can redistribute it
|
||||||
// and/or modify it under the terms of the GNU General
|
// and/or modify it under the terms of the GNU General
|
||||||
// Public License as published by the Free Software
|
// Public License as published by the Free Software
|
||||||
// Foundation; either version 3 of the License, or
|
// Foundation; either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
//
|
//
|
||||||
// This program is distributed in the hope that it will
|
// This program is distributed in the hope that it will
|
||||||
// be useful, but WITHOUT ANY WARRANTY; without even the
|
// be useful, but WITHOUT ANY WARRANTY; without even the
|
||||||
// implied warranty of MERCHANTABILITY or FITNESS FOR A
|
// implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
// PARTICULAR PURPOSE. See the GNU General Public
|
// PARTICULAR PURPOSE. See the GNU General Public
|
||||||
// License for more details.
|
// License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General
|
// You should have received a copy of the GNU General
|
||||||
// Public License along with this program.
|
// Public License along with this program.
|
||||||
// If not, see <http://www.gnu.org/licenses/>.
|
// If not, see <http://www.gnu.org/licenses/>.
|
||||||
//
|
//
|
||||||
// Licence can be viewed at
|
// Licence can be viewed at
|
||||||
// http://www.gnu.org/licenses/gpl-3.0.txt
|
// http://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
//
|
//
|
||||||
// Please maintain this license information along with authorship
|
// Please maintain this license information along with authorship
|
||||||
@@ -81,7 +81,7 @@ void SPIFlash::unselect() {
|
|||||||
//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
|
||||||
SPI.endTransaction();
|
SPI.endTransaction();
|
||||||
#else
|
#else
|
||||||
interrupts();
|
interrupts();
|
||||||
#endif
|
#endif
|
||||||
#ifndef ESP8266
|
#ifndef ESP8266
|
||||||
@@ -104,7 +104,7 @@ boolean SPIFlash::initialize()
|
|||||||
|
|
||||||
unselect();
|
unselect();
|
||||||
wakeup();
|
wakeup();
|
||||||
|
|
||||||
if (_jedecID == 0 || readDeviceId() == _jedecID) {
|
if (_jedecID == 0 || readDeviceId() == _jedecID) {
|
||||||
command(SPIFLASH_STATUSWRITE, true); // Write Status Register
|
command(SPIFLASH_STATUSWRITE, true); // Write Status Register
|
||||||
SPI.transfer(0); // Global Unprotect
|
SPI.transfer(0); // Global Unprotect
|
||||||
@@ -142,8 +142,9 @@ uint8_t* SPIFlash::readUniqueId()
|
|||||||
SPI.transfer(0);
|
SPI.transfer(0);
|
||||||
SPI.transfer(0);
|
SPI.transfer(0);
|
||||||
SPI.transfer(0);
|
SPI.transfer(0);
|
||||||
for (uint8_t i=0;i<8;i++)
|
for (uint8_t i=0;i<8;i++) {
|
||||||
UNIQUEID[i] = SPI.transfer(0);
|
UNIQUEID[i] = SPI.transfer(0);
|
||||||
|
}
|
||||||
unselect();
|
unselect();
|
||||||
return UNIQUEID;
|
return UNIQUEID;
|
||||||
}
|
}
|
||||||
@@ -166,8 +167,9 @@ void SPIFlash::readBytes(uint32_t addr, void* buf, uint16_t len) {
|
|||||||
SPI.transfer(addr >> 8);
|
SPI.transfer(addr >> 8);
|
||||||
SPI.transfer(addr);
|
SPI.transfer(addr);
|
||||||
SPI.transfer(0); //"dont care"
|
SPI.transfer(0); //"dont care"
|
||||||
for (uint16_t i = 0; i < len; ++i)
|
for (uint16_t i = 0; i < len; ++i) {
|
||||||
((uint8_t*) buf)[i] = SPI.transfer(0);
|
((uint8_t*) buf)[i] = SPI.transfer(0);
|
||||||
|
}
|
||||||
unselect();
|
unselect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,12 +241,12 @@ void SPIFlash::writeBytes(uint32_t addr, const void* buf, uint16_t len) {
|
|||||||
uint16_t i=0;
|
uint16_t i=0;
|
||||||
uint8_t oddAdr=0;
|
uint8_t oddAdr=0;
|
||||||
char s[5];
|
char s[5];
|
||||||
|
|
||||||
command(SPIFLASH_AAIWORDPROGRAM, true); // Byte/Page Program
|
command(SPIFLASH_AAIWORDPROGRAM, true); // Byte/Page Program
|
||||||
SPI.transfer(addr >> 16);
|
SPI.transfer(addr >> 16);
|
||||||
SPI.transfer(addr >> 8);
|
SPI.transfer(addr >> 8);
|
||||||
SPI.transfer(addr);
|
SPI.transfer(addr);
|
||||||
|
|
||||||
if (addr%2){
|
if (addr%2){
|
||||||
//start address is not even, i.e. first byte of word must be 0xff
|
//start address is not even, i.e. first byte of word must be 0xff
|
||||||
SPI.transfer(0xff);
|
SPI.transfer(0xff);
|
||||||
@@ -252,25 +254,31 @@ void SPIFlash::writeBytes(uint32_t addr, const void* buf, uint16_t len) {
|
|||||||
unselect();
|
unselect();
|
||||||
oddAdr=1; //following addresses must all be shifted one off
|
oddAdr=1; //following addresses must all be shifted one off
|
||||||
len--;
|
len--;
|
||||||
if (len > 0) command(SPIFLASH_AAIWORDPROGRAM); //If for loop will run issue Wordprogram command
|
if (len > 0) {
|
||||||
|
command(SPIFLASH_AAIWORDPROGRAM); //If for loop will run issue Wordprogram command
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0;i<(len/2);i++){
|
for (i=0;i<(len/2);i++){
|
||||||
//AAI command must be set before every new word
|
//AAI command must be set before every new word
|
||||||
if (i>0) command(SPIFLASH_AAIWORDPROGRAM); //Wordprogram command for first write has been issued before
|
if (i>0) {
|
||||||
|
command(SPIFLASH_AAIWORDPROGRAM); //Wordprogram command for first write has been issued before
|
||||||
|
}
|
||||||
SPI.transfer(((uint8_t*) buf)[i*2+oddAdr]);
|
SPI.transfer(((uint8_t*) buf)[i*2+oddAdr]);
|
||||||
SPI.transfer(((uint8_t*) buf)[i*2+1+oddAdr]);
|
SPI.transfer(((uint8_t*) buf)[i*2+1+oddAdr]);
|
||||||
unselect();
|
unselect();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len-i*2 == 1){
|
if (len-i*2 == 1){
|
||||||
//There is one byte (i.e. half word) left. This happens if len was odd or (len was even and addr odd)
|
//There is one byte (i.e. half word) left. This happens if len was odd or (len was even and addr odd)
|
||||||
if (i>0) command(SPIFLASH_AAIWORDPROGRAM); //if for loop had not run wordprogram command from before is still valid
|
if (i>0) {
|
||||||
|
command(SPIFLASH_AAIWORDPROGRAM); //if for loop had not run wordprogram command from before is still valid
|
||||||
|
}
|
||||||
SPI.transfer(((uint8_t*) buf)[i*2+oddAdr]);
|
SPI.transfer(((uint8_t*) buf)[i*2+oddAdr]);
|
||||||
SPI.transfer(0xff);
|
SPI.transfer(0xff);
|
||||||
unselect();
|
unselect();
|
||||||
}
|
}
|
||||||
|
|
||||||
command(SPIFLASH_WRITEDISABLE); //end AAI programming
|
command(SPIFLASH_WRITEDISABLE); //end AAI programming
|
||||||
unselect();
|
unselect();
|
||||||
#else
|
#else
|
||||||
@@ -284,11 +292,12 @@ void SPIFlash::writeBytes(uint32_t addr, const void* buf, uint16_t len) {
|
|||||||
SPI.transfer(addr >> 16);
|
SPI.transfer(addr >> 16);
|
||||||
SPI.transfer(addr >> 8);
|
SPI.transfer(addr >> 8);
|
||||||
SPI.transfer(addr);
|
SPI.transfer(addr);
|
||||||
|
|
||||||
for (uint16_t i = 0; i < n; i++)
|
for (uint16_t i = 0; i < n; i++) {
|
||||||
SPI.transfer(((uint8_t*) buf)[offset + i]);
|
SPI.transfer(((uint8_t*) buf)[offset + i]);
|
||||||
|
}
|
||||||
unselect();
|
unselect();
|
||||||
|
|
||||||
addr+=n; // adjust the addresses and remaining bytes by what we've just transferred.
|
addr+=n; // adjust the addresses and remaining bytes by what we've just transferred.
|
||||||
offset +=n;
|
offset +=n;
|
||||||
len -= n;
|
len -= n;
|
||||||
|
|||||||
Reference in New Issue
Block a user