From bfa493ce3eadf1cc436e24cfe7a66b44bdbd2287 Mon Sep 17 00:00:00 2001 From: Embedded Innovation Date: Thu, 28 Apr 2016 21:10:20 +0200 Subject: [PATCH 1/5] Added interrupt handling and reception queueing for nRF24 When nRF24 interrupt is connected to Arduino, handling of reception interrupts can be enabled. This will store all data received in a buffer which will prevent messages from getting lost when the Arduino is too busy to empty the FIFO. --- libraries/MySensors/MyConfig.h | 18 ++++ libraries/MySensors/core/MyTransportNRF24.cpp | 77 +++++++++++++-- libraries/MySensors/drivers/RF24/RF24.cpp | 40 +++++++- libraries/MySensors/drivers/RF24/RF24.h | 6 +- .../QueueTestGateway/QueueTestGateway.ino | 94 +++++++++++++++++++ .../examples/QueueTestNode/QueueTestNode.ino | 52 ++++++++++ libraries/MySensors/keywords.txt | 1 + 7 files changed, 276 insertions(+), 12 deletions(-) create mode 100644 libraries/MySensors/examples/QueueTestGateway/QueueTestGateway.ino create mode 100644 libraries/MySensors/examples/QueueTestNode/QueueTestNode.ino diff --git a/libraries/MySensors/MyConfig.h b/libraries/MySensors/MyConfig.h index 2bc11e1..234e1e3 100644 --- a/libraries/MySensors/MyConfig.h +++ b/libraries/MySensors/MyConfig.h @@ -368,6 +368,24 @@ #endif #endif +/** + * @def MY_RF24_IRQ_PIN + * @brief Disable RF24 interrupt pin usage by default. Override in sketch if needed. + */ +#define MY_RF24_IRQ_PIN_UNUSED 0 +#ifndef MY_RF24_IRQ_PIN + #define MY_RF24_IRQ_PIN MY_RF24_IRQ_PIN_UNUSED +#endif + +/** + * @def MY_RF24_MESSAGE_BUFFER_SIZE + * @brief Declare the amount of messages that can be buffered. Override in sketch if needed. + */ +#ifndef MY_RF24_MESSAGE_BUFFER_SIZE + #define MY_RF24_MESSAGE_BUFFER_SIZE (20) +#endif + + /** * @def MY_RF24_PA_LEVEL * @brief Default RF24 PA level. Override in sketch if needed. diff --git a/libraries/MySensors/core/MyTransportNRF24.cpp b/libraries/MySensors/core/MyTransportNRF24.cpp index 5aa1596..6589a09 100644 --- a/libraries/MySensors/core/MyTransportNRF24.cpp +++ b/libraries/MySensors/core/MyTransportNRF24.cpp @@ -20,17 +20,47 @@ #include "MyConfig.h" #include "MyTransport.h" #include "drivers/RF24/RF24.h" +#include "drivers/CircularBuffer/CircularBuffer.h" #if defined(MY_RF24_ENABLE_ENCRYPTION) #include "drivers/AES/AES.h" #endif -#if defined(MY_RF24_ENABLE_ENCRYPTION) - AES _aes; - uint8_t _dataenc[32] = {0}; - uint8_t _psk[16]; +#if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) +typedef struct _queuedMessage +{ + uint8_t m_to; /** Destination address of this message. */ + uint8_t m_len; /** Length of the data. */ + uint8_t m_data[MAX_MESSAGE_LENGTH]; /** The raw data. */ +} queuedMessage; + +/** Buffer to store queued messages in. */ +static queuedMessage queueStorage[MY_RF24_MESSAGE_BUFFER_SIZE]; +/** Circular buffer, which uses the queueStorage and administers stored messages. */ +static CircularBuffer receiveQueue(queueStorage, MY_RF24_MESSAGE_BUFFER_SIZE); + +static volatile uint8_t lostMessageCount = 0; + +static void rxCallback(const uint8_t to) +{ + if (!receiveQueue.full()) + { + queuedMessage* msg = receiveQueue.getFront(); + msg->m_len = readMessage(msg->m_data); + (void)receiveQueue.pushFront(msg); + } else { + // TODO: Message is not really lost, as it is still in the nRF FIFO. But once the FIFO is also full messages will get lost. + ++lostMessageCount; + } +} #endif +#if defined(MY_RF24_ENABLE_ENCRYPTION) + AES _aes; + uint8_t _dataenc[32] = {0}; + uint8_t _psk[16]; +#endif + bool transportInit() { #if defined(MY_RF24_ENABLE_ENCRYPTION) @@ -40,7 +70,10 @@ bool transportInit() { // Make sure it is purged from memory when set memset(_psk, 0, 16); #endif - + + #if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) + registerReceiveCallback( rxCallback ); + #endif return initializeRF24(); } @@ -71,13 +104,39 @@ bool transportSend(uint8_t recipient, const void* data, uint8_t len) { } bool transportAvailable(uint8_t *to) { - bool avail = IsDataAvailable(to); - return avail; + bool avail = false; + #if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) + queuedMessage* msg = receiveQueue.getBack(); + if (msg) + { + avail = true; + *to = msg->m_to; + } else { + // TODO: The nRF FIFO could still hold a message + } + #else + avail = IsDataAvailable(to); + #endif + return avail; } uint8_t transportReceive(void* data) { - uint8_t len = readMessage(data); - #if defined(MY_RF24_ENABLE_ENCRYPTION) + uint8_t len; + #if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) +// debug(PSTR("lost:%d\n"), lostMessageCount); + queuedMessage* msg = receiveQueue.getBack(); + if (msg) + { + len = msg->m_len; + (void)memcpy(data, msg->m_data, len); + (void)receiveQueue.popBack(); + } else { + // TODO: The nRF FIFO could still hold a message + } + #else + len = readMessage(data); + #endif + #if defined(MY_RF24_ENABLE_ENCRYPTION) // has to be adjusted, WIP! _aes.set_IV(0); // decrypt data diff --git a/libraries/MySensors/drivers/RF24/RF24.cpp b/libraries/MySensors/drivers/RF24/RF24.cpp index 1466005..c9fa914 100644 --- a/libraries/MySensors/drivers/RF24/RF24.cpp +++ b/libraries/MySensors/drivers/RF24/RF24.cpp @@ -22,8 +22,13 @@ #include "RF24.h" -uint8_t MY_RF24_BASE_ADDR[MY_RF24_ADDR_WIDTH] = { MY_RF24_BASE_RADIO_ID }; -uint8_t MY_RF24_NODE_ADDRESS = AUTO; +static uint8_t MY_RF24_BASE_ADDR[MY_RF24_ADDR_WIDTH] = { MY_RF24_BASE_RADIO_ID }; +static uint8_t MY_RF24_NODE_ADDRESS = AUTO; + +#if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) +typedef void (*receiveCallbackType)(const uint8_t); +static receiveCallbackType receiveCallback = NULL; +#endif void csn(bool level) { digitalWrite(MY_RF24_CS_PIN, level); @@ -204,14 +209,45 @@ uint8_t getNodeID(void) { return MY_RF24_NODE_ADDRESS; } +#if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) +static void irqHandler( void ) +{ + if (receiveCallback) + { + uint8_t to; + (void)IsDataAvailable(&to); + receiveCallback(to); + } else { + // clear RX interrupt + writeByteRegister(RF24_STATUS, _BV(RX_DR) ); + } +} + +void registerReceiveCallback( receiveCallbackType cb ) +{ + noInterrupts(); + receiveCallback = cb; + interrupts(); +} +#endif + bool initializeRF24(void) { // Initialize pins pinMode(MY_RF24_CE_PIN,OUTPUT); pinMode(MY_RF24_CS_PIN,OUTPUT); + #if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) + pinMode(MY_RF24_IRQ_PIN,INPUT); + #endif // Initialize SPI _SPI.begin(); ce(LOW); csn(HIGH); + #if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) + // assure SPI can be used from interrupt context + _SPI.usingInterrupt(digitalPinToInterrupt(MY_RF24_IRQ_PIN)); + // attach interrupt + attachInterrupt(digitalPinToInterrupt(MY_RF24_IRQ_PIN), irqHandler, FALLING); + #endif // CRC and power up writeByteRegister(NRF_CONFIG, MY_RF24_CONFIGURATION | _BV(PWR_UP) ) ; // settle >2ms diff --git a/libraries/MySensors/drivers/RF24/RF24.h b/libraries/MySensors/drivers/RF24/RF24.h index dc4ac68..c2adb8a 100644 --- a/libraries/MySensors/drivers/RF24/RF24.h +++ b/libraries/MySensors/drivers/RF24/RF24.h @@ -38,7 +38,11 @@ #define MY_RF24_SPI_DATA_MODE SPI_MODE0 // settings -#define MY_RF24_CONFIGURATION (uint8_t) (RF24_CRC_16 << 1) +#if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) + #define MY_RF24_CONFIGURATION (uint8_t)((RF24_CRC_16 << 1) | (1 << MASK_TX_DS) | (1 << MASK_MAX_RT)) +#else + #define MY_RF24_CONFIGURATION (uint8_t)((RF24_CRC_16 << 1) | (1 << MASK_RX_DR) | (1 << MASK_TX_DS) | (1 << MASK_MAX_RT)) +#endif #define MY_RF24_FEATURE (uint8_t)( _BV(EN_DPL) | _BV(EN_ACK_PAY) ) #define MY_RF24_RF_SETUP (uint8_t)( ((MY_RF24_DATARATE & 0b10 ) << 4) | ((MY_RF24_DATARATE & 0b01 ) << 3) | (MY_RF24_PA_LEVEL << 1) ) + 1 // +1 for Si24R1 diff --git a/libraries/MySensors/examples/QueueTestGateway/QueueTestGateway.ino b/libraries/MySensors/examples/QueueTestGateway/QueueTestGateway.ino new file mode 100644 index 0000000..c8ed43f --- /dev/null +++ b/libraries/MySensors/examples/QueueTestGateway/QueueTestGateway.ino @@ -0,0 +1,94 @@ + /** + * 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 + * 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. + * + ******************************* + * + * DESCRIPTION + * The ArduinoGateway prints data received from sensors on the serial link. + * The gateway accepts input on seral which will be sent out on radio network. + * + * The GW code is designed for Arduino Nano 328p / 16MHz + * + * Wire connections (OPTIONAL): + * - Inclusion button should be connected between digital pin 3 and GND + * - RX/TX/ERR leds need to be connected between +5V (anode) and digital pin 6/5/4 with resistor 270-330R in a series + * + * LEDs (OPTIONAL): + * - To use the feature, uncomment MY_LEDS_BLINKING_FEATURE in MyConfig.h + * - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved + * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly + * - ERR (red) - fast blink on error during transmission error or recieve crc error + * + */ + +#define MY_RADIO_NRF24 +#define MY_RF24_CHANNEL (100) +#define MY_RF24_DATARATE (RF24_1MBPS) +#define MY_GATEWAY_SERIAL +#define MY_LEDS_BLINKING_FEATURE +#define MY_DEFAULT_LED_BLINK_PERIOD 50 +#define MY_WITH_LEDS_BLINKING_INVERSE +#define MY_RF24_IRQ_PIN (2) + +#define MY_DEFAULT_ERR_LED_PIN A0 // Error led pin +#define MY_DEFAULT_RX_LED_PIN A1 // Receive led pin +#define MY_DEFAULT_TX_LED_PIN A2 // the PCB, on board LED + +//#define MY_DEBUG +//#define MY_DEBUG_VERBOSE_RF24 + +#include +#include + +void setup() { +} + +void presentation() { +} + + +void receive(const MyMessage &message) +{ + static uint16_t prevCount = 0; + uint16_t count = message.getUInt(); + if ((count-1) != prevCount) + { + Serial.print(F("Mismatch: prev=")); + Serial.print(prevCount); + Serial.print(F(" new=")); + Serial.println(count); + } + prevCount = count; +} + +const uint8_t maxCount = 100; + +void loop() { + static uint8_t count = 0; + ++count; + if (count++ > maxCount) + { + count = 0; + delay(1000); + } +} + + + + + diff --git a/libraries/MySensors/examples/QueueTestNode/QueueTestNode.ino b/libraries/MySensors/examples/QueueTestNode/QueueTestNode.ino new file mode 100644 index 0000000..47dfe22 --- /dev/null +++ b/libraries/MySensors/examples/QueueTestNode/QueueTestNode.ino @@ -0,0 +1,52 @@ +#include +#include + +#define MY_RADIO_NRF24 +#define MY_RF24_CHANNEL (100) +#define MY_NODE_ID (200) +#define MY_RF24_CE_PIN (9) +#define MY_RF24_CS_PIN (10) +//#define MY_RF24_IRQ_PIN (2) +#define MY_RF24_DATARATE (RF24_1MBPS) +#define MY_DEBUG +//#define MY_DEBUG_VERBOSE_RF24 + +#include +#include + +#undef debug +#ifndef NODEBUG +#define debug(x) Serial.print(x) +#define debugln(x) Serial.println(x) +#else +#define debug(x) +#define debugln(x) +#endif + +void presentation() +{ + sendSketchInfo("Test", "1.0"); + debug("ID: "); debugln(getNodeId()); + + present(0, S_CUSTOM); +} + +void receive(const MyMessage &message) +{ + // debug("Message "); debugln(message.type); +} + +void setup() +{ + debugln(F("---- Starting sensor ----")); +} + +void loop() +{ + static uint16_t count = 0; + send( MyMessage(0, V_VAR1).set(count) ); + ++count; + + delay(100); +} + diff --git a/libraries/MySensors/keywords.txt b/libraries/MySensors/keywords.txt index 7b18486..f679ead 100644 --- a/libraries/MySensors/keywords.txt +++ b/libraries/MySensors/keywords.txt @@ -66,6 +66,7 @@ MY_RF24_ENABLE_ENCRYPTION LITERAL1 MY_RF24_SPI_MAX_SPEED LITERAL1 MY_RF24_CE_PIN LITERAL1 MY_RF24_CS_PIN LITERAL1 +MY_RF24_IRQ_PIN LITERAL1 MY_RF24_PA_LEVEL LITERAL1 MY_RF24_CHANNEL LITERAL1 MY_RF24_DATARATE LITERAL1 From a200c36417a8d90315fd90ef983e907eb592417b Mon Sep 17 00:00:00 2001 From: Embedded Innovation Date: Thu, 28 Apr 2016 21:13:03 +0200 Subject: [PATCH 2/5] Added circular buffer --- .../drivers/CircularBuffer/CircularBuffer.h | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 libraries/MySensors/drivers/CircularBuffer/CircularBuffer.h diff --git a/libraries/MySensors/drivers/CircularBuffer/CircularBuffer.h b/libraries/MySensors/drivers/CircularBuffer/CircularBuffer.h new file mode 100644 index 0000000..46ba9a9 --- /dev/null +++ b/libraries/MySensors/drivers/CircularBuffer/CircularBuffer.h @@ -0,0 +1,163 @@ +/* + CircularBuffer - An Arduino circular buffering library for arbitrary types. + + Created by Ivo Pullens, Emmission, 2014-2016 -- www.emmission.nl + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef CircularBuffer_h +#define CircularBuffer_h +#include + +template class CircularBuffer +{ + public: + /** Constructor + * @param buffer Preallocated buffer of at least size records. + * @param size Number of records available in the buffer. + */ + CircularBuffer(T* buffer, const uint8_t size ) + : m_size(size), m_buff(buffer) + { + clear(); + } + + /** Clear all entries in the circular buffer. */ + void clear(void) + { + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + m_front = 0; + m_fill = 0; + } + } + + /** Test if the circular buffer is empty */ + inline bool empty(void) const + { + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + return !m_fill; + } + } + + /** Return the number of records stored in the buffer */ + inline uint8_t available(void) const + { + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + return m_fill; + } + } + + /** Test if the circular buffer is full */ + inline bool full(void) const + { + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + return m_fill == m_size; + } + } + + /** Aquire record on front of the buffer, for writing. + * After filling the record, it has to be pushed to actually + * add it to the buffer. + * @return Pointer to record, or NULL when buffer is full. + */ + T* getFront(void) const + { + T* f = NULL; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + if (!full()) + f = get(m_front); + } + return f; + } + + /** Push record to front of the buffer + * @param record Record to push. If record was aquired previously (using getFront) its + * data will not be copied as it is already present in the buffer. + * @return True, when record was pushed successfully. + */ + bool pushFront(T* record) + { + bool ok = false; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + if (!full()) + { + T* f = get(m_front); + if (f != record) + *f = *record; + m_front = (m_front+1) % m_size; + m_fill++; + ok = true; + } + } + return ok; + } + + /** Aquire record on back of the buffer, for reading. + * After reading the record, it has to be pop'ed to actually + * remove it from the buffer. + * @return Pointer to record, or NULL when buffer is empty. + */ + T* getBack(void) const + { + T* b = NULL; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + if (!empty()) + b = get(back()); + } + return b; + } + + /** Remove record from back of the buffer. + * @return True, when record was pop'ed successfully. + */ + bool popBack(void) + { + bool ok = false; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + if (!empty()) + { + m_fill--; + ok = true; + } + } + return ok; + } + + protected: + inline T * get(const uint8_t idx) const + { + return &(m_buff[idx]); + } + inline uint8_t back(void) const + { + return (m_front - m_fill + m_size) % m_size; + } + + const uint8_t m_size; // Total number of records that can be stored in the buffer. + T* const m_buff; // Ptr to buffer holding all records. + volatile uint8_t m_front; // Index of front element (not pushed yet). + volatile uint8_t m_fill; // Amount of records currently pushed. +}; + +#endif // CircularBuffer_h From 1caae29b3c19dae3234ad8b8522de688f639086b Mon Sep 17 00:00:00 2001 From: Embedded Innovation Date: Thu, 5 May 2016 20:37:12 +0200 Subject: [PATCH 3/5] Revert "Added circular buffer" This reverts commit a200c36417a8d90315fd90ef983e907eb592417b. --- .../drivers/CircularBuffer/CircularBuffer.h | 163 ------------------ 1 file changed, 163 deletions(-) delete mode 100644 libraries/MySensors/drivers/CircularBuffer/CircularBuffer.h diff --git a/libraries/MySensors/drivers/CircularBuffer/CircularBuffer.h b/libraries/MySensors/drivers/CircularBuffer/CircularBuffer.h deleted file mode 100644 index 46ba9a9..0000000 --- a/libraries/MySensors/drivers/CircularBuffer/CircularBuffer.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - CircularBuffer - An Arduino circular buffering library for arbitrary types. - - Created by Ivo Pullens, Emmission, 2014-2016 -- www.emmission.nl - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef CircularBuffer_h -#define CircularBuffer_h -#include - -template class CircularBuffer -{ - public: - /** Constructor - * @param buffer Preallocated buffer of at least size records. - * @param size Number of records available in the buffer. - */ - CircularBuffer(T* buffer, const uint8_t size ) - : m_size(size), m_buff(buffer) - { - clear(); - } - - /** Clear all entries in the circular buffer. */ - void clear(void) - { - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - m_front = 0; - m_fill = 0; - } - } - - /** Test if the circular buffer is empty */ - inline bool empty(void) const - { - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - return !m_fill; - } - } - - /** Return the number of records stored in the buffer */ - inline uint8_t available(void) const - { - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - return m_fill; - } - } - - /** Test if the circular buffer is full */ - inline bool full(void) const - { - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - return m_fill == m_size; - } - } - - /** Aquire record on front of the buffer, for writing. - * After filling the record, it has to be pushed to actually - * add it to the buffer. - * @return Pointer to record, or NULL when buffer is full. - */ - T* getFront(void) const - { - T* f = NULL; - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - if (!full()) - f = get(m_front); - } - return f; - } - - /** Push record to front of the buffer - * @param record Record to push. If record was aquired previously (using getFront) its - * data will not be copied as it is already present in the buffer. - * @return True, when record was pushed successfully. - */ - bool pushFront(T* record) - { - bool ok = false; - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - if (!full()) - { - T* f = get(m_front); - if (f != record) - *f = *record; - m_front = (m_front+1) % m_size; - m_fill++; - ok = true; - } - } - return ok; - } - - /** Aquire record on back of the buffer, for reading. - * After reading the record, it has to be pop'ed to actually - * remove it from the buffer. - * @return Pointer to record, or NULL when buffer is empty. - */ - T* getBack(void) const - { - T* b = NULL; - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - if (!empty()) - b = get(back()); - } - return b; - } - - /** Remove record from back of the buffer. - * @return True, when record was pop'ed successfully. - */ - bool popBack(void) - { - bool ok = false; - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - if (!empty()) - { - m_fill--; - ok = true; - } - } - return ok; - } - - protected: - inline T * get(const uint8_t idx) const - { - return &(m_buff[idx]); - } - inline uint8_t back(void) const - { - return (m_front - m_fill + m_size) % m_size; - } - - const uint8_t m_size; // Total number of records that can be stored in the buffer. - T* const m_buff; // Ptr to buffer holding all records. - volatile uint8_t m_front; // Index of front element (not pushed yet). - volatile uint8_t m_fill; // Amount of records currently pushed. -}; - -#endif // CircularBuffer_h From a1d837d4f7b0bbf4c3c9cf3c29b32cb723ea7387 Mon Sep 17 00:00:00 2001 From: Embedded Innovation Date: Thu, 5 May 2016 20:37:39 +0200 Subject: [PATCH 4/5] Revert "Added interrupt handling and reception queueing for nRF24" This reverts commit bfa493ce3eadf1cc436e24cfe7a66b44bdbd2287. --- libraries/MySensors/MyConfig.h | 18 ---- libraries/MySensors/core/MyTransportNRF24.cpp | 77 ++------------- libraries/MySensors/drivers/RF24/RF24.cpp | 40 +------- libraries/MySensors/drivers/RF24/RF24.h | 6 +- .../QueueTestGateway/QueueTestGateway.ino | 94 ------------------- .../examples/QueueTestNode/QueueTestNode.ino | 52 ---------- libraries/MySensors/keywords.txt | 1 - 7 files changed, 12 insertions(+), 276 deletions(-) delete mode 100644 libraries/MySensors/examples/QueueTestGateway/QueueTestGateway.ino delete mode 100644 libraries/MySensors/examples/QueueTestNode/QueueTestNode.ino diff --git a/libraries/MySensors/MyConfig.h b/libraries/MySensors/MyConfig.h index 234e1e3..2bc11e1 100644 --- a/libraries/MySensors/MyConfig.h +++ b/libraries/MySensors/MyConfig.h @@ -368,24 +368,6 @@ #endif #endif -/** - * @def MY_RF24_IRQ_PIN - * @brief Disable RF24 interrupt pin usage by default. Override in sketch if needed. - */ -#define MY_RF24_IRQ_PIN_UNUSED 0 -#ifndef MY_RF24_IRQ_PIN - #define MY_RF24_IRQ_PIN MY_RF24_IRQ_PIN_UNUSED -#endif - -/** - * @def MY_RF24_MESSAGE_BUFFER_SIZE - * @brief Declare the amount of messages that can be buffered. Override in sketch if needed. - */ -#ifndef MY_RF24_MESSAGE_BUFFER_SIZE - #define MY_RF24_MESSAGE_BUFFER_SIZE (20) -#endif - - /** * @def MY_RF24_PA_LEVEL * @brief Default RF24 PA level. Override in sketch if needed. diff --git a/libraries/MySensors/core/MyTransportNRF24.cpp b/libraries/MySensors/core/MyTransportNRF24.cpp index 6589a09..5aa1596 100644 --- a/libraries/MySensors/core/MyTransportNRF24.cpp +++ b/libraries/MySensors/core/MyTransportNRF24.cpp @@ -20,47 +20,17 @@ #include "MyConfig.h" #include "MyTransport.h" #include "drivers/RF24/RF24.h" -#include "drivers/CircularBuffer/CircularBuffer.h" #if defined(MY_RF24_ENABLE_ENCRYPTION) #include "drivers/AES/AES.h" #endif -#if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) -typedef struct _queuedMessage -{ - uint8_t m_to; /** Destination address of this message. */ - uint8_t m_len; /** Length of the data. */ - uint8_t m_data[MAX_MESSAGE_LENGTH]; /** The raw data. */ -} queuedMessage; - -/** Buffer to store queued messages in. */ -static queuedMessage queueStorage[MY_RF24_MESSAGE_BUFFER_SIZE]; -/** Circular buffer, which uses the queueStorage and administers stored messages. */ -static CircularBuffer receiveQueue(queueStorage, MY_RF24_MESSAGE_BUFFER_SIZE); - -static volatile uint8_t lostMessageCount = 0; - -static void rxCallback(const uint8_t to) -{ - if (!receiveQueue.full()) - { - queuedMessage* msg = receiveQueue.getFront(); - msg->m_len = readMessage(msg->m_data); - (void)receiveQueue.pushFront(msg); - } else { - // TODO: Message is not really lost, as it is still in the nRF FIFO. But once the FIFO is also full messages will get lost. - ++lostMessageCount; - } -} -#endif - #if defined(MY_RF24_ENABLE_ENCRYPTION) - AES _aes; - uint8_t _dataenc[32] = {0}; - uint8_t _psk[16]; + AES _aes; + uint8_t _dataenc[32] = {0}; + uint8_t _psk[16]; #endif - + bool transportInit() { #if defined(MY_RF24_ENABLE_ENCRYPTION) @@ -70,10 +40,7 @@ bool transportInit() { // Make sure it is purged from memory when set memset(_psk, 0, 16); #endif - - #if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) - registerReceiveCallback( rxCallback ); - #endif + return initializeRF24(); } @@ -104,39 +71,13 @@ bool transportSend(uint8_t recipient, const void* data, uint8_t len) { } bool transportAvailable(uint8_t *to) { - bool avail = false; - #if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) - queuedMessage* msg = receiveQueue.getBack(); - if (msg) - { - avail = true; - *to = msg->m_to; - } else { - // TODO: The nRF FIFO could still hold a message - } - #else - avail = IsDataAvailable(to); - #endif - return avail; + bool avail = IsDataAvailable(to); + return avail; } uint8_t transportReceive(void* data) { - uint8_t len; - #if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) -// debug(PSTR("lost:%d\n"), lostMessageCount); - queuedMessage* msg = receiveQueue.getBack(); - if (msg) - { - len = msg->m_len; - (void)memcpy(data, msg->m_data, len); - (void)receiveQueue.popBack(); - } else { - // TODO: The nRF FIFO could still hold a message - } - #else - len = readMessage(data); - #endif - #if defined(MY_RF24_ENABLE_ENCRYPTION) + uint8_t len = readMessage(data); + #if defined(MY_RF24_ENABLE_ENCRYPTION) // has to be adjusted, WIP! _aes.set_IV(0); // decrypt data diff --git a/libraries/MySensors/drivers/RF24/RF24.cpp b/libraries/MySensors/drivers/RF24/RF24.cpp index c9fa914..1466005 100644 --- a/libraries/MySensors/drivers/RF24/RF24.cpp +++ b/libraries/MySensors/drivers/RF24/RF24.cpp @@ -22,13 +22,8 @@ #include "RF24.h" -static uint8_t MY_RF24_BASE_ADDR[MY_RF24_ADDR_WIDTH] = { MY_RF24_BASE_RADIO_ID }; -static uint8_t MY_RF24_NODE_ADDRESS = AUTO; - -#if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) -typedef void (*receiveCallbackType)(const uint8_t); -static receiveCallbackType receiveCallback = NULL; -#endif +uint8_t MY_RF24_BASE_ADDR[MY_RF24_ADDR_WIDTH] = { MY_RF24_BASE_RADIO_ID }; +uint8_t MY_RF24_NODE_ADDRESS = AUTO; void csn(bool level) { digitalWrite(MY_RF24_CS_PIN, level); @@ -209,45 +204,14 @@ uint8_t getNodeID(void) { return MY_RF24_NODE_ADDRESS; } -#if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) -static void irqHandler( void ) -{ - if (receiveCallback) - { - uint8_t to; - (void)IsDataAvailable(&to); - receiveCallback(to); - } else { - // clear RX interrupt - writeByteRegister(RF24_STATUS, _BV(RX_DR) ); - } -} - -void registerReceiveCallback( receiveCallbackType cb ) -{ - noInterrupts(); - receiveCallback = cb; - interrupts(); -} -#endif - bool initializeRF24(void) { // Initialize pins pinMode(MY_RF24_CE_PIN,OUTPUT); pinMode(MY_RF24_CS_PIN,OUTPUT); - #if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) - pinMode(MY_RF24_IRQ_PIN,INPUT); - #endif // Initialize SPI _SPI.begin(); ce(LOW); csn(HIGH); - #if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) - // assure SPI can be used from interrupt context - _SPI.usingInterrupt(digitalPinToInterrupt(MY_RF24_IRQ_PIN)); - // attach interrupt - attachInterrupt(digitalPinToInterrupt(MY_RF24_IRQ_PIN), irqHandler, FALLING); - #endif // CRC and power up writeByteRegister(NRF_CONFIG, MY_RF24_CONFIGURATION | _BV(PWR_UP) ) ; // settle >2ms diff --git a/libraries/MySensors/drivers/RF24/RF24.h b/libraries/MySensors/drivers/RF24/RF24.h index c2adb8a..dc4ac68 100644 --- a/libraries/MySensors/drivers/RF24/RF24.h +++ b/libraries/MySensors/drivers/RF24/RF24.h @@ -38,11 +38,7 @@ #define MY_RF24_SPI_DATA_MODE SPI_MODE0 // settings -#if (MY_RF24_IRQ_PIN != MY_RF24_IRQ_PIN_UNUSED) - #define MY_RF24_CONFIGURATION (uint8_t)((RF24_CRC_16 << 1) | (1 << MASK_TX_DS) | (1 << MASK_MAX_RT)) -#else - #define MY_RF24_CONFIGURATION (uint8_t)((RF24_CRC_16 << 1) | (1 << MASK_RX_DR) | (1 << MASK_TX_DS) | (1 << MASK_MAX_RT)) -#endif +#define MY_RF24_CONFIGURATION (uint8_t) (RF24_CRC_16 << 1) #define MY_RF24_FEATURE (uint8_t)( _BV(EN_DPL) | _BV(EN_ACK_PAY) ) #define MY_RF24_RF_SETUP (uint8_t)( ((MY_RF24_DATARATE & 0b10 ) << 4) | ((MY_RF24_DATARATE & 0b01 ) << 3) | (MY_RF24_PA_LEVEL << 1) ) + 1 // +1 for Si24R1 diff --git a/libraries/MySensors/examples/QueueTestGateway/QueueTestGateway.ino b/libraries/MySensors/examples/QueueTestGateway/QueueTestGateway.ino deleted file mode 100644 index c8ed43f..0000000 --- a/libraries/MySensors/examples/QueueTestGateway/QueueTestGateway.ino +++ /dev/null @@ -1,94 +0,0 @@ - /** - * 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 - * 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. - * - ******************************* - * - * DESCRIPTION - * The ArduinoGateway prints data received from sensors on the serial link. - * The gateway accepts input on seral which will be sent out on radio network. - * - * The GW code is designed for Arduino Nano 328p / 16MHz - * - * Wire connections (OPTIONAL): - * - Inclusion button should be connected between digital pin 3 and GND - * - RX/TX/ERR leds need to be connected between +5V (anode) and digital pin 6/5/4 with resistor 270-330R in a series - * - * LEDs (OPTIONAL): - * - To use the feature, uncomment MY_LEDS_BLINKING_FEATURE in MyConfig.h - * - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved - * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly - * - ERR (red) - fast blink on error during transmission error or recieve crc error - * - */ - -#define MY_RADIO_NRF24 -#define MY_RF24_CHANNEL (100) -#define MY_RF24_DATARATE (RF24_1MBPS) -#define MY_GATEWAY_SERIAL -#define MY_LEDS_BLINKING_FEATURE -#define MY_DEFAULT_LED_BLINK_PERIOD 50 -#define MY_WITH_LEDS_BLINKING_INVERSE -#define MY_RF24_IRQ_PIN (2) - -#define MY_DEFAULT_ERR_LED_PIN A0 // Error led pin -#define MY_DEFAULT_RX_LED_PIN A1 // Receive led pin -#define MY_DEFAULT_TX_LED_PIN A2 // the PCB, on board LED - -//#define MY_DEBUG -//#define MY_DEBUG_VERBOSE_RF24 - -#include -#include - -void setup() { -} - -void presentation() { -} - - -void receive(const MyMessage &message) -{ - static uint16_t prevCount = 0; - uint16_t count = message.getUInt(); - if ((count-1) != prevCount) - { - Serial.print(F("Mismatch: prev=")); - Serial.print(prevCount); - Serial.print(F(" new=")); - Serial.println(count); - } - prevCount = count; -} - -const uint8_t maxCount = 100; - -void loop() { - static uint8_t count = 0; - ++count; - if (count++ > maxCount) - { - count = 0; - delay(1000); - } -} - - - - - diff --git a/libraries/MySensors/examples/QueueTestNode/QueueTestNode.ino b/libraries/MySensors/examples/QueueTestNode/QueueTestNode.ino deleted file mode 100644 index 47dfe22..0000000 --- a/libraries/MySensors/examples/QueueTestNode/QueueTestNode.ino +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include - -#define MY_RADIO_NRF24 -#define MY_RF24_CHANNEL (100) -#define MY_NODE_ID (200) -#define MY_RF24_CE_PIN (9) -#define MY_RF24_CS_PIN (10) -//#define MY_RF24_IRQ_PIN (2) -#define MY_RF24_DATARATE (RF24_1MBPS) -#define MY_DEBUG -//#define MY_DEBUG_VERBOSE_RF24 - -#include -#include - -#undef debug -#ifndef NODEBUG -#define debug(x) Serial.print(x) -#define debugln(x) Serial.println(x) -#else -#define debug(x) -#define debugln(x) -#endif - -void presentation() -{ - sendSketchInfo("Test", "1.0"); - debug("ID: "); debugln(getNodeId()); - - present(0, S_CUSTOM); -} - -void receive(const MyMessage &message) -{ - // debug("Message "); debugln(message.type); -} - -void setup() -{ - debugln(F("---- Starting sensor ----")); -} - -void loop() -{ - static uint16_t count = 0; - send( MyMessage(0, V_VAR1).set(count) ); - ++count; - - delay(100); -} - diff --git a/libraries/MySensors/keywords.txt b/libraries/MySensors/keywords.txt index f679ead..7b18486 100644 --- a/libraries/MySensors/keywords.txt +++ b/libraries/MySensors/keywords.txt @@ -66,7 +66,6 @@ MY_RF24_ENABLE_ENCRYPTION LITERAL1 MY_RF24_SPI_MAX_SPEED LITERAL1 MY_RF24_CE_PIN LITERAL1 MY_RF24_CS_PIN LITERAL1 -MY_RF24_IRQ_PIN LITERAL1 MY_RF24_PA_LEVEL LITERAL1 MY_RF24_CHANNEL LITERAL1 MY_RF24_DATARATE LITERAL1 From 00657dd64e3a3a036cf66e63d07c2aa3374821dc Mon Sep 17 00:00:00 2001 From: Embedded Innovation Date: Thu, 5 May 2016 20:39:46 +0200 Subject: [PATCH 5/5] Fix CRC setting for nRF24 --- libraries/MySensors/drivers/RF24/RF24.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/MySensors/drivers/RF24/RF24.h b/libraries/MySensors/drivers/RF24/RF24.h index dc4ac68..2f22354 100644 --- a/libraries/MySensors/drivers/RF24/RF24.h +++ b/libraries/MySensors/drivers/RF24/RF24.h @@ -38,7 +38,7 @@ #define MY_RF24_SPI_DATA_MODE SPI_MODE0 // settings -#define MY_RF24_CONFIGURATION (uint8_t) (RF24_CRC_16 << 1) +#define MY_RF24_CONFIGURATION (uint8_t) (RF24_CRC_16 << 2) #define MY_RF24_FEATURE (uint8_t)( _BV(EN_DPL) | _BV(EN_ACK_PAY) ) #define MY_RF24_RF_SETUP (uint8_t)( ((MY_RF24_DATARATE & 0b10 ) << 4) | ((MY_RF24_DATARATE & 0b01 ) << 3) | (MY_RF24_PA_LEVEL << 1) ) + 1 // +1 for Si24R1