diff --git a/MyConfig.h b/MyConfig.h index cf737a1..22039d1 100644 --- a/MyConfig.h +++ b/MyConfig.h @@ -67,6 +67,15 @@ #ifndef MY_BAUD_RATE #define MY_BAUD_RATE 115200 #endif + /** + * @def MY_SERIAL_OUTPUT_SIZE + * @brief Max. characters for serial output. + */ +#ifndef MY_SERIAL_OUTPUT_SIZE +#define MY_SERIAL_OUTPUT_SIZE (120u) +#endif + + // Disables over-the-air reset of node //#define MY_DISABLE_REMOTE_RESET diff --git a/core/MyGatewayTransportEthernet.cpp b/core/MyGatewayTransportEthernet.cpp index 498850f..a6abe91 100644 --- a/core/MyGatewayTransportEthernet.cpp +++ b/core/MyGatewayTransportEthernet.cpp @@ -116,9 +116,8 @@ bool gatewayTransportInit() { (void)WiFi.begin(MY_ESP8266_SSID, MY_ESP8266_PASSWORD); while (WiFi.status() != WL_CONNECTED) { - delay(500); + wait(500); MY_SERIALDEVICE.print(F(".")); - yield(); } MY_SERIALDEVICE.print(F("IP: ")); MY_SERIALDEVICE.println(WiFi.localIP()); diff --git a/core/MyGatewayTransportMQTTClient.cpp b/core/MyGatewayTransportMQTTClient.cpp index ea98f07..339d1aa 100644 --- a/core/MyGatewayTransportMQTTClient.cpp +++ b/core/MyGatewayTransportMQTTClient.cpp @@ -88,7 +88,7 @@ bool reconnectMQTT() { bool gatewayTransportConnect() { #if defined(MY_GATEWAY_ESP8266) while (WiFi.status() != WL_CONNECTED) { - delay(500); // delay calls yield + wait(500); MY_SERIALDEVICE.print("."); } MY_SERIALDEVICE.print("IP: "); diff --git a/core/MyHwATMega328.cpp b/core/MyHwATMega328.cpp index 5705590..6619747 100644 --- a/core/MyHwATMega328.cpp +++ b/core/MyHwATMega328.cpp @@ -219,7 +219,7 @@ uint16_t hwFreeMem() { #ifdef MY_DEBUG void hwDebugPrint(const char *fmt, ... ) { - char fmtBuffer[MY_DEBUG_BUFFER_SIZE]; + char fmtBuffer[MY_SERIAL_OUTPUT_SIZE]; #ifdef MY_GATEWAY_FEATURE // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) snprintf_P(fmtBuffer, sizeof(fmtBuffer), PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE); @@ -233,9 +233,9 @@ void hwDebugPrint(const char *fmt, ... ) { va_start (args, fmt ); #ifdef MY_GATEWAY_FEATURE // Truncate message if this is gateway node - vsnprintf_P(fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, fmt, args); - fmtBuffer[MY_GATEWAY_MAX_SEND_LENGTH-1] = '\n'; - fmtBuffer[MY_GATEWAY_MAX_SEND_LENGTH] = '\0'; + vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args); + fmtBuffer[sizeof(fmtBuffer) - 2] = '\n'; + fmtBuffer[sizeof(fmtBuffer) - 1] = '\0'; #else vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args); #endif diff --git a/core/MyHwATMega328.h b/core/MyHwATMega328.h index b8e64d1..bf38a24 100644 --- a/core/MyHwATMega328.h +++ b/core/MyHwATMega328.h @@ -35,7 +35,6 @@ #endif #define MY_SERIALDEVICE Serial -#define MY_DEBUG_BUFFER_SIZE 300 #if defined __AVR_ATmega328P__ #ifndef sleep_bod_disable @@ -73,21 +72,20 @@ do { \ #define hwReboot() wdt_enable(WDTO_15MS); while (1) #define hwMillis() millis() #define hwRandomNumberInit() randomSeed(analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN)) -#define hwReadConfig(__pos) (eeprom_read_byte((uint8_t*)(__pos))) +#define hwReadConfig(__pos) eeprom_read_byte((uint8_t*)(__pos)) #ifndef eeprom_update_byte - #define hwWriteConfig(loc, val) if((uint8_t)(val) != eeprom_read_byte((uint8_t*)(loc))) { eeprom_write_byte((uint8_t*)(loc), (val)); } + #define hwWriteConfig(__loc, __val) if((uint8_t)(__val) != eeprom_read_byte((uint8_t*)(__loc))) { eeprom_write_byte((uint8_t*)(__loc), (__val)); } #else - #define hwWriteConfig(__pos, __value) (eeprom_update_byte((uint8_t*)(__pos), (__value))) + #define hwWriteConfig(__pos, __val) eeprom_update_byte((uint8_t*)(__pos), (__val)) #endif -#define hwReadConfigBlock(__buf, __pos, __length) (eeprom_read_block((__buf), (void*)(__pos), (__length))) -#define hwWriteConfigBlock(__buf, __pos, __length) (eeprom_write_block((void*)(__buf), (void*)(__pos), (__length))) +#define hwReadConfigBlock(__buf, __pos, __length) eeprom_read_block((void*)(__buf), (void*)(__pos), (__length)) +#define hwWriteConfigBlock(__buf, __pos, __length) eeprom_write_block((void*)(__buf), (void*)(__pos), (__length)) -enum period_t -{ +enum period_t { SLEEP_15MS, SLEEP_30MS, SLEEP_60MS, diff --git a/core/MyHwESP8266.cpp b/core/MyHwESP8266.cpp index 5c48a0b..7901e4d 100644 --- a/core/MyHwESP8266.cpp +++ b/core/MyHwESP8266.cpp @@ -134,7 +134,7 @@ uint16_t hwFreeMem() { #ifdef MY_DEBUG void hwDebugPrint(const char *fmt, ... ) { - char fmtBuffer[MY_DEBUG_BUFFER_SIZE]; + char fmtBuffer[MY_SERIAL_OUTPUT_SIZE]; #ifdef MY_GATEWAY_FEATURE // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) snprintf_P(fmtBuffer, sizeof(fmtBuffer), PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE); @@ -144,9 +144,9 @@ void hwDebugPrint(const char *fmt, ... ) { va_start (args, fmt ); #ifdef MY_GATEWAY_FEATURE // Truncate message if this is gateway node - vsnprintf_P(fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, fmt, args); - fmtBuffer[MY_GATEWAY_MAX_SEND_LENGTH-1] = '\n'; - fmtBuffer[MY_GATEWAY_MAX_SEND_LENGTH] = '\0'; + vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args); + fmtBuffer[sizeof(fmtBuffer) - 2] = '\n'; + fmtBuffer[sizeof(fmtBuffer) - 1] = '\0'; #else vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args); #endif diff --git a/core/MyHwESP8266.h b/core/MyHwESP8266.h index 0f53ced..3b92169 100644 --- a/core/MyHwESP8266.h +++ b/core/MyHwESP8266.h @@ -26,7 +26,6 @@ #endif #define MY_SERIALDEVICE Serial -#define MY_DEBUG_BUFFER_SIZE 300 #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) diff --git a/core/MyHwSAMD.cpp b/core/MyHwSAMD.cpp index 3d79a48..1cf3662 100644 --- a/core/MyHwSAMD.cpp +++ b/core/MyHwSAMD.cpp @@ -113,7 +113,8 @@ void hwWatchdogReset() { } void hwReboot() { - // TODO: Not supported! + NVIC_SystemReset(); + while (true); } int8_t hwSleep(unsigned long ms) { @@ -142,13 +143,44 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG) uint16_t hwCPUVoltage() { - // TODO: Not supported! - return 0; + + // disable ADC + while (ADC->STATUS.bit.SYNCBUSY); + ADC->CTRLA.bit.ENABLE = 0x00; + + // internal 1V reference (default) + analogReference(AR_INTERNAL1V0); + // 12 bit resolution (default) + analogWriteResolution(12); + // MUXp 0x1B = SCALEDIOVCC/4 => connected to Vcc + ADC->INPUTCTRL.bit.MUXPOS = 0x1B ; + + // enable ADC + while (ADC->STATUS.bit.SYNCBUSY); + ADC->CTRLA.bit.ENABLE = 0x01; + // start conversion + while (ADC->STATUS.bit.SYNCBUSY); + ADC->SWTRIG.bit.START = 1; + // clear the Data Ready flag + ADC->INTFLAG.bit.RESRDY = 1; + // start conversion again, since The first conversion after the reference is changed must not be used. + while (ADC->STATUS.bit.SYNCBUSY); + ADC->SWTRIG.bit.START = 1; + + // waiting for conversion to complete + while (!ADC->INTFLAG.bit.RESRDY); + const uint32_t valueRead = ADC->RESULT.reg; + + // disable ADC + while (ADC->STATUS.bit.SYNCBUSY); + ADC->CTRLA.bit.ENABLE = 0x00; + + return valueRead * 4; } uint16_t hwCPUFrequency() { - // TODO: Not supported! - return 0; + // TODO: currently reporting compile time frequency (in 1/10MHz) + return F_CPU / 100000UL; } uint16_t hwFreeMem() { @@ -160,7 +192,7 @@ uint16_t hwFreeMem() { #ifdef MY_DEBUG void hwDebugPrint(const char *fmt, ... ) { if (MY_SERIALDEVICE) { - char fmtBuffer[MY_DEBUG_BUFFER_SIZE]; + char fmtBuffer[MY_SERIAL_OUTPUT_SIZE]; #ifdef MY_GATEWAY_FEATURE // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) snprintf(fmtBuffer, sizeof(fmtBuffer), PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE); @@ -170,9 +202,9 @@ void hwDebugPrint(const char *fmt, ... ) { va_start (args, fmt ); #ifdef MY_GATEWAY_FEATURE // Truncate message if this is gateway node - vsnprintf(fmtBuffer, 60, fmt, args); - fmtBuffer[59] = '\n'; - fmtBuffer[60] = '\0'; + vsnprintf(fmtBuffer, sizeof(fmtBuffer), fmt, args); + fmtBuffer[sizeof(fmtBuffer) - 2] = '\n'; + fmtBuffer[sizeof(fmtBuffer) - 1] = '\0'; #else vsnprintf(fmtBuffer, sizeof(fmtBuffer), fmt, args); #endif diff --git a/core/MyHwSAMD.h b/core/MyHwSAMD.h index 00ac1d6..7d23e07 100644 --- a/core/MyHwSAMD.h +++ b/core/MyHwSAMD.h @@ -52,15 +52,6 @@ void hwWriteConfig(int adr, uint8_t value); uint8_t hwReadConfig(int adr); #define MY_SERIALDEVICE SerialUSB -#define MY_DEBUG_BUFFER_SIZE 300 - - -/* -#define hwReadConfigBlock(__buf, __adr, __length) ( __length = __length) -#define hwWriteConfigBlock(__buf, __adr, __length) ( __length = __length) -#define hwWriteConfig(__adr, __value) ( __value = __value) -#define hwReadConfig(__adr) (0) -*/ /** * Disable all interrupts. diff --git a/core/MyLeds.cpp b/core/MyLeds.cpp index e8c42a1..0da6628 100644 --- a/core/MyLeds.cpp +++ b/core/MyLeds.cpp @@ -26,8 +26,7 @@ static uint8_t countRx; static uint8_t countTx; static uint8_t countErr; -static unsigned long prevTime = hwMillis() - LED_PROCESS_INTERVAL_MS; // Substract some, to make sure leds gets updated on first run. - +static unsigned long prevTime; inline void ledsInit() { @@ -37,16 +36,17 @@ inline void ledsInit() countErr = 0; // Setup led pins -#if defined(MY_DEFAULT_RX_LED_PIN) - pinMode(MY_DEFAULT_RX_LED_PIN, OUTPUT); -#endif -#if defined(MY_DEFAULT_TX_LED_PIN) - pinMode(MY_DEFAULT_TX_LED_PIN, OUTPUT); -#endif -#if defined(MY_DEFAULT_ERR_LED_PIN) - pinMode(MY_DEFAULT_ERR_LED_PIN, OUTPUT); -#endif - ledsProcess(); + #if defined(MY_DEFAULT_RX_LED_PIN) + pinMode(MY_DEFAULT_RX_LED_PIN, OUTPUT); + #endif + #if defined(MY_DEFAULT_TX_LED_PIN) + pinMode(MY_DEFAULT_TX_LED_PIN, OUTPUT); + #endif + #if defined(MY_DEFAULT_ERR_LED_PIN) + pinMode(MY_DEFAULT_ERR_LED_PIN, OUTPUT); + #endif + prevTime = hwMillis() - LED_PROCESS_INTERVAL_MS; // Substract some, to make sure leds gets updated on first run. + ledsProcess(); } void ledsProcess() { @@ -54,46 +54,58 @@ void ledsProcess() { if ((hwMillis() - prevTime) < LED_PROCESS_INTERVAL_MS) { return; } + prevTime = hwMillis(); - prevTime += LED_PROCESS_INTERVAL_MS; + uint8_t state; - uint8_t state; - - // For an On/Off ratio of 4, the pattern repeated will be [on, on, on, off] - // until the counter becomes 0. -#if defined(MY_DEFAULT_RX_LED_PIN) - state = (countRx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; - hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, state); - if (countRx) { + // For an On/Off ratio of 4, the pattern repeated will be [on, on, on, off] + // until the counter becomes 0. + #if defined(MY_DEFAULT_RX_LED_PIN) + if (countRx) { --countRx; } -#endif + state = (countRx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; + hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, state); + #endif -#if defined(MY_DEFAULT_TX_LED_PIN) - state = (countTx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; - hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, state); - if (countTx) { + #if defined(MY_DEFAULT_TX_LED_PIN) + if (countTx) { --countTx; } -#endif + state = (countTx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; + hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, state); + #endif -#if defined(MY_DEFAULT_ERR_LED_PIN) - state = (countErr & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; - hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, state); - if (countErr) { + #if defined(MY_DEFAULT_ERR_LED_PIN) + if (countErr) { --countErr; } -#endif + state = (countErr & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; + hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, state); + #endif } void ledsBlinkRx(uint8_t cnt) { - if (!countRx) { countRx = cnt*LED_ON_OFF_RATIO; } + if (!countRx) { + countRx = cnt*LED_ON_OFF_RATIO; + } + ledsProcess(); } void ledsBlinkTx(uint8_t cnt) { - if(!countTx) { countTx = cnt*LED_ON_OFF_RATIO; } + if(!countTx) { + countTx = cnt*LED_ON_OFF_RATIO; + } + ledsProcess(); } void ledsBlinkErr(uint8_t cnt) { - if(!countErr) { countErr = cnt*LED_ON_OFF_RATIO; } + if(!countErr) { + countErr = cnt*LED_ON_OFF_RATIO; + } + ledsProcess(); +} + +bool ledsBlinking() { + return countRx || countTx || countErr; } diff --git a/core/MyLeds.h b/core/MyLeds.h index e6f982d..e0fb121 100644 --- a/core/MyLeds.h +++ b/core/MyLeds.h @@ -43,6 +43,11 @@ void ledsBlinkTx(uint8_t cnt); void ledsBlinkErr(uint8_t cnt); void ledsProcess(); // do the actual blinking + /** + * Test if any LED is currently blinking. + * @return true when one or more LEDs are blinking, false otherwise. + */ + bool ledsBlinking(); #else // Remove led functions if feature is disabled diff --git a/core/MySensorsCore.cpp b/core/MySensorsCore.cpp index f84cfb5..1761b66 100644 --- a/core/MySensorsCore.cpp +++ b/core/MySensorsCore.cpp @@ -54,11 +54,7 @@ void _callbackTransportOk() } void _process(void) { - hwWatchdogReset(); - - #if defined (MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) - ledsProcess(); - #endif + doYield(); #if defined(MY_INCLUSION_MODE_FEATURE) inclusionProcess(); @@ -80,10 +76,7 @@ void _process(void) { void _infiniteLoop(void) { while(1) { - yield(); - #if defined (MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) - ledsProcess(); - #endif + doYield(); #if defined(__linux__) exit(1); #endif @@ -139,9 +132,8 @@ void _begin(void) { #if !defined(MY_TRANSPORT_RELAX) // check if transport ready while (!isTransportReady()) { - hwWatchdogReset(); transportProcess(); - yield(); + doYield(); } #else CORE_DEBUG(PSTR("MCO:BGN:MTR\n")); @@ -465,7 +457,6 @@ void wait(const uint32_t waitingMS) { const uint32_t enteringMS = hwMillis(); while (hwMillis() - enteringMS < waitingMS) { _process(); - yield(); } } @@ -476,12 +467,21 @@ bool wait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgtype) { bool expectedResponse = false; while ( (hwMillis() - enteringMS < waitingMS) && !expectedResponse ) { _process(); - yield(); expectedResponse = (mGetCommand(_msg) == cmd && _msg.type == msgtype); } return expectedResponse; } +void doYield(void) { + hwWatchdogReset(); + + yield(); + + #if defined (MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) + ledsProcess(); + #endif +} + int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2) { CORE_DEBUG(PSTR("MCO:SLP:MS=%lu,SMS=%d,I1=%d,M1=%d,I2=%d,M2=%d\n"), sleepingMS, smartSleep, interrupt1, mode1, interrupt2, mode2); // OTA FW feature: do not sleep if FW update ongoing @@ -513,7 +513,6 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in uint32_t sleepDeltaMS = 0; while (!isTransportReady() && (sleepDeltaMS < sleepingTimeMS) && (sleepDeltaMS < MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS)) { _process(); - yield(); sleepDeltaMS = hwMillis() - sleepEnterMS; } // sleep remainder @@ -539,6 +538,13 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in transportPowerDown(); #endif + #if defined (MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) + // Wait until leds finish their blinking pattern + while (ledsBlinking()) { + doYield(); + } + #endif + setIndication(INDICATION_SLEEP); int8_t result = MY_SLEEP_NOT_POSSIBLE; // default @@ -601,7 +607,7 @@ void _nodeLock(const char* str) while (1) { setIndication(INDICATION_ERR_LOCKED); CORE_DEBUG(PSTR("MCO:NLK:NODE LOCKED. TO UNLOCK, GND PIN %d AND RESET\n"), MY_NODE_UNLOCK_PIN); - yield(); + doYield(); (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID,C_INTERNAL, I_LOCKED).set(str)); #if defined(MY_SENSOR_NETWORK) transportPowerDown(); diff --git a/core/MySensorsCore.h b/core/MySensorsCore.h index 9272448..06b6c17 100644 --- a/core/MySensorsCore.h +++ b/core/MySensorsCore.h @@ -246,6 +246,13 @@ void wait(const uint32_t waitingMS); */ bool wait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgtype); +/** + * Function to allow scheduler to do some work. + * @remark Internally it will call yield, kick the watchdog and update led states. + */ +void doYield(void); + + /** * Sleep (PowerDownMode) the MCU and radio. Wake up on timer. * @param sleepingMS Number of milliseconds to sleep. diff --git a/core/MyTransport.cpp b/core/MyTransport.cpp index e921cad..811c582 100644 --- a/core/MyTransport.cpp +++ b/core/MyTransport.cpp @@ -504,7 +504,7 @@ bool transportWait(const uint32_t ms, const uint8_t cmd, const uint8_t msgtype){ while ((hwMillis() - enter < ms) && !expectedResponse) { // process incoming messages transportProcessFIFO(); - yield(); // process esp8266 stack, ignored for AVR + doYield(); expectedResponse = (mGetCommand(_msg) == cmd && _msg.type == msgtype); } return expectedResponse; diff --git a/core/MyTransportNRF24.cpp b/core/MyTransportNRF24.cpp index e458eee..9a21a25 100644 --- a/core/MyTransportNRF24.cpp +++ b/core/MyTransportNRF24.cpp @@ -25,125 +25,128 @@ #include "drivers/CircularBuffer/CircularBuffer.h" #if defined(MY_RF24_ENABLE_ENCRYPTION) - #include "drivers/AES/AES.h" +#include "drivers/AES/AES.h" #endif #if defined(MY_RX_MESSAGE_BUFFER_FEATURE) -typedef struct _transportQueuedMessage -{ - uint8_t m_len; // Length of the data - uint8_t m_data[MAX_MESSAGE_LENGTH]; // The raw data +typedef struct _transportQueuedMessage { + uint8_t m_len; // Length of the data + uint8_t m_data[MAX_MESSAGE_LENGTH]; // The raw data } transportQueuedMessage; /** Buffer to store queued messages in. */ static transportQueuedMessage transportRxQueueStorage[MY_RX_MESSAGE_BUFFER_SIZE]; /** Circular buffer, which uses the transportRxQueueStorage and administers stored messages. */ -static CircularBuffer transportRxQueue(transportRxQueueStorage, MY_RX_MESSAGE_BUFFER_SIZE); +static CircularBuffer transportRxQueue(transportRxQueueStorage, MY_RX_MESSAGE_BUFFER_SIZE); static volatile uint8_t transportLostMessageCount = 0; static void transportRxCallback(void) { - // Called for each message received by radio, from interrupt context. - // This function _must_ call RF24_readMessage() to de-assert interrupt line! - if (!transportRxQueue.full()) - { - transportQueuedMessage* msg = transportRxQueue.getFront(); - msg->m_len = RF24_readMessage(msg->m_data); // Read payload & clear RX_DR - (void)transportRxQueue.pushFront(msg); - } else { - // Queue is full. Discard message. - (void)RF24_readMessage(NULL); // Read payload & clear RX_DR - // Keep track of messages lost. Max 255, prevent wrapping. - if (transportLostMessageCount < 255) - { - ++transportLostMessageCount; - } - } + // Called for each message received by radio, from interrupt context. + // This function _must_ call RF24_readMessage() to de-assert interrupt line! + if (!transportRxQueue.full()) { + transportQueuedMessage* msg = transportRxQueue.getFront(); + msg->m_len = RF24_readMessage(msg->m_data); // Read payload & clear RX_DR + (void)transportRxQueue.pushFront(msg); + } else { + // Queue is full. Discard message. + (void)RF24_readMessage(NULL); // Read payload & clear RX_DR + // Keep track of messages lost. Max 255, prevent wrapping. + if (transportLostMessageCount < 255) { + ++transportLostMessageCount; + } + } } #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) - hwReadConfigBlock((void*)_psk, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); - //set up AES-key - _aes.set_key(_psk, 16); - // Make sure it is purged from memory when set - memset(_psk, 0, 16); - #endif - - #if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - RF24_registerReceiveCallback( transportRxCallback ); - #endif - return RF24_initialize(); +bool transportInit(void) +{ +#if defined(MY_RF24_ENABLE_ENCRYPTION) + hwReadConfigBlock((void*)_psk, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); + //set up AES-key + _aes.set_key(_psk, 16); + // Make sure it is purged from memory when set + memset(_psk, 0, 16); +#endif + +#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) + RF24_registerReceiveCallback( transportRxCallback ); +#endif + return RF24_initialize(); } -void transportSetAddress(uint8_t address) { - RF24_setNodeAddress(address); - RF24_startListening(); +void transportSetAddress(const uint8_t address) +{ + RF24_setNodeAddress(address); + RF24_startListening(); } -uint8_t transportGetAddress() { - return RF24_getNodeID(); +uint8_t transportGetAddress(void) +{ + return RF24_getNodeID(); } -bool transportSend(uint8_t recipient, const void* data, uint8_t len) { - #if defined(MY_RF24_ENABLE_ENCRYPTION) - // copy input data because it is read-only - memcpy(_dataenc,data,len); - // has to be adjusted, WIP! - _aes.set_IV(0); - len = len > 16 ? 32 : 16; - //encrypt data - _aes.cbc_encrypt(_dataenc, _dataenc, len/16); - bool status = RF24_sendMessage( recipient, _dataenc, len ); - #else - bool status = RF24_sendMessage( recipient, data, len ); - #endif - - return status; +bool transportSend(const uint8_t recipient, const void* data, uint8_t len) +{ +#if defined(MY_RF24_ENABLE_ENCRYPTION) + // copy input data because it is read-only + (void)memcpy(_dataenc,data,len); + // has to be adjusted, WIP! + _aes.set_IV(0); + len = len > 16 ? 32 : 16; + //encrypt data + _aes.cbc_encrypt(_dataenc, _dataenc, len/16); + return RF24_sendMessage(recipient, _dataenc, len); +#else + return RF24_sendMessage(recipient, data, len); +#endif } -bool transportAvailable() { - #if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - (void)RF24_isDataAvailable; // Prevent 'defined but not used' warning - return !transportRxQueue.empty(); - #else - return RF24_isDataAvailable(); - #endif +bool transportAvailable(void) +{ +#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) + (void)RF24_isDataAvailable; // Prevent 'defined but not used' warning + return !transportRxQueue.empty(); +#else + return RF24_isDataAvailable(); +#endif } -bool transportSanityCheck() { - return RF24_sanityCheck(); +bool transportSanityCheck(void) +{ + return RF24_sanityCheck(); } -uint8_t transportReceive(void* data) { - uint8_t len = 0; - #if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - transportQueuedMessage* msg = transportRxQueue.getBack(); - if (msg) { - len = msg->m_len; - (void)memcpy(data, msg->m_data, len); - (void)transportRxQueue.popBack(); - } - #else - len = RF24_readMessage(data); - #endif - #if defined(MY_RF24_ENABLE_ENCRYPTION) - // has to be adjusted, WIP! - _aes.set_IV(0); - // decrypt data - _aes.cbc_decrypt((byte*)(data), (byte*)(data), len>16?2:1); - #endif - return len; +uint8_t transportReceive(void* data) +{ + uint8_t len = 0; +#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) + transportQueuedMessage* msg = transportRxQueue.getBack(); + if (msg) { + len = msg->m_len; + (void)memcpy(data, msg->m_data, len); + (void)transportRxQueue.popBack(); + } +#else + len = RF24_readMessage(data); +#endif +#if defined(MY_RF24_ENABLE_ENCRYPTION) + // has to be adjusted, WIP! + _aes.set_IV(0); + // decrypt data + _aes.cbc_decrypt((byte*)(data), (byte*)(data), len>16?2:1); +#endif + return len; } -void transportPowerDown() { - RF24_powerDown(); +void transportPowerDown(void) +{ + RF24_powerDown(); } diff --git a/drivers/RF24/RF24.cpp b/drivers/RF24/RF24.cpp index 2a9d27f..34d1193 100644 --- a/drivers/RF24/RF24.cpp +++ b/drivers/RF24/RF24.cpp @@ -26,376 +26,415 @@ LOCAL uint8_t MY_RF24_BASE_ADDR[MY_RF24_ADDR_WIDTH] = { MY_RF24_BASE_RADIO_ID }; LOCAL uint8_t MY_RF24_NODE_ADDRESS = AUTO; #if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - LOCAL RF24_receiveCallbackType RF24_receiveCallback = NULL; +LOCAL RF24_receiveCallbackType RF24_receiveCallback = NULL; #endif #ifdef LINUX_ARCH_RASPBERRYPI - uint8_t spi_rxbuff[32+1] ; //SPI receive buffer (payload max 32 bytes) - uint8_t spi_txbuff[32+1] ; //SPI transmit buffer (payload max 32 bytes + 1 byte for the command) +uint8_t spi_rxbuff[32+1] ; //SPI receive buffer (payload max 32 bytes) +uint8_t spi_txbuff[32+1] ; //SPI transmit buffer (payload max 32 bytes + 1 byte for the command) #endif -LOCAL void RF24_csn(bool level) { - hwDigitalWrite(MY_RF24_CS_PIN, level); +LOCAL void RF24_csn(const bool level) +{ + hwDigitalWrite(MY_RF24_CS_PIN, level); } -LOCAL void RF24_ce(bool level) { - hwDigitalWrite(MY_RF24_CE_PIN, level); +LOCAL void RF24_ce(const bool level) +{ + hwDigitalWrite(MY_RF24_CE_PIN, level); } -LOCAL uint8_t RF24_spiMultiByteTransfer(uint8_t cmd, uint8_t* buf, uint8_t len, bool aReadMode) { - uint8_t status; - uint8_t* current = buf; - #if !defined(MY_SOFTSPI) - _SPI.beginTransaction(SPISettings(MY_RF24_SPI_MAX_SPEED, MY_RF24_SPI_DATA_ORDER, MY_RF24_SPI_DATA_MODE)); - #endif - RF24_csn(LOW); - // timing - delayMicroseconds(10); - #ifdef LINUX_ARCH_RASPBERRYPI - uint8_t * prx = spi_rxbuff; - uint8_t * ptx = spi_txbuff; - uint8_t size = len + 1; // Add register value to transmit buffer +LOCAL uint8_t RF24_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_t len, const bool aReadMode) +{ + uint8_t status; + uint8_t* current = buf; +#if !defined(MY_SOFTSPI) + _SPI.beginTransaction(SPISettings(MY_RF24_SPI_MAX_SPEED, MY_RF24_SPI_DATA_ORDER, MY_RF24_SPI_DATA_MODE)); +#endif + RF24_csn(LOW); + // timing + delayMicroseconds(10); +#ifdef LINUX_ARCH_RASPBERRYPI + uint8_t * prx = spi_rxbuff; + uint8_t * ptx = spi_txbuff; + uint8_t size = len + 1; // Add register value to transmit buffer - *ptx++ = cmd; - while ( len-- ) { - if (aReadMode) { - *ptx++ = NOP ; - } else { - *ptx++ = *current++; - } - } - _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); - if (aReadMode) { - if (size == 2) { - status = *++prx; // result is 2nd byte of receive buffer - } else { - status = *prx++; // status is 1st byte of receive buffer - // decrement before to skip status byte - while (--size) { *buf++ = *prx++; } - } - } else { - status = *prx; // status is 1st byte of receive buffer - } - #else - status = _SPI.transfer( cmd ); - while ( len-- ) { - if (aReadMode) { - status = _SPI.transfer( NOP ); - if (buf != NULL) { - *current++ = status; - } - } else status = _SPI.transfer(*current++); - } - #endif - RF24_csn(HIGH); - #if !defined(MY_SOFTSPI) - _SPI.endTransaction(); - #endif - // timing - delayMicroseconds(10); - return status; + *ptx++ = cmd; + while ( len-- ) { + if (aReadMode) { + *ptx++ = RF24_NOP; + } else { + *ptx++ = *current++; + } + } + _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); + if (aReadMode) { + if (size == 2) { + status = *++prx; // result is 2nd byte of receive buffer + } else { + status = *prx++; // status is 1st byte of receive buffer + // decrement before to skip status byte + while (--size) { + *buf++ = *prx++; + } + } + } else { + status = *prx; // status is 1st byte of receive buffer + } +#else + status = _SPI.transfer(cmd); + while ( len-- ) { + if (aReadMode) { + status = _SPI.transfer(RF24_NOP); + if (buf != NULL) { + *current++ = status; + } + } else { + status = _SPI.transfer(*current++); + } + } +#endif + RF24_csn(HIGH); +#if !defined(MY_SOFTSPI) + _SPI.endTransaction(); +#endif + // timing + delayMicroseconds(10); + return status; } -LOCAL uint8_t RF24_spiByteTransfer(uint8_t cmd) { - return RF24_spiMultiByteTransfer( cmd, NULL, 0, false); +LOCAL uint8_t RF24_spiByteTransfer(const uint8_t cmd) +{ + return RF24_spiMultiByteTransfer(cmd, NULL, 0, false); } -LOCAL uint8_t RF24_RAW_readByteRegister(uint8_t cmd) { - const uint8_t value = RF24_spiMultiByteTransfer( cmd, NULL, 1, true); - RF24_DEBUG(PSTR("RF24:read register, reg=%d, value=%d\n"), cmd & (R_REGISTER ^ 0xFF), value); - return value; +LOCAL uint8_t RF24_RAW_readByteRegister(const uint8_t cmd) +{ + const uint8_t value = RF24_spiMultiByteTransfer(cmd, NULL, 1, true); + RF24_DEBUG(PSTR("RF24:read register, reg=%d, value=%d\n"), cmd & RF24_REGISTER_MASK, value); + return value; } -LOCAL uint8_t RF24_RAW_writeByteRegister(uint8_t cmd, uint8_t value) { - RF24_DEBUG(PSTR("RF24:write register, reg=%d, value=%d\n"), cmd & (W_REGISTER ^ 0xFF), value); - return RF24_spiMultiByteTransfer( cmd , &value, 1, false); +LOCAL uint8_t RF24_RAW_writeByteRegister(const uint8_t cmd, uint8_t value) +{ + RF24_DEBUG(PSTR("RF24:write register, reg=%d, value=%d\n"), cmd & RF24_REGISTER_MASK, value); + return RF24_spiMultiByteTransfer( cmd , &value, 1, false); } -LOCAL void RF24_flushRX(void) { - RF24_DEBUG(PSTR("RF24:flushRX\n")); - RF24_spiByteTransfer( FLUSH_RX ); +LOCAL void RF24_flushRX(void) +{ + RF24_DEBUG(PSTR("RF24:flushRX\n")); + RF24_spiByteTransfer(RF24_FLUSH_RX); } -LOCAL void RF24_flushTX(void) { - RF24_DEBUG(PSTR("RF24:flushTX\n")); - RF24_spiByteTransfer( FLUSH_TX ); +LOCAL void RF24_flushTX(void) +{ + RF24_DEBUG(PSTR("RF24:flushTX\n")); + RF24_spiByteTransfer(RF24_FLUSH_TX); } -LOCAL uint8_t RF24_getStatus(void) { - return RF24_spiByteTransfer( NOP ); +LOCAL uint8_t RF24_getStatus(void) +{ + return RF24_spiByteTransfer(RF24_NOP); } -LOCAL uint8_t RF24_getFIFOStatus(void) { - return RF24_readByteRegister(FIFO_STATUS); +LOCAL uint8_t RF24_getFIFOStatus(void) +{ + return RF24_readByteRegister(RF24_FIFO_STATUS); } -LOCAL void RF24_setChannel(uint8_t channel) { - RF24_writeByteRegister(RF_CH, channel); +LOCAL void RF24_setChannel(const uint8_t channel) +{ + RF24_writeByteRegister(RF24_RF_CH,channel); } -LOCAL void RF24_setRetries(uint8_t retransmitDelay, uint8_t retransmitCount) { - RF24_writeByteRegister(SETUP_RETR, retransmitDelay << ARD | retransmitCount << ARC); +LOCAL void RF24_setRetries(const uint8_t retransmitDelay, const uint8_t retransmitCount) +{ + RF24_writeByteRegister(RF24_SETUP_RETR, retransmitDelay << RF24_ARD | retransmitCount << RF24_ARC); } -LOCAL void RF24_setAddressWidth(uint8_t width) { - RF24_writeByteRegister(SETUP_AW, width - 2); +LOCAL void RF24_setAddressWidth(const uint8_t width) +{ + RF24_writeByteRegister(RF24_SETUP_AW, width - 2); } -LOCAL void RF24_setRFSetup(uint8_t RFsetup) { - RF24_writeByteRegister(RF_SETUP, RFsetup); +LOCAL void RF24_setRFSetup(const uint8_t RFsetup) +{ + RF24_writeByteRegister(RF24_RF_SETUP, RFsetup); } -LOCAL void RF24_setFeature(uint8_t feature) { - RF24_writeByteRegister(FEATURE, feature); +LOCAL void RF24_setFeature(const uint8_t feature) +{ + RF24_writeByteRegister(RF24_FEATURE, feature); } -LOCAL void RF24_setPipe(uint8_t pipe) { - RF24_writeByteRegister(EN_RXADDR, pipe); +LOCAL void RF24_setPipe(const uint8_t pipe) +{ + RF24_writeByteRegister(RF24_EN_RXADDR, pipe); } -LOCAL void RF24_setAutoACK(uint8_t pipe) { - RF24_writeByteRegister(EN_AA, pipe); +LOCAL void RF24_setAutoACK(const uint8_t pipe) +{ + RF24_writeByteRegister(RF24_EN_AA, pipe); } -LOCAL void RF24_setDynamicPayload(uint8_t pipe) { - RF24_writeByteRegister(DYNPD, pipe); +LOCAL void RF24_setDynamicPayload(const uint8_t pipe) +{ + RF24_writeByteRegister(RF24_DYNPD, pipe); } -LOCAL void RF24_setRFConfiguration(uint8_t configuration) { - RF24_writeByteRegister(NRF_CONFIG, configuration); +LOCAL void RF24_setRFConfiguration(const uint8_t configuration) +{ + RF24_writeByteRegister(RF24_NRF_CONFIG, configuration); } -LOCAL void RF24_setPipeAddress(uint8_t pipe, uint8_t* address, uint8_t width) { - RF24_writeMultiByteRegister(pipe, address, width); +LOCAL void RF24_setPipeAddress(const uint8_t pipe, uint8_t* address, const uint8_t width) +{ + RF24_writeMultiByteRegister(pipe, address, width); } -LOCAL void RF24_setPipeLSB(uint8_t pipe, uint8_t LSB) { - RF24_writeByteRegister(pipe, LSB); +LOCAL void RF24_setPipeLSB(const uint8_t pipe, const uint8_t LSB) +{ + RF24_writeByteRegister(pipe, LSB); } -LOCAL uint8_t RF24_getObserveTX(void) { - return RF24_readByteRegister(OBSERVE_TX); +LOCAL uint8_t RF24_getObserveTX(void) +{ + return RF24_readByteRegister(RF24_OBSERVE_TX); } -LOCAL void RF24_setStatus(uint8_t status) { - RF24_writeByteRegister(RF24_STATUS, status); +LOCAL void RF24_setStatus(const uint8_t status) +{ + RF24_writeByteRegister(RF24_STATUS, status); } -LOCAL void RF24_enableFeatures(void) { - RF24_RAW_writeByteRegister(ACTIVATE, 0x73); +LOCAL void RF24_enableFeatures(void) +{ + RF24_RAW_writeByteRegister(RF24_ACTIVATE, 0x73); } -LOCAL void RF24_openWritingPipe(uint8_t recipient) { - RF24_DEBUG(PSTR("RF24:open writing pipe, recipient=%d\n"), recipient); - // only write LSB of RX0 and TX pipe - RF24_setPipeLSB(RX_ADDR_P0, recipient); - RF24_setPipeLSB(TX_ADDR, recipient); +LOCAL void RF24_openWritingPipe(const uint8_t recipient) +{ + RF24_DEBUG(PSTR("RF24:OPEN WPIPE,RCPT=%d\n"), recipient); // open writing pipe + // only write LSB of RX0 and TX pipe + RF24_setPipeLSB(RF24_RX_ADDR_P0, recipient); + RF24_setPipeLSB(RF24_TX_ADDR, recipient); } -LOCAL void RF24_startListening(void) { - RF24_DEBUG(PSTR("RF24:start listening\n")); - // toggle PRX - 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 - if(MY_RF24_NODE_ADDRESS!=AUTO) { - RF24_setPipeLSB(RX_ADDR_P0, MY_RF24_NODE_ADDRESS); - } - // start listening - RF24_ce(HIGH); +LOCAL void RF24_startListening(void) +{ + RF24_DEBUG(PSTR("RF24:STRT LIS\n")); // start listening + // toggle PRX + RF24_setRFConfiguration(MY_RF24_CONFIGURATION | _BV(RF24_PWR_UP) | _BV(RF24_PRIM_RX) ); + // all RX pipe addresses must be unique, therefore skip if node ID is AUTO + if(MY_RF24_NODE_ADDRESS!=AUTO) { + RF24_setPipeLSB(RF24_RX_ADDR_P0, MY_RF24_NODE_ADDRESS); + } + // start listening + RF24_ce(HIGH); } -LOCAL void RF24_stopListening(void) { - RF24_DEBUG(PSTR("RF24:stop listening\n")); - RF24_ce(LOW); - // timing - delayMicroseconds(130); - RF24_setRFConfiguration(MY_RF24_CONFIGURATION | _BV(PWR_UP) ); - // timing - delayMicroseconds(100); +LOCAL void RF24_stopListening(void) +{ + RF24_DEBUG(PSTR("RF24:STP LIS\n")); // stop listening + RF24_ce(LOW); + // timing + delayMicroseconds(130); + RF24_setRFConfiguration(MY_RF24_CONFIGURATION | _BV(RF24_PWR_UP) ); + // timing + delayMicroseconds(100); } -LOCAL void RF24_powerDown(void) { - RF24_ce(LOW); - RF24_setRFConfiguration(MY_RF24_CONFIGURATION); - RF24_DEBUG(PSTR("RF24:power down\n")); +LOCAL void RF24_powerDown(void) +{ + RF24_ce(LOW); + RF24_setRFConfiguration(MY_RF24_CONFIGURATION); + RF24_DEBUG(PSTR("RF24:PD\n")); // power down } -LOCAL bool RF24_sendMessage( uint8_t recipient, const void* buf, uint8_t len ) { - uint8_t status; - - RF24_stopListening(); - RF24_openWritingPipe( recipient ); - RF24_DEBUG(PSTR("RF24:send message to %d, len=%d\n"),recipient,len); - // flush TX FIFO - RF24_flushTX(); - // this command is affected in clones (e.g. Si24R1): flipped NoACK bit when using W_TX_PAYLOAD_NO_ACK / W_TX_PAYLOAD - // AutoACK is disabled on the broadcasting pipe - NO_ACK prevents resending - RF24_spiMultiByteTransfer(recipient == BROADCAST_ADDRESS ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD, (uint8_t*)buf, len, false ); - // go, TX starts after ~10us - RF24_ce(HIGH); - // timeout counter to detect HW issues - uint16_t timeout = 0xFFFF; - do { - status = RF24_getStatus(); - } while (!(status & ( _BV(MAX_RT) | _BV(TX_DS) )) && timeout--); - // timeout value after successful TX on 16Mhz AVR ~ 65500, i.e. msg is transmitted after ~36 loop cycles - RF24_ce(LOW); - // reset interrupts - RF24_setStatus(_BV(TX_DS) | _BV(MAX_RT) ); - // Max retries exceeded - if( status & _BV(MAX_RT)){ - // flush packet - RF24_DEBUG(PSTR("RF24:MAX_RT\n")); - RF24_flushTX(); - } - RF24_startListening(); - // true if message sent - return ( status & _BV(TX_DS) ); +LOCAL bool RF24_sendMessage(const uint8_t recipient, const void* buf, const uint8_t len) +{ + uint8_t RF24_status; + RF24_stopListening(); + RF24_openWritingPipe( recipient ); + RF24_DEBUG(PSTR("RF24:SND:TO=%d,LEN=%d\n"),recipient,len); // send message + // flush TX FIFO + RF24_flushTX(); + // this command is affected in clones (e.g. Si24R1): flipped NoACK bit when using W_TX_PAYLOAD_NO_ACK / W_TX_PAYLOAD + // AutoACK is disabled on the broadcasting pipe - NO_ACK prevents resending + RF24_spiMultiByteTransfer(recipient == BROADCAST_ADDRESS ? RF24_WRITE_TX_PAYLOAD_NO_ACK : RF24_WRITE_TX_PAYLOAD, (uint8_t*)buf, len, false ); + // go, TX starts after ~10us + RF24_ce(HIGH); + // timeout counter to detect HW issues + uint16_t timeout = 0xFFFF; + do { + RF24_status = RF24_getStatus(); + } while (!(RF24_status & ( _BV(RF24_MAX_RT) | _BV(RF24_TX_DS) )) && timeout--); + // timeout value after successful TX on 16Mhz AVR ~ 65500, i.e. msg is transmitted after ~36 loop cycles + RF24_ce(LOW); + // reset interrupts + RF24_setStatus(_BV(RF24_TX_DS) | _BV(RF24_MAX_RT) ); + // Max retries exceeded + if(RF24_status & _BV(RF24_MAX_RT)) { + // flush packet + RF24_DEBUG(PSTR("!RF24:SND:MAX_RT\n")); // max retries, no ACK + RF24_flushTX(); + } + RF24_startListening(); + // true if message sent + return (RF24_status & _BV(RF24_TX_DS)); } -LOCAL uint8_t RF24_getDynamicPayloadSize(void) { - uint8_t result = RF24_spiMultiByteTransfer(R_RX_PL_WID, NULL, 1, true); - // check if payload size invalid - if(result > 32) { - RF24_DEBUG(PSTR("RF24:invalid payload length = %d\n"),result); - RF24_flushRX(); - result = 0; - } - return result; +LOCAL uint8_t RF24_getDynamicPayloadSize(void) +{ + uint8_t result = RF24_spiMultiByteTransfer(RF24_READ_RX_PL_WID, NULL, 1, true); + // check if payload size invalid + if(result > 32) { + RF24_DEBUG(PSTR("!RF24:GDP:PAYL LEN INVALID=%d\n"),result); // payload len invalid + RF24_flushRX(); + result = 0; + } + return result; } -LOCAL bool RF24_isDataAvailable() { - return ( !(RF24_getFIFOStatus() & _BV(0)) ); +LOCAL bool RF24_isDataAvailable() +{ + return (!(RF24_getFIFOStatus() & _BV(0)) ); } -LOCAL uint8_t RF24_readMessage( void* buf) { - const uint8_t len = RF24_getDynamicPayloadSize(); - RF24_DEBUG(PSTR("RF24:read message, len=%d\n"), len); - RF24_spiMultiByteTransfer( R_RX_PAYLOAD , (uint8_t*)buf, len, true ); - // clear RX interrupt - RF24_setStatus(_BV(RX_DR) ); - return len; +LOCAL uint8_t RF24_readMessage(void* buf) +{ + const uint8_t len = RF24_getDynamicPayloadSize(); + RF24_DEBUG(PSTR("RF24:RDM:MSG LEN=%d\n"), len); // read message + RF24_spiMultiByteTransfer(RF24_READ_RX_PAYLOAD,(uint8_t*)buf,len,true); + // clear RX interrupt + RF24_setStatus(_BV(RF24_RX_DR)); + return len; } -LOCAL void RF24_setNodeAddress(uint8_t address) { - if(address!=AUTO){ - MY_RF24_NODE_ADDRESS = address; - // enable node pipe - RF24_setPipe(_BV(ERX_P0 + BROADCAST_PIPE) | _BV(ERX_P0) ); - // enable autoACK on pipe 0 - RF24_setAutoACK(_BV(ENAA_P0) ); - } +LOCAL void RF24_setNodeAddress(const uint8_t address) +{ + if(address!=AUTO) { + MY_RF24_NODE_ADDRESS = address; + // enable node pipe + RF24_setPipe(_BV(RF24_ERX_P0 + RF24_BROADCAST_PIPE) | _BV(RF24_ERX_P0)); + // enable autoACK on pipe 0 + RF24_setAutoACK(_BV(RF24_ENAA_P0)); + } } -LOCAL uint8_t RF24_getNodeID(void) { - return MY_RF24_NODE_ADDRESS; +LOCAL uint8_t RF24_getNodeID(void) +{ + return MY_RF24_NODE_ADDRESS; } -LOCAL bool RF24_sanityCheck(void) { - // detect HW defect, configuration errors or interrupted SPI line, CE disconnect cannot be detected - return (RF24_readByteRegister(RF_SETUP) == MY_RF24_RF_SETUP) & (RF24_readByteRegister(RF_CH) == MY_RF24_CHANNEL); +LOCAL bool RF24_sanityCheck(void) +{ + // detect HW defect, configuration errors or interrupted SPI line, CE disconnect cannot be detected + return (RF24_readByteRegister(RF24_RF_SETUP) == MY_RF24_RF_SETUP) & (RF24_readByteRegister(RF24_RF_CH) == MY_RF24_CHANNEL); } #if defined(MY_RX_MESSAGE_BUFFER_FEATURE) -LOCAL void RF24_irqHandler( void ) +LOCAL void RF24_irqHandler(void) { - if (RF24_receiveCallback) - { - // Will stay for a while (several 100us) in this interrupt handler. Any interrupts from serial - // rx coming in during our stay will not be handled and will cause characters to be lost. - // As a workaround we re-enable interrupts to allow nested processing of other interrupts. - // Our own handler is disconnected to prevent recursive calling of this handler. - #if defined(MY_GATEWAY_SERIAL) && !defined(__linux__) - detachInterrupt(digitalPinToInterrupt(MY_RF24_IRQ_PIN)); - interrupts(); - #endif - // Read FIFO until empty. - // Procedure acc. to datasheet (pg. 63): - // 1.Read payload, 2.Clear RX_DR IRQ, 3.Read FIFO_status, 4.Repeat when more data available. - // Datasheet (ch. 8.5) states, that the nRF de-asserts IRQ after reading STATUS. + if (RF24_receiveCallback) { + // Will stay for a while (several 100us) in this interrupt handler. Any interrupts from serial + // rx coming in during our stay will not be handled and will cause characters to be lost. + // As a workaround we re-enable interrupts to allow nested processing of other interrupts. + // Our own handler is disconnected to prevent recursive calling of this handler. +#if defined(MY_GATEWAY_SERIAL) && !defined(__linux__) + detachInterrupt(digitalPinToInterrupt(MY_RF24_IRQ_PIN)); + interrupts(); +#endif + // Read FIFO until empty. + // Procedure acc. to datasheet (pg. 63): + // 1.Read payload, 2.Clear RX_DR IRQ, 3.Read FIFO_status, 4.Repeat when more data available. + // Datasheet (ch. 8.5) states, that the nRF de-asserts IRQ after reading STATUS. - // Start checking if RX-FIFO is not empty, as we might end up here from an interrupt - // for a message we've already read. - while (RF24_isDataAvailable()) { - RF24_receiveCallback(); // Must call RF24_readMessage(), which will clear RX_DR IRQ ! - } - // Restore our interrupt handler. - #if defined(MY_GATEWAY_SERIAL) && !defined(__linux__) - noInterrupts(); - attachInterrupt(digitalPinToInterrupt(MY_RF24_IRQ_PIN), RF24_irqHandler, FALLING); - #endif - } else { - // clear RX interrupt - RF24_setStatus(_BV(RX_DR)); - } + // Start checking if RX-FIFO is not empty, as we might end up here from an interrupt + // for a message we've already read. + while (RF24_isDataAvailable()) { + RF24_receiveCallback(); // Must call RF24_readMessage(), which will clear RX_DR IRQ ! + } + // Restore our interrupt handler. +#if defined(MY_GATEWAY_SERIAL) && !defined(__linux__) + noInterrupts(); + attachInterrupt(digitalPinToInterrupt(MY_RF24_IRQ_PIN), RF24_irqHandler, FALLING); +#endif + } else { + // clear RX interrupt + RF24_setStatus(_BV(RF24_RX_DR)); + } } -LOCAL void RF24_registerReceiveCallback( RF24_receiveCallbackType cb ) { - MY_CRITICAL_SECTION { - RF24_receiveCallback = cb; - } +LOCAL void RF24_registerReceiveCallback(RF24_receiveCallbackType cb) +{ + MY_CRITICAL_SECTION { + RF24_receiveCallback = cb; + } } #endif -LOCAL bool RF24_initialize(void) { - // prevent warning - (void)RF24_getObserveTX; +LOCAL bool RF24_initialize(void) +{ + // prevent warning + (void)RF24_getObserveTX; - // Initialize pins - hwPinMode(MY_RF24_CE_PIN,OUTPUT); - hwPinMode(MY_RF24_CS_PIN,OUTPUT); - #if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - hwPinMode(MY_RF24_IRQ_PIN,INPUT); - #endif - // Initialize SPI - _SPI.begin(); - RF24_ce(LOW); - RF24_csn(HIGH); - #if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - // assure SPI can be used from interrupt context - // Note: ESP8266 & SoftSPI currently do not support interrupt usage for SPI, - // therefore it is unsafe to use MY_RF24_IRQ_PIN with ESP8266/SoftSPI! - _SPI.usingInterrupt(digitalPinToInterrupt(MY_RF24_IRQ_PIN)); - // attach interrupt - attachInterrupt(digitalPinToInterrupt(MY_RF24_IRQ_PIN), RF24_irqHandler, FALLING); - #endif - // CRC and power up - RF24_setRFConfiguration(MY_RF24_CONFIGURATION | _BV(PWR_UP) ) ; - // settle >2ms - delay(5); - // set address width - RF24_setAddressWidth(MY_RF24_ADDR_WIDTH); - // auto retransmit delay 1500us, auto retransmit count 15 - RF24_setRetries(RF24_ARD, RF24_ARC); - // set channel - RF24_setChannel(MY_RF24_CHANNEL); - // set data rate and pa level - RF24_setRFSetup(MY_RF24_RF_SETUP); - // toggle features (necessary on some clones and non-P versions) - RF24_enableFeatures(); - // enable ACK payload and dynamic payload - RF24_setFeature(MY_RF24_FEATURE); - // sanity check (this function is P/non-P independent) - if (!RF24_sanityCheck()) { - RF24_DEBUG(PSTR("!RF24:Sanity check failed: configuration mismatch! Check wiring or replace module\n")); - return false; - } - // enable broadcasting pipe - RF24_setPipe(_BV(ERX_P0 + BROADCAST_PIPE)); - // disable AA on all pipes, activate when node pipe set - RF24_setAutoACK(0x00); - // enable dynamic payloads on used pipes - RF24_setDynamicPayload(_BV(DPL_P0 + BROADCAST_PIPE) | _BV(DPL_P0)); - // listen to broadcast pipe - MY_RF24_BASE_ADDR[0] = BROADCAST_ADDRESS; - RF24_setPipeAddress(RX_ADDR_P0 + BROADCAST_PIPE, (uint8_t*)&MY_RF24_BASE_ADDR, BROADCAST_PIPE > 1 ? 1 : MY_RF24_ADDR_WIDTH); - // pipe 0, set full address, later only LSB is updated - RF24_setPipeAddress(RX_ADDR_P0, (uint8_t*)&MY_RF24_BASE_ADDR, MY_RF24_ADDR_WIDTH); - RF24_setPipeAddress(TX_ADDR, (uint8_t*)&MY_RF24_BASE_ADDR, MY_RF24_ADDR_WIDTH); - // reset FIFO - RF24_flushRX(); - RF24_flushTX(); - // reset interrupts - RF24_setStatus(_BV(TX_DS) | _BV(MAX_RT) | _BV(RX_DR)); - return true; + // Initialize pins + hwPinMode(MY_RF24_CE_PIN,OUTPUT); + hwPinMode(MY_RF24_CS_PIN,OUTPUT); +#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) + hwPinMode(MY_RF24_IRQ_PIN,INPUT); +#endif + // Initialize SPI + _SPI.begin(); + RF24_ce(LOW); + RF24_csn(HIGH); +#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) + // assure SPI can be used from interrupt context + // Note: ESP8266 & SoftSPI currently do not support interrupt usage for SPI, + // therefore it is unsafe to use MY_RF24_IRQ_PIN with ESP8266/SoftSPI! + _SPI.usingInterrupt(digitalPinToInterrupt(MY_RF24_IRQ_PIN)); + // attach interrupt + attachInterrupt(digitalPinToInterrupt(MY_RF24_IRQ_PIN), RF24_irqHandler, FALLING); +#endif + // CRC and power up + RF24_setRFConfiguration(MY_RF24_CONFIGURATION | _BV(RF24_PWR_UP)) ; + // settle >2ms + delay(5); + // set address width + RF24_setAddressWidth(MY_RF24_ADDR_WIDTH); + // auto retransmit delay 1500us, auto retransmit count 15 + RF24_setRetries(RF24_SET_ARD, RF24_SET_ARC); + // set channel + RF24_setChannel(MY_RF24_CHANNEL); + // set data rate and pa level + RF24_setRFSetup(MY_RF24_RF_SETUP); + // toggle features (necessary on some clones and non-P versions) + RF24_enableFeatures(); + // enable ACK payload and dynamic payload + RF24_setFeature(MY_RF24_FEATURE); + // sanity check (this function is P/non-P independent) + if (!RF24_sanityCheck()) { + RF24_DEBUG(PSTR("!RF24:INIT:SANCHK FAIL\n")); // sanity check failed, check wiring or replace module + return false; + } + // enable broadcasting pipe + RF24_setPipe(_BV(RF24_ERX_P0 + RF24_BROADCAST_PIPE)); + // disable AA on all pipes, activate when node pipe set + RF24_setAutoACK(0x00); + // enable dynamic payloads on used pipes + RF24_setDynamicPayload(_BV(RF24_DPL_P0 + RF24_BROADCAST_PIPE) | _BV(RF24_DPL_P0)); + // listen to broadcast pipe + MY_RF24_BASE_ADDR[0] = BROADCAST_ADDRESS; + RF24_setPipeAddress(RF24_RX_ADDR_P0 + RF24_BROADCAST_PIPE, (uint8_t*)&MY_RF24_BASE_ADDR, RF24_BROADCAST_PIPE > 1 ? 1 : MY_RF24_ADDR_WIDTH); + // pipe 0, set full address, later only LSB is updated + RF24_setPipeAddress(RF24_RX_ADDR_P0, (uint8_t*)&MY_RF24_BASE_ADDR, MY_RF24_ADDR_WIDTH); + RF24_setPipeAddress(RF24_TX_ADDR, (uint8_t*)&MY_RF24_BASE_ADDR, MY_RF24_ADDR_WIDTH); + // reset FIFO + RF24_flushRX(); + RF24_flushTX(); + // reset interrupts + RF24_setStatus(_BV(RF24_TX_DS) | _BV(RF24_MAX_RT) | _BV(RF24_RX_DR)); + return true; } diff --git a/drivers/RF24/RF24.h b/drivers/RF24/RF24.h index d1e8f57..ae98d94 100644 --- a/drivers/RF24/RF24.h +++ b/drivers/RF24/RF24.h @@ -83,16 +83,16 @@ // RF24 settings #if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - #define MY_RF24_CONFIGURATION (uint8_t) ((RF24_CRC_16 << 2) | (1 << MASK_TX_DS) | (1 << MASK_MAX_RT)) + #define MY_RF24_CONFIGURATION (uint8_t) ((RF24_CRC_16 << 2) | (1 << RF24_MASK_TX_DS) | (1 << RF24_MASK_MAX_RT)) #else #define MY_RF24_CONFIGURATION (uint8_t) (RF24_CRC_16 << 2) #endif -#define MY_RF24_FEATURE (uint8_t)( _BV(EN_DPL) | _BV(EN_ACK_PAY) ) +#define MY_RF24_FEATURE (uint8_t)( _BV(RF24_EN_DPL) | _BV(RF24_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 // pipes -#define BROADCAST_PIPE 1 -#define NODE_PIPE 0 +#define RF24_BROADCAST_PIPE (1) +#define RF24_NODE_PIPE (0) // debug #if defined(MY_DEBUG_VERBOSE_RF24) @@ -102,146 +102,146 @@ #endif // PA levels -#define RF24_PA_MIN 0 -#define RF24_PA_LOW 1 -#define RF24_PA_HIGH 2 -#define RF24_PA_MAX 3 +#define RF24_PA_MIN (0) +#define RF24_PA_LOW (1) +#define RF24_PA_HIGH (2) +#define RF24_PA_MAX (3) // data rate -#define RF24_1MBPS 0 -#define RF24_2MBPS 1 -#define RF24_250KBPS 2 +#define RF24_1MBPS (0) +#define RF24_2MBPS (1) +#define RF24_250KBPS (2) // CRC -#define RF24_CRC_DISABLED 0 -#define RF24_CRC_8 2 -#define RF24_CRC_16 3 +#define RF24_CRC_DISABLED (0) +#define RF24_CRC_8 (2) +#define RF24_CRC_16 (3) // ARD, auto retry delay -#define RF24_ARD 5 //=1500us +#define RF24_SET_ARD (5) //=1500us // ARD, auto retry count -#define RF24_ARC 15 +#define RF24_SET_ARC (15) // nRF24L01(+) register definitions -#define NRF_CONFIG 0x00 -#define EN_AA 0x01 -#define EN_RXADDR 0x02 -#define SETUP_AW 0x03 -#define SETUP_RETR 0x04 -#define RF_CH 0x05 -#define RF_SETUP 0x06 -#define RF24_STATUS 0x07 -#define OBSERVE_TX 0x08 -#define CD 0x09 -#define RX_ADDR_P0 0x0A -#define RX_ADDR_P1 0x0B -#define RX_ADDR_P2 0x0C -#define RX_ADDR_P3 0x0D -#define RX_ADDR_P4 0x0E -#define RX_ADDR_P5 0x0F -#define TX_ADDR 0x10 -#define RX_PW_P0 0x11 -#define RX_PW_P1 0x12 -#define RX_PW_P2 0x13 -#define RX_PW_P3 0x14 -#define RX_PW_P4 0x15 -#define RX_PW_P5 0x16 -#define FIFO_STATUS 0x17 -#define DYNPD 0x1C -#define FEATURE 0x1D +#define RF24_NRF_CONFIG (0x00) +#define RF24_EN_AA (0x01) +#define RF24_EN_RXADDR (0x02) +#define RF24_SETUP_AW (0x03) +#define RF24_SETUP_RETR (0x04) +#define RF24_RF_CH (0x05) +#define RF24_RF_SETUP (0x06) +#define RF24_STATUS (0x07) +#define RF24_OBSERVE_TX (0x08) +#define RF24_CD (0x09) +#define RF24_RX_ADDR_P0 (0x0A) +#define RF24_RX_ADDR_P1 (0x0B) +#define RF24_RX_ADDR_P2 (0x0C) +#define RF24_RX_ADDR_P3 (0x0D) +#define RF24_RX_ADDR_P4 (0x0E) +#define RF24_RX_ADDR_P5 (0x0F) +#define RF24_TX_ADDR (0x10) +#define RF24_RX_PW_P0 (0x11) +#define RF24_RX_PW_P1 (0x12) +#define RF24_RX_PW_P2 (0x13) +#define RF24_RX_PW_P3 (0x14) +#define RF24_RX_PW_P4 (0x15) +#define RF24_RX_PW_P5 (0x16) +#define RF24_FIFO_STATUS (0x17) +#define RF24_DYNPD (0x1C) +#define RF24_FEATURE (0x1D) // instructions -#define R_REGISTER 0x00 -#define RPD 0x09 -#define W_REGISTER 0x20 -#define REGISTER_MASK 0x1F -#define ACTIVATE 0x50 -#define R_RX_PL_WID 0x60 -#define R_RX_PAYLOAD 0x61 -#define W_TX_PAYLOAD 0xA0 -#define W_ACK_PAYLOAD 0xA8 -#define W_TX_PAYLOAD_NO_ACK 0xB0 -#define FLUSH_TX 0xE1 -#define FLUSH_RX 0xE2 -#define REUSE_TX_PL 0xE3 -#define NOP 0xFF +#define RF24_READ_REGISTER (0x00) +#define RF24_RPD (0x09) +#define RF24_WRITE_REGISTER (0x20) +#define RF24_REGISTER_MASK (0x1F) +#define RF24_ACTIVATE (0x50) +#define RF24_READ_RX_PL_WID (0x60) +#define RF24_READ_RX_PAYLOAD (0x61) +#define RF24_WRITE_TX_PAYLOAD (0xA0) +#define RF24_WRITE_ACK_PAYLOAD (0xA8) +#define RF24_WRITE_TX_PAYLOAD_NO_ACK (0xB0) +#define RF24_FLUSH_TX (0xE1) +#define RF24_FLUSH_RX (0xE2) +#define RF24_REUSE_TX_PL (0xE3) +#define RF24_NOP (0xFF) // bit mnemonics -#define MASK_RX_DR 6 -#define MASK_TX_DS 5 -#define MASK_MAX_RT 4 -#define EN_CRC 3 -#define CRCO 2 -#define PWR_UP 1 -#define PRIM_RX 0 +#define RF24_MASK_RX_DR (6) +#define RF24_MASK_TX_DS (5) +#define RF24_MASK_MAX_RT (4) +#define RF24_EN_CRC (3) +#define RF24_CRCO (2) +#define RF24_PWR_UP (1) +#define RF24_PRIM_RX (0) // auto ACK -#define ENAA_P5 5 -#define ENAA_P4 4 -#define ENAA_P3 3 -#define ENAA_P2 2 -#define ENAA_P1 1 -#define ENAA_P0 0 +#define RF24_ENAA_P5 (5) +#define RF24_ENAA_P4 (4) +#define RF24_ENAA_P3 (3) +#define RF24_ENAA_P2 (2) +#define RF24_ENAA_P1 (1) +#define RF24_ENAA_P0 (0) // rx pipe -#define ERX_P5 5 -#define ERX_P4 4 -#define ERX_P3 3 -#define ERX_P2 2 -#define ERX_P1 1 -#define ERX_P0 0 +#define RF24_ERX_P5 (5) +#define RF24_ERX_P4 (4) +#define RF24_ERX_P3 (3) +#define RF24_ERX_P2 (2) +#define RF24_ERX_P1 (1) +#define RF24_ERX_P0 (0) // dynamic payload -#define DPL_P5 5 -#define DPL_P4 4 -#define DPL_P3 3 -#define DPL_P2 2 -#define DPL_P1 1 -#define DPL_P0 0 +#define RF24_DPL_P5 (5) +#define RF24_DPL_P4 (4) +#define RF24_DPL_P3 (3) +#define RF24_DPL_P2 (2) +#define RF24_DPL_P1 (1) +#define RF24_DPL_P0 (0) -#define AW 0 -#define ARD 4 -#define ARC 0 -#define PLL_LOCK 4 -#define RF_DR 3 -#define RF_PWR 6 -#define RX_DR 6 -#define TX_DS 5 -#define MAX_RT 4 -#define RX_P_NO 1 -#define TX_FULL 0 -#define PLOS_CNT 4 -#define ARC_CNT 0 -#define TX_REUSE 6 -#define FIFO_FULL 5 -#define TX_EMPTY 4 -#define RX_FULL 1 -#define RX_EMPTY 0 +#define RF24_AW (0) +#define RF24_ARD (4) +#define RF24_ARC (0) +#define RF24_PLL_LOCK (4) +#define RF24_RF_DR (3) +#define RF24_RF_PWR (6) +#define RF24_RX_DR (6) +#define RF24_TX_DS (5) +#define RF24_MAX_RT (4) +#define RF24_RX_P_NO (1) +#define RF24_TX_FULL (0) +#define RF24_PLOS_CNT (4) +#define RF24_ARC_CNT (0) +#define RF24_TX_REUSE (6) +#define RF24_FIFO_FULL (5) +#define RF24_TX_EMPTY (4) +#define RF24_RX_FULL (1) +#define RF24_RX_EMPTY (0) // features -#define EN_DPL 2 -#define EN_ACK_PAY 1 -#define EN_DYN_ACK 0 +#define RF24_EN_DPL (2) +#define RF24_EN_ACK_PAY (1) +#define RF24_EN_DYN_ACK (0) -#define LNA_HCURR 0 -#define RF_DR_LOW 5 -#define RF_DR_HIGH 3 -#define RF_PWR_LOW 1 -#define RF_PWR_HIGH 2 +#define RF24_LNA_HCURR (0) +#define RF24_RF_DR_LOW (5) +#define RF24_RF_DR_HIGH (3) +#define RF24_RF_PWR_LOW (1) +#define RF24_RF_PWR_HIGH (2) // functions -LOCAL void RF24_csn(bool level); -LOCAL void RF24_ce(bool level); -LOCAL uint8_t RF24_spiMultiByteTransfer(uint8_t cmd, uint8_t* buf, uint8_t len, bool aReadMode); -LOCAL uint8_t RF24_spiByteTransfer(uint8_t cmd); -LOCAL uint8_t RF24_RAW_readByteRegister(uint8_t cmd); -LOCAL uint8_t RF24_RAW_writeByteRegister(uint8_t cmd, uint8_t value); +LOCAL void RF24_csn(const bool level); +LOCAL void RF24_ce(const bool level); +LOCAL uint8_t RF24_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, const uint8_t len, const bool aReadMode); +LOCAL uint8_t RF24_spiByteTransfer(const uint8_t cmd); +LOCAL uint8_t RF24_RAW_readByteRegister(const uint8_t cmd); +LOCAL uint8_t RF24_RAW_writeByteRegister(const uint8_t cmd, const uint8_t value); -#define RF24_readByteRegister(reg) RF24_RAW_readByteRegister( R_REGISTER | ( REGISTER_MASK & (reg) ) ) -#define RF24_writeByteRegister(reg, value) RF24_RAW_writeByteRegister( W_REGISTER | ( REGISTER_MASK & (reg) ), value ) -#define RF24_writeMultiByteRegister(reg, buf, len) RF24_spiMultiByteTransfer( W_REGISTER | ( REGISTER_MASK & (reg) ), (uint8_t*)buf, len, false ) +#define RF24_readByteRegister(__reg) RF24_RAW_readByteRegister(RF24_READ_REGISTER | (RF24_REGISTER_MASK & __reg)) +#define RF24_writeByteRegister(__reg,__value) RF24_RAW_writeByteRegister(RF24_WRITE_REGISTER | (RF24_REGISTER_MASK & __reg), __value) +#define RF24_writeMultiByteRegister(__reg,__buf,__len) RF24_spiMultiByteTransfer(RF24_WRITE_REGISTER | (RF24_REGISTER_MASK & __reg),(uint8_t*)__buf, __len,false) LOCAL void RF24_flushRX(void); LOCAL void RF24_flushTX(void); @@ -251,27 +251,27 @@ LOCAL void RF24_openWritingPipe(uint8_t recipient); LOCAL void RF24_startListening(void); LOCAL void RF24_stopListening(void); LOCAL void RF24_powerDown(void); -LOCAL bool RF24_sendMessage(uint8_t recipient, const void* buf, uint8_t len); +LOCAL bool RF24_sendMessage(const uint8_t recipient, const void* buf, const uint8_t len); LOCAL uint8_t RF24_getDynamicPayloadSize(void); LOCAL bool RF24_isDataAvailable(); LOCAL uint8_t RF24_readMessage(void* buf); -LOCAL void RF24_setNodeAddress(uint8_t address); +LOCAL void RF24_setNodeAddress(const uint8_t address); LOCAL uint8_t RF24_getNodeID(void); LOCAL bool RF24_sanityCheck(void); LOCAL bool RF24_initialize(void); -LOCAL void RF24_setChannel(uint8_t channel); -LOCAL void RF24_setRetries(uint8_t retransmitDelay, uint8_t retransmitCount); -LOCAL void RF24_setAddressWidth(uint8_t width); -LOCAL void RF24_setRFSetup(uint8_t RFsetup); -LOCAL void RF24_setFeature(uint8_t feature); -LOCAL void RF24_setPipe(uint8_t pipe); -LOCAL void RF24_setAutoACK(uint8_t pipe); -LOCAL void RF24_setDynamicPayload(uint8_t pipe); -LOCAL void RF24_setRFConfiguration(uint8_t configuration); -LOCAL void RF24_setPipeAddress(uint8_t pipe, uint8_t* address, uint8_t width); -LOCAL void RF24_setPipeLSB(uint8_t pipe, uint8_t LSB); +LOCAL void RF24_setChannel(const uint8_t channel); +LOCAL void RF24_setRetries(const uint8_t retransmitDelay, const uint8_t retransmitCount); +LOCAL void RF24_setAddressWidth(const uint8_t width); +LOCAL void RF24_setRFSetup(const uint8_t RFsetup); +LOCAL void RF24_setFeature(const uint8_t feature); +LOCAL void RF24_setPipe(const uint8_t pipe); +LOCAL void RF24_setAutoACK(const uint8_t pipe); +LOCAL void RF24_setDynamicPayload(const uint8_t pipe); +LOCAL void RF24_setRFConfiguration(const uint8_t configuration); +LOCAL void RF24_setPipeAddress(const uint8_t pipe, uint8_t* address, const uint8_t width); +LOCAL void RF24_setPipeLSB(const uint8_t pipe, const uint8_t LSB); LOCAL uint8_t RF24_getObserveTX(void); -LOCAL void RF24_setStatus(uint8_t status); +LOCAL void RF24_setStatus(const uint8_t status); LOCAL void RF24_enableFeatures(void); #if defined(MY_RX_MESSAGE_BUFFER_FEATURE) @@ -282,7 +282,7 @@ LOCAL void RF24_enableFeatures(void); * by calling RF24_readMessage(). Otherwise the interrupt will not get deasserted * and message reception will stop. */ - LOCAL void RF24_registerReceiveCallback( RF24_receiveCallbackType cb ); + LOCAL void RF24_registerReceiveCallback(RF24_receiveCallbackType cb); #endif #endif // __RF24_H__ \ No newline at end of file