diff --git a/.astylerc b/.tools/astyle/config/style.cfg similarity index 96% rename from .astylerc rename to .tools/astyle/config/style.cfg index ebd67ec..363270e 100644 --- a/.astylerc +++ b/.tools/astyle/config/style.cfg @@ -14,7 +14,7 @@ max-code-length=100 break-after-logical # Preprocessor blocks should be indented -indent-preproc-block +#indent-preproc-block # Preprocessor definitions should be indented if linebroken indent-preproc-define diff --git a/MyConfig.h b/MyConfig.h index 9a9f317..1efd397 100644 --- a/MyConfig.h +++ b/MyConfig.h @@ -67,10 +67,10 @@ #ifndef MY_BAUD_RATE #define MY_BAUD_RATE 115200 #endif - /** - * @def MY_SERIAL_OUTPUT_SIZE - * @brief Max. characters for serial output. - */ +/** +* @def MY_SERIAL_OUTPUT_SIZE +* @brief Max. characters for serial output. +*/ #ifndef MY_SERIAL_OUTPUT_SIZE #define MY_SERIAL_OUTPUT_SIZE (120u) #endif @@ -107,7 +107,7 @@ #endif /** * @def MY_TRANSPORT_SANITY_CHECK -* @brief If enabled, node will check transport in regular intervals to detect HW issues and re-initialize in case of failure. +* @brief If enabled, node will check transport in regular intervals to detect HW issues and re-initialize in case of failure. * This feature is enabled for all repeater nodes (incl. GW) */ //#define MY_TRANSPORT_SANITY_CHECK @@ -121,7 +121,7 @@ #endif /** * @def MY_TRANSPORT_DISCOVERY_INTERVAL_MS -* @brief This is a gateway-only feature: Interval (in ms) to issue network discovery checks +* @brief This is a gateway-only feature: Interval (in ms) to issue network discovery checks */ #ifndef MY_TRANSPORT_DISCOVERY_INTERVAL_MS #define MY_TRANSPORT_DISCOVERY_INTERVAL_MS (10*60*1000ul) @@ -145,34 +145,34 @@ */ #define MY_REGISTRATION_FEATURE - /** - * @def MY_REGISTRATION_RETRIES - * @brief Number of registration retries if no reply received from GW/controller - */ +/** +* @def MY_REGISTRATION_RETRIES +* @brief Number of registration retries if no reply received from GW/controller +*/ #ifndef MY_REGISTRATION_RETRIES #define MY_REGISTRATION_RETRIES (3u) #endif - /** - * @def MY_REGISTRATION_DEFAULT - * @brief Node registration default - this applies if no registration response is received from controller - */ +/** +* @def MY_REGISTRATION_DEFAULT +* @brief Node registration default - this applies if no registration response is received from controller +*/ #define MY_REGISTRATION_DEFAULT true - /** - * @def MY_REGISTRATION_CONTROLLER - * @brief If enabled, node registration request has to be handled by controller - */ - // #define MY_REGISTRATION_CONTROLLER +/** +* @def MY_REGISTRATION_CONTROLLER +* @brief If enabled, node registration request has to be handled by controller +*/ +// #define MY_REGISTRATION_CONTROLLER - /** - * @def MY_CORE_COMPATIBILITY_CHECK - * @brief If enabled, library compatibility is checked during node registration. Incompatible libraries are unable to send sensor data. - */ +/** +* @def MY_CORE_COMPATIBILITY_CHECK +* @brief If enabled, library compatibility is checked during node registration. Incompatible libraries are unable to send sensor data. +*/ #define MY_CORE_COMPATIBILITY_CHECK - /** +/** * @def MY_TRANSPORT_WAIT_READY_MS * @brief Timeout in MS until transport is ready during startup, set to 0 for no timeout */ @@ -323,11 +323,11 @@ * @brief The default input pin used for the inclusion mode button. */ #ifndef MY_INCLUSION_MODE_BUTTON_PIN - #if defined(ARDUINO_ARCH_ESP8266) - #define MY_INCLUSION_MODE_BUTTON_PIN 5 - #else - #define MY_INCLUSION_MODE_BUTTON_PIN 3 - #endif +#if defined(ARDUINO_ARCH_ESP8266) +#define MY_INCLUSION_MODE_BUTTON_PIN 5 +#else +#define MY_INCLUSION_MODE_BUTTON_PIN 3 +#endif #endif /** @@ -488,15 +488,15 @@ * @brief Default RF24 chip enable pin setting. Override in sketch if needed. */ #ifndef MY_RF24_CE_PIN - #if defined(ARDUINO_ARCH_ESP8266) - #define MY_RF24_CE_PIN 4 - #elif defined(ARDUINO_ARCH_SAMD) - #define MY_RF24_CE_PIN 27 - #elif defined(LINUX_ARCH_RASPBERRYPI) - #define MY_RF24_CE_PIN 22 - #else - #define MY_RF24_CE_PIN 9 - #endif +#if defined(ARDUINO_ARCH_ESP8266) +#define MY_RF24_CE_PIN 4 +#elif defined(ARDUINO_ARCH_SAMD) +#define MY_RF24_CE_PIN 27 +#elif defined(LINUX_ARCH_RASPBERRYPI) +#define MY_RF24_CE_PIN 22 +#else +#define MY_RF24_CE_PIN 9 +#endif #endif /** @@ -504,15 +504,15 @@ * @brief Default RF24 chip select pin setting. Override in sketch if needed. */ #ifndef MY_RF24_CS_PIN - #if defined(ARDUINO_ARCH_ESP8266) - #define MY_RF24_CS_PIN 15 - #elif defined(ARDUINO_ARCH_SAMD) - #define MY_RF24_CS_PIN 3 - #elif defined(LINUX_ARCH_RASPBERRYPI) - #define MY_RF24_CS_PIN 24 - #else - #define MY_RF24_CS_PIN 10 - #endif +#if defined(ARDUINO_ARCH_ESP8266) +#define MY_RF24_CS_PIN 15 +#elif defined(ARDUINO_ARCH_SAMD) +#define MY_RF24_CS_PIN 3 +#elif defined(LINUX_ARCH_RASPBERRYPI) +#define MY_RF24_CS_PIN 24 +#else +#define MY_RF24_CS_PIN 10 +#endif #endif /** @@ -528,9 +528,9 @@ * @brief Declare the amount of incoming messages that can be buffered. */ #ifdef MY_RX_MESSAGE_BUFFER_FEATURE - #ifndef MY_RX_MESSAGE_BUFFER_SIZE - #define MY_RX_MESSAGE_BUFFER_SIZE (20) - #endif +#ifndef MY_RX_MESSAGE_BUFFER_SIZE +#define MY_RX_MESSAGE_BUFFER_SIZE (20) +#endif #endif /** @@ -639,9 +639,9 @@ * @brief Set to true if @ref MY_IS_RFM69HW is set. */ #ifdef MY_IS_RFM69HW - #define MY_RFM69HW true +#define MY_RFM69HW true #else - #define MY_RFM69HW false +#define MY_RFM69HW false #endif /** @@ -673,11 +673,11 @@ * @brief RF69 IRQ pin number. */ #ifndef MY_RF69_IRQ_NUM - #if defined(ARDUINO_ARCH_ESP8266) - #define MY_RF69_IRQ_NUM RF69_IRQ_PIN - #else - #define MY_RF69_IRQ_NUM RF69_IRQ_NUM - #endif +#if defined(ARDUINO_ARCH_ESP8266) +#define MY_RF69_IRQ_NUM RF69_IRQ_PIN +#else +#define MY_RF69_IRQ_NUM RF69_IRQ_NUM +#endif #endif // Enables RFM69 encryption (all nodes and gateway must have this enabled, and all must be personalized with the same AES key) @@ -694,28 +694,28 @@ * This must match the hardware version of the RFM95 radio. */ #ifndef MY_RFM95_FREQUENCY - #define MY_RFM95_FREQUENCY (868.1f) +#define MY_RFM95_FREQUENCY (868.1f) #endif - /** - * @def MY_RFM95_MODEM_CONFIGRUATION - * @brief RFM95 modem configuration, see table - * - * BW = Bandwidth in kHz - * CR = Error correction code - * SF = Spreading factor, chips / symbol - * - * | CONFIG | BW | CR | SF | Comment - * |------------------------|-------|-----|------|----------------------------- - * | RFM95_BW125CR45SF128 | 125 | 4/5 | 128 | Default, medium range - * | RFM95_BW500CR45SF128 | 500 | 4/5 | 128 | Fast, short range - * | RFM95_BW31_25CR48SF512 | 31.25 | 4/8 | 512 | Slow, long range - * | RFM95_BW125CR48SF4096 | 125 | 4/8 | 4096 | Slow, long range - * - */ +/** +* @def MY_RFM95_MODEM_CONFIGRUATION +* @brief RFM95 modem configuration, see table +* +* BW = Bandwidth in kHz +* CR = Error correction code +* SF = Spreading factor, chips / symbol +* +* | CONFIG | BW | CR | SF | Comment +* |------------------------|-------|-----|------|----------------------------- +* | RFM95_BW125CR45SF128 | 125 | 4/5 | 128 | Default, medium range +* | RFM95_BW500CR45SF128 | 500 | 4/5 | 128 | Fast, short range +* | RFM95_BW31_25CR48SF512 | 31.25 | 4/8 | 512 | Slow, long range +* | RFM95_BW125CR48SF4096 | 125 | 4/8 | 4096 | Slow, long range +* +*/ #ifndef MY_RFM95_MODEM_CONFIGRUATION - // default - #define MY_RFM95_MODEM_CONFIGRUATION RFM95_BW125CR45SF128 +// default +#define MY_RFM95_MODEM_CONFIGRUATION RFM95_BW125CR45SF128 #endif /** @@ -729,7 +729,7 @@ * @brief RFM95 IRQ pin */ #ifndef MY_RFM95_IRQ_PIN - #define MY_RFM95_IRQ_PIN RFM95_IRQ_PIN +#define MY_RFM95_IRQ_PIN RFM95_IRQ_PIN #endif /** @@ -737,7 +737,7 @@ * @brief RFM95 SPI chip select pin */ #ifndef MY_RFM95_SPI_CS - #define MY_RFM95_SPI_CS RFM95_SPI_CS +#define MY_RFM95_SPI_CS RFM95_SPI_CS #endif /** @@ -745,21 +745,21 @@ * @brief RFM95 TX power level. */ #ifndef MY_RFM95_TX_POWER - #define MY_RFM95_TX_POWER 13 +#define MY_RFM95_TX_POWER 13 #endif - /** - * @def MY_RFM95_ATC_MODE_DISABLED - * @brief Enable to disable ATC mode - */ +/** +* @def MY_RFM95_ATC_MODE_DISABLED +* @brief Enable to disable ATC mode +*/ //#define MY_RFM95_ATC_MODE_DISABLED - /** - * @def MY_RFM95_ATC_TARGET_RSSI - * @brief Traget RSSI level for ATC mode - */ +/** +* @def MY_RFM95_ATC_TARGET_RSSI +* @brief Traget RSSI level for ATC mode +*/ #ifndef MY_RFM95_ATC_TARGET_RSSI - #define MY_RFM95_ATC_TARGET_RSSI (-60) +#define MY_RFM95_ATC_TARGET_RSSI (-60) #endif @@ -779,11 +779,11 @@ * @brief The Ethernet TCP/UDP port to open on controller or gateway. */ #ifndef MY_PORT - #ifdef MY_GATEWAY_MQTT_CLIENT - #define MY_PORT 1883 - #else - #define MY_PORT 5003 - #endif +#ifdef MY_GATEWAY_MQTT_CLIENT +#define MY_PORT 1883 +#else +#define MY_PORT 5003 +#endif #endif // Static ip address of gateway (if this is disabled, DHCP will be used) diff --git a/MySensors.h b/MySensors.h index a338823..6471f8a 100644 --- a/MySensors.h +++ b/MySensors.h @@ -41,60 +41,60 @@ * @brief Contain a string describing the class of sketch/node (gateway/repeater/sensor). */ #if defined(MY_GATEWAY_SERIAL) || defined(MY_GATEWAY_W5100) || defined(MY_GATEWAY_ENC28J60) || defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_LINUX) || defined(MY_GATEWAY_MQTT_CLIENT) - #define MY_GATEWAY_FEATURE - #define MY_IS_GATEWAY (true) - #define MY_NODE_TYPE "GW" +#define MY_GATEWAY_FEATURE +#define MY_IS_GATEWAY (true) +#define MY_NODE_TYPE "GW" #elif defined(MY_REPEATER_FEATURE) - #define MY_IS_GATEWAY (false) - #define MY_NODE_TYPE "REPEATER" +#define MY_IS_GATEWAY (false) +#define MY_NODE_TYPE "REPEATER" #else - #define MY_IS_GATEWAY (false) - #define MY_NODE_TYPE "NODE" +#define MY_IS_GATEWAY (false) +#define MY_NODE_TYPE "NODE" #endif // Enable radio "feature" if one of the radio types was enabled #if defined(MY_RADIO_NRF24) || defined(MY_RADIO_RFM69) || defined(MY_RADIO_RFM95) || defined(MY_RS485) - #define MY_SENSOR_NETWORK +#define MY_SENSOR_NETWORK #endif // HARDWARE #if defined(ARDUINO_ARCH_ESP8266) - // Remove PSTR macros from debug prints - #undef PSTR - #define PSTR(x) (x) - //#undef F - //#define F(x) (x) - #include "core/MyHwESP8266.cpp" +// Remove PSTR macros from debug prints +#undef PSTR +#define PSTR(x) (x) +//#undef F +//#define F(x) (x) +#include "core/MyHwESP8266.cpp" #elif defined(ARDUINO_ARCH_AVR) - #include "drivers/AVR/DigitalWriteFast/digitalWriteFast.h" - #include "core/MyHwATMega328.cpp" +#include "drivers/AVR/DigitalWriteFast/digitalWriteFast.h" +#include "core/MyHwATMega328.cpp" #elif defined(ARDUINO_ARCH_SAMD) - #include "core/MyHwSAMD.cpp" +#include "core/MyHwSAMD.cpp" #elif defined(__linux__) - #ifdef LINUX_ARCH_RASPBERRYPI - #include "core/MyHwRPi.cpp" - #else - #include "core/MyHwLinuxGeneric.cpp" - #endif +#ifdef LINUX_ARCH_RASPBERRYPI +#include "core/MyHwRPi.cpp" +#else +#include "core/MyHwLinuxGeneric.cpp" +#endif #endif // LEDS #if !defined(MY_DEFAULT_ERR_LED_PIN) && defined(MY_HW_ERR_LED_PIN) - #define MY_DEFAULT_ERR_LED_PIN MY_HW_ERR_LED_PIN +#define MY_DEFAULT_ERR_LED_PIN MY_HW_ERR_LED_PIN #endif #if !defined(MY_DEFAULT_TX_LED_PIN) && defined(MY_HW_TX_LED_PIN) - #define MY_DEFAULT_TX_LED_PIN MY_HW_TX_LED_PIN +#define MY_DEFAULT_TX_LED_PIN MY_HW_TX_LED_PIN #endif #if !defined(MY_DEFAULT_RX_LED_PIN) && defined(MY_HW_TX_LED_PIN) - #define MY_DEFAULT_RX_LED_PIN MY_HW_TX_LED_PIN +#define MY_DEFAULT_RX_LED_PIN MY_HW_TX_LED_PIN #endif #if defined(MY_LEDS_BLINKING_FEATURE) #error MY_LEDS_BLINKING_FEATURE is now removed from MySensors core,\ - define MY_DEFAULT_ERR_LED_PIN, MY_DEFAULT_TX_LED_PIN or\ - MY_DEFAULT_RX_LED_PIN in your sketch instead to enable LEDs +define MY_DEFAULT_ERR_LED_PIN, MY_DEFAULT_TX_LED_PIN or\ +MY_DEFAULT_RX_LED_PIN in your sketch instead to enable LEDs #endif /** @@ -106,9 +106,9 @@ #endif #if defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) - #include "core/MyLeds.cpp" +#include "core/MyLeds.cpp" #else - #include "core/MyLeds.h" +#include "core/MyLeds.h" #endif #include "core/MyIndication.cpp" @@ -116,221 +116,221 @@ // INCLUSION MODE #if defined(MY_INCLUSION_MODE_FEATURE) - #include "core/MyInclusionMode.cpp" +#include "core/MyInclusionMode.cpp" #endif // SIGNING #if defined(MY_SIGNING_ATSHA204) || defined(MY_SIGNING_SOFT) - #define MY_SIGNING_FEATURE +#define MY_SIGNING_FEATURE #endif #include "core/MySigning.cpp" #include "drivers/ATSHA204/sha256.cpp" #if defined(MY_SIGNING_FEATURE) - // SIGNING COMMON FUNCTIONS - #if defined(MY_SIGNING_ATSHA204) && defined(MY_SIGNING_SOFT) - #error Only one signing engine can be activated - #endif - #if defined(MY_SIGNING_ATSHA204) && defined(__linux__) - #error No support for ATSHA204 on this platform - #endif +// SIGNING COMMON FUNCTIONS +#if defined(MY_SIGNING_ATSHA204) && defined(MY_SIGNING_SOFT) +#error Only one signing engine can be activated +#endif +#if defined(MY_SIGNING_ATSHA204) && defined(__linux__) +#error No support for ATSHA204 on this platform +#endif - #if defined(MY_SIGNING_ATSHA204) - #include "core/MySigningAtsha204.cpp" - #include "drivers/ATSHA204/ATSHA204.cpp" - #elif defined(MY_SIGNING_SOFT) - #include "core/MySigningAtsha204Soft.cpp" - #endif +#if defined(MY_SIGNING_ATSHA204) +#include "core/MySigningAtsha204.cpp" +#include "drivers/ATSHA204/ATSHA204.cpp" +#elif defined(MY_SIGNING_SOFT) +#include "core/MySigningAtsha204Soft.cpp" +#endif #endif // FLASH #if defined(MY_OTA_FIRMWARE_FEATURE) - #include "drivers/SPIFlash/SPIFlash.cpp" - #include "core/MyOTAFirmwareUpdate.cpp" +#include "drivers/SPIFlash/SPIFlash.cpp" +#include "core/MyOTAFirmwareUpdate.cpp" #endif // GATEWAY - TRANSPORT #if defined(MY_CONTROLLER_IP_ADDRESS) || defined(MY_CONTROLLER_URL_ADDRESS) - #define MY_GATEWAY_CLIENT_MODE +#define MY_GATEWAY_CLIENT_MODE #endif #if defined(MY_USE_UDP) && !defined(MY_GATEWAY_CLIENT_MODE) - #error You must specify MY_CONTROLLER_IP_ADDRESS or MY_CONTROLLER_URL_ADDRESS for UDP +#error You must specify MY_CONTROLLER_IP_ADDRESS or MY_CONTROLLER_URL_ADDRESS for UDP #endif #if defined(MY_GATEWAY_MQTT_CLIENT) - #if defined(MY_SENSOR_NETWORK) - // We assume that a gateway having a radio also should act as repeater - #define MY_REPEATER_FEATURE - #endif - // GATEWAY - COMMON FUNCTIONS - // We support MQTT Client using W5100, ESP8266 and Linux - #if !defined(MY_GATEWAY_CLIENT_MODE) - #error You must specify MY_CONTROLLER_IP_ADDRESS or MY_CONTROLLER_URL_ADDRESS - #endif +#if defined(MY_SENSOR_NETWORK) +// We assume that a gateway having a radio also should act as repeater +#define MY_REPEATER_FEATURE +#endif +// GATEWAY - COMMON FUNCTIONS +// We support MQTT Client using W5100, ESP8266 and Linux +#if !defined(MY_GATEWAY_CLIENT_MODE) +#error You must specify MY_CONTROLLER_IP_ADDRESS or MY_CONTROLLER_URL_ADDRESS +#endif - #if !defined(MY_MQTT_PUBLISH_TOPIC_PREFIX) - #error You must specify a topic publish prefix MY_MQTT_PUBLISH_TOPIC_PREFIX for this MQTT client - #endif - #if !defined(MY_MQTT_SUBSCRIBE_TOPIC_PREFIX) - #error You must specify a topic subscribe prefix MY_MQTT_SUBSCRIBE_TOPIC_PREFIX for this MQTT client - #endif +#if !defined(MY_MQTT_PUBLISH_TOPIC_PREFIX) +#error You must specify a topic publish prefix MY_MQTT_PUBLISH_TOPIC_PREFIX for this MQTT client +#endif +#if !defined(MY_MQTT_SUBSCRIBE_TOPIC_PREFIX) +#error You must specify a topic subscribe prefix MY_MQTT_SUBSCRIBE_TOPIC_PREFIX for this MQTT client +#endif - #if !defined(MY_MQTT_CLIENT_ID) - #error You must define a unique MY_MQTT_CLIENT_ID for this MQTT client - #endif +#if !defined(MY_MQTT_CLIENT_ID) +#error You must define a unique MY_MQTT_CLIENT_ID for this MQTT client +#endif - #include "core/MyGatewayTransport.cpp" - #include "core/MyProtocolMySensors.cpp" +#include "core/MyGatewayTransport.cpp" +#include "core/MyProtocolMySensors.cpp" - #if defined(MY_GATEWAY_LINUX) - #include "drivers/Linux/EthernetClient.h" - #include "drivers/Linux/EthernetServer.h" - #include "drivers/Linux/IPAddress.h" - #endif - #include "drivers/PubSubClient/PubSubClient.cpp" - #include "core/MyGatewayTransportMQTTClient.cpp" +#if defined(MY_GATEWAY_LINUX) +#include "drivers/Linux/EthernetClient.h" +#include "drivers/Linux/EthernetServer.h" +#include "drivers/Linux/IPAddress.h" +#endif +#include "drivers/PubSubClient/PubSubClient.cpp" +#include "core/MyGatewayTransportMQTTClient.cpp" #elif defined(MY_GATEWAY_FEATURE) - // GATEWAY - COMMON FUNCTIONS - #include "core/MyGatewayTransport.cpp" +// GATEWAY - COMMON FUNCTIONS +#include "core/MyGatewayTransport.cpp" - #include "core/MyProtocolMySensors.cpp" +#include "core/MyProtocolMySensors.cpp" - // GATEWAY - CONFIGURATION - #if defined(MY_SENSOR_NETWORK) - // We assume that a gateway having a radio also should act as repeater - #define MY_REPEATER_FEATURE - #endif - #if !defined(MY_PORT) - #error You must define MY_PORT (controller or gatway port to open) - #endif - #if defined(MY_GATEWAY_ESP8266) - // GATEWAY - ESP8266 - #include "core/MyGatewayTransportEthernet.cpp" - #elif defined(MY_GATEWAY_LINUX) - // GATEWAY - Generic Linux - #include "drivers/Linux/EthernetClient.h" - #include "drivers/Linux/EthernetServer.h" - #include "drivers/Linux/IPAddress.h" - #include "core/MyGatewayTransportEthernet.cpp" - #elif defined(MY_GATEWAY_W5100) - // GATEWAY - W5100 - #include "core/MyGatewayTransportEthernet.cpp" - #elif defined(MY_GATEWAY_ENC28J60) - // GATEWAY - ENC28J60 - #if defined(MY_USE_UDP) - #error UDP mode is not available for ENC28J60 - #endif - #include "core/MyGatewayTransportEthernet.cpp" - #elif defined(MY_GATEWAY_SERIAL) - // GATEWAY - SERIAL - #include "core/MyGatewayTransportSerial.cpp" - #endif +// GATEWAY - CONFIGURATION +#if defined(MY_SENSOR_NETWORK) +// We assume that a gateway having a radio also should act as repeater +#define MY_REPEATER_FEATURE +#endif +#if !defined(MY_PORT) +#error You must define MY_PORT (controller or gatway port to open) +#endif +#if defined(MY_GATEWAY_ESP8266) +// GATEWAY - ESP8266 +#include "core/MyGatewayTransportEthernet.cpp" +#elif defined(MY_GATEWAY_LINUX) +// GATEWAY - Generic Linux +#include "drivers/Linux/EthernetClient.h" +#include "drivers/Linux/EthernetServer.h" +#include "drivers/Linux/IPAddress.h" +#include "core/MyGatewayTransportEthernet.cpp" +#elif defined(MY_GATEWAY_W5100) +// GATEWAY - W5100 +#include "core/MyGatewayTransportEthernet.cpp" +#elif defined(MY_GATEWAY_ENC28J60) +// GATEWAY - ENC28J60 +#if defined(MY_USE_UDP) +#error UDP mode is not available for ENC28J60 +#endif +#include "core/MyGatewayTransportEthernet.cpp" +#elif defined(MY_GATEWAY_SERIAL) +// GATEWAY - SERIAL +#include "core/MyGatewayTransportSerial.cpp" +#endif #endif // RAM ROUTING TABLE #if defined(MY_RAM_ROUTING_TABLE_FEATURE) && defined(MY_REPEATER_FEATURE) - // activate feature based on architecture - #if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_SAMD) || defined(LINUX_ARCH_RASPBERRYPI) - #define MY_RAM_ROUTING_TABLE_ENABLED - #elif defined(ARDUINO_ARCH_AVR) - // memory limited, enable with care - // #define MY_RAM_ROUTING_TABLE_ENABLED - #endif +// activate feature based on architecture +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_SAMD) || defined(LINUX_ARCH_RASPBERRYPI) +#define MY_RAM_ROUTING_TABLE_ENABLED +#elif defined(ARDUINO_ARCH_AVR) +// memory limited, enable with care +// #define MY_RAM_ROUTING_TABLE_ENABLED +#endif #endif #if defined(MY_TRANSPORT_DONT_CARE_MODE) - #error This directive is deprecated, set MY_TRANSPORT_WAIT_READY_MS instead! +#error This directive is deprecated, set MY_TRANSPORT_WAIT_READY_MS instead! #endif // RADIO #if defined(MY_RADIO_NRF24) || defined(MY_RADIO_RFM69) || defined(MY_RADIO_RFM95) ||defined(MY_RS485) - // SOFTSPI - #ifdef MY_SOFTSPI - #if defined(ARDUINO_ARCH_ESP8266) - #error Soft SPI is not available on ESP8266 - #endif - #include "drivers/AVR/DigitalIO/DigitalIO.h" - #endif +// SOFTSPI +#ifdef MY_SOFTSPI +#if defined(ARDUINO_ARCH_ESP8266) +#error Soft SPI is not available on ESP8266 +#endif +#include "drivers/AVR/DigitalIO/DigitalIO.h" +#endif - #if defined(MY_RADIO_NRF24) && defined(__linux__) && !defined(LINUX_ARCH_RASPBERRYPI) - #error No support for nRF24 radio on this platform - #endif +#if defined(MY_RADIO_NRF24) && defined(__linux__) && !defined(LINUX_ARCH_RASPBERRYPI) +#error No support for nRF24 radio on this platform +#endif - #include "core/MyTransport.cpp" - - // count enabled transports - #if defined(MY_RADIO_NRF24) - #define __RF24CNT 1 - #else - #define __RF24CNT 0 - #endif - #if defined(MY_RADIO_RFM69) - #define __RFM69CNT 1 - #else - #define __RFM69CNT 0 - #endif - #if defined(MY_RADIO_RFM95) - #define __RFM95CNT 1 - #else - #define __RFM95CNT 0 - #endif - #if defined(MY_RS485) - #define __RS485CNT 1 - #else - #define __RS485CNT 0 - #endif +#include "core/MyTransport.cpp" + +// count enabled transports +#if defined(MY_RADIO_NRF24) +#define __RF24CNT 1 +#else +#define __RF24CNT 0 +#endif +#if defined(MY_RADIO_RFM69) +#define __RFM69CNT 1 +#else +#define __RFM69CNT 0 +#endif +#if defined(MY_RADIO_RFM95) +#define __RFM95CNT 1 +#else +#define __RFM95CNT 0 +#endif +#if defined(MY_RS485) +#define __RS485CNT 1 +#else +#define __RS485CNT 0 +#endif - #if (__RF24CNT + __RFM69CNT + __RFM95CNT + __RS485CNT > 1) - #error Only one forward link driver can be activated - #endif +#if (__RF24CNT + __RFM69CNT + __RFM95CNT + __RS485CNT > 1) +#error Only one forward link driver can be activated +#endif - #if defined(MY_RADIO_NRF24) - #if defined(MY_RF24_ENABLE_ENCRYPTION) - #include "drivers/AES/AES.cpp" - #endif - #include "drivers/RF24/RF24.cpp" - #include "core/MyTransportNRF24.cpp" - #elif defined(MY_RS485) - #if !defined(MY_RS485_HWSERIAL) - #if defined(__linux__) - #error You must specify MY_RS485_HWSERIAL for RS485 transport - #endif - #include "drivers/AltSoftSerial/AltSoftSerial.cpp" - #endif - #include "core/MyTransportRS485.cpp" - #elif defined(MY_RADIO_RFM69) - #include "drivers/RFM69/RFM69.cpp" - #include "core/MyTransportRFM69.cpp" - #elif defined(MY_RADIO_RFM95) - #include "drivers/RFM95/RFM95.cpp" - #include "core/MyTransportRFM95.cpp" - #endif +#if defined(MY_RADIO_NRF24) +#if defined(MY_RF24_ENABLE_ENCRYPTION) +#include "drivers/AES/AES.cpp" +#endif +#include "drivers/RF24/RF24.cpp" +#include "core/MyTransportNRF24.cpp" +#elif defined(MY_RS485) +#if !defined(MY_RS485_HWSERIAL) +#if defined(__linux__) +#error You must specify MY_RS485_HWSERIAL for RS485 transport +#endif +#include "drivers/AltSoftSerial/AltSoftSerial.cpp" +#endif +#include "core/MyTransportRS485.cpp" +#elif defined(MY_RADIO_RFM69) +#include "drivers/RFM69/RFM69.cpp" +#include "core/MyTransportRFM69.cpp" +#elif defined(MY_RADIO_RFM95) +#include "drivers/RFM95/RFM95.cpp" +#include "core/MyTransportRFM95.cpp" +#endif #endif #if defined(MY_PARENT_NODE_IS_STATIC) && (MY_PARENT_NODE_ID == AUTO) - #error Parent is static but no parent ID defined. +#error Parent is static but no parent ID defined. #endif // Make sure to disable child features when parent feature is disabled #if !defined(MY_SENSOR_NETWORK) - #undef MY_OTA_FIRMWARE_FEATURE - #undef MY_REPEATER_FEATURE - #undef MY_SIGNING_NODE_WHITELISTING - #undef MY_SIGNING_FEATURE +#undef MY_OTA_FIRMWARE_FEATURE +#undef MY_REPEATER_FEATURE +#undef MY_SIGNING_NODE_WHITELISTING +#undef MY_SIGNING_FEATURE #endif #if !defined(MY_GATEWAY_FEATURE) - #undef MY_INCLUSION_MODE_FEATURE - #undef MY_INCLUSION_BUTTON_FEATURE +#undef MY_INCLUSION_MODE_FEATURE +#undef MY_INCLUSION_BUTTON_FEATURE #endif #if !defined(MY_CORE_ONLY) - #if !defined(MY_GATEWAY_FEATURE) && !defined(MY_SENSOR_NETWORK) - #error No forward link or gateway feature activated. This means nowhere to send messages! Pretty pointless. - #endif +#if !defined(MY_GATEWAY_FEATURE) && !defined(MY_SENSOR_NETWORK) +#error No forward link or gateway feature activated. This means nowhere to send messages! Pretty pointless. +#endif #endif #include "core/MyCapabilities.h" @@ -340,13 +340,13 @@ #include #if !defined(MY_CORE_ONLY) - #if defined(ARDUINO_ARCH_ESP8266) - #include "core/MyMainESP8266.cpp" - #elif defined(__linux__) - #include "core/MyMainLinux.cpp" - #else - #include "core/MyMainDefault.cpp" - #endif +#if defined(ARDUINO_ARCH_ESP8266) +#include "core/MyMainESP8266.cpp" +#elif defined(__linux__) +#include "core/MyMainLinux.cpp" +#else +#include "core/MyMainDefault.cpp" +#endif #endif #endif diff --git a/core/MyCapabilities.h b/core/MyCapabilities.h index 8b8abcc..3b45fec 100644 --- a/core/MyCapabilities.h +++ b/core/MyCapabilities.h @@ -22,60 +22,60 @@ #define MyCapabilities_h #if defined(MY_DISABLE_REMOTE_RESET) - #define MY_CAP_RESET "N" +#define MY_CAP_RESET "N" #else - #define MY_CAP_RESET "R" +#define MY_CAP_RESET "R" #endif #if defined(MY_OTA_FIRMWARE_FEATURE) - #define MY_CAP_OTA_FW "O" +#define MY_CAP_OTA_FW "O" #else - #define MY_CAP_OTA_FW "N" +#define MY_CAP_OTA_FW "N" #endif #if defined(MY_RADIO_NRF24) - #define MY_CAP_RADIO "N" +#define MY_CAP_RADIO "N" #elif defined(MY_RADIO_RFM69) - #define MY_CAP_RADIO "R" +#define MY_CAP_RADIO "R" #elif defined(MY_RADIO_RFM95) - #define MY_CAP_RADIO "L" +#define MY_CAP_RADIO "L" #elif defined(MY_RS485) - #define MY_CAP_RADIO "S" +#define MY_CAP_RADIO "S" #else - #define MY_CAP_RADIO "-" +#define MY_CAP_RADIO "-" #endif #if defined(MY_GATEWAY_FEATURE) - #define MY_CAP_TYPE "G" +#define MY_CAP_TYPE "G" #elif defined(MY_REPEATER_FEATURE) - #define MY_CAP_TYPE "R" +#define MY_CAP_TYPE "R" #else - #define MY_CAP_TYPE "N" +#define MY_CAP_TYPE "N" #endif #if defined(ARDUINO_ARCH_SAMD) - #define MY_CAP_ARCH "S" +#define MY_CAP_ARCH "S" #elif defined(ARDUINO_ARCH_ESP8266) - #define MY_CAP_ARCH "E" +#define MY_CAP_ARCH "E" #elif defined(ARDUINO_ARCH_AVR) - #define MY_CAP_ARCH "A" +#define MY_CAP_ARCH "A" #else - #define MY_CAP_ARCH "-" +#define MY_CAP_ARCH "-" #endif #if defined(MY_SIGNING_ATSHA204) - #define MY_CAP_SIGN "A" +#define MY_CAP_SIGN "A" #elif defined(MY_SIGNING_SOFT) - #define MY_CAP_SIGN "S" +#define MY_CAP_SIGN "S" #else - #define MY_CAP_SIGN "-" +#define MY_CAP_SIGN "-" #endif #if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - #define MY_CAP_RXBUF "Q" +#define MY_CAP_RXBUF "Q" #else - #define MY_CAP_RXBUF "-" +#define MY_CAP_RXBUF "-" #endif diff --git a/core/MyEepromAddresses.h b/core/MyEepromAddresses.h index 417ffa8..1150233 100644 --- a/core/MyEepromAddresses.h +++ b/core/MyEepromAddresses.h @@ -17,17 +17,17 @@ * version 2 as published by the Free Software Foundation. */ - /** - * @file MyEepromAddresses.h - * @brief Eeprom addresses for MySensors library data - * - * @defgroup MyEepromAddressesgrp MyEepromAddresses - * @ingroup internals - * @{ - * - */ +/** +* @file MyEepromAddresses.h +* @brief Eeprom addresses for MySensors library data +* +* @defgroup MyEepromAddressesgrp MyEepromAddresses +* @ingroup internals +* @{ +* +*/ + - #ifndef MyEepromAddresses_h #define MyEepromAddresses_h @@ -60,7 +60,7 @@ /** @brief Address routing table */ #define EEPROM_ROUTES_ADDRESS (EEPROM_DISTANCE_ADDRESS + SIZE_DISTANCE) /** @brief Address configuration bytes sent by controller */ -#define EEPROM_CONTROLLER_CONFIG_ADDRESS (EEPROM_ROUTES_ADDRESS + SIZE_ROUTES) +#define EEPROM_CONTROLLER_CONFIG_ADDRESS (EEPROM_ROUTES_ADDRESS + SIZE_ROUTES) /** @brief Address firmware type */ #define EEPROM_FIRMWARE_TYPE_ADDRESS (EEPROM_CONTROLLER_CONFIG_ADDRESS + SIZE_CONTROLLER_CONFIG) /** @brief Address firmware version */ @@ -76,13 +76,13 @@ /** @brief Address soft signing HMAC key. This is set with @ref SecurityPersonalizer.ino */ #define EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS (EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS + SIZE_WHITELIST_REQUIREMENT_TABLE) /** @brief Address soft signing serial key. This is set with @ref SecurityPersonalizer.ino */ -#define EEPROM_SIGNING_SOFT_SERIAL_ADDRESS (EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS + SIZE_SIGNING_SOFT_HMAC_KEY) +#define EEPROM_SIGNING_SOFT_SERIAL_ADDRESS (EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS + SIZE_SIGNING_SOFT_HMAC_KEY) /** @brief Address RF AES encryption key. This is set with @ref SecurityPersonalizer.ino */ #define EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS (EEPROM_SIGNING_SOFT_SERIAL_ADDRESS + SIZE_SIGNING_SOFT_SERIAL) /** @brief Address node lock couner. This is set with @ref SecurityPersonalizer.ino */ #define EEPROM_NODE_LOCK_COUNTER (EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS + SIZE_RF_ENCRYPTION_AES_KEY) /** @brief First free address for sketch static configuration */ -#define EEPROM_LOCAL_CONFIG_ADDRESS (EEPROM_NODE_LOCK_COUNTER + SIZE_NODE_LOCK_COUNTER) +#define EEPROM_LOCAL_CONFIG_ADDRESS (EEPROM_NODE_LOCK_COUNTER + SIZE_NODE_LOCK_COUNTER) #endif // MyEepromAddresses_h diff --git a/core/MyGatewayTransport.cpp b/core/MyGatewayTransport.cpp index c4aad27..1b76324 100644 --- a/core/MyGatewayTransport.cpp +++ b/core/MyGatewayTransport.cpp @@ -25,7 +25,8 @@ extern bool transportSendRoute(MyMessage &message); extern MyMessage _msg; extern MyMessage _msgTmp; -inline void gatewayTransportProcess() { +inline void gatewayTransportProcess() +{ if (gatewayTransportAvailable()) { _msg = gatewayTransportReceive(); if (_msg.destination == GATEWAY_ADDRESS) { @@ -34,7 +35,8 @@ inline void gatewayTransportProcess() { if (mGetRequestAck(_msg)) { // Copy message _msgTmp = _msg; - mSetRequestAck(_msgTmp, false); // Reply without ack flag (otherwise we would end up in an eternal loop) + mSetRequestAck(_msgTmp, + false); // Reply without ack flag (otherwise we would end up in an eternal loop) mSetAck(_msgTmp, true); _msgTmp.sender = getNodeId(); _msgTmp.destination = _msg.sender; @@ -44,11 +46,11 @@ inline void gatewayTransportProcess() { if (_msg.type == I_VERSION) { // Request for version. Create the response gatewayTransportSend(buildGw(_msgTmp, I_VERSION).set(MYSENSORS_LIBRARY_VERSION)); - #ifdef MY_INCLUSION_MODE_FEATURE +#ifdef MY_INCLUSION_MODE_FEATURE } else if (_msg.type == I_INCLUSION_MODE) { // Request to change inclusion mode inclusionModeSet(atoi(_msg.data) == 1); - #endif +#endif } else { _processInternalMessages(); } @@ -59,9 +61,9 @@ inline void gatewayTransportProcess() { } } } else { - #if defined(MY_SENSOR_NETWORK) - transportSendRoute(_msg); - #endif +#if defined(MY_SENSOR_NETWORK) + transportSendRoute(_msg); +#endif } } } diff --git a/core/MyGatewayTransport.h b/core/MyGatewayTransport.h index 8df4b59..a23178e 100644 --- a/core/MyGatewayTransport.h +++ b/core/MyGatewayTransport.h @@ -6,7 +6,7 @@ * network topology allowing messages to be routed to nodes. * * Created by Tomas Hozza - * Copyright (C) 2015 Tomas Hozza + * Copyright (C) 2015 Tomas Hozza * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors * * Documentation: http://www.mysensors.org diff --git a/core/MyGatewayTransportEthernet.cpp b/core/MyGatewayTransportEthernet.cpp index a6abe91..6c77c94 100644 --- a/core/MyGatewayTransportEthernet.cpp +++ b/core/MyGatewayTransportEthernet.cpp @@ -19,15 +19,15 @@ #include "MyGatewayTransport.h" - // global variables +// global variables extern MyMessage _msgTmp; #if defined(MY_CONTROLLER_IP_ADDRESS) - IPAddress _ethernetControllerIP(MY_CONTROLLER_IP_ADDRESS); +IPAddress _ethernetControllerIP(MY_CONTROLLER_IP_ADDRESS); #endif #if defined(MY_IP_ADDRESS) - IPAddress _ethernetGatewayIP(MY_IP_ADDRESS); +IPAddress _ethernetGatewayIP(MY_IP_ADDRESS); #endif uint8_t _ethernetGatewayMAC[] = { MY_MAC_ADDRESS }; uint16_t _ethernetGatewayPort = MY_PORT; @@ -35,137 +35,133 @@ MyMessage _ethernetMsg; #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) -typedef struct -{ +typedef struct { char string[MY_GATEWAY_MAX_RECEIVE_LENGTH]; uint8_t idx; } inputBuffer; #if defined(MY_GATEWAY_ESP8266) - // Some re-defines to make code more readable below - #define EthernetServer WiFiServer - #define EthernetClient WiFiClient - #define EthernetUDP WiFiUDP +// Some re-defines to make code more readable below +#define EthernetServer WiFiServer +#define EthernetClient WiFiClient +#define EthernetUDP WiFiUDP - #if defined(MY_IP_ADDRESS) - IPAddress _gatewayIp(MY_IP_GATEWAY_ADDRESS); - IPAddress _subnetIp(MY_IP_SUBNET_ADDRESS); - #endif +#if defined(MY_IP_ADDRESS) +IPAddress _gatewayIp(MY_IP_GATEWAY_ADDRESS); +IPAddress _subnetIp(MY_IP_SUBNET_ADDRESS); +#endif #endif #if defined(MY_USE_UDP) - EthernetUDP _ethernetServer; +EthernetUDP _ethernetServer; #elif defined(MY_GATEWAY_LINUX) - EthernetServer _ethernetServer(_ethernetGatewayPort, MY_GATEWAY_MAX_CLIENTS); +EthernetServer _ethernetServer(_ethernetGatewayPort, MY_GATEWAY_MAX_CLIENTS); #elif defined(MY_GATEWAY_CLIENT_MODE) - // Nothing to do here +// Nothing to do here #else - EthernetServer _ethernetServer(_ethernetGatewayPort); +EthernetServer _ethernetServer(_ethernetGatewayPort); #endif #if defined(MY_GATEWAY_CLIENT_MODE) - static EthernetClient client = EthernetClient(); - static inputBuffer inputString; +static EthernetClient client = EthernetClient(); +static inputBuffer inputString; #elif defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_LINUX) - static EthernetClient clients[MY_GATEWAY_MAX_CLIENTS]; - static bool clientsConnected[MY_GATEWAY_MAX_CLIENTS]; - static inputBuffer inputString[MY_GATEWAY_MAX_CLIENTS]; +static EthernetClient clients[MY_GATEWAY_MAX_CLIENTS]; +static bool clientsConnected[MY_GATEWAY_MAX_CLIENTS]; +static inputBuffer inputString[MY_GATEWAY_MAX_CLIENTS]; #else - static EthernetClient client = EthernetClient(); - static inputBuffer inputString; +static EthernetClient client = EthernetClient(); +static inputBuffer inputString; #endif #ifndef MY_IP_ADDRESS - void gatewayTransportRenewIP(); +void gatewayTransportRenewIP(); #endif // On W5100 boards with SPI_EN exposed we can use the real SPI bus together with radio // (if we enable it during usage) #ifdef MY_W5100_SPI_EN - void _w5100_spi_en(bool enable) - { - if (enable) - { - // Pull up pin - hwPinMode(MY_W5100_SPI_EN, INPUT); - hwDigitalWrite(MY_W5100_SPI_EN, HIGH); - } - else - { - // Ground pin - hwPinMode(MY_W5100_SPI_EN, OUTPUT); - hwDigitalWrite(MY_W5100_SPI_EN, LOW); - } +void _w5100_spi_en(bool enable) +{ + if (enable) { + // Pull up pin + hwPinMode(MY_W5100_SPI_EN, INPUT); + hwDigitalWrite(MY_W5100_SPI_EN, HIGH); + } else { + // Ground pin + hwPinMode(MY_W5100_SPI_EN, OUTPUT); + hwDigitalWrite(MY_W5100_SPI_EN, LOW); } +} #else - #define _w5100_spi_en(x) +#define _w5100_spi_en(x) #endif -bool gatewayTransportInit() { +bool gatewayTransportInit() +{ _w5100_spi_en(true); - #if defined(MY_GATEWAY_ESP8266) - #if defined(MY_ESP8266_SSID) - // Turn off access point - WiFi.mode (WIFI_STA); - #if defined(MY_ESP8266_HOSTNAME) - WiFi.hostname(MY_ESP8266_HOSTNAME); - #endif - #ifdef MY_IP_ADDRESS - WiFi.config(_ethernetGatewayIP, _gatewayIp, _subnetIp); - #endif - (void)WiFi.begin(MY_ESP8266_SSID, MY_ESP8266_PASSWORD); - while (WiFi.status() != WL_CONNECTED) - { - wait(500); - MY_SERIALDEVICE.print(F(".")); - } - MY_SERIALDEVICE.print(F("IP: ")); - MY_SERIALDEVICE.println(WiFi.localIP()); - #endif - #elif defined(MY_GATEWAY_LINUX) - // Nothing to do here - #else - #ifdef MY_IP_ADDRESS - Ethernet.begin(_ethernetGatewayMAC, _ethernetGatewayIP); - #else - // Get IP address from DHCP - if (!Ethernet.begin(_ethernetGatewayMAC)) { - MY_SERIALDEVICE.print(F("DHCP FAILURE...")); - _w5100_spi_en(false); - return false; - } - #endif - MY_SERIALDEVICE.print(F("IP: ")); - MY_SERIALDEVICE.println(Ethernet.localIP()); - // give the Ethernet interface a second to initialize - delay(1000); - #endif /* MY_GATEWAY_ESP8266 */ +#if defined(MY_GATEWAY_ESP8266) +#if defined(MY_ESP8266_SSID) + // Turn off access point + WiFi.mode (WIFI_STA); +#if defined(MY_ESP8266_HOSTNAME) + WiFi.hostname(MY_ESP8266_HOSTNAME); +#endif +#ifdef MY_IP_ADDRESS + WiFi.config(_ethernetGatewayIP, _gatewayIp, _subnetIp); +#endif + (void)WiFi.begin(MY_ESP8266_SSID, MY_ESP8266_PASSWORD); + while (WiFi.status() != WL_CONNECTED) { + wait(500); + MY_SERIALDEVICE.print(F(".")); + } + MY_SERIALDEVICE.print(F("IP: ")); + MY_SERIALDEVICE.println(WiFi.localIP()); +#endif +#elif defined(MY_GATEWAY_LINUX) + // Nothing to do here +#else +#ifdef MY_IP_ADDRESS + Ethernet.begin(_ethernetGatewayMAC, _ethernetGatewayIP); +#else + // Get IP address from DHCP + if (!Ethernet.begin(_ethernetGatewayMAC)) { + MY_SERIALDEVICE.print(F("DHCP FAILURE...")); + _w5100_spi_en(false); + return false; + } +#endif + MY_SERIALDEVICE.print(F("IP: ")); + MY_SERIALDEVICE.println(Ethernet.localIP()); + // give the Ethernet interface a second to initialize + delay(1000); +#endif /* MY_GATEWAY_ESP8266 */ - #ifdef MY_USE_UDP - _ethernetServer.begin(_ethernetGatewayPort); - #elif defined(MY_GATEWAY_CLIENT_MODE) - #if defined(MY_CONTROLLER_URL_ADDRESS) - if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) { - #else - if (client.connect(_ethernetControllerIP, MY_PORT)) { - #endif - debug(PSTR("Eth: connect\n")); - _w5100_spi_en(false); - gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete.")); - _w5100_spi_en(true); - presentNode(); - } else { - client.stop(); - debug(PSTR("Eth: Failed to connect\n")); - } - #else - #if defined(MY_GATEWAY_LINUX) && defined(MY_IP_ADDRESS) - _ethernetServer.begin(_ethernetGatewayIP); - #else - // we have to use pointers due to the constructor of EthernetServer - _ethernetServer.begin(); - #endif - #endif /* USE_UDP */ +#ifdef MY_USE_UDP + _ethernetServer.begin(_ethernetGatewayPort); +#elif defined(MY_GATEWAY_CLIENT_MODE) +#if defined(MY_CONTROLLER_URL_ADDRESS) + if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) { +#else + if (client.connect(_ethernetControllerIP, MY_PORT)) { +#endif + debug(PSTR("Eth: connect\n")); + _w5100_spi_en(false); + gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete.")); + _w5100_spi_en(true); + presentNode(); + } else { + client.stop(); + debug(PSTR("Eth: Failed to connect\n")); + } +#else +#if defined(MY_GATEWAY_LINUX) && defined(MY_IP_ADDRESS) + _ethernetServer.begin(_ethernetGatewayIP); +#else + // we have to use pointers due to the constructor of EthernetServer + _ethernetServer.begin(); +#endif +#endif /* USE_UDP */ _w5100_spi_en(false); return true; } @@ -178,240 +174,239 @@ bool gatewayTransportSend(MyMessage &message) setIndication(INDICATION_GW_TX); _w5100_spi_en(true); - #if defined(MY_GATEWAY_CLIENT_MODE) - #if defined(MY_USE_UDP) - #if defined(MY_CONTROLLER_URL_ADDRESS) - _ethernetServer.beginPacket(MY_CONTROLLER_URL_ADDRESS, MY_PORT); - #else - _ethernetServer.beginPacket(_ethernetControllerIP, MY_PORT); - #endif - _ethernetServer.write(_ethernetMsg, strlen(_ethernetMsg)); - // returns 1 if the packet was sent successfully - nbytes = _ethernetServer.endPacket(); - #else - if (!client.connected()) { - client.stop(); - #if defined(MY_CONTROLLER_URL_ADDRESS) - if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) { - #else - if (client.connect(_ethernetControllerIP, MY_PORT)) { - #endif - debug(PSTR("Eth: connect\n")); - _w5100_spi_en(false); - gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete.")); - _w5100_spi_en(true); - presentNode(); - } else { - // connecting to the server failed! - debug(PSTR("Eth: Failed to connect\n")); - _w5100_spi_en(false); - return false; - } - } - nbytes = client.write(_ethernetMsg, strlen(_ethernetMsg)); - #endif - #else - // Send message to connected clients - #if defined(MY_GATEWAY_ESP8266) - for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) - { - if (clients[i] && clients[i].connected()) - { - nbytes += clients[i].write((uint8_t*)_ethernetMsg, strlen(_ethernetMsg)); - } - } - #else - nbytes = _ethernetServer.write(_ethernetMsg); - #endif - #endif /* MY_GATEWAY_CLIENT_MODE */ +#if defined(MY_GATEWAY_CLIENT_MODE) +#if defined(MY_USE_UDP) +#if defined(MY_CONTROLLER_URL_ADDRESS) + _ethernetServer.beginPacket(MY_CONTROLLER_URL_ADDRESS, MY_PORT); +#else + _ethernetServer.beginPacket(_ethernetControllerIP, MY_PORT); +#endif + _ethernetServer.write(_ethernetMsg, strlen(_ethernetMsg)); + // returns 1 if the packet was sent successfully + nbytes = _ethernetServer.endPacket(); +#else + if (!client.connected()) { + client.stop(); +#if defined(MY_CONTROLLER_URL_ADDRESS) + if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) { +#else + if (client.connect(_ethernetControllerIP, MY_PORT)) { +#endif + debug(PSTR("Eth: connect\n")); + _w5100_spi_en(false); + gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete.")); + _w5100_spi_en(true); + presentNode(); + } else { + // connecting to the server failed! + debug(PSTR("Eth: Failed to connect\n")); + _w5100_spi_en(false); + return false; + } + } + nbytes = client.write(_ethernetMsg, strlen(_ethernetMsg)); +#endif +#else + // Send message to connected clients +#if defined(MY_GATEWAY_ESP8266) + for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) { + if (clients[i] && clients[i].connected()) { + nbytes += clients[i].write((uint8_t*)_ethernetMsg, strlen(_ethernetMsg)); + } + } +#else + nbytes = _ethernetServer.write(_ethernetMsg); +#endif +#endif /* MY_GATEWAY_CLIENT_MODE */ _w5100_spi_en(false); return (nbytes > 0); } #if (defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_LINUX)) && !defined(MY_GATEWAY_CLIENT_MODE) - bool _readFromClient(uint8_t i) { - while (clients[i].connected() && clients[i].available()) { - char inChar = clients[i].read(); - if (inputString[i].idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) { - // if newline then command is complete - if (inChar == '\n' || inChar == '\r') { - // Add string terminator and prepare for the next message - inputString[i].string[inputString[i].idx] = 0; - debug(PSTR("Client %d: %s\n"), i, inputString[i].string); - inputString[i].idx = 0; - if (protocolParse(_ethernetMsg, inputString[i].string)) { - return true; - } - - } else { - // add it to the inputString: - inputString[i].string[inputString[i].idx++] = inChar; - } - } else { - // Incoming message too long. Throw away - debug(PSTR("Client %d: Message too long\n"), i); +bool _readFromClient(uint8_t i) +{ + while (clients[i].connected() && clients[i].available()) { + char inChar = clients[i].read(); + if (inputString[i].idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) { + // if newline then command is complete + if (inChar == '\n' || inChar == '\r') { + // Add string terminator and prepare for the next message + inputString[i].string[inputString[i].idx] = 0; + debug(PSTR("Client %d: %s\n"), i, inputString[i].string); inputString[i].idx = 0; - // Finished with this client's message. Next loop() we'll see if there's more to read. - break; - } - } - return false; - } -#else - bool _readFromClient() { - while (client.connected() && client.available()) { - char inChar = client.read(); - if (inputString.idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) { - // if newline then command is complete - if (inChar == '\n' || inChar == '\r') { - // Add string terminator and prepare for the next message - inputString.string[inputString.idx] = 0; - debug(PSTR("Eth: %s\n"), inputString.string); - inputString.idx = 0; - if (protocolParse(_ethernetMsg, inputString.string)) { - return true; - } - - } else { - // add it to the inputString: - inputString.string[inputString.idx++] = inChar; + if (protocolParse(_ethernetMsg, inputString[i].string)) { + return true; } + } else { - // Incoming message too long. Throw away - debug(PSTR("Eth: Message too long\n")); - inputString.idx = 0; - // Finished with this client's message. Next loop() we'll see if there's more to read. - break; + // add it to the inputString: + inputString[i].string[inputString[i].idx++] = inChar; } + } else { + // Incoming message too long. Throw away + debug(PSTR("Client %d: Message too long\n"), i); + inputString[i].idx = 0; + // Finished with this client's message. Next loop() we'll see if there's more to read. + break; } - return false; } + return false; +} +#else +bool _readFromClient() +{ + while (client.connected() && client.available()) { + char inChar = client.read(); + if (inputString.idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) { + // if newline then command is complete + if (inChar == '\n' || inChar == '\r') { + // Add string terminator and prepare for the next message + inputString.string[inputString.idx] = 0; + debug(PSTR("Eth: %s\n"), inputString.string); + inputString.idx = 0; + if (protocolParse(_ethernetMsg, inputString.string)) { + return true; + } + + } else { + // add it to the inputString: + inputString.string[inputString.idx++] = inChar; + } + } else { + // Incoming message too long. Throw away + debug(PSTR("Eth: Message too long\n")); + inputString.idx = 0; + // Finished with this client's message. Next loop() we'll see if there's more to read. + break; + } + } + return false; +} #endif bool gatewayTransportAvailable() { _w5100_spi_en(true); - #if !defined(MY_IP_ADDRESS) && defined(MY_GATEWAY_W5100) - // renew IP address using DHCP - gatewayTransportRenewIP(); - #endif +#if !defined(MY_IP_ADDRESS) && defined(MY_GATEWAY_W5100) + // renew IP address using DHCP + gatewayTransportRenewIP(); +#endif - #ifdef MY_USE_UDP - int packet_size = _ethernetServer.parsePacket(); +#ifdef MY_USE_UDP + int packet_size = _ethernetServer.parsePacket(); - if (packet_size) { - //debug(PSTR("UDP packet available. Size:%d\n"), packet_size); - #if defined(MY_GATEWAY_ESP8266) - _ethernetServer.read(inputString[0].string, MY_GATEWAY_MAX_RECEIVE_LENGTH); - inputString[0].string[packet_size] = 0; - debug(PSTR("UDP packet received: %s\n"), inputString[0].string); - const bool ok = protocolParse(_ethernetMsg, inputString[0].string); - #else - _ethernetServer.read(inputString.string, MY_GATEWAY_MAX_RECEIVE_LENGTH); - inputString.string[packet_size] = 0; - debug(PSTR("UDP packet received: %s\n"), inputString.string); - _w5100_spi_en(false); - const bool ok = protocolParse(_ethernetMsg, inputString.string); - #endif - if (ok) - { - setIndication(INDICATION_GW_RX); - } - return ok; + if (packet_size) { + //debug(PSTR("UDP packet available. Size:%d\n"), packet_size); +#if defined(MY_GATEWAY_ESP8266) + _ethernetServer.read(inputString[0].string, MY_GATEWAY_MAX_RECEIVE_LENGTH); + inputString[0].string[packet_size] = 0; + debug(PSTR("UDP packet received: %s\n"), inputString[0].string); + const bool ok = protocolParse(_ethernetMsg, inputString[0].string); +#else + _ethernetServer.read(inputString.string, MY_GATEWAY_MAX_RECEIVE_LENGTH); + inputString.string[packet_size] = 0; + debug(PSTR("UDP packet received: %s\n"), inputString.string); + _w5100_spi_en(false); + const bool ok = protocolParse(_ethernetMsg, inputString.string); +#endif + if (ok) { + setIndication(INDICATION_GW_RX); } - #elif defined(MY_GATEWAY_CLIENT_MODE) - if (!client.connected()) { - client.stop(); - #if defined(MY_CONTROLLER_URL_ADDRESS) - if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) { - #else - if (client.connect(_ethernetControllerIP, MY_PORT)) { - #endif - debug(PSTR("Eth: connect\n")); - _w5100_spi_en(false); + return ok; + } +#elif defined(MY_GATEWAY_CLIENT_MODE) + if (!client.connected()) { + client.stop(); +#if defined(MY_CONTROLLER_URL_ADDRESS) + if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) { +#else + if (client.connect(_ethernetControllerIP, MY_PORT)) { +#endif + debug(PSTR("Eth: connect\n")); + _w5100_spi_en(false); + gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete.")); + _w5100_spi_en(true); + presentNode(); + } else { + debug(PSTR("Eth: Failed to connect\n")); + _w5100_spi_en(false); + return false; + } + } + if (_readFromClient()) { + setIndication(INDICATION_GW_RX); + _w5100_spi_en(false); + return true; + } +#else +#if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_LINUX) + // ESP8266: Go over list of clients and stop any that are no longer connected. + // If the server has a new client connection it will be assigned to a free slot. + bool allSlotsOccupied = true; + for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) { + if (!clients[i].connected()) { + if (clientsConnected[i]) { + debug(PSTR("Client %d disconnected\n"), i); + clients[i].stop(); + } + //check if there are any new clients + if (_ethernetServer.hasClient()) { + clients[i] = _ethernetServer.available(); + inputString[i].idx = 0; + debug(PSTR("Client %d connected\n"), i); gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete.")); - _w5100_spi_en(true); + // Send presentation of locally attached sensors (and node if applicable) presentNode(); - } else { - debug(PSTR("Eth: Failed to connect\n")); - _w5100_spi_en(false); - return false; } } - if (_readFromClient()) { + bool connected = clients[i].connected(); + clientsConnected[i] = connected; + allSlotsOccupied &= connected; + } + if (allSlotsOccupied && _ethernetServer.hasClient()) { + //no free/disconnected spot so reject + debug(PSTR("No free slot available\n")); + EthernetClient c = _ethernetServer.available(); + c.stop(); + } + // Loop over clients connect and read available data + for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) { + if (_readFromClient(i)) { setIndication(INDICATION_GW_RX); _w5100_spi_en(false); return true; } - #else - #if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_LINUX) - // ESP8266: Go over list of clients and stop any that are no longer connected. - // If the server has a new client connection it will be assigned to a free slot. - bool allSlotsOccupied = true; - for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) { - if (!clients[i].connected()) { - if (clientsConnected[i]) { - debug(PSTR("Client %d disconnected\n"), i); - clients[i].stop(); - } - //check if there are any new clients - if (_ethernetServer.hasClient()) { - clients[i] = _ethernetServer.available(); - inputString[i].idx = 0; - debug(PSTR("Client %d connected\n"), i); - gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete.")); - // Send presentation of locally attached sensors (and node if applicable) - presentNode(); - } - } - bool connected = clients[i].connected(); - clientsConnected[i] = connected; - allSlotsOccupied &= connected; + } +#else + // W5100/ENC module does not have hasClient-method. We can only serve one client at the time. + EthernetClient newclient = _ethernetServer.available(); + // if a new client connects make sure to dispose any previous existing sockets + if (newclient) { + if (client != newclient) { + client.stop(); + client = newclient; + debug(PSTR("Eth: connect\n")); + _w5100_spi_en(false); + gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete.")); + _w5100_spi_en(true); + presentNode(); + } + } + if (client) { + if (!client.connected()) { + debug(PSTR("Eth: disconnect\n")); + client.stop(); + } else { + if (_readFromClient()) { + setIndication(INDICATION_GW_RX); + _w5100_spi_en(false); + return true; } - if (allSlotsOccupied && _ethernetServer.hasClient()) { - //no free/disconnected spot so reject - debug(PSTR("No free slot available\n")); - EthernetClient c = _ethernetServer.available(); - c.stop(); - } - // Loop over clients connect and read available data - for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) { - if (_readFromClient(i)) { - setIndication(INDICATION_GW_RX); - _w5100_spi_en(false); - return true; - } - } - #else - // W5100/ENC module does not have hasClient-method. We can only serve one client at the time. - EthernetClient newclient = _ethernetServer.available(); - // if a new client connects make sure to dispose any previous existing sockets - if (newclient) { - if (client != newclient) { - client.stop(); - client = newclient; - debug(PSTR("Eth: connect\n")); - _w5100_spi_en(false); - gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete.")); - _w5100_spi_en(true); - presentNode(); - } - } - if (client) { - if (!client.connected()) { - debug(PSTR("Eth: disconnect\n")); - client.stop(); - } else { - if (_readFromClient()) { - setIndication(INDICATION_GW_RX); - _w5100_spi_en(false); - return true; - } - } - } - #endif /* MY_GATEWAY_ESP8266 */ - #endif + } + } +#endif /* MY_GATEWAY_ESP8266 */ +#endif _w5100_spi_en(false); return false; } diff --git a/core/MyGatewayTransportMQTTClient.cpp b/core/MyGatewayTransportMQTTClient.cpp index 339d1aa..dc3634c 100644 --- a/core/MyGatewayTransportMQTTClient.cpp +++ b/core/MyGatewayTransportMQTTClient.cpp @@ -23,23 +23,23 @@ #include "MyGatewayTransport.h" #if defined MY_CONTROLLER_IP_ADDRESS - IPAddress _brokerIp(MY_CONTROLLER_IP_ADDRESS); +IPAddress _brokerIp(MY_CONTROLLER_IP_ADDRESS); #endif #if defined(MY_GATEWAY_ESP8266) - #define EthernetClient WiFiClient - #if defined(MY_IP_ADDRESS) - IPAddress _gatewayIp(MY_IP_GATEWAY_ADDRESS); - IPAddress _subnetIp(MY_IP_SUBNET_ADDRESS); - #endif +#define EthernetClient WiFiClient +#if defined(MY_IP_ADDRESS) +IPAddress _gatewayIp(MY_IP_GATEWAY_ADDRESS); +IPAddress _subnetIp(MY_IP_SUBNET_ADDRESS); +#endif #elif defined(MY_GATEWAY_LINUX) - // Nothing to do here +// Nothing to do here #else - uint8_t _MQTT_clientMAC[] = { MY_MAC_ADDRESS }; +uint8_t _MQTT_clientMAC[] = { MY_MAC_ADDRESS }; #endif #if defined(MY_IP_ADDRESS) - IPAddress _MQTT_clientIp(MY_IP_ADDRESS); +IPAddress _MQTT_clientIp(MY_IP_ADDRESS); #endif static EthernetClient _MQTT_ethClient; @@ -48,7 +48,8 @@ static bool _MQTT_connecting = true; static bool _MQTT_available = false; static MyMessage _MQTT_msg; -bool gatewayTransportSend(MyMessage &message) { +bool gatewayTransportSend(MyMessage &message) +{ if (!_MQTT_client.connected()) { return false; } @@ -58,19 +59,21 @@ bool gatewayTransportSend(MyMessage &message) { return _MQTT_client.publish(topic, message.getString(_convBuffer)); } -void incomingMQTT(char* topic, uint8_t* payload, unsigned int length) { +void incomingMQTT(char* topic, uint8_t* payload, unsigned int length) +{ debug(PSTR("Message arrived on topic: %s\n"), topic); _MQTT_available = protocolMQTTParse(_MQTT_msg, topic, payload, length); } -bool reconnectMQTT() { +bool reconnectMQTT() +{ debug(PSTR("Attempting MQTT connection...\n")); // Attempt to connect if (_MQTT_client.connect(MY_MQTT_CLIENT_ID #if defined(MY_MQTT_USER) && defined(MY_MQTT_PASSWORD) - , MY_MQTT_USER, MY_MQTT_PASSWORD + , MY_MQTT_USER, MY_MQTT_PASSWORD #endif - )) { + )) { debug(PSTR("MQTT connected\n")); // Send presentation of locally attached sensors (and node if applicable) @@ -85,58 +88,60 @@ bool reconnectMQTT() { return false; } -bool gatewayTransportConnect() { - #if defined(MY_GATEWAY_ESP8266) - while (WiFi.status() != WL_CONNECTED) { - wait(500); - MY_SERIALDEVICE.print("."); - } - MY_SERIALDEVICE.print("IP: "); - MY_SERIALDEVICE.println(WiFi.localIP()); - #elif defined(MY_GATEWAY_LINUX) - #if defined(MY_IP_ADDRESS) - //TODO - #endif - #else - #ifdef MY_IP_ADDRESS - Ethernet.begin(_MQTT_clientMAC, _MQTT_clientIp); - #else - // Get IP address from DHCP - if (!Ethernet.begin(_MQTT_clientMAC)) { - MY_SERIALDEVICE.print("DHCP FAILURE..."); - _MQTT_connecting = false; - return false; - } - #endif - MY_SERIALDEVICE.print("IP: "); - MY_SERIALDEVICE.println(Ethernet.localIP()); - // give the Ethernet interface a second to initialize - delay(1000); - #endif +bool gatewayTransportConnect() +{ +#if defined(MY_GATEWAY_ESP8266) + while (WiFi.status() != WL_CONNECTED) { + wait(500); + MY_SERIALDEVICE.print("."); + } + MY_SERIALDEVICE.print("IP: "); + MY_SERIALDEVICE.println(WiFi.localIP()); +#elif defined(MY_GATEWAY_LINUX) +#if defined(MY_IP_ADDRESS) + //TODO +#endif +#else +#ifdef MY_IP_ADDRESS + Ethernet.begin(_MQTT_clientMAC, _MQTT_clientIp); +#else + // Get IP address from DHCP + if (!Ethernet.begin(_MQTT_clientMAC)) { + MY_SERIALDEVICE.print("DHCP FAILURE..."); + _MQTT_connecting = false; + return false; + } +#endif + MY_SERIALDEVICE.print("IP: "); + MY_SERIALDEVICE.println(Ethernet.localIP()); + // give the Ethernet interface a second to initialize + delay(1000); +#endif return true; } -bool gatewayTransportInit() { +bool gatewayTransportInit() +{ _MQTT_connecting = true; - #if defined(MY_CONTROLLER_IP_ADDRESS) - _MQTT_client.setServer(_brokerIp, MY_PORT); - #else - _MQTT_client.setServer(MY_CONTROLLER_URL_ADDRESS, MY_PORT); - #endif +#if defined(MY_CONTROLLER_IP_ADDRESS) + _MQTT_client.setServer(_brokerIp, MY_PORT); +#else + _MQTT_client.setServer(MY_CONTROLLER_URL_ADDRESS, MY_PORT); +#endif - _MQTT_client.setCallback(incomingMQTT); + _MQTT_client.setCallback(incomingMQTT); - #if defined(MY_GATEWAY_ESP8266) - // Turn off access point - WiFi.mode(WIFI_STA); - #if defined(MY_ESP8266_HOSTNAME) - WiFi.hostname(MY_ESP8266_HOSTNAME); - #endif - (void)WiFi.begin(MY_ESP8266_SSID, MY_ESP8266_PASSWORD); - #ifdef MY_IP_ADDRESS - WiFi.config(_MQTT_clientIp, _gatewayIp, _subnetIp); - #endif - #endif +#if defined(MY_GATEWAY_ESP8266) + // Turn off access point + WiFi.mode(WIFI_STA); +#if defined(MY_ESP8266_HOSTNAME) + WiFi.hostname(MY_ESP8266_HOSTNAME); +#endif + (void)WiFi.begin(MY_ESP8266_SSID, MY_ESP8266_PASSWORD); +#ifdef MY_IP_ADDRESS + WiFi.config(_MQTT_clientIp, _gatewayIp, _subnetIp); +#endif +#endif gatewayTransportConnect(); @@ -144,10 +149,11 @@ bool gatewayTransportInit() { return true; } -bool gatewayTransportAvailable() { +bool gatewayTransportAvailable() +{ if (_MQTT_connecting) { return false; - } + } //keep lease on dhcp address //Ethernet.maintain(); if (!_MQTT_client.connected()) { @@ -161,7 +167,8 @@ bool gatewayTransportAvailable() { return _MQTT_available; } -MyMessage & gatewayTransportReceive() { +MyMessage & gatewayTransportReceive() +{ // Return the last parsed message _MQTT_available = false; return _MQTT_msg; diff --git a/core/MyGatewayTransportSerial.cpp b/core/MyGatewayTransportSerial.cpp index 45f05e6..4528d6e 100644 --- a/core/MyGatewayTransportSerial.cpp +++ b/core/MyGatewayTransportSerial.cpp @@ -23,21 +23,23 @@ #include "MyMessage.h" #include "MyProtocol.h" - // global variables +// global variables extern MyMessage _msgTmp; char _serialInputString[MY_GATEWAY_MAX_RECEIVE_LENGTH]; // A buffer for incoming commands from serial interface uint8_t _serialInputPos; MyMessage _serialMsg; -bool gatewayTransportSend(MyMessage &message) { - setIndication(INDICATION_GW_TX); +bool gatewayTransportSend(MyMessage &message) +{ + setIndication(INDICATION_GW_TX); MY_SERIALDEVICE.print(protocolFormat(message)); // Serial print is always successful return true; } -bool gatewayTransportInit() { +bool gatewayTransportInit() +{ gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete.")); // Send presentation of locally attached sensors (and node if applicable) presentNode(); @@ -45,7 +47,8 @@ bool gatewayTransportInit() { return true; } -bool gatewayTransportAvailable() { +bool gatewayTransportAvailable() +{ while (MY_SERIALDEVICE.available()) { // get the new byte: char inChar = (char) MY_SERIALDEVICE.read(); @@ -55,11 +58,10 @@ bool gatewayTransportAvailable() { if (inChar == '\n') { _serialInputString[_serialInputPos] = 0; bool ok = protocolParse(_serialMsg, _serialInputString); - if (ok) - { - setIndication(INDICATION_GW_RX); - } - _serialInputPos = 0; + if (ok) { + setIndication(INDICATION_GW_RX); + } + _serialInputPos = 0; return ok; } else { // add it to the inputString: @@ -74,7 +76,8 @@ bool gatewayTransportAvailable() { return false; } -MyMessage & gatewayTransportReceive() { +MyMessage & gatewayTransportReceive() +{ // Return the last parsed message return _serialMsg; } diff --git a/core/MyHw.h b/core/MyHw.h index 99bfcc6..3b4cfba 100644 --- a/core/MyHw.h +++ b/core/MyHw.h @@ -17,12 +17,12 @@ * version 2 as published by the Free Software Foundation. */ - /** - * @file MyHw.h - * - * MySensors hardware abstraction layer - */ - +/** +* @file MyHw.h +* +* MySensors hardware abstraction layer +*/ + #ifndef MyHw_h #define MyHw_h @@ -76,7 +76,8 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms); * @param ms Time to sleep, in [ms]. * @return -1 when woken by timer, or interrupt number when woken by interrupt. */ -int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms); +int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, + unsigned long ms); #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG) /** @@ -102,7 +103,7 @@ uint16_t hwFreeMem(); void hwDebugPrint(const char *fmt, ... ); #endif -/** +/** * @def MY_CRITICAL_SECTION * @brief Creates a block of code that is guaranteed to be executed atomically. * Upon entering the block all interrupts are disabled, and re-enabled upon @@ -112,12 +113,12 @@ void hwDebugPrint(const char *fmt, ... ); * platform (e.g AVR): * @code * volatile uint16_t val = 0; - * + * * void interrupHandler() * { * val = ~val; * } - * + * * void loop() * { * uint16_t copy_val; @@ -131,7 +132,7 @@ void hwDebugPrint(const char *fmt, ... ); * interrupted during execution. */ #ifdef DOXYGEN - #define MY_CRITICAL_SECTION +#define MY_CRITICAL_SECTION #endif /* DOXYGEN */ #endif // #ifdef MyHw_h diff --git a/core/MyHwATMega328.cpp b/core/MyHwATMega328.cpp index 6619747..50c2e51 100644 --- a/core/MyHwATMega328.cpp +++ b/core/MyHwATMega328.cpp @@ -23,32 +23,33 @@ #define INVALID_INTERRUPT_NUM (0xFFu) -volatile uint8_t _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; // Interrupt number that woke the mcu. -volatile uint8_t _wakeUp1Interrupt = INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp1-callback. -volatile uint8_t _wakeUp2Interrupt = INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp2-callback. +volatile uint8_t _wokeUpByInterrupt = + INVALID_INTERRUPT_NUM; // Interrupt number that woke the mcu. +volatile uint8_t _wakeUp1Interrupt = + INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp1-callback. +volatile uint8_t _wakeUp2Interrupt = + INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp2-callback. void wakeUp1() //place to send the interrupts { detachInterrupt(_wakeUp1Interrupt); - if (_wakeUp2Interrupt != INVALID_INTERRUPT_NUM) - { - detachInterrupt(_wakeUp2Interrupt); - } + if (_wakeUp2Interrupt != INVALID_INTERRUPT_NUM) { + detachInterrupt(_wakeUp2Interrupt); + } _wokeUpByInterrupt = _wakeUp1Interrupt; } void wakeUp2() //place to send the second interrupts { detachInterrupt(_wakeUp2Interrupt); - if (_wakeUp1Interrupt != INVALID_INTERRUPT_NUM) - { - detachInterrupt(_wakeUp1Interrupt); - } + if (_wakeUp1Interrupt != INVALID_INTERRUPT_NUM) { + detachInterrupt(_wakeUp1Interrupt); + } _wokeUpByInterrupt = _wakeUp2Interrupt; } bool interruptWakeUp() { - return _wokeUpByInterrupt != INVALID_INTERRUPT_NUM; + return _wokeUpByInterrupt != INVALID_INTERRUPT_NUM; } // Watchdog Timer interrupt service routine. This routine is required @@ -57,13 +58,13 @@ ISR (WDT_vect) { } -void hwPowerDown(period_t period) { +void hwPowerDown(period_t period) +{ // disable ADC for power saving ADCSRA &= ~(1 << ADEN); // save WDT settings uint8_t WDTsave = WDTCSR; - if (period != SLEEP_FOREVER) - { + if (period != SLEEP_FOREVER) { wdt_enable(period); // enable WDT interrupt before system reset WDTCSR |= (1 << WDCE) | (1 << WDIE); @@ -74,14 +75,14 @@ void hwPowerDown(period_t period) { set_sleep_mode(SLEEP_MODE_PWR_DOWN); cli(); sleep_enable(); - #if defined __AVR_ATmega328P__ - sleep_bod_disable(); - #endif +#if defined __AVR_ATmega328P__ + sleep_bod_disable(); +#endif // Enable interrupts & sleep until WDT or ext. interrupt 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_disable(); + sleep_disable(); // restore previous WDT settings cli(); wdt_reset(); @@ -94,42 +95,77 @@ void hwPowerDown(period_t period) { ADCSRA |= (1 << ADEN); } -void hwInternalSleep(unsigned long ms) { +void hwInternalSleep(unsigned long ms) +{ // Let serial prints finish (debug, log etc) - #ifndef MY_DISABLED_SERIAL - MY_SERIALDEVICE.flush(); - #endif - while (!interruptWakeUp() && ms >= 8000) { hwPowerDown(SLEEP_8S); ms -= 8000; } - if (!interruptWakeUp() && ms >= 4000) { hwPowerDown(SLEEP_4S); ms -= 4000; } - if (!interruptWakeUp() && ms >= 2000) { hwPowerDown(SLEEP_2S); ms -= 2000; } - if (!interruptWakeUp() && ms >= 1000) { hwPowerDown(SLEEP_1S); ms -= 1000; } - if (!interruptWakeUp() && ms >= 500) { hwPowerDown(SLEEP_500MS); ms -= 500; } - if (!interruptWakeUp() && ms >= 250) { hwPowerDown(SLEEP_250MS); ms -= 250; } - if (!interruptWakeUp() && ms >= 125) { hwPowerDown(SLEEP_120MS); ms -= 120; } - if (!interruptWakeUp() && ms >= 64) { hwPowerDown(SLEEP_60MS); ms -= 60; } - if (!interruptWakeUp() && ms >= 32) { hwPowerDown(SLEEP_30MS); ms -= 30; } - if (!interruptWakeUp() && ms >= 16) { hwPowerDown(SLEEP_15MS); ms -= 15; } +#ifndef MY_DISABLED_SERIAL + MY_SERIALDEVICE.flush(); +#endif + while (!interruptWakeUp() && ms >= 8000) { + hwPowerDown(SLEEP_8S); + ms -= 8000; + } + if (!interruptWakeUp() && ms >= 4000) { + hwPowerDown(SLEEP_4S); + ms -= 4000; + } + if (!interruptWakeUp() && ms >= 2000) { + hwPowerDown(SLEEP_2S); + ms -= 2000; + } + if (!interruptWakeUp() && ms >= 1000) { + hwPowerDown(SLEEP_1S); + ms -= 1000; + } + if (!interruptWakeUp() && ms >= 500) { + hwPowerDown(SLEEP_500MS); + ms -= 500; + } + if (!interruptWakeUp() && ms >= 250) { + hwPowerDown(SLEEP_250MS); + ms -= 250; + } + if (!interruptWakeUp() && ms >= 125) { + hwPowerDown(SLEEP_120MS); + ms -= 120; + } + if (!interruptWakeUp() && ms >= 64) { + hwPowerDown(SLEEP_60MS); + ms -= 60; + } + if (!interruptWakeUp() && ms >= 32) { + hwPowerDown(SLEEP_30MS); + ms -= 30; + } + if (!interruptWakeUp() && ms >= 16) { + hwPowerDown(SLEEP_15MS); + ms -= 15; + } } -int8_t hwSleep(unsigned long ms) { +int8_t hwSleep(unsigned long ms) +{ hwInternalSleep(ms); return MY_WAKE_UP_BY_TIMER; } -int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { +int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) +{ return hwSleep(interrupt,mode,INVALID_INTERRUPT_NUM,0u,ms); } -int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { - // Disable interrupts until going to sleep, otherwise interrupts occurring between attachInterrupt() - // and sleep might cause the ATMega to not wakeup from sleep as interrupt has already be handled! +int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, + unsigned long ms) +{ + // Disable interrupts until going to sleep, otherwise interrupts occurring between attachInterrupt() + // and sleep might cause the ATMega to not wakeup from sleep as interrupt has already be handled! cli(); // attach interrupts - _wakeUp1Interrupt = interrupt1; - _wakeUp2Interrupt = interrupt2; - if (interrupt1 != INVALID_INTERRUPT_NUM) { - attachInterrupt(interrupt1, wakeUp1, mode1); - } + _wakeUp1Interrupt = interrupt1; + _wakeUp2Interrupt = interrupt2; + if (interrupt1 != INVALID_INTERRUPT_NUM) { + attachInterrupt(interrupt1, wakeUp1, mode1); + } if (interrupt2 != INVALID_INTERRUPT_NUM) { attachInterrupt(interrupt2, wakeUp2, mode2); } @@ -139,40 +175,41 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo hwInternalSleep(ms); } else { // sleep until ext interrupt triggered - hwPowerDown(SLEEP_FOREVER); + hwPowerDown(SLEEP_FOREVER); } - // Assure any interrupts attached, will get detached when they did not occur. - if (interrupt1 != INVALID_INTERRUPT_NUM) { - detachInterrupt(interrupt1); - } + // Assure any interrupts attached, will get detached when they did not occur. + if (interrupt1 != INVALID_INTERRUPT_NUM) { + detachInterrupt(interrupt1); + } if (interrupt2 != INVALID_INTERRUPT_NUM) { detachInterrupt(interrupt2); } - // Return what woke the mcu. - int8_t ret = MY_WAKE_UP_BY_TIMER; // default: no interrupt triggered, timer wake up - if (interruptWakeUp()) { - ret = static_cast(_wokeUpByInterrupt); - } - // Clear woke-up-by-interrupt flag, so next sleeps won't return immediately. - _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; + // Return what woke the mcu. + int8_t ret = MY_WAKE_UP_BY_TIMER; // default: no interrupt triggered, timer wake up + if (interruptWakeUp()) { + ret = static_cast(_wokeUpByInterrupt); + } + // Clear woke-up-by-interrupt flag, so next sleeps won't return immediately. + _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; return ret; } #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG) -uint16_t hwCPUVoltage() { +uint16_t hwCPUVoltage() +{ // Measure Vcc against 1.1V Vref - #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - ADMUX = (_BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1)); - #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) - ADMUX = (_BV(MUX5) | _BV(MUX0)); - #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) - ADMUX = (_BV(MUX3) | _BV(MUX2)); - #else - ADMUX = (_BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1)); - #endif +#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + ADMUX = (_BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1)); +#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) + ADMUX = (_BV(MUX5) | _BV(MUX0)); +#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) + ADMUX = (_BV(MUX3) | _BV(MUX2)); +#else + ADMUX = (_BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1)); +#endif // Vref settle delay(70); // Do conversion @@ -182,7 +219,8 @@ uint16_t hwCPUVoltage() { return (1125300UL) / ADC; } -uint16_t hwCPUFrequency() { +uint16_t hwCPUFrequency() +{ cli(); // setup timer1 TIFR1 = 0xFF; @@ -210,7 +248,8 @@ uint16_t hwCPUFrequency() { return TCNT1 * 2048UL / 100000UL; } -uint16_t hwFreeMem() { +uint16_t hwFreeMem() +{ extern int __heap_start, *__brkval; int v; return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); @@ -218,27 +257,28 @@ uint16_t hwFreeMem() { #endif #ifdef MY_DEBUG -void hwDebugPrint(const char *fmt, ... ) { +void hwDebugPrint(const char *fmt, ... ) +{ 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); - MY_SERIALDEVICE.print(fmtBuffer); - #else - // prepend timestamp (AVR nodes) - MY_SERIALDEVICE.print(hwMillis()); - MY_SERIALDEVICE.print(" "); - #endif +#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); + MY_SERIALDEVICE.print(fmtBuffer); +#else + // prepend timestamp (AVR nodes) + MY_SERIALDEVICE.print(hwMillis()); + MY_SERIALDEVICE.print(" "); +#endif va_list args; va_start (args, fmt ); - #ifdef MY_GATEWAY_FEATURE - // Truncate message if this is gateway node - 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 +#ifdef MY_GATEWAY_FEATURE + // Truncate message if this is gateway node + 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 va_end (args); MY_SERIALDEVICE.print(fmtBuffer); MY_SERIALDEVICE.flush(); diff --git a/core/MyHwATMega328.h b/core/MyHwATMega328.h index bb5962f..7be0d47 100644 --- a/core/MyHwATMega328.h +++ b/core/MyHwATMega328.h @@ -39,18 +39,18 @@ #if defined __AVR_ATmega328P__ #ifndef sleep_bod_disable #define sleep_bod_disable() \ -do { \ - unsigned char tempreg; \ - __asm__ __volatile__("in %[tempreg], %[mcucr]" "\n\t" \ - "ori %[tempreg], %[bods_bodse]" "\n\t" \ - "out %[mcucr], %[tempreg]" "\n\t" \ - "andi %[tempreg], %[not_bodse]" "\n\t" \ - "out %[mcucr], %[tempreg]" \ - : [tempreg] "=&d" (tempreg) \ - : [mcucr] "I" _SFR_IO_ADDR(MCUCR), \ - [bods_bodse] "i" (_BV(BODS) | _BV(BODSE)), \ - [not_bodse] "i" (~_BV(BODSE))); \ -} while (0) + do { \ + unsigned char tempreg; \ + __asm__ __volatile__("in %[tempreg], %[mcucr]" "\n\t" \ + "ori %[tempreg], %[bods_bodse]" "\n\t" \ + "out %[mcucr], %[tempreg]" "\n\t" \ + "andi %[tempreg], %[not_bodse]" "\n\t" \ + "out %[mcucr], %[tempreg]" \ + : [tempreg] "=&d" (tempreg) \ + : [mcucr] "I" _SFR_IO_ADDR(MCUCR), \ + [bods_bodse] "i" (_BV(BODS) | _BV(BODSE)), \ + [not_bodse] "i" (~_BV(BODSE))); \ + } while (0) #endif #endif @@ -63,9 +63,9 @@ do { \ #if defined(MY_DISABLED_SERIAL) - #define hwInit() +#define hwInit() #else - #define hwInit() MY_SERIALDEVICE.begin(MY_BAUD_RATE) +#define hwInit() MY_SERIALDEVICE.begin(MY_BAUD_RATE) #endif #define hwWatchdogReset() wdt_reset() @@ -96,7 +96,7 @@ enum period_t { void hwInternalSleep(unsigned long ms); #ifndef DOXYGEN - #define MY_CRITICAL_SECTION ATOMIC_BLOCK(ATOMIC_RESTORESTATE) +#define MY_CRITICAL_SECTION ATOMIC_BLOCK(ATOMIC_RESTORESTATE) #endif /* DOXYGEN */ #endif diff --git a/core/MyHwESP8266.cpp b/core/MyHwESP8266.cpp index c4d39d1..3985769 100644 --- a/core/MyHwESP8266.cpp +++ b/core/MyHwESP8266.cpp @@ -23,7 +23,7 @@ void hwInit(void) { #if !defined(MY_DISABLED_SERIAL) - MY_SERIALDEVICE.begin(MY_BAUD_RATE, SERIAL_8N1, MY_ESP8266_SERIAL_MODE, 1); + MY_SERIALDEVICE.begin(MY_BAUD_RATE, SERIAL_8N1, MY_ESP8266_SERIAL_MODE, 1); MY_SERIALDEVICE.setDebugOutput(true); #endif EEPROM.begin(EEPROM_size); @@ -31,12 +31,11 @@ void hwInit(void) void hwReadConfigBlock(void* buf, void* addr, size_t length) { - uint8_t* dst = static_cast(buf); - int pos = reinterpret_cast(addr); - while (length-- > 0) - { - *dst++ = EEPROM.read(pos++); - } + uint8_t* dst = static_cast(buf); + int pos = reinterpret_cast(addr); + while (length-- > 0) { + *dst++ = EEPROM.read(pos++); + } } void hwWriteConfigBlock(void* buf, void* addr, size_t length) @@ -52,9 +51,9 @@ void hwWriteConfigBlock(void* buf, void* addr, size_t length) uint8_t hwReadConfig(const int addr) { - uint8_t value; - hwReadConfigBlock(&value, reinterpret_cast(addr), 1); - return value; + uint8_t value; + hwReadConfigBlock(&value, reinterpret_cast(addr), 1); + return value; } void hwWriteConfig(const int addr, uint8_t value) @@ -63,13 +62,15 @@ void hwWriteConfig(const int addr, uint8_t value) } -int8_t hwSleep(unsigned long ms) { +int8_t hwSleep(unsigned long ms) +{ // TODO: Not supported! (void)ms; return MY_SLEEP_NOT_POSSIBLE; } -int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { +int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) +{ // TODO: Not supported! (void)interrupt; (void)mode; @@ -77,7 +78,9 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { return MY_SLEEP_NOT_POSSIBLE; } -int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { +int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, + unsigned long ms) +{ // TODO: Not supported! (void)interrupt1; (void)mode1; @@ -90,39 +93,43 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG) ADC_MODE(ADC_VCC); -uint16_t hwCPUVoltage() { +uint16_t hwCPUVoltage() +{ // in mV return ESP.getVcc(); } -uint16_t hwCPUFrequency() { +uint16_t hwCPUFrequency() +{ // in 1/10Mhz return ESP.getCpuFreqMHz()*10; } -uint16_t hwFreeMem() { +uint16_t hwFreeMem() +{ return ESP.getFreeHeap(); } #endif #ifdef MY_DEBUG -void hwDebugPrint(const char *fmt, ... ) { +void hwDebugPrint(const char *fmt, ... ) +{ 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); - MY_SERIALDEVICE.print(fmtBuffer); - #endif +#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); + MY_SERIALDEVICE.print(fmtBuffer); +#endif va_list args; va_start (args, fmt ); - #ifdef MY_GATEWAY_FEATURE - // Truncate message if this is gateway node - 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 +#ifdef MY_GATEWAY_FEATURE + // Truncate message if this is gateway node + 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 va_end (args); MY_SERIALDEVICE.print(fmtBuffer); MY_SERIALDEVICE.flush(); diff --git a/core/MyHwESP8266.h b/core/MyHwESP8266.h index f95ace0..03f6225 100644 --- a/core/MyHwESP8266.h +++ b/core/MyHwESP8266.h @@ -54,11 +54,11 @@ uint8_t hwReadConfig(const int addr); */ static __inline__ void __psRestore(const uint32_t *__s) { - xt_wsr_ps( *__s ); + xt_wsr_ps( *__s ); } - + #ifndef DOXYGEN - #define MY_CRITICAL_SECTION for ( uint32_t __psSaved __attribute__((__cleanup__(__psRestore))) = xt_rsil(15), __ToDo = 1; __ToDo ; __ToDo = 0 ) +#define MY_CRITICAL_SECTION for ( uint32_t __psSaved __attribute__((__cleanup__(__psRestore))) = xt_rsil(15), __ToDo = 1; __ToDo ; __ToDo = 0 ) #endif /* DOXYGEN */ #endif // #ifdef ARDUINO_ARCH_ESP8266 diff --git a/core/MyHwLinuxGeneric.cpp b/core/MyHwLinuxGeneric.cpp index ea7a47c..e90b596 100644 --- a/core/MyHwLinuxGeneric.cpp +++ b/core/MyHwLinuxGeneric.cpp @@ -30,12 +30,12 @@ void hwInit() { #ifdef MY_GATEWAY_SERIAL MY_SERIALDEVICE.begin(MY_BAUD_RATE); - #ifdef MY_LINUX_SERIAL_GROUPNAME - if (!MY_SERIALDEVICE.setGroupPerm(MY_LINUX_SERIAL_GROUPNAME)) { - logError("Unable to change permission for serial port device.\n"); - exit(1); - } - #endif +#ifdef MY_LINUX_SERIAL_GROUPNAME + if (!MY_SERIALDEVICE.setGroupPerm(MY_LINUX_SERIAL_GROUPNAME)) { + logError("Unable to change permission for serial port device.\n"); + exit(1); + } +#endif #endif } @@ -88,14 +88,15 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) } // Not supported! -int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) +int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, + unsigned long ms) { (void)interrupt1; (void)mode1; (void)interrupt2; (void)mode2; (void)ms; - + return MY_SLEEP_NOT_POSSIBLE; } @@ -105,13 +106,13 @@ uint16_t hwCPUVoltage() // TODO: Not supported! return 0; } - + uint16_t hwCPUFrequency() { // TODO: Not supported! return 0; } - + uint16_t hwFreeMem() { // TODO: Not supported! diff --git a/core/MyHwLinuxGeneric.h b/core/MyHwLinuxGeneric.h index 4603176..d10cd17 100644 --- a/core/MyHwLinuxGeneric.h +++ b/core/MyHwLinuxGeneric.h @@ -16,7 +16,7 @@ * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. */ - + #ifndef MyHwLinuxGeneric_h #define MyHwLinuxGeneric_h @@ -26,9 +26,9 @@ #include "SerialPort.h" #ifdef MY_IS_SERIAL_PTY - SerialPort Serial = SerialPort(MY_LINUX_SERIAL_PTY, true); +SerialPort Serial = SerialPort(MY_LINUX_SERIAL_PTY, true); #else - SerialPort Serial = SerialPort(MY_LINUX_SERIAL_PORT); +SerialPort Serial = SerialPort(MY_LINUX_SERIAL_PORT); #endif #define MY_SERIALDEVICE Serial @@ -50,38 +50,40 @@ inline void hwRandomNumberInit(); inline unsigned long hwMillis(); #ifdef MY_RF24_IRQ_PIN - static pthread_mutex_t hw_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t hw_mutex = PTHREAD_MUTEX_INITIALIZER; - static __inline__ void __hwUnlock(const uint8_t *__s) { - pthread_mutex_unlock(&hw_mutex); - (void)__s; - } +static __inline__ void __hwUnlock(const uint8_t *__s) +{ + pthread_mutex_unlock(&hw_mutex); + (void)__s; +} - static __inline__ void __hwLock() { - pthread_mutex_lock(&hw_mutex); - } +static __inline__ void __hwLock() +{ + pthread_mutex_lock(&hw_mutex); +} #endif #if defined(DOXYGEN) - #define ATOMIC_BLOCK_CLEANUP +#define ATOMIC_BLOCK_CLEANUP #elif defined(MY_RF24_IRQ_PIN) - #define ATOMIC_BLOCK_CLEANUP uint8_t __atomic_loop \ - __attribute__((__cleanup__( __hwUnlock ))) = 1 +#define ATOMIC_BLOCK_CLEANUP uint8_t __atomic_loop \ + __attribute__((__cleanup__( __hwUnlock ))) = 1 #else - #define ATOMIC_BLOCK_CLEANUP +#define ATOMIC_BLOCK_CLEANUP #endif /* DOXYGEN */ #if defined(DOXYGEN) - #define ATOMIC_BLOCK +#define ATOMIC_BLOCK #elif defined(MY_RF24_IRQ_PIN) - #define ATOMIC_BLOCK for ( ATOMIC_BLOCK_CLEANUP, __hwLock(); \ - __atomic_loop ; __atomic_loop = 0 ) +#define ATOMIC_BLOCK for ( ATOMIC_BLOCK_CLEANUP, __hwLock(); \ + __atomic_loop ; __atomic_loop = 0 ) #else - #define ATOMIC_BLOCK +#define ATOMIC_BLOCK #endif /* DOXYGEN */ #ifndef DOXYGEN - #define MY_CRITICAL_SECTION ATOMIC_BLOCK +#define MY_CRITICAL_SECTION ATOMIC_BLOCK #endif /* DOXYGEN */ #endif diff --git a/core/MyHwRPi.cpp b/core/MyHwRPi.cpp index 79c04ce..989af5f 100644 --- a/core/MyHwRPi.cpp +++ b/core/MyHwRPi.cpp @@ -29,12 +29,12 @@ void hwInit() { #ifdef MY_GATEWAY_SERIAL MY_SERIALDEVICE.begin(MY_BAUD_RATE); - #ifdef MY_LINUX_SERIAL_GROUPNAME - if (!MY_SERIALDEVICE.setGroupPerm(MY_LINUX_SERIAL_GROUPNAME)) { - logError("Unable to change permission for serial port device.\n"); - exit(1); - } - #endif +#ifdef MY_LINUX_SERIAL_GROUPNAME + if (!MY_SERIALDEVICE.setGroupPerm(MY_LINUX_SERIAL_GROUPNAME)) { + logError("Unable to change permission for serial port device.\n"); + exit(1); + } +#endif #endif } @@ -87,46 +87,47 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) } // Not supported! -int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) +int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, + unsigned long ms) { (void)interrupt1; (void)mode1; (void)interrupt2; (void)mode2; (void)ms; - + return MY_SLEEP_NOT_POSSIBLE; } #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG) - uint16_t hwCPUVoltage() - { - // TODO: Not supported! - return 0; - } - - uint16_t hwCPUFrequency() - { - // TODO: Not supported! - return 0; - } - - uint16_t hwFreeMem() - { - // TODO: Not supported! - return 0; - } +uint16_t hwCPUVoltage() +{ + // TODO: Not supported! + return 0; +} + +uint16_t hwCPUFrequency() +{ + // TODO: Not supported! + return 0; +} + +uint16_t hwFreeMem() +{ + // TODO: Not supported! + return 0; +} #endif #ifdef MY_DEBUG - void hwDebugPrint(const char *fmt, ...) - { - va_list args; +void hwDebugPrint(const char *fmt, ...) +{ + va_list args; - va_start(args, fmt); - vlogDebug(fmt, args); - va_end(args); - } + va_start(args, fmt); + vlogDebug(fmt, args); + va_end(args); +} #endif void hwDigitalWrite(uint8_t pin, uint8_t value) diff --git a/core/MyHwRPi.h b/core/MyHwRPi.h index a4f3c64..2e39d13 100644 --- a/core/MyHwRPi.h +++ b/core/MyHwRPi.h @@ -16,7 +16,7 @@ * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. */ - + #ifndef MyHwRPi_h #define MyHwRPi_h @@ -26,15 +26,18 @@ #include "log.h" #include "bcm2835.h" -class Bcm2835Init { +class Bcm2835Init +{ public: - Bcm2835Init() { + Bcm2835Init() + { if (!bcm2835_init()) { logError("Failed to initialized bcm2835.\n"); exit(1); } } - ~Bcm2835Init() { + ~Bcm2835Init() + { bcm2835_close(); } }; diff --git a/core/MyHwSAMD.cpp b/core/MyHwSAMD.cpp index 1cf3662..b5c2207 100644 --- a/core/MyHwSAMD.cpp +++ b/core/MyHwSAMD.cpp @@ -42,118 +42,125 @@ ISR (WDT_vect) -void i2c_eeprom_write_byte(unsigned int eeaddress, byte data ) { - int rdata = data; - Wire.beginTransmission(I2C_EEP_ADDRESS); - Wire.write((int)(eeaddress >> 8)); // MSB - Wire.write((int)(eeaddress & 0xFF)); // LSB - Wire.write(rdata); - Wire.endTransmission(); +void i2c_eeprom_write_byte(unsigned int eeaddress, byte data ) +{ + int rdata = data; + Wire.beginTransmission(I2C_EEP_ADDRESS); + Wire.write((int)(eeaddress >> 8)); // MSB + Wire.write((int)(eeaddress & 0xFF)); // LSB + Wire.write(rdata); + Wire.endTransmission(); } -byte i2c_eeprom_read_byte(unsigned int eeaddress ) { - byte rdata = 0xFF; - Wire.beginTransmission(I2C_EEP_ADDRESS); - Wire.write((int)(eeaddress >> 8)); // MSB - Wire.write((int)(eeaddress & 0xFF)); // LSB - Wire.endTransmission(); - Wire.requestFrom(I2C_EEP_ADDRESS,1); - if (Wire.available()) { - rdata = Wire.read(); - } - return rdata; +byte i2c_eeprom_read_byte(unsigned int eeaddress ) +{ + byte rdata = 0xFF; + Wire.beginTransmission(I2C_EEP_ADDRESS); + Wire.write((int)(eeaddress >> 8)); // MSB + Wire.write((int)(eeaddress & 0xFF)); // LSB + Wire.endTransmission(); + Wire.requestFrom(I2C_EEP_ADDRESS,1); + if (Wire.available()) { + rdata = Wire.read(); + } + return rdata; } void hwReadConfigBlock(void* buf, void* adr, size_t length) { - uint8_t* dst = static_cast(buf); - int offs = reinterpret_cast(adr); - while (length-- > 0) - { - *dst++ = i2c_eeprom_read_byte(offs++); - } + uint8_t* dst = static_cast(buf); + int offs = reinterpret_cast(adr); + while (length-- > 0) { + *dst++ = i2c_eeprom_read_byte(offs++); + } } void hwWriteConfigBlock(void* buf, void* adr, size_t length) { - uint8_t* src = static_cast(buf); - int offs = reinterpret_cast(adr); - while (length-- > 0) - { - i2c_eeprom_write_byte(offs++, *src++); - } + uint8_t* src = static_cast(buf); + int offs = reinterpret_cast(adr); + while (length-- > 0) { + i2c_eeprom_write_byte(offs++, *src++); + } } uint8_t hwReadConfig(int adr) { - uint8_t value; - hwReadConfigBlock(&value, reinterpret_cast(adr), 1); - return value; + uint8_t value; + hwReadConfigBlock(&value, reinterpret_cast(adr), 1); + return value; } void hwWriteConfig(int adr, uint8_t value) { - uint8_t curr = hwReadConfig(adr); - if (curr != value) - { - hwWriteConfigBlock(&value, reinterpret_cast(adr), 1); - } + uint8_t curr = hwReadConfig(adr); + if (curr != value) { + hwWriteConfigBlock(&value, reinterpret_cast(adr), 1); + } } -void hwInit() { - MY_SERIALDEVICE.begin(MY_BAUD_RATE); - #if defined(MY_GATEWAY_SERIAL) - while (!MY_SERIALDEVICE) {} - #endif - Wire.begin(); +void hwInit() +{ + MY_SERIALDEVICE.begin(MY_BAUD_RATE); +#if defined(MY_GATEWAY_SERIAL) + while (!MY_SERIALDEVICE) {} +#endif + Wire.begin(); } -void hwWatchdogReset() { - // TODO: Not supported! +void hwWatchdogReset() +{ + // TODO: Not supported! } -void hwReboot() { +void hwReboot() +{ NVIC_SystemReset(); while (true); } -int8_t hwSleep(unsigned long ms) { - // TODO: Not supported! - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; +int8_t hwSleep(unsigned long ms) +{ + // TODO: Not supported! + (void)ms; + return MY_SLEEP_NOT_POSSIBLE; } -int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { - // TODO: Not supported! - (void)interrupt; - (void)mode; - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; +int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) +{ + // TODO: Not supported! + (void)interrupt; + (void)mode; + (void)ms; + return MY_SLEEP_NOT_POSSIBLE; } -int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { - // TODO: Not supported! - (void)interrupt1; - (void)mode1; - (void)interrupt2; - (void)mode2; - (void)ms; - return MY_SLEEP_NOT_POSSIBLE; +int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, + unsigned long ms) +{ + // TODO: Not supported! + (void)interrupt1; + (void)mode1; + (void)interrupt2; + (void)mode2; + (void)ms; + return MY_SLEEP_NOT_POSSIBLE; } #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG) -uint16_t hwCPUVoltage() { +uint16_t hwCPUVoltage() +{ // 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 ; + ADC->INPUTCTRL.bit.MUXPOS = 0x1B ; // enable ADC while (ADC->STATUS.bit.SYNCBUSY); @@ -178,41 +185,44 @@ uint16_t hwCPUVoltage() { return valueRead * 4; } -uint16_t hwCPUFrequency() { +uint16_t hwCPUFrequency() +{ // TODO: currently reporting compile time frequency (in 1/10MHz) return F_CPU / 100000UL; } -uint16_t hwFreeMem() { +uint16_t hwFreeMem() +{ // TODO: Not supported! return 0; } #endif #ifdef MY_DEBUG -void hwDebugPrint(const char *fmt, ... ) { - if (MY_SERIALDEVICE) { - char fmtBuffer[MY_SERIAL_OUTPUT_SIZE]; - #ifdef MY_GATEWAY_FEATURE +void hwDebugPrint(const char *fmt, ... ) +{ + if (MY_SERIALDEVICE) { + 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); MY_SERIALDEVICE.print(fmtBuffer); - #endif - va_list args; - va_start (args, fmt ); - #ifdef MY_GATEWAY_FEATURE +#endif + va_list args; + va_start (args, fmt ); +#ifdef MY_GATEWAY_FEATURE // Truncate message if this is gateway node vsnprintf(fmtBuffer, sizeof(fmtBuffer), fmt, args); fmtBuffer[sizeof(fmtBuffer) - 2] = '\n'; fmtBuffer[sizeof(fmtBuffer) - 1] = '\0'; - #else +#else vsnprintf(fmtBuffer, sizeof(fmtBuffer), fmt, args); - #endif - va_end (args); - MY_SERIALDEVICE.print(fmtBuffer); -// MY_SERIALDEVICE.flush(); +#endif + va_end (args); + MY_SERIALDEVICE.print(fmtBuffer); + // MY_SERIALDEVICE.flush(); - //MY_SERIALDEVICE.write(freeRam()); - } + //MY_SERIALDEVICE.write(freeRam()); + } } #endif diff --git a/core/MyHwSAMD.h b/core/MyHwSAMD.h index 7d23e07..f8ce6ee 100644 --- a/core/MyHwSAMD.h +++ b/core/MyHwSAMD.h @@ -59,21 +59,21 @@ uint8_t hwReadConfig(int adr); */ static __inline__ uint8_t __disableIntsRetVal(void) { - __disable_irq(); - return 1; + __disable_irq(); + return 1; } - -/** + +/** * Restore priority mask register. * Helper function for MY_CRITICAL_SECTION. */ static __inline__ void __priMaskRestore(const uint32_t *priMask) { - __set_PRIMASK(*priMask); + __set_PRIMASK(*priMask); } #ifndef DOXYGEN - #define MY_CRITICAL_SECTION for ( uint32_t __savePriMask __attribute__((__cleanup__(__priMaskRestore))) = __get_PRIMASK(), __ToDo = __disableIntsRetVal(); __ToDo ; __ToDo = 0 ) +#define MY_CRITICAL_SECTION for ( uint32_t __savePriMask __attribute__((__cleanup__(__priMaskRestore))) = __get_PRIMASK(), __ToDo = __disableIntsRetVal(); __ToDo ; __ToDo = 0 ) #endif /* DOXYGEN */ #endif // #ifdef ARDUINO_ARCH_SAMD diff --git a/core/MyInclusionMode.cpp b/core/MyInclusionMode.cpp index c9dbfa6..a3a2319 100644 --- a/core/MyInclusionMode.cpp +++ b/core/MyInclusionMode.cpp @@ -19,41 +19,44 @@ #include "MyInclusionMode.h" - // global variables +// global variables extern MyMessage _msgTmp; unsigned long _inclusionStartTime; bool _inclusionMode; -inline void inclusionInit() { +inline void inclusionInit() +{ _inclusionMode = false; - #if defined(MY_INCLUSION_BUTTON_FEATURE) - // Setup digital in that triggers inclusion mode - hwPinMode(MY_INCLUSION_MODE_BUTTON_PIN, INPUT); - hwDigitalWrite(MY_INCLUSION_MODE_BUTTON_PIN, HIGH); - #endif +#if defined(MY_INCLUSION_BUTTON_FEATURE) + // Setup digital in that triggers inclusion mode + hwPinMode(MY_INCLUSION_MODE_BUTTON_PIN, INPUT); + hwDigitalWrite(MY_INCLUSION_MODE_BUTTON_PIN, HIGH); +#endif } -void inclusionModeSet(bool newMode) { - if (newMode != _inclusionMode) { - _inclusionMode = newMode; - // Send back mode change to controller - gatewayTransportSend(buildGw(_msgTmp, I_INCLUSION_MODE).set((uint8_t)(_inclusionMode?1:0))); - if (_inclusionMode) { - _inclusionStartTime = hwMillis(); - } - } +void inclusionModeSet(bool newMode) +{ + if (newMode != _inclusionMode) { + _inclusionMode = newMode; + // Send back mode change to controller + gatewayTransportSend(buildGw(_msgTmp, I_INCLUSION_MODE).set((uint8_t)(_inclusionMode?1:0))); + if (_inclusionMode) { + _inclusionStartTime = hwMillis(); + } + } } -inline void inclusionProcess() { - #ifdef MY_INCLUSION_BUTTON_FEATURE +inline void inclusionProcess() +{ +#ifdef MY_INCLUSION_BUTTON_FEATURE if (!_inclusionMode && hwDigitalRead(MY_INCLUSION_MODE_BUTTON_PIN) == MY_INCLUSION_BUTTON_PRESSED) { // Start inclusion mode inclusionModeSet(true); } - #endif +#endif if (_inclusionMode && hwMillis()-_inclusionStartTime>MY_INCLUSION_MODE_DURATION*1000L) { // inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode diff --git a/core/MyIndication.cpp b/core/MyIndication.cpp index 9447823..72faa22 100644 --- a/core/MyIndication.cpp +++ b/core/MyIndication.cpp @@ -25,25 +25,22 @@ void setIndication( const indication_t ind ) { #if defined(MY_DEFAULT_TX_LED_PIN) - if ((INDICATION_TX == ind) || (INDICATION_GW_TX == ind)) - { - ledsBlinkTx(1); - } else + if ((INDICATION_TX == ind) || (INDICATION_GW_TX == ind)) { + ledsBlinkTx(1); + } else #endif #if defined(MY_DEFAULT_RX_LED_PIN) - if ((INDICATION_RX == ind) || (INDICATION_GW_RX == ind)) - { - ledsBlinkRx(1); - } else + if ((INDICATION_RX == ind) || (INDICATION_GW_RX == ind)) { + ledsBlinkRx(1); + } else #endif #if defined(MY_DEFAULT_ERR_LED_PIN) - if (ind > INDICATION_ERR_START) - { - // Number of blinks indicates which error occurred. - ledsBlinkErr(ind-INDICATION_ERR_START); - } + if (ind > INDICATION_ERR_START) { + // Number of blinks indicates which error occurred. + ledsBlinkErr(ind-INDICATION_ERR_START); + } #endif - if (indication) { - indication(ind); - } + if (indication) { + indication(ind); + } } diff --git a/core/MyIndication.h b/core/MyIndication.h index 7e9cd07..0e2f8ea 100644 --- a/core/MyIndication.h +++ b/core/MyIndication.h @@ -24,44 +24,44 @@ * Indication type */ typedef enum { - INDICATION_TX = 0, //!< Sent a message. - INDICATION_RX, //!< Received a message. - - INDICATION_GW_TX, //!< Gateway transmit message. - INDICATION_GW_RX, //!< Gateway receive message. - - INDICATION_FIND_PARENT, //!< Start finding parent node. - INDICATION_GOT_PARENT, //!< Found parent node. - INDICATION_REQ_NODEID, //!< Request node ID. - INDICATION_GOT_NODEID, //!< Got a node ID. - INDICATION_CHECK_UPLINK, //!< Check uplink - INDICATION_REQ_REGISTRATION, //!< Request node registration. - INDICATION_GOT_REGISTRATION, //!< Got registration reponse. - INDICATION_REBOOT, //!< Rebooting node. - INDICATION_PRESENT, //!< Presenting node to gateway. - INDICATION_CLEAR_ROUTING, //!< Clear routing table requested. - INDICATION_SLEEP, //!< Node goes to sleep. - INDICATION_WAKEUP, //!< Node just woke from sleep. - INDICATION_FW_UPDATE_START, //!< Start of OTA firmware update process. - INDICATION_FW_UPDATE_RX, //!< Received a piece of firmware data. + INDICATION_TX = 0, //!< Sent a message. + INDICATION_RX, //!< Received a message. - INDICATION_ERR_START = 100, - INDICATION_ERR_TX, //!< Failed to transmit message. + INDICATION_GW_TX, //!< Gateway transmit message. + INDICATION_GW_RX, //!< Gateway receive message. + + INDICATION_FIND_PARENT, //!< Start finding parent node. + INDICATION_GOT_PARENT, //!< Found parent node. + INDICATION_REQ_NODEID, //!< Request node ID. + INDICATION_GOT_NODEID, //!< Got a node ID. + INDICATION_CHECK_UPLINK, //!< Check uplink + INDICATION_REQ_REGISTRATION, //!< Request node registration. + INDICATION_GOT_REGISTRATION, //!< Got registration reponse. + INDICATION_REBOOT, //!< Rebooting node. + INDICATION_PRESENT, //!< Presenting node to gateway. + INDICATION_CLEAR_ROUTING, //!< Clear routing table requested. + INDICATION_SLEEP, //!< Node goes to sleep. + INDICATION_WAKEUP, //!< Node just woke from sleep. + INDICATION_FW_UPDATE_START, //!< Start of OTA firmware update process. + INDICATION_FW_UPDATE_RX, //!< Received a piece of firmware data. + + INDICATION_ERR_START = 100, + INDICATION_ERR_TX, //!< Failed to transmit message. INDICATION_ERR_TRANSPORT_FAILURE, //!< Transport failure. - INDICATION_ERR_INIT_TRANSPORT, //!< MySensors transport hardware (radio) init failure. - INDICATION_ERR_FIND_PARENT, //!< Failed to find parent node. - INDICATION_ERR_GET_NODEID, //!< Failed to receive node ID. + INDICATION_ERR_INIT_TRANSPORT, //!< MySensors transport hardware (radio) init failure. + INDICATION_ERR_FIND_PARENT, //!< Failed to find parent node. + INDICATION_ERR_GET_NODEID, //!< Failed to receive node ID. INDICATION_ERR_CHECK_UPLINK, //!< Failed to check uplink - INDICATION_ERR_SIGN, //!< Error signing. + INDICATION_ERR_SIGN, //!< Error signing. INDICATION_ERR_LENGTH, //!< Invalid message length. - INDICATION_ERR_VERSION, //!< Protocol version mismatch. - INDICATION_ERR_NET_FULL, //!< Network full. All node ID's are taken. - INDICATION_ERR_INIT_GWTRANSPORT, //!< Gateway transport hardware init failure. - INDICATION_ERR_LOCKED, //!< Node is locked. - INDICATION_ERR_FW_FLASH_INIT, //!< Firmware update flash initialisation failure. - INDICATION_ERR_FW_TIMEOUT, //!< Firmware update timeout. - INDICATION_ERR_FW_CHECKSUM, //!< Firmware update checksum mismatch. - INDICATION_ERR_END + INDICATION_ERR_VERSION, //!< Protocol version mismatch. + INDICATION_ERR_NET_FULL, //!< Network full. All node ID's are taken. + INDICATION_ERR_INIT_GWTRANSPORT, //!< Gateway transport hardware init failure. + INDICATION_ERR_LOCKED, //!< Node is locked. + INDICATION_ERR_FW_FLASH_INIT, //!< Firmware update flash initialisation failure. + INDICATION_ERR_FW_TIMEOUT, //!< Firmware update timeout. + INDICATION_ERR_FW_CHECKSUM, //!< Firmware update checksum mismatch. + INDICATION_ERR_END } indication_t; /** diff --git a/core/MyLeds.cpp b/core/MyLeds.cpp index 3138be3..f27f718 100644 --- a/core/MyLeds.cpp +++ b/core/MyLeds.cpp @@ -34,22 +34,24 @@ inline void ledsInit() countRx = 0; countTx = 0; countErr = 0; - + // Setup led pins - #if defined(MY_DEFAULT_RX_LED_PIN) - hwPinMode(MY_DEFAULT_RX_LED_PIN, OUTPUT); - #endif - #if defined(MY_DEFAULT_TX_LED_PIN) - hwPinMode(MY_DEFAULT_TX_LED_PIN, OUTPUT); - #endif - #if defined(MY_DEFAULT_ERR_LED_PIN) - hwPinMode(MY_DEFAULT_ERR_LED_PIN, OUTPUT); - #endif - prevTime = hwMillis() - LED_PROCESS_INTERVAL_MS; // Substract some, to make sure leds gets updated on first run. +#if defined(MY_DEFAULT_RX_LED_PIN) + hwPinMode(MY_DEFAULT_RX_LED_PIN, OUTPUT); +#endif +#if defined(MY_DEFAULT_TX_LED_PIN) + hwPinMode(MY_DEFAULT_TX_LED_PIN, OUTPUT); +#endif +#if defined(MY_DEFAULT_ERR_LED_PIN) + hwPinMode(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() { +void ledsProcess() +{ // Just return if it is not the time... if ((hwMillis() - prevTime) < LED_PROCESS_INTERVAL_MS) { return; @@ -60,52 +62,56 @@ void ledsProcess() { // 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; - } - state = (countRx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; - hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, state); - #endif +#if defined(MY_DEFAULT_RX_LED_PIN) + if (countRx) { + --countRx; + } + 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) - if (countTx) { - --countTx; - } - state = (countTx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; - hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, state); - #endif +#if defined(MY_DEFAULT_TX_LED_PIN) + if (countTx) { + --countTx; + } + 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) - if (countErr) { - --countErr; - } - state = (countErr & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; - hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, state); - #endif +#if defined(MY_DEFAULT_ERR_LED_PIN) + if (countErr) { + --countErr; + } + state = (countErr & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; + hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, state); +#endif } -void ledsBlinkRx(uint8_t cnt) { +void ledsBlinkRx(uint8_t cnt) +{ if (!countRx) { countRx = cnt*LED_ON_OFF_RATIO; } ledsProcess(); } -void ledsBlinkTx(uint8_t cnt) { +void ledsBlinkTx(uint8_t cnt) +{ if(!countTx) { countTx = cnt*LED_ON_OFF_RATIO; } ledsProcess(); } -void ledsBlinkErr(uint8_t cnt) { +void ledsBlinkErr(uint8_t cnt) +{ if(!countErr) { countErr = cnt*LED_ON_OFF_RATIO; } ledsProcess(); } -bool ledsBlinking() { +bool ledsBlinking() +{ return countRx || countTx || countErr; } diff --git a/core/MyLeds.h b/core/MyLeds.h index e0fb121..ab78ab2 100644 --- a/core/MyLeds.h +++ b/core/MyLeds.h @@ -30,30 +30,30 @@ #endif #if defined(MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) - #define ledBlinkTx(x,...) ledsBlinkTx(x) - #define ledBlinkRx(x,...) ledsBlinkRx(x) - #define ledBlinkErr(x,...) ledsBlinkErr(x) +#define ledBlinkTx(x,...) ledsBlinkTx(x) +#define ledBlinkRx(x,...) ledsBlinkRx(x) +#define ledBlinkErr(x,...) ledsBlinkErr(x) - /** - * Blink with LEDs - * @param cnt how many blink cycles to keep the LED on. Default cycle is 300ms - */ - void ledsInit(); - void ledsBlinkRx(uint8_t cnt); - 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(); +/** + * Blink with LEDs + * @param cnt how many blink cycles to keep the LED on. Default cycle is 300ms + */ +void ledsInit(); +void ledsBlinkRx(uint8_t cnt); +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 - #define ledBlinkTx(x,...) - #define ledBlinkRx(x,...) - #define ledBlinkErr(x,...) +// Remove led functions if feature is disabled +#define ledBlinkTx(x,...) +#define ledBlinkRx(x,...) +#define ledBlinkErr(x,...) #endif #endif diff --git a/core/MyMainDefault.cpp b/core/MyMainDefault.cpp index c4aa0e6..0e006fd 100644 --- a/core/MyMainDefault.cpp +++ b/core/MyMainDefault.cpp @@ -16,20 +16,21 @@ * 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 extern "C" void __libc_init_array(void); -int main(void) { +int main(void) +{ init(); - #if defined(USBCON) - #if defined(ARDUINO_ARCH_SAMD) - __libc_init_array(); - USBDevice.init(); - #endif - USBDevice.attach(); - #endif +#if defined(USBCON) +#if defined(ARDUINO_ARCH_SAMD) + __libc_init_array(); + USBDevice.init(); +#endif + USBDevice.attach(); +#endif _begin(); // Startup MySensors library for(;;) { diff --git a/core/MyMainESP8266.cpp b/core/MyMainESP8266.cpp index 2b76eec..608a60f 100644 --- a/core/MyMainESP8266.cpp +++ b/core/MyMainESP8266.cpp @@ -16,7 +16,7 @@ * 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: //#define CONT_STACKSIZE 4096 #include "Schedule.h" @@ -38,27 +38,31 @@ extern "C" { struct rst_info resetInfo; extern "C" { - extern const uint32_t __attribute__((section(".ver_number"))) core_version = ARDUINO_ESP8266_GIT_VER; + extern const uint32_t __attribute__((section(".ver_number"))) core_version = + ARDUINO_ESP8266_GIT_VER; const char* core_release = #ifdef ARDUINO_ESP8266_RELEASE - ARDUINO_ESP8266_RELEASE; + ARDUINO_ESP8266_RELEASE; #else - NULL; + NULL; #endif } // extern "C" -int atexit(void(*func)()) { +int atexit(void(*func)()) +{ (void)func; return 0; } extern "C" void ets_update_cpu_frequency(int freqmhz); void initVariant() __attribute__((weak)); -void initVariant() { +void initVariant() +{ } void preloop_update_frequency() __attribute__((weak)); -void preloop_update_frequency() { +void preloop_update_frequency() +{ #if defined(F_CPU) && (F_CPU == 160000000L) REG_SET_BIT(0x3ff00014, BIT(0)); ets_update_cpu_frequency(160); @@ -73,37 +77,40 @@ static os_event_t g_loop_queue[LOOP_QUEUE_SIZE]; static uint32_t g_micros_at_task_start; -extern "C" void esp_yield() { +extern "C" void esp_yield() +{ if (cont_can_yield(&g_cont)) { cont_yield(&g_cont); } } -extern "C" void esp_schedule() { +extern "C" void esp_schedule() +{ ets_post(LOOP_TASK_PRIORITY, 0, 0); } -extern "C" void __yield() { +extern "C" void __yield() +{ if (cont_can_yield(&g_cont)) { esp_schedule(); esp_yield(); - } - else { + } else { panic(); } } extern "C" void yield(void) __attribute__((weak, alias("__yield"))); -extern "C" void optimistic_yield(uint32_t interval_us) { +extern "C" void optimistic_yield(uint32_t interval_us) +{ if (cont_can_yield(&g_cont) && - (system_get_time() - g_micros_at_task_start) > interval_us) - { + (system_get_time() - g_micros_at_task_start) > interval_us) { yield(); } } -static void loop_wrapper() { +static void loop_wrapper() +{ static bool setup_done = false; preloop_update_frequency(); if (!setup_done) { @@ -116,7 +123,8 @@ static void loop_wrapper() { esp_schedule(); } -static void loop_task(os_event_t *events) { +static void loop_task(os_event_t *events) +{ (void)events; g_micros_at_task_start = system_get_time(); cont_run(&g_cont, &loop_wrapper); @@ -125,7 +133,8 @@ static void loop_task(os_event_t *events) { } } -static void do_global_ctors(void) { +static void do_global_ctors(void) +{ void(**p)(void) = &__init_array_end; while (p != &__init_array_start) { (*--p)(); @@ -138,7 +147,8 @@ extern "C" void gdb_init(void) __attribute__((weak, alias("__gdb_init"))); extern "C" void __gdb_do_break() {} extern "C" void gdb_do_break(void) __attribute__((weak, alias("__gdb_do_break"))); -void init_done() { +void init_done() +{ system_set_os_print(1); gdb_init(); do_global_ctors(); @@ -146,7 +156,8 @@ void init_done() { } -extern "C" void user_init(void) { +extern "C" void user_init(void) +{ struct rst_info *rtc_info_ptr = system_get_rst_info(); memcpy((void *)&resetInfo, (void *)rtc_info_ptr, sizeof(resetInfo)); @@ -159,8 +170,8 @@ extern "C" void user_init(void) { cont_init(&g_cont); ets_task(loop_task, - LOOP_TASK_PRIORITY, g_loop_queue, - LOOP_QUEUE_SIZE); + LOOP_TASK_PRIORITY, g_loop_queue, + LOOP_QUEUE_SIZE); system_init_done_cb(&init_done); } diff --git a/core/MyMainLinux.cpp b/core/MyMainLinux.cpp index 7c4ec6b..5e875ec 100644 --- a/core/MyMainLinux.cpp +++ b/core/MyMainLinux.cpp @@ -16,7 +16,7 @@ * 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 #include #include @@ -40,13 +40,13 @@ void handle_sigint(int sig) return; } - #ifdef MY_RF24_IRQ_PIN - detachInterrupt(MY_RF24_IRQ_PIN); - #endif +#ifdef MY_RF24_IRQ_PIN + detachInterrupt(MY_RF24_IRQ_PIN); +#endif - #if defined(MY_GATEWAY_SERIAL) - MY_SERIALDEVICE.end(); - #endif +#if defined(MY_GATEWAY_SERIAL) + MY_SERIALDEVICE.end(); +#endif closelog(); @@ -103,19 +103,19 @@ static int daemonize(void) void print_usage() { printf("Usage: mysgw [options]\n\n" \ - "Options:\n" \ - " -h, --help Display a short summary of all program options.\n" \ - " -d, --debug Enable debug.\n" \ - " -b, --background Run as a background process.\n" - " --gen-soft-hmac-key Generate and print a soft hmac key.\n" - " --gen-soft-serial-key Generate and print a soft serial key.\n" - " --gen-aes-key Generate and print an aes encryption key.\n" - " --print-soft-hmac-key Print the soft hmac key from the config file.\n" - " --print-soft-serial-key Print the soft serial key from the config file.\n" - " --print-aes-key Print the aes encryption key from the config file.\n" - " --set-soft-hmac-key Write a soft hmac key to the config file.\n" - " --set-soft-serial-key Write a soft serial key to the config file.\n" - " --set-aes-key Write an aes encryption key to the config file.\n"); + "Options:\n" \ + " -h, --help Display a short summary of all program options.\n" \ + " -d, --debug Enable debug.\n" \ + " -b, --background Run as a background process.\n" + " --gen-soft-hmac-key Generate and print a soft hmac key.\n" + " --gen-soft-serial-key Generate and print a soft serial key.\n" + " --gen-aes-key Generate and print an aes encryption key.\n" + " --print-soft-hmac-key Print the soft hmac key from the config file.\n" + " --print-soft-serial-key Print the soft serial key from the config file.\n" + " --print-aes-key Print the aes encryption key from the config file.\n" + " --set-soft-hmac-key Write a soft hmac key to the config file.\n" + " --set-soft-serial-key Write a soft serial key to the config file.\n" + " --set-aes-key Write an aes encryption key to the config file.\n"); } void print_soft_sign_hmac_key(uint8_t *key_ptr = NULL) @@ -137,7 +137,9 @@ void print_soft_sign_hmac_key(uint8_t *key_ptr = NULL) printf("#define MY_SOFT_HMAC_KEY "); for (int i=0; i<32; i++) { printf("%#02X", key_ptr[i]); - if (i < 31) printf(","); + if (i < 31) { + printf(","); + } } printf("\n\n"); } @@ -155,7 +157,7 @@ void generate_soft_sign_hmac_key() print_soft_sign_hmac_key(key); printf("To use this key, run mysgw with:\n" - " --set-soft-hmac-key="); + " --set-soft-hmac-key="); for (int i = 0; i < 32; i++) { printf("%02X", key[i]); } @@ -172,12 +174,13 @@ void set_soft_sign_hmac_key(char *key_str) } else { for (int i = 0; i < 64; ++i) { char c = key_str[i]; - if (c <= '9') + if (c <= '9') { n = c - '0'; - else if (c >= 'a') + } else if (c >= 'a') { n = c - 'a' + 10; - else + } else { n = c - 'A' + 10; + } if ((i & 0x1) == 0) { key[i/2] = n * 16; @@ -209,7 +212,9 @@ void print_soft_sign_serial_key(uint8_t *key_ptr = NULL) printf("#define MY_SOFT_SERIAL "); for (int i=0; i<9; i++) { printf("%#02X", key_ptr[i]); - if (i < 8) printf(","); + if (i < 8) { + printf(","); + } } printf("\n\n"); } @@ -227,7 +232,7 @@ void generate_soft_sign_serial_key() print_soft_sign_serial_key(key); printf("To use this key, run mysgw with:\n" - " --set-soft-serial-key="); + " --set-soft-serial-key="); for (int i = 0; i < 9; i++) { printf("%02X", key[i]); } @@ -244,12 +249,13 @@ void set_soft_sign_serial_key(char *key_str) } else { for (int i = 0; i < 18; ++i) { char c = key_str[i]; - if (c <= '9') + if (c <= '9') { n = c - '0'; - else if (c >= 'a') + } else if (c >= 'a') { n = c - 'a' + 10; - else + } else { n = c - 'A' + 10; + } if ((i & 0x1) == 0) { key[i/2] = n * 16; @@ -281,7 +287,9 @@ void print_aes_key(uint8_t *key_ptr = NULL) printf("#define MY_AES_KEY "); for (int i=0; i<16; i++) { printf("%#02X", key_ptr[i]); - if (i < 15) printf(","); + if (i < 15) { + printf(","); + } } printf("\n\n"); } @@ -299,7 +307,7 @@ void generate_aes_key() print_aes_key(key); printf("To use this key, run mysgw with:\n" - " --set-aes-key="); + " --set-aes-key="); for (int i = 0; i < 16; i++) { printf("%02X", key[i]); } @@ -316,12 +324,13 @@ void set_aes_key(char *key_str) } else { for (int i = 0; i < 32; ++i) { char c = key_str[i]; - if (c <= '9') + if (c <= '9') { n = c - '0'; - else if (c >= 'a') + } else if (c >= 'a') { n = c - 'a' + 10; - else + } else { n = c - 'A' + 10; + } if ((i & 0x1) == 0) { key[i/2] = n * 16; @@ -364,48 +373,48 @@ int main(int argc, char *argv[]) int long_index = 0; while ((opt = getopt_long(argc, argv,"hdbABCDEFGHI", long_options, &long_index )) != -1) { switch (opt) { - case 'h': - print_usage(); - exit(0); - case 'd': - debug = 1; - break; - case 'b': - foreground = 0; - break; - case 'A': - generate_soft_sign_hmac_key(); - exit(0); - case 'B': - generate_soft_sign_serial_key(); - exit(0); - case 'C': - generate_aes_key(); - exit(0); - case 'D': - print_soft_sign_hmac_key(); - exit(0); - case 'E': - print_soft_sign_serial_key(); - exit(0); - case 'F': - print_aes_key(); - exit(0); - case 'G': - key = strdup(optarg); - set_soft_sign_hmac_key(key); - exit(0); - case 'H': - key = strdup(optarg); - set_soft_sign_serial_key(key); - exit(0); - case 'I': - key = strdup(optarg); - set_aes_key(key); - exit(0); - default: - print_usage(); - exit(0); + case 'h': + print_usage(); + exit(0); + case 'd': + debug = 1; + break; + case 'b': + foreground = 0; + break; + case 'A': + generate_soft_sign_hmac_key(); + exit(0); + case 'B': + generate_soft_sign_serial_key(); + exit(0); + case 'C': + generate_aes_key(); + exit(0); + case 'D': + print_soft_sign_hmac_key(); + exit(0); + case 'E': + print_soft_sign_serial_key(); + exit(0); + case 'F': + print_aes_key(); + exit(0); + case 'G': + key = strdup(optarg); + set_soft_sign_hmac_key(key); + exit(0); + case 'H': + key = strdup(optarg); + set_soft_sign_serial_key(key); + exit(0); + case 'I': + key = strdup(optarg); + set_aes_key(key); + exit(0); + default: + print_usage(); + exit(0); } } diff --git a/core/MyMessage.cpp b/core/MyMessage.cpp index bce0ae8..c5baf51 100644 --- a/core/MyMessage.cpp +++ b/core/MyMessage.cpp @@ -25,45 +25,49 @@ MyMessage::MyMessage() { - clear(); + clear(); } MyMessage::MyMessage(uint8_t _sensor, uint8_t _type) { - clear(); + clear(); sensor = _sensor; type = _type; } void MyMessage::clear() { - last = 0u; - sender = 0u; + last = 0u; + sender = 0u; destination = 0u; // Gateway is default destination - version_length = 0u; - command_ack_payload = 0u; - type = 0u; - sensor = 0u; - (void)memset(data, 0u, sizeof(data)); + version_length = 0u; + command_ack_payload = 0u; + type = 0u; + sensor = 0u; + (void)memset(data, 0u, sizeof(data)); // set message protocol version miSetVersion(PROTOCOL_VERSION); } -bool MyMessage::isAck() const { +bool MyMessage::isAck() const +{ return miGetAck(); } -uint8_t MyMessage::getCommand() const { +uint8_t MyMessage::getCommand() const +{ return miGetCommand(); } /* Getters for payload converted to desired form */ -void* MyMessage::getCustom() const { +void* MyMessage::getCustom() const +{ return (void *)data; } -const char* MyMessage::getString() const { +const char* MyMessage::getString() const +{ uint8_t payloadType = miGetPayloadType(); if (payloadType == P_STRING) { return data; @@ -73,19 +77,19 @@ const char* MyMessage::getString() const { } // 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; if (k <= 9) { return '0' + k; - } - else { + } else { return 'A' + k - 10; - } + } } -char* MyMessage::getCustomString(char *buffer) const { - for (uint8_t i = 0; i < miGetLength(); i++) - { +char* MyMessage::getCustomString(char *buffer) const +{ + for (uint8_t i = 0; i < miGetLength(); i++) { buffer[i * 2] = i2h(data[i] >> 4); buffer[(i * 2) + 1] = i2h(data[i]); } @@ -93,7 +97,8 @@ char* MyMessage::getCustomString(char *buffer) const { return buffer; } -char* MyMessage::getStream(char *buffer) const { +char* MyMessage::getStream(char *buffer) const +{ uint8_t cmd = miGetCommand(); if ((cmd == C_STREAM) && (buffer != NULL)) { return getCustomString(buffer); @@ -102,7 +107,8 @@ char* MyMessage::getStream(char *buffer) const { } } -char* MyMessage::getString(char *buffer) const { +char* MyMessage::getString(char *buffer) const +{ uint8_t payloadType = miGetPayloadType(); if (buffer != NULL) { if (payloadType == P_STRING) { @@ -129,11 +135,13 @@ char* MyMessage::getString(char *buffer) const { } } -bool MyMessage::getBool() const { +bool MyMessage::getBool() const +{ return getByte(); } -uint8_t MyMessage::getByte() const { +uint8_t MyMessage::getByte() const +{ if (miGetPayloadType() == P_BYTE) { return data[0]; } else if (miGetPayloadType() == P_STRING) { @@ -144,7 +152,8 @@ uint8_t MyMessage::getByte() const { } -float MyMessage::getFloat() const { +float MyMessage::getFloat() const +{ if (miGetPayloadType() == P_FLOAT32) { return fValue; } else if (miGetPayloadType() == P_STRING) { @@ -154,7 +163,8 @@ float MyMessage::getFloat() const { } } -int32_t MyMessage::getLong() const { +int32_t MyMessage::getLong() const +{ if (miGetPayloadType() == P_LONG32) { return lValue; } else if (miGetPayloadType() == P_STRING) { @@ -164,7 +174,8 @@ int32_t MyMessage::getLong() const { } } -uint32_t MyMessage::getULong() const { +uint32_t MyMessage::getULong() const +{ if (miGetPayloadType() == P_ULONG32) { return ulValue; } else if (miGetPayloadType() == P_STRING) { @@ -174,7 +185,8 @@ uint32_t MyMessage::getULong() const { } } -int16_t MyMessage::getInt() const { +int16_t MyMessage::getInt() const +{ if (miGetPayloadType() == P_INT16) { return iValue; } else if (miGetPayloadType() == P_STRING) { @@ -184,7 +196,8 @@ int16_t MyMessage::getInt() const { } } -uint16_t MyMessage::getUInt() const { +uint16_t MyMessage::getUInt() const +{ if (miGetPayloadType() == P_UINT16) { return uiValue; } else if (miGetPayloadType() == P_STRING) { @@ -195,23 +208,27 @@ uint16_t MyMessage::getUInt() const { } -MyMessage& MyMessage::setType(uint8_t _type) { +MyMessage& MyMessage::setType(uint8_t _type) +{ type = _type; return *this; } -MyMessage& MyMessage::setSensor(uint8_t _sensor) { +MyMessage& MyMessage::setSensor(uint8_t _sensor) +{ sensor = _sensor; return *this; } -MyMessage& MyMessage::setDestination(uint8_t _destination) { +MyMessage& MyMessage::setDestination(uint8_t _destination) +{ destination = _destination; return *this; } // 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); miSetLength(payloadLength); miSetPayloadType(P_CUSTOM); @@ -219,7 +236,8 @@ MyMessage& MyMessage::set(void* value, uint8_t length) { return *this; } -MyMessage& MyMessage::set(const char* value) { +MyMessage& MyMessage::set(const char* value) +{ uint8_t length = value == NULL ? 0 : min(strlen(value), (size_t)MAX_PAYLOAD); miSetLength(length); miSetPayloadType(P_STRING); @@ -231,21 +249,24 @@ MyMessage& MyMessage::set(const char* value) { return *this; } -MyMessage& MyMessage::set(bool value) { +MyMessage& MyMessage::set(bool value) +{ miSetLength(1); miSetPayloadType(P_BYTE); data[0] = value; return *this; } -MyMessage& MyMessage::set(uint8_t value) { +MyMessage& MyMessage::set(uint8_t value) +{ miSetLength(1); miSetPayloadType(P_BYTE); data[0] = value; return *this; } -MyMessage& MyMessage::set(float value, uint8_t decimals) { +MyMessage& MyMessage::set(float value, uint8_t decimals) +{ miSetLength(5); // 32 bit float + persi miSetPayloadType(P_FLOAT32); fValue=value; @@ -253,28 +274,32 @@ MyMessage& MyMessage::set(float value, uint8_t decimals) { return *this; } -MyMessage& MyMessage::set(uint32_t value) { +MyMessage& MyMessage::set(uint32_t value) +{ miSetPayloadType(P_ULONG32); miSetLength(4); ulValue = value; return *this; } -MyMessage& MyMessage::set(int32_t value) { +MyMessage& MyMessage::set(int32_t value) +{ miSetPayloadType(P_LONG32); miSetLength(4); lValue = value; return *this; } -MyMessage& MyMessage::set(uint16_t value) { +MyMessage& MyMessage::set(uint16_t value) +{ miSetPayloadType(P_UINT16); miSetLength(2); uiValue = value; return *this; } -MyMessage& MyMessage::set(int16_t value) { +MyMessage& MyMessage::set(int16_t value) +{ miSetPayloadType(P_INT16); miSetLength(2); iValue = value; diff --git a/core/MyMessage.h b/core/MyMessage.h index 890e5f2..822dc19 100644 --- a/core/MyMessage.h +++ b/core/MyMessage.h @@ -52,11 +52,11 @@ typedef enum { /// @brief Type of sensor (used when presenting sensors) typedef enum { S_DOOR = 0, //!< Door sensor, V_TRIPPED, V_ARMED - S_MOTION = 1, //!< Motion sensor, V_TRIPPED, V_ARMED + S_MOTION = 1, //!< Motion sensor, V_TRIPPED, V_ARMED S_SMOKE = 2, //!< Smoke sensor, V_TRIPPED, V_ARMED S_BINARY = 3, //!< Binary light or relay, V_STATUS, V_WATT S_LIGHT = 3, //!< \deprecated Same as S_BINARY, **** DEPRECATED, DO NOT USE **** - S_DIMMER = 4, //!< Dimmable light or fan device, V_STATUS (on/off), V_PERCENTAGE (dimmer level 0-100), V_WATT + S_DIMMER = 4, //!< Dimmable light or fan device, V_STATUS (on/off), V_PERCENTAGE (dimmer level 0-100), V_WATT S_COVER = 5, //!< Blinds or window cover, V_UP, V_DOWN, V_STOP, V_PERCENTAGE (open/close to a percentage) S_TEMP = 6, //!< Temperature sensor, V_TEMP S_HUM = 7, //!< Humidity sensor, V_HUM @@ -70,38 +70,38 @@ typedef enum { S_DISTANCE = 15, //!< Distance sensor, V_DISTANCE S_LIGHT_LEVEL = 16, //!< Light level sensor, V_LIGHT_LEVEL (uncalibrated in percentage), V_LEVEL (light level in lux) S_ARDUINO_NODE = 17, //!< Used (internally) for presenting a non-repeating Arduino node - S_ARDUINO_REPEATER_NODE = 18, //!< Used (internally) for presenting a repeating Arduino node + S_ARDUINO_REPEATER_NODE = 18, //!< Used (internally) for presenting a repeating Arduino node S_LOCK = 19, //!< Lock device, V_LOCK_STATUS S_IR = 20, //!< IR device, V_IR_SEND, V_IR_RECEIVE S_WATER = 21, //!< Water meter, V_FLOW, V_VOLUME S_AIR_QUALITY = 22, //!< Air quality sensor, V_LEVEL - S_CUSTOM = 23, //!< Custom sensor + S_CUSTOM = 23, //!< Custom sensor S_DUST = 24, //!< Dust sensor, V_LEVEL - S_SCENE_CONTROLLER = 25, //!< Scene controller device, V_SCENE_ON, V_SCENE_OFF. - S_RGB_LIGHT = 26, //!< RGB light. Send color component data using V_RGB. Also supports V_WATT + S_SCENE_CONTROLLER = 25, //!< Scene controller device, V_SCENE_ON, V_SCENE_OFF. + S_RGB_LIGHT = 26, //!< RGB light. Send color component data using V_RGB. Also supports V_WATT S_RGBW_LIGHT = 27, //!< RGB light with an additional White component. Send data using V_RGBW. Also supports V_WATT S_COLOR_SENSOR = 28, //!< Color sensor, send color information using V_RGB S_HVAC = 29, //!< Thermostat/HVAC device. V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COLD, V_HVAC_FLOW_STATE, V_HVAC_FLOW_MODE, V_TEMP - S_MULTIMETER = 30, //!< Multimeter device, V_VOLTAGE, V_CURRENT, V_IMPEDANCE + S_MULTIMETER = 30, //!< Multimeter device, V_VOLTAGE, V_CURRENT, V_IMPEDANCE S_SPRINKLER = 31, //!< Sprinkler, V_STATUS (turn on/off), V_TRIPPED (if fire detecting device) S_WATER_LEAK = 32, //!< Water leak sensor, V_TRIPPED, V_ARMED S_SOUND = 33, //!< Sound sensor, V_TRIPPED, V_ARMED, V_LEVEL (sound level in dB) S_VIBRATION = 34, //!< Vibration sensor, V_TRIPPED, V_ARMED, V_LEVEL (vibration in Hz) - S_MOISTURE = 35, //!< Moisture sensor, V_TRIPPED, V_ARMED, V_LEVEL (water content or moisture in percentage?) + S_MOISTURE = 35, //!< Moisture sensor, V_TRIPPED, V_ARMED, V_LEVEL (water content or moisture in percentage?) S_INFO = 36, //!< LCD text device / Simple information device on controller, V_TEXT S_GAS = 37, //!< Gas meter, V_FLOW, V_VOLUME S_GPS = 38, //!< GPS Sensor, V_POSITION - S_WATER_QUALITY = 39 //!< V_TEMP, V_PH, V_ORP, V_EC, V_STATUS + S_WATER_QUALITY = 39 //!< V_TEMP, V_PH, V_ORP, V_EC, V_STATUS } mysensor_sensor; /// @brief Type of sensor data (for set/req/ack messages) typedef enum { V_TEMP = 0, //!< S_TEMP. Temperature S_TEMP, S_HEATER, S_HVAC V_HUM = 1, //!< S_HUM. Humidity - V_STATUS = 2, //!< S_BINARY, S_DIMMER, S_SPRINKLER, S_HVAC, S_HEATER. Used for setting/reporting binary (on/off) status. 1=on, 0=off + V_STATUS = 2, //!< S_BINARY, S_DIMMER, S_SPRINKLER, S_HVAC, S_HEATER. Used for setting/reporting binary (on/off) status. 1=on, 0=off V_LIGHT = 2, //!< \deprecated Same as V_STATUS, **** DEPRECATED, DO NOT USE **** - V_PERCENTAGE = 3, //!< S_DIMMER. Used for sending a percentage value 0-100 (%). - V_DIMMER = 3, //!< \deprecated Same as V_PERCENTAGE, **** DEPRECATED, DO NOT USE **** + V_PERCENTAGE = 3, //!< S_DIMMER. Used for sending a percentage value 0-100 (%). + V_DIMMER = 3, //!< \deprecated Same as V_PERCENTAGE, **** DEPRECATED, DO NOT USE **** V_PRESSURE = 4, //!< S_BARO. Atmospheric Pressure V_FORECAST = 5, //!< S_BARO. Whether forecast. string of "stable", "sunny", "cloudy", "unstable", "thunderstorm" or "unknown" V_RAIN = 6, //!< S_RAIN. Amount of rain @@ -119,12 +119,12 @@ typedef enum { V_KWH = 18, //!< S_POWER. Accumulated number of KWH for a power meter V_SCENE_ON = 19, //!< S_SCENE_CONTROLLER. Turn on a scene V_SCENE_OFF = 20, //!< S_SCENE_CONTROLLER. Turn of a scene - V_HVAC_FLOW_STATE = 21, //!< S_HEATER, S_HVAC. HVAC flow state ("Off", "HeatOn", "CoolOn", or "AutoChangeOver") + V_HVAC_FLOW_STATE = 21, //!< S_HEATER, S_HVAC. HVAC flow state ("Off", "HeatOn", "CoolOn", or "AutoChangeOver") V_HEATER = 21, //!< \deprecated Same as V_HVAC_FLOW_STATE, **** DEPRECATED, DO NOT USE **** - V_HVAC_SPEED = 22, //!< S_HVAC, S_HEATER. HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto") + V_HVAC_SPEED = 22, //!< S_HVAC, S_HEATER. HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto") V_LIGHT_LEVEL = 23, //!< S_LIGHT_LEVEL. Uncalibrated light level. 0-100%. Use V_LEVEL for light level in lux - V_VAR1 = 24, //!< VAR1 - V_VAR2 = 25, //!< VAR2 + V_VAR1 = 24, //!< VAR1 + V_VAR2 = 25, //!< VAR2 V_VAR3 = 26, //!< VAR3 V_VAR4 = 27, //!< VAR4 V_VAR5 = 28, //!< VAR5 @@ -137,11 +137,11 @@ typedef enum { V_VOLUME = 35, //!< S_WATER. Water volume V_LOCK_STATUS = 36, //!< S_LOCK. Set or get lock status. 1=Locked, 0=Unlocked V_LEVEL = 37, //!< S_DUST, S_AIR_QUALITY, S_SOUND (dB), S_VIBRATION (hz), S_LIGHT_LEVEL (lux) - V_VOLTAGE = 38, //!< S_MULTIMETER + V_VOLTAGE = 38, //!< S_MULTIMETER V_CURRENT = 39, //!< S_MULTIMETER V_RGB = 40, //!< S_RGB_LIGHT, S_COLOR_SENSOR. Sent as ASCII hex: RRGGBB (RR=red, GG=green, BB=blue component) V_RGBW = 41, //!< S_RGBW_LIGHT. Sent as ASCII hex: RRGGBBWW (WW=white component) - V_ID = 42, //!< Used for sending in sensors hardware ids (i.e. OneWire DS1820b). + V_ID = 42, //!< Used for sending in sensors hardware ids (i.e. OneWire DS1820b). V_UNIT_PREFIX = 43, //!< Allows sensors to send in a string representing the unit prefix to be displayed in GUI, not parsed by controller! E.g. cm, m, km, inch. V_HVAC_SETPOINT_COOL = 44, //!< S_HVAC. HVAC cool setpoint (Integer between 0-100) V_HVAC_SETPOINT_HEAT = 45, //!< S_HEATER, S_HVAC. HVAC/Heater setpoint (Integer between 0-100) @@ -151,11 +151,11 @@ typedef enum { V_POSITION = 49, //!< GPS position and altitude. Payload: latitude;longitude;altitude(m). E.g. "55.722526;13.017972;18" V_IR_RECORD = 50, //!< Record IR codes S_IR for playback V_PH = 51, //!< S_WATER_QUALITY, water PH - V_ORP = 52, //!< S_WATER_QUALITY, water ORP : redox potential in mV - V_EC = 53, //!< S_WATER_QUALITY, water electric conductivity μS/cm (microSiemens/cm) - V_VAR = 54, //!< S_POWER, Reactive power: volt-ampere reactive (var) - V_VA = 55, //!< S_POWER, Apparent power: volt-ampere (VA) - V_POWER_FACTOR = 56, //!< S_POWER, Ratio of real power to apparent power: floating point value in the range [-1,..,1] + V_ORP = 52, //!< S_WATER_QUALITY, water ORP : redox potential in mV + V_EC = 53, //!< S_WATER_QUALITY, water electric conductivity μS/cm (microSiemens/cm) + V_VAR = 54, //!< S_POWER, Reactive power: volt-ampere reactive (var) + V_VA = 55, //!< S_POWER, Apparent power: volt-ampere (VA) + V_POWER_FACTOR = 56, //!< S_POWER, Ratio of real power to apparent power: floating point value in the range [-1,..,1] } mysensor_data; @@ -284,10 +284,10 @@ public: char i2h(uint8_t i) const; - /** - * Clear message contents. - */ - void clear(); + /** + * Clear message contents. + */ + void clear(); /** * If payload is something else than P_STRING you can have the payload value converted @@ -331,8 +331,7 @@ public: #else typedef union { -struct -{ + struct { #endif uint8_t last; // 8 bit - Id of last node this message passed @@ -340,12 +339,12 @@ struct uint8_t destination; // 8 bit - Id of destination node uint8_t version_length; // 2 bit - Protocol version - // 1 bit - Signed flag - // 5 bit - Length of payload + // 1 bit - Signed flag + // 5 bit - Length of payload uint8_t command_ack_payload; // 3 bit - Command type - // 1 bit - Request an ack - Indicator that receiver should send an ack back. - // 1 bit - Is ack messsage - Indicator that this is the actual ack message. - // 3 bit - Payload data type + // 1 bit - Request an ack - Indicator that receiver should send an ack back. + // 1 bit - Is ack messsage - Indicator that this is the actual ack message. + // 3 bit - Payload data type uint8_t type; // 8 bit - Type varies depending on command uint8_t sensor; // 8 bit - Id of sensor that this message concerns. @@ -364,7 +363,7 @@ struct }; struct { // Presentation messages uint8_t version; // Library version - uint8_t sensorType; // Sensor type hint for controller, see table above + uint8_t sensorType; // Sensor type hint for controller, see table above }; char data[MAX_PAYLOAD + 1]; } __attribute__((packed)); @@ -372,7 +371,7 @@ struct } __attribute__((packed)); #else }; -uint8_t array[HEADER_SIZE + MAX_PAYLOAD + 1]; +uint8_t array[HEADER_SIZE + MAX_PAYLOAD + 1]; } __attribute__((packed)) MyMessage; #endif #endif diff --git a/core/MyOTAFirmwareUpdate.cpp b/core/MyOTAFirmwareUpdate.cpp index 02749c1..31f212e 100644 --- a/core/MyOTAFirmwareUpdate.cpp +++ b/core/MyOTAFirmwareUpdate.cpp @@ -33,7 +33,8 @@ uint8_t _firmwareRetry; void readFirmwareSettings(void) { - hwReadConfigBlock((void*)&_nodeFirmwareConfig, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(nodeFirmwareConfig_t)); + hwReadConfigBlock((void*)&_nodeFirmwareConfig, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, + sizeof(nodeFirmwareConfig_t)); } void firmwareOTAUpdateRequest(void) @@ -41,7 +42,7 @@ void firmwareOTAUpdateRequest(void) const uint32_t enterMS = hwMillis(); if (_firmwareUpdateOngoing && (enterMS - _firmwareLastRequest > MY_OTA_RETRY_DELAY)) { if (!_firmwareRetry) { - setIndication(INDICATION_ERR_FW_TIMEOUT); + setIndication(INDICATION_ERR_FW_TIMEOUT); OTA_DEBUG(PSTR("!OTA:FRQ:FW UPD FAIL\n")); // fw update failed // Give up. We have requested MY_OTA_RETRY times without any packet in return. _firmwareUpdateOngoing = false; @@ -54,8 +55,10 @@ void firmwareOTAUpdateRequest(void) firmwareRequest.type = _nodeFirmwareConfig.type; firmwareRequest.version = _nodeFirmwareConfig.version; firmwareRequest.block = (_firmwareBlock - 1); - OTA_DEBUG(PSTR("OTA:FRQ:FW REQ,T=%04X,V=%04X,B=%04X\n"), _nodeFirmwareConfig.type, _nodeFirmwareConfig.version, _firmwareBlock - 1); // request FW update block - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_REQUEST, false).set(&firmwareRequest, sizeof(requestFirmwareBlock_t))); + OTA_DEBUG(PSTR("OTA:FRQ:FW REQ,T=%04X,V=%04X,B=%04X\n"), _nodeFirmwareConfig.type, + _nodeFirmwareConfig.version, _firmwareBlock - 1); // request FW update block + (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_REQUEST, + false).set(&firmwareRequest, sizeof(requestFirmwareBlock_t))); } } @@ -65,13 +68,13 @@ bool firmwareOTAUpdateProcess(void) nodeFirmwareConfig_t *firmwareConfigResponse = (nodeFirmwareConfig_t *)_msg.data; // compare with current node configuration, if they differ, start FW fetch process if (memcmp(&_nodeFirmwareConfig, firmwareConfigResponse, sizeof(nodeFirmwareConfig_t))) { - setIndication(INDICATION_FW_UPDATE_START); + setIndication(INDICATION_FW_UPDATE_START); OTA_DEBUG(PSTR("OTA:FWP:UPDATE\n")); // FW update initiated // copy new FW config (void)memcpy(&_nodeFirmwareConfig, firmwareConfigResponse, sizeof(nodeFirmwareConfig_t)); // Init flash if (!_flash.initialize()) { - setIndication(INDICATION_ERR_FW_FLASH_INIT); + setIndication(INDICATION_ERR_FW_FLASH_INIT); OTA_DEBUG(PSTR("!OTA:FWP:FLASH INIT FAIL\n")); // failed to initialise flash _firmwareUpdateOngoing = false; } else { @@ -91,12 +94,13 @@ bool firmwareOTAUpdateProcess(void) } else if (_msg.type == ST_FIRMWARE_RESPONSE) { if (_firmwareUpdateOngoing) { // Save block to flash - setIndication(INDICATION_FW_UPDATE_RX); + setIndication(INDICATION_FW_UPDATE_RX); OTA_DEBUG(PSTR("OTA:FWP:RECV B=%04X\n"), _firmwareBlock); // received FW block // extract FW block replyFirmwareBlock_t *firmwareResponse = (replyFirmwareBlock_t *)_msg.data; // write to flash - _flash.writeBytes( ((_firmwareBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET, firmwareResponse->data, FIRMWARE_BLOCK_SIZE); + _flash.writeBytes( ((_firmwareBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET, + firmwareResponse->data, FIRMWARE_BLOCK_SIZE); // wait until flash written while (_flash.busy()) {} _firmwareBlock--; @@ -107,7 +111,8 @@ bool firmwareOTAUpdateProcess(void) if (transportIsValidFirmware()) { OTA_DEBUG(PSTR("OTA:FWP:CRC OK\n")); // FW checksum ok // Write the new firmware config to eeprom - hwWriteConfigBlock((void*)&_nodeFirmwareConfig, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(nodeFirmwareConfig_t)); + hwWriteConfigBlock((void*)&_nodeFirmwareConfig, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, + sizeof(nodeFirmwareConfig_t)); // All seems ok, write size and signature to flash (DualOptiboot will pick this up and flash it) const uint16_t firmwareSize = FIRMWARE_BLOCK_SIZE * _nodeFirmwareConfig.blocks; const uint8_t OTAbuffer[FIRMWARE_START_OFFSET] = {'F','L','X','I','M','G',':', (uint8_t)(firmwareSize >> 8), (uint8_t)(firmwareSize & 0xff),':'}; @@ -116,7 +121,7 @@ bool firmwareOTAUpdateProcess(void) while (_flash.busy()) {} hwReboot(); } else { - setIndication(INDICATION_ERR_FW_CHECKSUM); + setIndication(INDICATION_ERR_FW_CHECKSUM); OTA_DEBUG(PSTR("!OTA:FWP:CRC FAIL\n")); } } @@ -142,7 +147,8 @@ void presentBootloaderInformation(void) // add bootloader information requestFirmwareConfig->BLVersion = MY_OTA_BOOTLOADER_VERSION; _firmwareUpdateOngoing = false; - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_CONFIG_REQUEST, false)); + (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, + ST_FIRMWARE_CONFIG_REQUEST, false)); } bool isFirmwareUpdateOngoing(void) { @@ -158,8 +164,7 @@ bool transportIsValidFirmware(void) for (int8_t j = 0; j < 8; ++j) { if (crc & 1) { crc = (crc >> 1) ^ 0xA001; - } - else { + } else { crc = (crc >> 1); } } diff --git a/core/MyOTAFirmwareUpdate.h b/core/MyOTAFirmwareUpdate.h index 24846d8..6f9d12d 100644 --- a/core/MyOTAFirmwareUpdate.h +++ b/core/MyOTAFirmwareUpdate.h @@ -17,38 +17,38 @@ * version 2 as published by the Free Software Foundation. */ - /** - * @file MyOTAFirmwareUpdate.h - * - * @defgroup MyOTAFirmwaregrp MyOTAFirmwareUpdate - * @ingroup internals - * @{ - * - * MyOTAFirmwareUpdate-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE - * - [!] Exclamation mark is prepended in case of error or warning - * - SYSTEM: - * - OTA messages emitted by MyOTAFirmwareUpdate - * - SUB SYSTEMS: - * - OTA:FRQ from @ref firmwareOTAUpdateRequest() - * - OTA:FWP from @ref firmwareOTAUpdateProcess() - * - * MyOTAFirmwareUpdate debug log messages: - * - * |E| SYS | SUB | Message | Comment - * |-|------|-------|-------------------------------------------|---------------------------------------------------------------------------- - * | | OTA | FWP | UPDATE | FW update initiated - * |!| OTA | FWP | FLASH INIT FAIL | Failed to initialise flash - * | | OTA | FWP | UPDATE SKIPPED | FW update skipped, no newer version available - * | | OTA | FWP | RECV B=%04X | Received FW block (B) - * | | OTA | FWP | FW END | FW received, proceed to CRC verification - * | | OTA | FWP | CRC OK | FW CRC verification OK - * |!| OTA | FWP | CRC FAIL | FW CRC verification failed - * | | OTA | FRQ | FW REQ,T=%04X,V=%04X,B=%04X | Request FW update, FW type (T), version (V), block (B) - * |!| OTA | FRQ | FW UPD FAIL | FW update failed - * - * - * @brief API declaration for MyOTAFirmwareUpdate - */ +/** +* @file MyOTAFirmwareUpdate.h +* +* @defgroup MyOTAFirmwaregrp MyOTAFirmwareUpdate +* @ingroup internals +* @{ +* +* MyOTAFirmwareUpdate-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE +* - [!] Exclamation mark is prepended in case of error or warning +* - SYSTEM: +* - OTA messages emitted by MyOTAFirmwareUpdate +* - SUB SYSTEMS: +* - OTA:FRQ from @ref firmwareOTAUpdateRequest() +* - OTA:FWP from @ref firmwareOTAUpdateProcess() +* +* MyOTAFirmwareUpdate debug log messages: +* +* |E| SYS | SUB | Message | Comment +* |-|------|-------|-------------------------------------------|---------------------------------------------------------------------------- +* | | OTA | FWP | UPDATE | FW update initiated +* |!| OTA | FWP | FLASH INIT FAIL | Failed to initialise flash +* | | OTA | FWP | UPDATE SKIPPED | FW update skipped, no newer version available +* | | OTA | FWP | RECV B=%04X | Received FW block (B) +* | | OTA | FWP | FW END | FW received, proceed to CRC verification +* | | OTA | FWP | CRC OK | FW CRC verification OK +* |!| OTA | FWP | CRC FAIL | FW CRC verification failed +* | | OTA | FRQ | FW REQ,T=%04X,V=%04X,B=%04X | Request FW update, FW type (T), version (V), block (B) +* |!| OTA | FRQ | FW UPD FAIL | FW update failed +* +* +* @brief API declaration for MyOTAFirmwareUpdate +*/ #ifndef MyOTAFirmwareUpdate_h @@ -67,9 +67,9 @@ #define MY_OTA_BOOTLOADER_VERSION (MY_OTA_BOOTLOADER_MINOR_VERSION * 256 + MY_OTA_BOOTLOADER_MAJOR_VERSION) //!< Bootloader version #if defined(MY_DEBUG) - #define OTA_DEBUG(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug +#define OTA_DEBUG(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug #else - #define OTA_DEBUG(x,...) //!< debug NULL +#define OTA_DEBUG(x,...) //!< debug NULL #endif /** * @brief FW config structure, stored in eeprom diff --git a/core/MyProtocolMySensors.cpp b/core/MyProtocolMySensors.cpp index d046e57..a591891 100755 --- a/core/MyProtocolMySensors.cpp +++ b/core/MyProtocolMySensors.cpp @@ -27,7 +27,8 @@ uint8_t protocolH2i(char c); char _fmtBuffer[MY_GATEWAY_MAX_SEND_LENGTH]; char _convBuffer[MAX_PAYLOAD*2+1]; -bool protocolParse(MyMessage &message, char *inputString) { +bool protocolParse(MyMessage &message, char *inputString) +{ char *str, *p, *value=NULL; uint8_t bvalue[MAX_PAYLOAD]; uint8_t blen = 0; @@ -36,48 +37,48 @@ bool protocolParse(MyMessage &message, char *inputString) { // Extract command data coming on serial line for (str = strtok_r(inputString, ";", &p); // split using semicolon - str && i < 6; // loop while str is not null an max 5 times - str = strtok_r(NULL, ";", &p) // get subsequent tokens - ) { + str && i < 6; // loop while str is not null an max 5 times + str = strtok_r(NULL, ";", &p) // get subsequent tokens + ) { switch (i) { - case 0: // Radioid (destination) - message.destination = atoi(str); - break; - case 1: // Childid - message.sensor = atoi(str); - break; - case 2: // Message type - command = atoi(str); - mSetCommand(message, command); - break; - case 3: // Should we request ack from destination? - mSetRequestAck(message, atoi(str)?1:0); - break; - case 4: // Data type - message.type = atoi(str); - break; - case 5: // Variable value - if (command == C_STREAM) { - blen = 0; - uint8_t val; - while (*str) { - val = protocolH2i(*str++) << 4; - val += protocolH2i(*str++); - bvalue[blen] = val; - blen++; - } - } else { - value = str; - // Remove trailing carriage return and newline character (if it exists) - uint8_t lastCharacter = strlen(value)-1; - if (value[lastCharacter] == '\r') { - value[lastCharacter] = 0; - } - if (value[lastCharacter] == '\n') { - value[lastCharacter] = 0; - } + case 0: // Radioid (destination) + message.destination = atoi(str); + break; + case 1: // Childid + message.sensor = atoi(str); + break; + case 2: // Message type + command = atoi(str); + mSetCommand(message, command); + break; + case 3: // Should we request ack from destination? + mSetRequestAck(message, atoi(str)?1:0); + break; + case 4: // Data type + message.type = atoi(str); + break; + case 5: // Variable value + if (command == C_STREAM) { + blen = 0; + uint8_t val; + while (*str) { + val = protocolH2i(*str++) << 4; + val += protocolH2i(*str++); + bvalue[blen] = val; + blen++; } - break; + } else { + value = str; + // Remove trailing carriage return and newline character (if it exists) + uint8_t lastCharacter = strlen(value)-1; + if (value[lastCharacter] == '\r') { + value[lastCharacter] = 0; + } + if (value[lastCharacter] == '\n') { + value[lastCharacter] = 0; + } + } + break; } i++; } @@ -91,68 +92,74 @@ bool protocolParse(MyMessage &message, char *inputString) { mSetAck(message, false); if (command == C_STREAM) { message.set(bvalue, blen); - } - else { + } else { message.set(value); } return true; } -char * protocolFormat(MyMessage &message) { - snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%d;%d;%d;%d;%d;%s\n"), message.sender, message.sensor, (uint8_t)mGetCommand(message), (uint8_t)mGetAck(message), message.type, message.getString(_convBuffer)); +char * protocolFormat(MyMessage &message) +{ + snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%d;%d;%d;%d;%d;%s\n"), message.sender, + message.sensor, (uint8_t)mGetCommand(message), (uint8_t)mGetAck(message), message.type, + message.getString(_convBuffer)); return _fmtBuffer; } -char * protocolFormatMQTTTopic(const char* prefix, MyMessage &message) { - snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%s/%d/%d/%d/%d/%d"), prefix, message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type); +char * protocolFormatMQTTTopic(const char* prefix, MyMessage &message) +{ + snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%s/%d/%d/%d/%d/%d"), prefix, + message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type); return _fmtBuffer; } -char * protocolFormatMQTTSubscribe(const char* prefix) { +char * protocolFormatMQTTSubscribe(const char* prefix) +{ snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%s/+/+/+/+/+"), prefix); return _fmtBuffer; } #ifdef MY_GATEWAY_MQTT_CLIENT -bool protocolMQTTParse(MyMessage &message, char* topic, uint8_t* payload, unsigned int length) { +bool protocolMQTTParse(MyMessage &message, char* topic, uint8_t* payload, unsigned int length) +{ char *str, *p; uint8_t i = 0; uint8_t bvalue[MAX_PAYLOAD]; uint8_t blen = 0; uint8_t command = 0; - if (topic != strstr(topic, MY_MQTT_SUBSCRIBE_TOPIC_PREFIX)) { + if (topic != strstr(topic, MY_MQTT_SUBSCRIBE_TOPIC_PREFIX)) { // Prefix doesn't match incoming topic return false; } for (str = strtok_r(topic + strlen(MY_MQTT_SUBSCRIBE_TOPIC_PREFIX) + 1, "/", &p); str && i <= 5; - str = strtok_r(NULL, "/", &p)) { + str = strtok_r(NULL, "/", &p)) { switch (i) { - case 0: { - // Node id - message.destination = atoi(str); - break; - } - case 1: { - // Sensor id - message.sensor = atoi(str); - break; - } - case 2: { - // Command type - command = atoi(str); - mSetCommand(message, command); - break; - } - case 3: { - // Ack flag - mSetRequestAck(message, atoi(str)?1:0); - break; - } - case 4: { - // Sub type - message.type = atoi(str); - break; - } + case 0: { + // Node id + message.destination = atoi(str); + break; + } + case 1: { + // Sensor id + message.sensor = atoi(str); + break; + } + case 2: { + // Command type + command = atoi(str); + mSetCommand(message, command); + break; + } + case 3: { + // Ack flag + mSetRequestAck(message, atoi(str)?1:0); + break; + } + case 4: { + // Sub type + message.type = atoi(str); + break; + } } i++; } @@ -188,15 +195,14 @@ bool protocolMQTTParse(MyMessage &message, char* topic, uint8_t* payload, unsign } #endif -uint8_t protocolH2i(char c) { +uint8_t protocolH2i(char c) +{ uint8_t i = 0; if (c <= '9') { i += c - '0'; - } - else if (c >= 'a') { + } else if (c >= 'a') { i += c - 'a' + 10; - } - else { + } else { i += c - 'A' + 10; } return i; diff --git a/core/MySensorsCore.cpp b/core/MySensorsCore.cpp index be567a5..934eeb1 100644 --- a/core/MySensorsCore.cpp +++ b/core/MySensorsCore.cpp @@ -20,8 +20,8 @@ #include "MySensorsCore.h" #if defined(__linux__) - #include - #include +#include +#include #endif // message buffers @@ -32,7 +32,7 @@ MyMessage _msgTmp; // Buffer for temporary messages (acks and nonces among othe static coreConfig_t _coreConfig; #if defined(MY_DEBUG) - char _convBuf[MAX_PAYLOAD*2+1]; +char _convBuf[MAX_PAYLOAD*2+1]; #endif // Callback for transport=ok transition @@ -47,37 +47,40 @@ void _callbackTransportReady(void) } } -void _process(void) { +void _process(void) +{ doYield(); - #if defined(MY_INCLUSION_MODE_FEATURE) - inclusionProcess(); - #endif +#if defined(MY_INCLUSION_MODE_FEATURE) + inclusionProcess(); +#endif - #if defined(MY_GATEWAY_FEATURE) - gatewayTransportProcess(); - #endif +#if defined(MY_GATEWAY_FEATURE) + gatewayTransportProcess(); +#endif - #if defined(MY_SENSOR_NETWORK) - transportProcess(); - #endif +#if defined(MY_SENSOR_NETWORK) + transportProcess(); +#endif - #if defined(__linux__) - // To avoid high cpu usage - usleep(10000); // 10ms - #endif +#if defined(__linux__) + // To avoid high cpu usage + usleep(10000); // 10ms +#endif } -void _infiniteLoop(void) { +void _infiniteLoop(void) +{ while(1) { doYield(); - #if defined(__linux__) - exit(1); - #endif +#if defined(__linux__) + exit(1); +#endif } } -void _begin(void) { +void _begin(void) +{ // reset wdt hwWatchdogReset(); @@ -87,58 +90,60 @@ void _begin(void) { hwInit(); - CORE_DEBUG(PSTR("MCO:BGN:INIT " MY_NODE_TYPE ",CP=" MY_CAPABILITIES ",VER=" MYSENSORS_LIBRARY_VERSION "\n")); + CORE_DEBUG(PSTR("MCO:BGN:INIT " MY_NODE_TYPE ",CP=" MY_CAPABILITIES ",VER=" + MYSENSORS_LIBRARY_VERSION "\n")); // set defaults _coreConfig.presentationSent = false; - + // Call before() in sketch (if it exists) if (before) { CORE_DEBUG(PSTR("MCO:BGN:BFR\n")); // before callback before(); } - #if defined(MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) - ledsInit(); - #endif +#if defined(MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) + ledsInit(); +#endif signerInit(); // Read latest received controller configuration from EEPROM // Note: _coreConfig.isMetric is bool, hence empty EEPROM (=0xFF) evaluates to true (default) - hwReadConfigBlock((void*)&_coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(controllerConfig_t)); + hwReadConfigBlock((void*)&_coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, + sizeof(controllerConfig_t)); - #if defined(MY_OTA_FIRMWARE_FEATURE) - // Read firmware config from EEPROM, i.e. type, version, CRC, blocks - readFirmwareSettings(); - #endif +#if defined(MY_OTA_FIRMWARE_FEATURE) + // Read firmware config from EEPROM, i.e. type, version, CRC, blocks + readFirmwareSettings(); +#endif + +#if defined(MY_SENSOR_NETWORK) + // Save static parent ID in eeprom (used by bootloader) + hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, MY_PARENT_NODE_ID); + // Initialise transport layer + transportInitialise(); + // Register transport=ready callback + transportRegisterReadyCallback(_callbackTransportReady); + // wait until transport is ready + (void)transportWaitUntilReady(MY_TRANSPORT_WAIT_READY_MS); +#endif - #if defined(MY_SENSOR_NETWORK) - // Save static parent ID in eeprom (used by bootloader) - hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, MY_PARENT_NODE_ID); - // Initialise transport layer - transportInitialise(); - // Register transport=ready callback - transportRegisterReadyCallback(_callbackTransportReady); - // wait until transport is ready - (void)transportWaitUntilReady(MY_TRANSPORT_WAIT_READY_MS); - #endif - _checkNodeLock(); - - #if defined(MY_GATEWAY_FEATURE) - #if defined(MY_INCLUSION_BUTTON_FEATURE) - inclusionInit(); - #endif - // initialise the transport driver - if (!gatewayTransportInit()) { - setIndication(INDICATION_ERR_INIT_GWTRANSPORT); - CORE_DEBUG(PSTR("!MCO:BGN:TSP FAIL\n")); - // Nothing more we can do - _infiniteLoop(); - } - #endif +#if defined(MY_GATEWAY_FEATURE) +#if defined(MY_INCLUSION_BUTTON_FEATURE) + inclusionInit(); +#endif + + // initialise the transport driver + if (!gatewayTransportInit()) { + setIndication(INDICATION_ERR_INIT_GWTRANSPORT); + CORE_DEBUG(PSTR("!MCO:BGN:TSP FAIL\n")); + // Nothing more we can do + _infiniteLoop(); + } +#endif // Call sketch setup if (setup) { @@ -164,7 +169,8 @@ void _registerNode(void) uint8_t counter = MY_REGISTRATION_RETRIES; // only proceed if register response received or retries exceeded do { - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_REGISTRATION_REQUEST).set(MY_CORE_VERSION)); + (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, + I_REGISTRATION_REQUEST).set(MY_CORE_VERSION)); } while (!wait(2000, C_INTERNAL, I_REGISTRATION_RESPONSE) && counter--); #else _coreConfig.nodeRegistered = true; @@ -172,40 +178,42 @@ void _registerNode(void) #endif } -void presentNode(void) { +void presentNode(void) +{ setIndication(INDICATION_PRESENT); // Present node and request config - #if defined(MY_GATEWAY_FEATURE) - // Send presentation for this gateway device - #if defined(MY_REPEATER_FEATURE) - (void)present(NODE_SENSOR_ID, S_ARDUINO_REPEATER_NODE); - #else - (void)present(NODE_SENSOR_ID, S_ARDUINO_NODE); - #endif - #else +#if defined(MY_GATEWAY_FEATURE) + // Send presentation for this gateway device +#if defined(MY_REPEATER_FEATURE) + (void)present(NODE_SENSOR_ID, S_ARDUINO_REPEATER_NODE); +#else + (void)present(NODE_SENSOR_ID, S_ARDUINO_NODE); +#endif +#else - #if defined(MY_OTA_FIRMWARE_FEATURE) - presentBootloaderInformation(); - #endif +#if defined(MY_OTA_FIRMWARE_FEATURE) + presentBootloaderInformation(); +#endif - // Send signing preferences for this node to the GW - signerPresentation(_msgTmp, GATEWAY_ADDRESS); + // Send signing preferences for this node to the GW + signerPresentation(_msgTmp, GATEWAY_ADDRESS); - // Send presentation for this radio node - #if defined(MY_REPEATER_FEATURE) - (void)present(NODE_SENSOR_ID, S_ARDUINO_REPEATER_NODE); - #else - (void)present(NODE_SENSOR_ID, S_ARDUINO_NODE); - #endif + // Send presentation for this radio node +#if defined(MY_REPEATER_FEATURE) + (void)present(NODE_SENSOR_ID, S_ARDUINO_REPEATER_NODE); +#else + (void)present(NODE_SENSOR_ID, S_ARDUINO_NODE); +#endif - // Send a configuration exchange request to controller - // Node sends parent node. Controller answers with latest node configuration - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CONFIG).set(getParentNodeId())); + // Send a configuration exchange request to controller + // Node sends parent node. Controller answers with latest node configuration + (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, + I_CONFIG).set(getParentNodeId())); - // Wait configuration reply. - (void)wait(2000, C_INTERNAL, I_CONFIG); + // Wait configuration reply. + (void)wait(2000, C_INTERNAL, I_CONFIG); - #endif +#endif if (presentation) { presentation(); @@ -240,213 +248,229 @@ uint8_t getDistanceGW(void) #endif } -controllerConfig_t getConfig(void) { +controllerConfig_t getConfig(void) +{ return _coreConfig.controllerConfig; } -bool _sendRoute(MyMessage &message) { - #if defined(MY_CORE_ONLY) - (void)message; - #endif - #if defined(MY_GATEWAY_FEATURE) - if (message.destination == getNodeId()) { - // This is a message sent from a sensor attached on the gateway node. - // Pass it directly to the gateway transport layer. - return gatewayTransportSend(message); - } - #endif - #if defined(MY_SENSOR_NETWORK) - return transportSendRoute(message); - #else - return false; - #endif +bool _sendRoute(MyMessage &message) +{ +#if defined(MY_CORE_ONLY) + (void)message; +#endif +#if defined(MY_GATEWAY_FEATURE) + if (message.destination == getNodeId()) { + // This is a message sent from a sensor attached on the gateway node. + // Pass it directly to the gateway transport layer. + return gatewayTransportSend(message); + } +#endif +#if defined(MY_SENSOR_NETWORK) + return transportSendRoute(message); +#else + return false; +#endif } -bool send(MyMessage &message, const bool enableAck) { +bool send(MyMessage &message, const bool enableAck) +{ message.sender = getNodeId(); mSetCommand(message, C_SET); mSetRequestAck(message, enableAck); - #if defined(MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE) - if (_coreConfig.nodeRegistered) { - return _sendRoute(message); - } - else { - CORE_DEBUG(PSTR("!MCO:SND:NODE NOT REG\n")); // node not registered - return false; - } - #else +#if defined(MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE) + if (_coreConfig.nodeRegistered) { return _sendRoute(message); - #endif - } - -bool sendBatteryLevel(const uint8_t value, const bool ack) { - return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_BATTERY_LEVEL, ack).set(value)); -} - -bool sendHeartbeat(const bool ack) { - #if defined(MY_SENSOR_NETWORK) - const uint32_t heartbeat = transportGetHeartbeat(); - return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT_RESPONSE, ack).set(heartbeat)); - #else - (void)ack; + } else { + CORE_DEBUG(PSTR("!MCO:SND:NODE NOT REG\n")); // node not registered return false; - #endif + } +#else + return _sendRoute(message); +#endif } -bool present(const uint8_t childSensorId, const uint8_t sensorType, const char *description, const bool ack) { - return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType, ack).set(childSensorId==NODE_SENSOR_ID?MYSENSORS_LIBRARY_VERSION:description)); +bool sendBatteryLevel(const uint8_t value, const bool ack) +{ + return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_BATTERY_LEVEL, + ack).set(value)); } -bool sendSketchInfo(const char *name, const char *version, const bool ack) { +bool sendHeartbeat(const bool ack) +{ +#if defined(MY_SENSOR_NETWORK) + const uint32_t heartbeat = transportGetHeartbeat(); + return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT_RESPONSE, + ack).set(heartbeat)); +#else + (void)ack; + return false; +#endif +} + +bool present(const uint8_t childSensorId, const uint8_t sensorType, const char *description, + const bool ack) +{ + return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType, + ack).set(childSensorId==NODE_SENSOR_ID?MYSENSORS_LIBRARY_VERSION:description)); +} + +bool sendSketchInfo(const char *name, const char *version, const bool ack) +{ bool result = true; if (name) { - result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME, ack).set(name)); + result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME, + ack).set(name)); } if (version) { - result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION, ack).set(version)); + result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION, + ack).set(version)); } return result; } -bool request(const uint8_t childSensorId, const uint8_t variableType, const uint8_t destination) { +bool request(const uint8_t childSensorId, const uint8_t variableType, const uint8_t destination) +{ return _sendRoute(build(_msgTmp, destination, childSensorId, C_REQ, variableType).set("")); } -bool requestTime(const bool ack) { +bool requestTime(const bool ack) +{ return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_TIME, ack).set("")); } // Message delivered through _msg -bool _processInternalMessages(void) { +bool _processInternalMessages(void) +{ const uint8_t type = _msg.type; if (_msg.sender == GATEWAY_ADDRESS) { if (type == I_REBOOT) { - #if !defined(MY_DISABLE_REMOTE_RESET) - // Requires MySensors or other bootloader with watchdogs enabled - setIndication(INDICATION_REBOOT); - hwReboot(); - #endif - } - else if (type == I_REGISTRATION_RESPONSE) { - #if defined (MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE) - _coreConfig.nodeRegistered = _msg.getBool(); - setIndication(INDICATION_GOT_REGISTRATION); - CORE_DEBUG(PSTR("MCO:PIM:NODE REG=%d\n"), _coreConfig.nodeRegistered); // node registration - #endif - } - else if (type == I_CONFIG) { +#if !defined(MY_DISABLE_REMOTE_RESET) + // Requires MySensors or other bootloader with watchdogs enabled + setIndication(INDICATION_REBOOT); + hwReboot(); +#endif + } else if (type == I_REGISTRATION_RESPONSE) { +#if defined (MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE) + _coreConfig.nodeRegistered = _msg.getBool(); + setIndication(INDICATION_GOT_REGISTRATION); + CORE_DEBUG(PSTR("MCO:PIM:NODE REG=%d\n"), _coreConfig.nodeRegistered); // node registration +#endif + } else if (type == I_CONFIG) { // Pick up configuration from controller (currently only metric/imperial) and store it in eeprom if changed - _coreConfig.controllerConfig.isMetric = _msg.data[0] == 0x00 || _msg.data[0] == 'M'; // metric if null terminated or M - hwWriteConfigBlock((void*)&_coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(controllerConfig_t)); - } - else if (type == I_PRESENTATION) { + _coreConfig.controllerConfig.isMetric = _msg.data[0] == 0x00 || + _msg.data[0] == 'M'; // metric if null terminated or M + hwWriteConfigBlock((void*)&_coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, + sizeof(controllerConfig_t)); + } else if (type == I_PRESENTATION) { // Re-send node presentation to controller presentNode(); - } - else if (type == I_HEARTBEAT_REQUEST) { + } else if (type == I_HEARTBEAT_REQUEST) { (void)sendHeartbeat(); - } - else if (type == I_TIME) { + } else if (type == I_TIME) { // Deliver time to callback if (receiveTime) { receiveTime(_msg.getULong()); } - } - else if (type == I_CHILDREN) { - #if defined(MY_REPEATER_FEATURE) - if (_msg.data[0] == 'C') { - // Clears child relay data for this node - setIndication(INDICATION_CLEAR_ROUTING); - transportClearRoutingTable(); - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN).set("OK")); - } - #endif - } - else if (type == I_DEBUG) { - #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG) - const char debug_msg = _msg.data[0]; - if (debug_msg == 'R') { // routing table - #if defined(MY_REPEATER_FEATURE) - for (uint16_t cnt = 0; cnt < SIZE_ROUTES; cnt++) { - const uint8_t route = transportGetRoute(cnt); - if (route != BROADCAST_ADDRESS) { - CORE_DEBUG(PSTR("MCO:PIM:ROUTE N=%d,R=%d\n"), cnt, route); - uint8_t outBuf[2] = { (uint8_t)cnt,route }; - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(outBuf, 2)); - wait(200); - } + } else if (type == I_CHILDREN) { +#if defined(MY_REPEATER_FEATURE) + if (_msg.data[0] == 'C') { + // Clears child relay data for this node + setIndication(INDICATION_CLEAR_ROUTING); + transportClearRoutingTable(); + (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN).set("OK")); + } +#endif + } else if (type == I_DEBUG) { +#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG) + const char debug_msg = _msg.data[0]; + if (debug_msg == 'R') { // routing table +#if defined(MY_REPEATER_FEATURE) + for (uint16_t cnt = 0; cnt < SIZE_ROUTES; cnt++) { + const uint8_t route = transportGetRoute(cnt); + if (route != BROADCAST_ADDRESS) { + CORE_DEBUG(PSTR("MCO:PIM:ROUTE N=%d,R=%d\n"), cnt, route); + uint8_t outBuf[2] = { (uint8_t)cnt,route }; + (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(outBuf, + 2)); + wait(200); } - #endif } - else if (debug_msg == 'V') { // CPU voltage - (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(hwCPUVoltage())); +#endif + } else if (debug_msg == 'V') { // CPU voltage + (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, + I_DEBUG).set(hwCPUVoltage())); + } else if (debug_msg == 'F') { // CPU frequency in 1/10Mhz + (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, + I_DEBUG).set(hwCPUFrequency())); + } else if (debug_msg == 'M') { // free memory + (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, + I_DEBUG).set(hwFreeMem())); + } 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")); + for (int i = EEPROM_START; i= MY_CORE_MIN_VERSION); - #endif +#if defined(MY_CORE_COMPATIBILITY_CHECK) + approveRegistration = (_msg.getByte() >= MY_CORE_MIN_VERSION); +#endif - #if (F_CPU>16000000) - // delay for fast GW and slow nodes - delay(5); - #endif - (void)_sendRoute(build(_msgTmp, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_REGISTRATION_RESPONSE).set(approveRegistration)); - #else - return false; // processing of this request via controller - #endif - #endif +#if (F_CPU>16000000) + // delay for fast GW and slow nodes + delay(5); +#endif + (void)_sendRoute(build(_msgTmp, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, + I_REGISTRATION_RESPONSE).set(approveRegistration)); +#else + return false; // processing of this request via controller +#endif +#endif + } else { + return false; } - else return false; } return true; } -void saveState(const uint8_t pos, const uint8_t value) { +void saveState(const uint8_t pos, const uint8_t value) +{ hwWriteConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos, value); } -uint8_t loadState(const uint8_t pos) { +uint8_t loadState(const uint8_t pos) +{ return hwReadConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos); } -void wait(const uint32_t waitingMS) { +void wait(const uint32_t waitingMS) +{ const uint32_t enteringMS = hwMillis(); while (hwMillis() - enteringMS < waitingMS) { _process(); } } -bool wait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType) { +bool wait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType) +{ const uint32_t enteringMS = hwMillis(); // invalidate msg type _msg.type = !msgType; @@ -458,127 +482,138 @@ bool wait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType) { return expectedResponse; } -void doYield(void) { +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 +#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); +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 - #if defined(MY_OTA_FIRMWARE_FEATURE) - if (isFirmwareUpdateOngoing()) { - debug(PSTR("!MCO:SLP:FWUPD\n")); // sleeping not possible, FW update ongoing - wait(sleepingMS); - return MY_SLEEP_NOT_POSSIBLE; - } - #endif - // repeater feature: sleeping not possible - #if defined(MY_REPEATER_FEATURE) - (void)smartSleep; - (void)interrupt1; - (void)mode1; - (void)interrupt2; - (void)mode2; - - CORE_DEBUG(PSTR("!MCO:SLP:REP\n")); // sleeping not possible, repeater feature enabled +#if defined(MY_OTA_FIRMWARE_FEATURE) + if (isFirmwareUpdateOngoing()) { + debug(PSTR("!MCO:SLP:FWUPD\n")); // sleeping not possible, FW update ongoing wait(sleepingMS); return MY_SLEEP_NOT_POSSIBLE; - #else - uint32_t sleepingTimeMS = sleepingMS; - #if defined(MY_SENSOR_NETWORK) - // Do not sleep if transport not ready - if (!isTransportReady()) { - CORE_DEBUG(PSTR("!MCO:SLP:TNR\n")); // sleeping not possible, transport not ready - const uint32_t sleepEnterMS = hwMillis(); - uint32_t sleepDeltaMS = 0; - while (!isTransportReady() && (sleepDeltaMS < sleepingTimeMS) && (sleepDeltaMS < MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS)) { - _process(); - sleepDeltaMS = hwMillis() - sleepEnterMS; - } - // sleep remainder - if (sleepDeltaMS < sleepingTimeMS) { - sleepingTimeMS -= sleepDeltaMS; // calculate remaining sleeping time - CORE_DEBUG(PSTR("MCO:SLP:MS=%lu\n"), sleepingTimeMS); - } - else { - // no sleeping time left - return MY_SLEEP_NOT_POSSIBLE; - } - } - #endif + } +#endif + // repeater feature: sleeping not possible +#if defined(MY_REPEATER_FEATURE) + (void)smartSleep; + (void)interrupt1; + (void)mode1; + (void)interrupt2; + (void)mode2; - if (smartSleep) { - // notify controller about going to sleep - (void)sendHeartbeat(); - wait(MY_SMART_SLEEP_WAIT_DURATION_MS); // listen for incoming messages + CORE_DEBUG(PSTR("!MCO:SLP:REP\n")); // sleeping not possible, repeater feature enabled + wait(sleepingMS); + return MY_SLEEP_NOT_POSSIBLE; +#else + uint32_t sleepingTimeMS = sleepingMS; +#if defined(MY_SENSOR_NETWORK) + // Do not sleep if transport not ready + if (!isTransportReady()) { + CORE_DEBUG(PSTR("!MCO:SLP:TNR\n")); // sleeping not possible, transport not ready + const uint32_t sleepEnterMS = hwMillis(); + uint32_t sleepDeltaMS = 0; + while (!isTransportReady() && (sleepDeltaMS < sleepingTimeMS) && + (sleepDeltaMS < MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS)) { + _process(); + sleepDeltaMS = hwMillis() - sleepEnterMS; } - - #if defined(MY_SENSOR_NETWORK) - CORE_DEBUG(PSTR("MCO:SLP:TPD\n")); // sleep, power down transport - 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 - - if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 != INTERRUPT_NOT_DEFINED) { - // both IRQs - result = hwSleep(interrupt1, mode1, interrupt2, mode2, sleepingTimeMS); - } - else if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) { - // one IRQ - result = hwSleep(interrupt1, mode1, sleepingTimeMS); - } - else if (interrupt1 == INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) { - // no IRQ - result = hwSleep(sleepingTimeMS); + // sleep remainder + if (sleepDeltaMS < sleepingTimeMS) { + sleepingTimeMS -= sleepDeltaMS; // calculate remaining sleeping time + CORE_DEBUG(PSTR("MCO:SLP:MS=%lu\n"), sleepingTimeMS); + } else { + // no sleeping time left + return MY_SLEEP_NOT_POSSIBLE; } + } +#endif - setIndication(INDICATION_WAKEUP); - CORE_DEBUG(PSTR("MCO:SLP:WUP=%d\n"), result); // sleep wake-up - return result; - #endif + if (smartSleep) { + // notify controller about going to sleep + (void)sendHeartbeat(); + wait(MY_SMART_SLEEP_WAIT_DURATION_MS); // listen for incoming messages + } + +#if defined(MY_SENSOR_NETWORK) + CORE_DEBUG(PSTR("MCO:SLP:TPD\n")); // sleep, power down transport + 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 + + if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 != INTERRUPT_NOT_DEFINED) { + // both IRQs + result = hwSleep(interrupt1, mode1, interrupt2, mode2, sleepingTimeMS); + } else if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) { + // one IRQ + result = hwSleep(interrupt1, mode1, sleepingTimeMS); + } else if (interrupt1 == INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) { + // no IRQ + result = hwSleep(sleepingTimeMS); + } + + setIndication(INDICATION_WAKEUP); + CORE_DEBUG(PSTR("MCO:SLP:WUP=%d\n"), result); // sleep wake-up + return result; +#endif } // sleep functions -int8_t sleep(const uint32_t sleepingMS, const bool smartSleep) { +int8_t sleep(const uint32_t sleepingMS, const bool smartSleep) +{ return _sleep(sleepingMS, smartSleep); } -int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS, const bool smartSleep) { +int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS, + const bool smartSleep) +{ return _sleep(sleepingMS, smartSleep, interrupt, mode); } -int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t sleepingMS, const bool smartSleep) { +int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, + const uint8_t mode2, const uint32_t sleepingMS, const bool smartSleep) +{ return _sleep(sleepingMS, smartSleep, interrupt1, mode1, interrupt2, mode2); } // deprecated smartSleep() functions -int8_t smartSleep(const uint32_t sleepingMS) { +int8_t smartSleep(const uint32_t sleepingMS) +{ // compatibility return _sleep(sleepingMS, true); } -int8_t smartSleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS) { +int8_t smartSleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS) +{ // compatibility return _sleep(sleepingMS, true, interrupt, mode); } -int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t sleepingMS) { +int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, + const uint8_t mode2, const uint32_t sleepingMS) +{ // compatibility return _sleep(sleepingMS, true, interrupt1, mode1, interrupt2, mode2); } @@ -595,10 +630,10 @@ void _nodeLock(const char* str) CORE_DEBUG(PSTR("MCO:NLK:NODE LOCKED. TO UNLOCK, GND PIN %d AND RESET\n"), MY_NODE_UNLOCK_PIN); doYield(); (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID,C_INTERNAL, I_LOCKED).set(str)); - #if defined(MY_SENSOR_NETWORK) - transportPowerDown(); - CORE_DEBUG(PSTR("MCO:NLK:TPD\n")); // power down transport - #endif +#if defined(MY_SENSOR_NETWORK) + transportPowerDown(); + CORE_DEBUG(PSTR("MCO:NLK:TPD\n")); // power down transport +#endif setIndication(INDICATION_SLEEP); (void)hwSleep((unsigned long)1000*60*30); // Sleep for 30 min before resending LOCKED message setIndication(INDICATION_WAKEUP); @@ -625,14 +660,12 @@ void _checkNodeLock(void) hwPinMode(MY_NODE_UNLOCK_PIN, INPUT); setIndication(INDICATION_ERR_LOCKED); CORE_DEBUG(PSTR("MCO:BGN:NODE UNLOCKED\n")); - } - else { + } else { // Disable pullup hwPinMode(MY_NODE_UNLOCK_PIN, INPUT); _nodeLock("LDB"); //Locked during boot } - } - else if (hwReadConfig(EEPROM_NODE_LOCK_COUNTER) == 0xFF) { + } else if (hwReadConfig(EEPROM_NODE_LOCK_COUNTER) == 0xFF) { // Reset walue hwWriteConfig(EEPROM_NODE_LOCK_COUNTER, MY_NODE_LOCK_COUNTER_MAX); } diff --git a/core/MySensorsCore.h b/core/MySensorsCore.h index 1c82e0b..6ae969d 100644 --- a/core/MySensorsCore.h +++ b/core/MySensorsCore.h @@ -17,51 +17,51 @@ * version 2 as published by the Free Software Foundation. */ - /** - * @file MySensorsCore.h - * - * @defgroup MySensorsCoregrp MySensorsCore - * @ingroup internals - * @{ - * - * MySensorsCore-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE - * - [!] Exclamation mark is prepended in case of error or warning - * - SYSTEM: - * - MCO messages emitted by MySensorsCore - * - SUB SYSTEMS: - * - MCO:BGN from @ref _begin() - * - MCO:REG from @ref _registerNode() - * - MCO:SND from @ref send() - * - MCO:PIM from @ref _processInternalMessages() - * - MCO:NLK from nodeLock() - * - * MySensorsCore debug log messages: - * - * |E| SYS | SUB | Message | Comment - * |-|------|-------|-----------------------------------------------|---------------------------------------------------------------------------- - * | | MCO | BGN | INIT %%s,CP=%%s,LIB=%%s | Core initialization, capabilities (CP), library version (VER) - * | | MCO | BGN | BFR | Callback before() - * | | MCO | BGN | MTR | MY_TRANSPORT_RELAXED enabled - * | | MCO | BGN | STP | Callback setup() - * | | MCO | BGN | INIT OK,TSP=%%d | Core initialised, transport status (TSP), 1=initialised, 0=not initialised, NA=not available - * | | MCO | BGN | NODE UNLOCKED | Node successfully unlocked (see signing chapter) - * |!| MCO | BGN | TSP FAIL | Transport initialization failed - * | | MCO | REG | REQ | Registration request - * | | MCO | REG | NOT NEEDED | No registration needed (i.e. GW) - * |!| MCO | SND | NODE NOT REG | Node is not registered, cannot send message - * | | MCO | PIM | NODE REG=%%d | Registration response received, registration status (REG) - * | | MCO | PIM | ROUTE N=%%d,R=%%d | Routing table, messages to node (N) are routed via node (R) - * | | MCO | SLP | MS=%%lu,SMS=%%d,I1=%%d,M1=%%d,I2=%%d,M2=%%d | Sleep node, time (MS), smartSleep (SMS), Int1/M1, Int2/M2 - * | | MCO | SLP | TPD | Sleep node, powerdown transport - * | | MCO | SLP | WUP=%%d | Node woke-up, reason/IRQ (WUP) - * |!| MCO | SLP | FWUPD | Sleeping not possible, FW update ongoing - * |!| MCO | SLP | REP | Sleeping not possible, repeater feature enabled - * | | MCO | NLK | NODE LOCKED. UNLOCK: GND PIN %%d AND RESET | Node locked during booting, see signing chapter for additional information - * | | MCO | NLK | TPD | Powerdown transport - * - * - * @brief API declaration for MySensorsCore - */ +/** +* @file MySensorsCore.h +* +* @defgroup MySensorsCoregrp MySensorsCore +* @ingroup internals +* @{ +* +* MySensorsCore-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE +* - [!] Exclamation mark is prepended in case of error or warning +* - SYSTEM: +* - MCO messages emitted by MySensorsCore +* - SUB SYSTEMS: +* - MCO:BGN from @ref _begin() +* - MCO:REG from @ref _registerNode() +* - MCO:SND from @ref send() +* - MCO:PIM from @ref _processInternalMessages() +* - MCO:NLK from nodeLock() +* +* MySensorsCore debug log messages: +* +* |E| SYS | SUB | Message | Comment +* |-|------|-------|-----------------------------------------------|---------------------------------------------------------------------------- +* | | MCO | BGN | INIT %%s,CP=%%s,LIB=%%s | Core initialization, capabilities (CP), library version (VER) +* | | MCO | BGN | BFR | Callback before() +* | | MCO | BGN | MTR | MY_TRANSPORT_RELAXED enabled +* | | MCO | BGN | STP | Callback setup() +* | | MCO | BGN | INIT OK,TSP=%%d | Core initialised, transport status (TSP), 1=initialised, 0=not initialised, NA=not available +* | | MCO | BGN | NODE UNLOCKED | Node successfully unlocked (see signing chapter) +* |!| MCO | BGN | TSP FAIL | Transport initialization failed +* | | MCO | REG | REQ | Registration request +* | | MCO | REG | NOT NEEDED | No registration needed (i.e. GW) +* |!| MCO | SND | NODE NOT REG | Node is not registered, cannot send message +* | | MCO | PIM | NODE REG=%%d | Registration response received, registration status (REG) +* | | MCO | PIM | ROUTE N=%%d,R=%%d | Routing table, messages to node (N) are routed via node (R) +* | | MCO | SLP | MS=%%lu,SMS=%%d,I1=%%d,M1=%%d,I2=%%d,M2=%%d | Sleep node, time (MS), smartSleep (SMS), Int1/M1, Int2/M2 +* | | MCO | SLP | TPD | Sleep node, powerdown transport +* | | MCO | SLP | WUP=%%d | Node woke-up, reason/IRQ (WUP) +* |!| MCO | SLP | FWUPD | Sleeping not possible, FW update ongoing +* |!| MCO | SLP | REP | Sleeping not possible, repeater feature enabled +* | | MCO | NLK | NODE LOCKED. UNLOCK: GND PIN %%d AND RESET | Node locked during booting, see signing chapter for additional information +* | | MCO | NLK | TPD | Powerdown transport +* +* +* @brief API declaration for MySensorsCore +*/ #ifndef MySensorsCore_h @@ -86,11 +86,11 @@ #ifdef MY_DEBUG - #define debug(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug, to be removed (follow-up PR) - #define CORE_DEBUG(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug +#define debug(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug, to be removed (follow-up PR) +#define CORE_DEBUG(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug #else - #define debug(x,...) //!< debug NULL, to be removed (follow-up PR) - #define CORE_DEBUG(x,...) //!< debug NULL +#define debug(x,...) //!< debug NULL, to be removed (follow-up PR) +#define CORE_DEBUG(x,...) //!< debug NULL #endif @@ -143,7 +143,8 @@ void presentNode(void); * @param description A textual description of the sensor. * @return true Returns true if message reached the first stop on its way to destination. */ -bool present(const uint8_t sensorId, const uint8_t sensorType, const char *description="", const bool ack = false); +bool present(const uint8_t sensorId, const uint8_t sensorType, const char *description="", + const bool ack = false); /** * Sends sketch meta information to the gateway. Not mandatory but a nice thing to do. @@ -189,7 +190,8 @@ bool sendHeartbeat(const bool ack = false); * @param destination The nodeId of other node in radio network. Default is gateway * @return true Returns true if message reached the first stop on its way to destination. */ -bool request(const uint8_t childSensorId, const uint8_t variableType, const uint8_t destination = GATEWAY_ADDRESS); +bool request(const uint8_t childSensorId, const uint8_t variableType, + const uint8_t destination = GATEWAY_ADDRESS); /** * Requests time from controller. Answer will be delivered to receiveTime function in sketch. @@ -269,7 +271,8 @@ int8_t sleep(const uint32_t sleepingMS, const bool smartSleep = false); * @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep * @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) */ -int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS = 0, const bool smartSleep = false); +int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS = 0, + const bool smartSleep = false); /** * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts. @@ -283,7 +286,8 @@ int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepin * @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep. * @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) */ -int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t sleepingMS = 0, const bool smartSleep = false); +int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, + const uint8_t mode2, const uint32_t sleepingMS = 0, const bool smartSleep = false); /** * \deprecated Use sleep(ms, true) instead @@ -316,7 +320,8 @@ int8_t smartSleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sl * @param sleepingMS Number of milliseconds to sleep or 0 to sleep forever * @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) */ -int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t sleepingMS = 0); +int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, + const uint8_t mode2, const uint32_t sleepingMS = 0); /** * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts. @@ -330,7 +335,9 @@ int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t i * @param smartSleep (optional) Set True if sending heartbeat and process incoming messages before going to sleep. * @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) */ -int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep = false, const uint8_t interrupt1 = INTERRUPT_NOT_DEFINED, const uint8_t mode1 = MODE_NOT_DEFINED, const uint8_t interrupt2 = INTERRUPT_NOT_DEFINED, const uint8_t mode2 = MODE_NOT_DEFINED); +int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep = false, + const uint8_t interrupt1 = INTERRUPT_NOT_DEFINED, const uint8_t mode1 = MODE_NOT_DEFINED, + const uint8_t interrupt2 = INTERRUPT_NOT_DEFINED, const uint8_t mode2 = MODE_NOT_DEFINED); /** @@ -412,7 +419,9 @@ void loop(void) __attribute__((weak)); // Inline function and macros -static inline MyMessage& build(MyMessage &msg, const uint8_t destination, const uint8_t sensor, const uint8_t command, const uint8_t type, const bool ack = false) { +static inline MyMessage& build(MyMessage &msg, const uint8_t destination, const uint8_t sensor, + const uint8_t command, const uint8_t type, const bool ack = false) +{ msg.sender = getNodeId(); msg.destination = destination; msg.sensor = sensor; @@ -423,7 +432,8 @@ static inline MyMessage& build(MyMessage &msg, const uint8_t destination, const return msg; } -static inline MyMessage& buildGw(MyMessage &msg, const uint8_t type) { +static inline MyMessage& buildGw(MyMessage &msg, const uint8_t type) +{ msg.sender = GATEWAY_ADDRESS; msg.destination = GATEWAY_ADDRESS; msg.sensor = NODE_SENSOR_ID; diff --git a/core/MySigning.cpp b/core/MySigning.cpp index bdfa4e9..872cb4b 100644 --- a/core/MySigning.cpp +++ b/core/MySigning.cpp @@ -82,22 +82,24 @@ extern bool signerAtsha204SignMsg(MyMessage &msg); #endif // Helper function to centralize signing/verification exceptions -static bool skipSign(MyMessage &msg) { +static bool skipSign(MyMessage &msg) +{ if mGetAck(msg) { SIGN_DEBUG(PSTR("Skipping security for ACK on command %d type %d\n"), mGetCommand(msg), msg.type); return true; } else if (mGetCommand(msg) == C_INTERNAL && - (msg.type == I_NONCE_REQUEST || msg.type == I_NONCE_RESPONSE || msg.type == I_SIGNING_PRESENTATION || - msg.type == I_ID_REQUEST || msg.type == I_ID_RESPONSE || - msg.type == I_FIND_PARENT_REQUEST || msg.type == I_FIND_PARENT_RESPONSE || - msg.type == I_HEARTBEAT_REQUEST || msg.type == I_HEARTBEAT_RESPONSE || - msg.type == I_PING || msg.type == I_PONG || - msg.type == I_REGISTRATION_REQUEST )) { + (msg.type == I_NONCE_REQUEST || msg.type == I_NONCE_RESPONSE || + msg.type == I_SIGNING_PRESENTATION || + msg.type == I_ID_REQUEST || msg.type == I_ID_RESPONSE || + msg.type == I_FIND_PARENT_REQUEST || msg.type == I_FIND_PARENT_RESPONSE || + msg.type == I_HEARTBEAT_REQUEST || msg.type == I_HEARTBEAT_RESPONSE || + msg.type == I_PING || msg.type == I_PONG || + msg.type == I_REGISTRATION_REQUEST )) { SIGN_DEBUG(PSTR("Skipping security for command %d type %d\n"), mGetCommand(msg), msg.type); return true; } else if (mGetCommand(msg) == C_STREAM && - (msg.type == ST_FIRMWARE_REQUEST || msg.type == ST_FIRMWARE_RESPONSE || - msg.type == ST_SOUND || msg.type == ST_IMAGE)) { + (msg.type == ST_FIRMWARE_REQUEST || msg.type == ST_FIRMWARE_RESPONSE || + msg.type == ST_SOUND || msg.type == ST_IMAGE)) { SIGN_DEBUG(PSTR("Skipping security for command %d type %d\n"), mGetCommand(msg), msg.type); return true; } else { @@ -107,7 +109,8 @@ static bool skipSign(MyMessage &msg) { #endif // MY_SIGNING_FEATURE // Helper to prepare a signing presentation message -static void prepareSigningPresentation(MyMessage &msg, uint8_t destination) { +static void prepareSigningPresentation(MyMessage &msg, uint8_t destination) +{ // Only supports version 1 for now (void)build(msg, destination, NODE_SENSOR_ID, C_INTERNAL, I_SIGNING_PRESENTATION).set(""); mSetLength(msg, 2); @@ -116,15 +119,16 @@ static void prepareSigningPresentation(MyMessage &msg, uint8_t destination) { msg.data[1] = 0; } -void signerInit(void) { +void signerInit(void) +{ #if defined(MY_SIGNING_FEATURE) // Read out the signing requirements from EEPROM hwReadConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, - sizeof(_doSign)); + sizeof(_doSign)); // Read out the whitelist requirements from EEPROM hwReadConfigBlock((void*)_doWhitelist, (void*)EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS, - sizeof(_doWhitelist)); + sizeof(_doWhitelist)); #if defined(MY_SIGNING_SOFT) signerAtsha204SoftInit(); @@ -135,7 +139,8 @@ void signerInit(void) { #endif } -void signerPresentation(MyMessage &msg, uint8_t destination) { +void signerPresentation(MyMessage &msg, uint8_t destination) +{ prepareSigningPresentation(msg, destination); #if defined(MY_SIGNING_REQUEST_SIGNATURES) @@ -157,7 +162,8 @@ void signerPresentation(MyMessage &msg, uint8_t destination) { } } -bool signerProcessInternal(MyMessage &msg) { +bool signerProcessInternal(MyMessage &msg) +{ uint8_t sender = msg.sender; (void)sender; #if !defined(MY_SIGNING_FEATURE) @@ -166,8 +172,9 @@ bool signerProcessInternal(MyMessage &msg) { // If we act as gateway and do not have the signing feature and receive a signing request we still // need to do make sure the requester does not believe the gateway still require signatures prepareSigningPresentation(msg, sender); - SIGN_DEBUG(PSTR("Informing node %d that we do not require signatures because we do not support it\n"), - sender); + SIGN_DEBUG( + PSTR("Informing node %d that we do not require signatures because we do not support it\n"), + sender); if (!_sendRoute(msg)) { SIGN_DEBUG(PSTR("Failed to transmit signing presentation!\n")); } @@ -183,7 +190,8 @@ bool signerProcessInternal(MyMessage &msg) { if (msg.type == I_NONCE_REQUEST) { #if defined(MY_NODE_LOCK_FEATURE) nof_nonce_requests++; - SIGN_DEBUG(PSTR("Nonce requests left until lockdown: %d\n"), MY_NODE_LOCK_COUNTER_MAX-nof_nonce_requests); + SIGN_DEBUG(PSTR("Nonce requests left until lockdown: %d\n"), + MY_NODE_LOCK_COUNTER_MAX-nof_nonce_requests); if (nof_nonce_requests >= MY_NODE_LOCK_COUNTER_MAX) { _nodeLock("TMNR"); //Too many nonces requested } @@ -192,113 +200,113 @@ bool signerProcessInternal(MyMessage &msg) { if (signerAtsha204SoftGetNonce(msg)) { #endif #if defined(MY_SIGNING_ATSHA204) - if (signerAtsha204GetNonce(msg)) { + if (signerAtsha204GetNonce(msg)) { #endif - if (!_sendRoute(build(msg, msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_NONCE_RESPONSE))) { - SIGN_DEBUG(PSTR("Failed to transmit nonce!\n")); + if (!_sendRoute(build(msg, msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_NONCE_RESPONSE))) { + SIGN_DEBUG(PSTR("Failed to transmit nonce!\n")); + } else { + SIGN_DEBUG(PSTR("Transmitted nonce\n")); + } } else { - SIGN_DEBUG(PSTR("Transmitted nonce\n")); + SIGN_DEBUG(PSTR("Failed to generate nonce!\n")); + } + return true; // No need to further process I_NONCE_REQUEST + } else if (msg.type == I_SIGNING_PRESENTATION) { + if (msg.data[0] != SIGNING_PRESENTATION_VERSION_1) { + SIGN_DEBUG(PSTR("Unsupported signing presentation version (%d)!\n"), msg.data[0]); + return true; // Just drop this presentation message } - } else { - SIGN_DEBUG(PSTR("Failed to generate nonce!\n")); - } - return true; // No need to further process I_NONCE_REQUEST - } else if (msg.type == I_SIGNING_PRESENTATION) { - if (msg.data[0] != SIGNING_PRESENTATION_VERSION_1) { - SIGN_DEBUG(PSTR("Unsupported signing presentation version (%d)!\n"), msg.data[0]); - return true; // Just drop this presentation message - } // We only handle version 1 here... - if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) { - // We received an indicator that the sender require us to sign all messages we send to it - SIGN_DEBUG(PSTR("Mark node %d as one that require signed messages\n"), msg.sender); - SET_SIGN(msg.sender); - } else { - // We received an indicator that the sender does not require us to sign all messages we send to it - SIGN_DEBUG(PSTR("Mark node %d as one that do not require signed messages\n"), msg.sender); - CLEAR_SIGN(msg.sender); - } + if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) { + // We received an indicator that the sender require us to sign all messages we send to it + SIGN_DEBUG(PSTR("Mark node %d as one that require signed messages\n"), msg.sender); + SET_SIGN(msg.sender); + } else { + // We received an indicator that the sender does not require us to sign all messages we send to it + SIGN_DEBUG(PSTR("Mark node %d as one that do not require signed messages\n"), msg.sender); + CLEAR_SIGN(msg.sender); + } if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) { - // We received an indicator that the sender require us to salt signatures with serial - SIGN_DEBUG(PSTR("Mark node %d as one that require whitelisting\n"), msg.sender); - SET_WHITELIST(msg.sender); - } else { - // We received an indicator that the sender does not require us to sign all messages we send to it - SIGN_DEBUG(PSTR("Mark node %d as one that do not require whitelisting\n"), msg.sender); - CLEAR_WHITELIST(msg.sender); - } + // We received an indicator that the sender require us to salt signatures with serial + SIGN_DEBUG(PSTR("Mark node %d as one that require whitelisting\n"), msg.sender); + SET_WHITELIST(msg.sender); + } else { + // We received an indicator that the sender does not require us to sign all messages we send to it + SIGN_DEBUG(PSTR("Mark node %d as one that do not require whitelisting\n"), msg.sender); + CLEAR_WHITELIST(msg.sender); + } - // Save updated tables - hwWriteConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, - sizeof(_doSign)); - hwWriteConfigBlock((void*)_doWhitelist, (void*)EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS, - sizeof(_doWhitelist)); + // Save updated tables + hwWriteConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, + sizeof(_doSign)); + hwWriteConfigBlock((void*)_doWhitelist, (void*)EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS, + sizeof(_doWhitelist)); - // Inform sender about our preference if we are a gateway, but only require signing if the sender - // required signing unless we explicitly configure it to - // We do not want a gateway to require signing from all nodes in a network just because it wants one node - // to sign it's messages unless we explicitly configure it to + // Inform sender about our preference if we are a gateway, but only require signing if the sender + // required signing unless we explicitly configure it to + // We do not want a gateway to require signing from all nodes in a network just because it wants one node + // to sign it's messages unless we explicitly configure it to #if defined(MY_GATEWAY_FEATURE) - prepareSigningPresentation(msg, sender); + prepareSigningPresentation(msg, sender); #if defined(MY_SIGNING_REQUEST_SIGNATURES) - if (DO_SIGN(sender)) { - msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES; - } + if (DO_SIGN(sender)) { + msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES; + } #if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL) - msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES; + msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES; #endif #endif #if defined(MY_SIGNING_NODE_WHITELISTING) - if (DO_WHITELIST(sender)) { - msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING; - } + if (DO_WHITELIST(sender)) { + msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING; + } #if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL) - msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING; + msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING; #endif #endif - if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) { - SIGN_DEBUG(PSTR("Informing node %d that we require signatures\n"), sender); - } else { - SIGN_DEBUG(PSTR("Informing node %d that we do not require signatures\n"), sender); - } - if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) { - SIGN_DEBUG(PSTR("Informing node %d that we require whitelisting\n"), sender); - } else { - SIGN_DEBUG(PSTR("Informing node %d that we do not require whitelisting\n"), sender); - } - if (!_sendRoute(msg)) { - SIGN_DEBUG(PSTR("Failed to transmit signing presentation!\n")); - } + if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) { + SIGN_DEBUG(PSTR("Informing node %d that we require signatures\n"), sender); + } else { + SIGN_DEBUG(PSTR("Informing node %d that we do not require signatures\n"), sender); + } + if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) { + SIGN_DEBUG(PSTR("Informing node %d that we require whitelisting\n"), sender); + } else { + SIGN_DEBUG(PSTR("Informing node %d that we do not require whitelisting\n"), sender); + } + if (!_sendRoute(msg)) { + SIGN_DEBUG(PSTR("Failed to transmit signing presentation!\n")); + } #endif // MY_GATEWAY_FEATURE - return true; // No need to further process I_SIGNING_PRESENTATION - } else if (msg.type == I_NONCE_RESPONSE) { - // Proceed with signing if nonce has been received - SIGN_DEBUG(PSTR("Nonce received from %d. Proceeding with signing...\n"), sender); - if (sender != _msgSign.destination) { - SIGN_DEBUG(PSTR("Nonce did not come from the destination (%d) of the message to be signed! " - "It came from %d.\n"), _msgSign.destination, sender); - SIGN_DEBUG(PSTR("Silently discarding this nonce\n")); - return true; // No need to further process I_NONCE_RESPONSE - } + return true; // No need to further process I_SIGNING_PRESENTATION + } else if (msg.type == I_NONCE_RESPONSE) { + // Proceed with signing if nonce has been received + SIGN_DEBUG(PSTR("Nonce received from %d. Proceeding with signing...\n"), sender); + if (sender != _msgSign.destination) { + SIGN_DEBUG(PSTR("Nonce did not come from the destination (%d) of the message to be signed! " + "It came from %d.\n"), _msgSign.destination, sender); + SIGN_DEBUG(PSTR("Silently discarding this nonce\n")); + return true; // No need to further process I_NONCE_RESPONSE + } #if defined(MY_SIGNING_SOFT) - signerAtsha204SoftPutNonce(msg); + signerAtsha204SoftPutNonce(msg); #endif #if defined(MY_SIGNING_ATSHA204) - signerAtsha204PutNonce(msg); + signerAtsha204PutNonce(msg); #endif #if defined(MY_SIGNING_SOFT) - if (!signerAtsha204SoftSignMsg(_msgSign)) { + if (!signerAtsha204SoftSignMsg(_msgSign)) { #endif #if defined(MY_SIGNING_ATSHA204) - if (!signerAtsha204SignMsg(_msgSign)) { + if (!signerAtsha204SignMsg(_msgSign)) { #endif - SIGN_DEBUG(PSTR("Failed to sign message!\n")); - } else { - SIGN_DEBUG(PSTR("Message signed\n")); - _signingNonceStatus = SIGN_OK; // _msgSign now contains the signed message pending transmission - } - return true; // No need to further process I_NONCE_RESPONSE - } + SIGN_DEBUG(PSTR("Failed to sign message!\n")); + } else { + SIGN_DEBUG(PSTR("Message signed\n")); + _signingNonceStatus = SIGN_OK; // _msgSign now contains the signed message pending transmission + } + return true; // No need to further process I_NONCE_RESPONSE + } #endif // MY_SIGNING_FEATURE return false; } @@ -323,7 +331,8 @@ bool signerSignMsg(MyMessage &msg) { } else { // Send nonce-request _signingNonceStatus=SIGN_WAITING_FOR_NONCE; - if (!_sendRoute(build(_msgSign, msg.destination, msg.sensor, C_INTERNAL, I_NONCE_REQUEST).set(""))) { + if (!_sendRoute(build(_msgSign, msg.destination, msg.sensor, C_INTERNAL, + I_NONCE_REQUEST).set(""))) { SIGN_DEBUG(PSTR("Failed to transmit nonce request!\n")); return false; } @@ -332,7 +341,8 @@ bool signerSignMsg(MyMessage &msg) { // Other messages could come in-between. We trust _process() takes care of them unsigned long enter = hwMillis(); _msgSign = msg; // Copy the message to sign since message buffer might be touched in _process() - while (hwMillis() - enter < MY_VERIFICATION_TIMEOUT_MS && _signingNonceStatus==SIGN_WAITING_FOR_NONCE) { + while (hwMillis() - enter < MY_VERIFICATION_TIMEOUT_MS && + _signingNonceStatus==SIGN_WAITING_FOR_NONCE) { _process(); } if (hwMillis() - enter > MY_VERIFICATION_TIMEOUT_MS) { @@ -375,8 +385,7 @@ bool signerVerifyMsg(MyMessage &msg) { // Internal messages of certain types are not verified if (skipSign(msg)) { verificationResult = true; - } - else if (!mGetSigned(msg)) { + } else if (!mGetSigned(msg)) { // Got unsigned message that should have been signed SIGN_DEBUG(PSTR("Message is not signed, but it should have been!\n")); verificationResult = false; @@ -397,7 +406,8 @@ bool signerVerifyMsg(MyMessage &msg) { nof_failed_verifications = 0; } else { nof_failed_verifications++; - SIGN_DEBUG(PSTR("Failed verification attempts left until lockdown: %d\n"), MY_NODE_LOCK_COUNTER_MAX-nof_failed_verifications); + SIGN_DEBUG(PSTR("Failed verification attempts left until lockdown: %d\n"), + MY_NODE_LOCK_COUNTER_MAX-nof_failed_verifications); if (nof_failed_verifications >= MY_NODE_LOCK_COUNTER_MAX) { _nodeLock("TMFV"); //Too many failed verifications } diff --git a/core/MySigning.h b/core/MySigning.h index 761f3e3..4efacf7 100644 --- a/core/MySigning.h +++ b/core/MySigning.h @@ -99,7 +99,7 @@ * scramble into “garbage” when transmitted over the air and then reassembled by a receiving node before being fed in “the clear” up the stack * at the receiving end. * - * There are methods and possibilities to provide encryption also in software, but if this is done, it is my recommendation that this is done + * There are methods and possibilities to provide encryption also in software, but if this is done, it is my recommendation that this is done * after integrity- and authentication information has been provided to the message (if this is desired). Integrity and authentication is of * course not mandatory and some might be happy with only having encryption to cover their need for security. I, however, have only focused on * integrity and authenticity while at the same time keeping the current message routing mechanisms intact and therefore leave @@ -313,7 +313,7 @@ * The whitelist is stored on the node that require signatures. When a received message is verified, the serial of the sender is looked up in a * list stored on the receiving node, and the corresponding serial stored in the list for that sender is then included in the signature verification * process. The list is stored as the value of the flag that enables whitelisting, @ref MY_SIGNING_NODE_WHITELISTING.
- * + * * Whitelisting is achieved by 'salting' the signature with some node-unique information known to the receiver. In the case of ATSHA204A this is the * unique serial number programmed into the circuit. This unique number is never transmitted over the air in clear text, so Eve will not be able to * figure out a "trusted" serial by snooping on the traffic.
@@ -523,7 +523,7 @@ void signerInit(void); * @param destination Node ID of the destination. */ void signerPresentation(MyMessage &msg, uint8_t destination); - + /** * @brief Manages internal signing message handshaking. * @@ -574,7 +574,7 @@ bool signerPutNonce(MyMessage &msg); * deinitializations and enter a power saving state within this call. * \n@b Usage: This function is typically called as action when receiving a @ref I_NONCE_RESPONSE * message and after @ref signerPutNonce() has successfully been executed. - * + * * @param msg The message to sign. * @returns @c true if successful, else @c false. */ diff --git a/core/MySigningAtsha204.cpp b/core/MySigningAtsha204.cpp index 3b53069..87b2e19 100644 --- a/core/MySigningAtsha204.cpp +++ b/core/MySigningAtsha204.cpp @@ -41,7 +41,7 @@ uint8_t _signing_tx_buffer[SHA204_CMD_SIZE_MAX]; extern uint8_t _doWhitelist[32]; #ifdef MY_SIGNING_NODE_WHITELISTING - const whitelist_entry_t _signing_whitelist[] = MY_SIGNING_NODE_WHITELISTING; +const whitelist_entry_t _signing_whitelist[] = MY_SIGNING_NODE_WHITELISTING; #endif static void signerCalculateSignature(MyMessage &msg, bool signing); @@ -54,21 +54,20 @@ static char i2h(uint8_t i) uint8_t k = i & 0x0F; if (k <= 9) { return '0' + k; - } - else { + } else { return 'A' + k - 10; } } -static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz) { +static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz) +{ static char printBuffer[300]; #ifdef MY_GATEWAY_FEATURE // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) snprintf_P(printBuffer, 299, PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE); MY_SERIALDEVICE.print(printBuffer); #endif - for (int i=0; i> 4); printBuffer[(i * 2) + 1] = i2h(buf[i]); } @@ -78,8 +77,7 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, printBuffer[MY_GATEWAY_MAX_SEND_LENGTH-1-strlen_P((const char*)str)] = '\0'; #endif MY_SERIALDEVICE.print(str); - if (sz > 0) - { + if (sz > 0) { MY_SERIALDEVICE.print(printBuffer); } MY_SERIALDEVICE.println(""); @@ -88,13 +86,16 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, #define DEBUG_SIGNING_PRINTBUF(str, buf, sz) #endif -void signerAtsha204Init(void) { +void signerAtsha204Init(void) +{ atsha204_init(MY_SIGNING_ATSHA204_PIN); } -bool signerAtsha204CheckTimer(void) { +bool signerAtsha204CheckTimer(void) +{ if (_signing_verification_ongoing) { - if (hwMillis() < _signing_timestamp || hwMillis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) { + if (hwMillis() < _signing_timestamp || + hwMillis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) { DEBUG_SIGNING_PRINTBUF(F("Verification timeout"), NULL, 0); // Purge nonce memset(_signing_signing_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH); @@ -106,14 +107,15 @@ bool signerAtsha204CheckTimer(void) { return true; } -bool signerAtsha204GetNonce(MyMessage &msg) { +bool signerAtsha204GetNonce(MyMessage &msg) +{ DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204"), NULL, 0); // Generate random number for use as nonce // We used a basic whitening technique that XORs each byte in a 32byte random value with current hwMillis() counter // This 32-byte random value is then hashed (SHA256) to produce the resulting nonce (void)atsha204_wakeup(_signing_temp_message); if (atsha204_execute(SHA204_RANDOM, RANDOM_SEED_UPDATE, 0, 0, NULL, - RANDOM_COUNT, _signing_tx_buffer, RANDOM_RSP_SIZE, _signing_rx_buffer) != SHA204_SUCCESS) { + RANDOM_COUNT, _signing_tx_buffer, RANDOM_RSP_SIZE, _signing_rx_buffer) != SHA204_SUCCESS) { DEBUG_SIGNING_PRINTBUF(F("Failed to generate nonce"), NULL, 0); return false; } @@ -140,7 +142,8 @@ bool signerAtsha204GetNonce(MyMessage &msg) { return true; } -void signerAtsha204PutNonce(MyMessage &msg) { +void signerAtsha204PutNonce(MyMessage &msg) +{ DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204"), NULL, 0); memcpy(_signing_signing_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD); @@ -148,7 +151,8 @@ void signerAtsha204PutNonce(MyMessage &msg) { memset(&_signing_signing_nonce[MAX_PAYLOAD], 0xAA, sizeof(_signing_signing_nonce)-MAX_PAYLOAD); } -bool signerAtsha204SignMsg(MyMessage &msg) { +bool signerAtsha204SignMsg(MyMessage &msg) +{ // If we cannot fit any signature in the message, refuse to sign it if (mGetLength(msg) > MAX_PAYLOAD-2) { DEBUG_SIGNING_PRINTBUF(F("Message too large"), NULL, 0); @@ -161,10 +165,12 @@ bool signerAtsha204SignMsg(MyMessage &msg) { if (DO_WHITELIST(msg.destination)) { // Salt the signature with the senders nodeId and the unique serial of the ATSHA device - memcpy(_signing_signing_nonce, &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed + memcpy(_signing_signing_nonce, &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], + 32); // We can reuse the nonce buffer now since it is no longer needed _signing_signing_nonce[32] = msg.sender; atsha204_getSerialNumber(&_signing_signing_nonce[33]); - (void)signerSha256(_signing_signing_nonce, 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place + (void)signerSha256(_signing_signing_nonce, + 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place DEBUG_SIGNING_PRINTBUF(F("Signature salted with serial"), NULL, 0); } @@ -175,13 +181,16 @@ bool signerAtsha204SignMsg(MyMessage &msg) { _signing_rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER; // Transfer as much signature data as the remaining space in the message permits - memcpy(&msg.data[mGetLength(msg)], &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg)); - DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg)); + memcpy(&msg.data[mGetLength(msg)], &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], + MAX_PAYLOAD-mGetLength(msg)); + DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], + MAX_PAYLOAD-mGetLength(msg)); return true; } -bool signerAtsha204VerifyMsg(MyMessage &msg) { +bool signerAtsha204VerifyMsg(MyMessage &msg) +{ if (!_signing_verification_ongoing) { DEBUG_SIGNING_PRINTBUF(F("No active verification session"), NULL, 0); return false; @@ -198,7 +207,8 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) { return false; } - DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg)); + DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], + MAX_PAYLOAD-mGetLength(msg)); signerCalculateSignature(msg, false); // Get signature of message #ifdef MY_SIGNING_NODE_WHITELISTING @@ -207,10 +217,12 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) { for (j=0; j < NUM_OF(_signing_whitelist); j++) { if (_signing_whitelist[j].nodeId == msg.sender) { DEBUG_SIGNING_PRINTBUF(F("Sender found in whitelist"), NULL, 0); - memcpy(_signing_verifying_nonce, &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed + memcpy(_signing_verifying_nonce, &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], + 32); // We can reuse the nonce buffer now since it is no longer needed _signing_verifying_nonce[32] = msg.sender; memcpy(&_signing_verifying_nonce[33], _signing_whitelist[j].serial, SHA204_SERIAL_SZ); - (void)signerSha256(_signing_verifying_nonce, 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place + (void)signerSha256(_signing_verifying_nonce, + 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place break; } } @@ -229,8 +241,10 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) { _signing_rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER; // Compare the caluclated signature with the provided signature - if (signerMemcmp(&msg.data[mGetLength(msg)], &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg))) { - DEBUG_SIGNING_PRINTBUF(F("Signature bad: "), &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg)); + if (signerMemcmp(&msg.data[mGetLength(msg)], &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], + MAX_PAYLOAD-mGetLength(msg))) { + DEBUG_SIGNING_PRINTBUF(F("Signature bad: "), &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], + MAX_PAYLOAD-mGetLength(msg)); #ifdef MY_SIGNING_NODE_WHITELISTING DEBUG_SIGNING_PRINTBUF(F("Is the sender whitelisted and serial correct?"), NULL, 0); #endif @@ -243,42 +257,49 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) { } // Helper to calculate signature of msg (returned in _signing_rx_buffer[SHA204_BUFFER_POS_DATA]) -static void signerCalculateSignature(MyMessage &msg, bool signing) { +static void signerCalculateSignature(MyMessage &msg, bool signing) +{ (void)atsha204_wakeup(_signing_temp_message); memset(_signing_temp_message, 0, 32); - memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); + memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE], + MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); // Program the data to sign into the ATSHA204 - DEBUG_SIGNING_PRINTBUF(F("Message to process: "), (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); - DEBUG_SIGNING_PRINTBUF(F("Current nonce: "), signing ? _signing_signing_nonce : _signing_verifying_nonce, 32); - (void)atsha204_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, 8 << 3, 32, _signing_temp_message, - WRITE_COUNT_LONG, _signing_tx_buffer, WRITE_RSP_SIZE, _signing_rx_buffer); + DEBUG_SIGNING_PRINTBUF(F("Message to process: "), (uint8_t*)&msg.data[1-HEADER_SIZE], + MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); + DEBUG_SIGNING_PRINTBUF(F("Current nonce: "), + signing ? _signing_signing_nonce : _signing_verifying_nonce, 32); + (void)atsha204_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, 8 << 3, 32, + _signing_temp_message, + WRITE_COUNT_LONG, _signing_tx_buffer, WRITE_RSP_SIZE, _signing_rx_buffer); // Program the nonce to use for the signature (has to be done just before GENDIG due to chip limitations) (void)atsha204_execute(SHA204_NONCE, NONCE_MODE_PASSTHROUGH, 0, NONCE_NUMIN_SIZE_PASSTHROUGH, - signing ? _signing_signing_nonce : _signing_verifying_nonce, - NONCE_COUNT_LONG, _signing_tx_buffer, NONCE_RSP_SIZE_SHORT, _signing_rx_buffer); + signing ? _signing_signing_nonce : _signing_verifying_nonce, + NONCE_COUNT_LONG, _signing_tx_buffer, NONCE_RSP_SIZE_SHORT, _signing_rx_buffer); // Purge nonce when used - memset(signing ? _signing_signing_nonce : _signing_verifying_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH); + memset(signing ? _signing_signing_nonce : _signing_verifying_nonce, 0x00, + NONCE_NUMIN_SIZE_PASSTHROUGH); // Generate digest of data and nonce (void)atsha204_execute(SHA204_GENDIG, GENDIG_ZONE_DATA, 8, 0, NULL, - GENDIG_COUNT_DATA, _signing_tx_buffer, GENDIG_RSP_SIZE, _signing_rx_buffer); + GENDIG_COUNT_DATA, _signing_tx_buffer, GENDIG_RSP_SIZE, _signing_rx_buffer); // Calculate HMAC of message+nonce digest and secret key (void)atsha204_execute(SHA204_HMAC, HMAC_MODE_SOURCE_FLAG_MATCH, 0, 0, NULL, - HMAC_COUNT, _signing_tx_buffer, HMAC_RSP_SIZE, _signing_rx_buffer); + HMAC_COUNT, _signing_tx_buffer, HMAC_RSP_SIZE, _signing_rx_buffer); DEBUG_SIGNING_PRINTBUF(F("HMAC: "), &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], 32); } // Helper to calculate a generic SHA256 digest of provided buffer (only supports one block) // The pointer to the hash is returned, but the hash is also stored in _signing_rx_buffer[SHA204_BUFFER_POS_DATA]) -static uint8_t* signerSha256(const uint8_t* data, size_t sz) { +static uint8_t* signerSha256(const uint8_t* data, size_t sz) +{ // Initiate SHA256 calculator (void)atsha204_execute(SHA204_SHA, SHA_INIT, 0, 0, NULL, - SHA_COUNT_SHORT, _signing_tx_buffer, SHA_RSP_SIZE_SHORT, _signing_rx_buffer); + SHA_COUNT_SHORT, _signing_tx_buffer, SHA_RSP_SIZE_SHORT, _signing_rx_buffer); // Calculate a hash memset(_signing_temp_message, 0x00, SHA_MSG_SIZE); @@ -288,7 +309,7 @@ static uint8_t* signerSha256(const uint8_t* data, size_t sz) { _signing_temp_message[SHA_MSG_SIZE-2] = (sz >> 5); _signing_temp_message[SHA_MSG_SIZE-1] = (sz << 3); (void)atsha204_execute(SHA204_SHA, SHA_CALC, 0, SHA_MSG_SIZE, _signing_temp_message, - SHA_COUNT_LONG, _signing_tx_buffer, SHA_RSP_SIZE_LONG, _signing_rx_buffer); + SHA_COUNT_LONG, _signing_tx_buffer, SHA_RSP_SIZE_LONG, _signing_rx_buffer); DEBUG_SIGNING_PRINTBUF(F("SHA256: "), &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], 32); return &_signing_rx_buffer[SHA204_BUFFER_POS_DATA]; diff --git a/core/MySigningAtsha204Soft.cpp b/core/MySigningAtsha204Soft.cpp index cec7ad6..a24da6c 100644 --- a/core/MySigningAtsha204Soft.cpp +++ b/core/MySigningAtsha204Soft.cpp @@ -47,49 +47,47 @@ extern uint8_t _doWhitelist[32]; static uint8_t _signing_node_serial_info[9]; #ifdef MY_SIGNING_NODE_WHITELISTING - const whitelist_entry_t _signing_whitelist[] = MY_SIGNING_NODE_WHITELISTING; +const whitelist_entry_t _signing_whitelist[] = MY_SIGNING_NODE_WHITELISTING; #endif static void signerCalculateSignature(MyMessage &msg, bool signing); #ifdef MY_DEBUG_VERBOSE_SIGNING static char i2h(uint8_t i) - { +{ uint8_t k = i & 0x0F; if (k <= 9) { return '0' + k; - } - else { + } else { return 'A' + k - 10; } } #ifdef __linux__ -static void DEBUG_SIGNING_PRINTBUF(const char *str, uint8_t* buf, uint8_t sz) { +static void DEBUG_SIGNING_PRINTBUF(const char *str, uint8_t* buf, uint8_t sz) +{ static char printBuffer[300]; - for (int i=0; i> 4); printBuffer[(i * 2) + 1] = i2h(buf[i]); } printBuffer[sz * 2] = '\0'; debug(str); - if (sz > 0) - { + if (sz > 0) { debug(printBuffer); } } #else -static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz) { +static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz) +{ static char printBuffer[300]; #ifdef MY_GATEWAY_FEATURE // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) snprintf_P(printBuffer, 299, PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE); MY_SERIALDEVICE.print(printBuffer); #endif - for (int i=0; i> 4); printBuffer[(i * 2) + 1] = i2h(buf[i]); } @@ -99,8 +97,7 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, printBuffer[MY_GATEWAY_MAX_SEND_LENGTH-1-strlen_P((const char*)str)] = '\0'; #endif MY_SERIALDEVICE.print(str); - if (sz > 0) - { + if (sz > 0) { MY_SERIALDEVICE.print(printBuffer); } MY_SERIALDEVICE.println(""); @@ -110,7 +107,8 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, #define DEBUG_SIGNING_PRINTBUF(str, buf, sz) #endif -void signerAtsha204SoftInit(void) { +void signerAtsha204SoftInit(void) +{ // initialize pseudo-RNG hwRandomNumberInit(); // Set secrets @@ -118,9 +116,11 @@ void signerAtsha204SoftInit(void) { hwReadConfigBlock((void*)_signing_node_serial_info, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9); } -bool signerAtsha204SoftCheckTimer(void) { +bool signerAtsha204SoftCheckTimer(void) +{ if (_signing_verification_ongoing) { - if (hwMillis() < _signing_timestamp || hwMillis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) { + if (hwMillis() < _signing_timestamp || + hwMillis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) { DEBUG_SIGNING_PRINTBUF(F("Verification timeout"), NULL, 0); // Purge nonce memset(_signing_signing_nonce, 0xAA, 32); @@ -132,7 +132,8 @@ bool signerAtsha204SoftCheckTimer(void) { return true; } -bool signerAtsha204SoftGetNonce(MyMessage &msg) { +bool signerAtsha204SoftGetNonce(MyMessage &msg) +{ 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 @@ -160,7 +161,8 @@ bool signerAtsha204SoftGetNonce(MyMessage &msg) { return true; } -void signerAtsha204SoftPutNonce(MyMessage &msg) { +void signerAtsha204SoftPutNonce(MyMessage &msg) +{ DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204Soft"), NULL, 0); memcpy(_signing_signing_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD); @@ -168,7 +170,8 @@ void signerAtsha204SoftPutNonce(MyMessage &msg) { memset(&_signing_signing_nonce[MAX_PAYLOAD], 0xAA, sizeof(_signing_signing_nonce)-MAX_PAYLOAD); } -bool signerAtsha204SoftSignMsg(MyMessage &msg) { +bool signerAtsha204SoftSignMsg(MyMessage &msg) +{ // If we cannot fit any signature in the message, refuse to sign it if (mGetLength(msg) > MAX_PAYLOAD-2) { DEBUG_SIGNING_PRINTBUF(F("Message too large"), NULL, 0); @@ -199,12 +202,14 @@ bool signerAtsha204SoftSignMsg(MyMessage &msg) { // Transfer as much signature data as the remaining space in the message permits memcpy(&msg.data[mGetLength(msg)], _signing_hmac, MAX_PAYLOAD-mGetLength(msg)); - DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg)); + DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], + MAX_PAYLOAD-mGetLength(msg)); return true; } -bool signerAtsha204SoftVerifyMsg(MyMessage &msg) { +bool signerAtsha204SoftVerifyMsg(MyMessage &msg) +{ if (!_signing_verification_ongoing) { DEBUG_SIGNING_PRINTBUF(F("No active verification session"), NULL, 0); return false; @@ -222,7 +227,8 @@ bool signerAtsha204SoftVerifyMsg(MyMessage &msg) { } // Get signature of message - DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg)); + DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], + MAX_PAYLOAD-mGetLength(msg)); signerCalculateSignature(msg, false); #ifdef MY_SIGNING_NODE_WHITELISTING @@ -268,11 +274,15 @@ bool signerAtsha204SoftVerifyMsg(MyMessage &msg) { } // Helper to calculate signature of msg (returned in hmac) -static void signerCalculateSignature(MyMessage &msg, bool signing) { +static void signerCalculateSignature(MyMessage &msg, bool signing) +{ memset(_signing_temp_message, 0, 32); - memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); - DEBUG_SIGNING_PRINTBUF(F("Message to process: "), (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); - DEBUG_SIGNING_PRINTBUF(F("Current nonce: "), signing ? _signing_signing_nonce : _signing_verifying_nonce, 32); + memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE], + MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); + DEBUG_SIGNING_PRINTBUF(F("Message to process: "), (uint8_t*)&msg.data[1-HEADER_SIZE], + MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); + DEBUG_SIGNING_PRINTBUF(F("Current nonce: "), + signing ? _signing_signing_nonce : _signing_verifying_nonce, 32); // ATSHA204 calculates the HMAC with a PSK and a SHA256 digest of the following data: // 32 bytes zeroes diff --git a/core/MyTransport.cpp b/core/MyTransport.cpp index 5d3a1ca..969e299 100644 --- a/core/MyTransport.cpp +++ b/core/MyTransport.cpp @@ -31,7 +31,7 @@ static transportState_t stFailure = { stFailureTransition, stFailureUpdate }; static transportSM_t _transportSM; // transport configuration -static transportConfig_t _transportConfig; +static transportConfig_t _transportConfig; // callback transportOk transportCallback_t transportReady_cb = NULL; @@ -41,167 +41,170 @@ extern MyMessage _msg; // incoming message extern MyMessage _msgTmp; // outgoing message #if defined(MY_RAM_ROUTING_TABLE_ENABLED) - static routingTable_t _transportRoutingTable; //!< routing table - static uint32_t _lastRoutingTableSave; //!< last routing table dump +static routingTable_t _transportRoutingTable; //!< routing table +static uint32_t _lastRoutingTableSave; //!< last routing table dump #endif // regular sanity check, activated by default on GW and repeater nodes #if defined(MY_TRANSPORT_SANITY_CHECK) - static uint32_t _lastSanityCheck; //!< last sanity check +static uint32_t _lastSanityCheck; //!< last sanity check #endif // regular network discovery, sends I_DISCOVER_REQUESTS to update routing table // sufficient to have GW triggering requests to also update repeater nodes #if defined(MY_GATEWAY_FEATURE) - static uint32_t _lastNetworkDiscovery; //! last network discovery +static uint32_t _lastNetworkDiscovery; //! last network discovery #endif // stInit: initialise transport HW -void stInitTransition(void) { +void stInitTransition(void) +{ TRANSPORT_DEBUG(PSTR("TSM:INIT\n")); // initialise status variables _transportSM.pingActive = false; _transportSM.transportActive = false; _transportSM.lastUplinkCheck = 0ul; - #if defined(MY_TRANSPORT_SANITY_CHECK) - _lastSanityCheck = hwMillis(); - #endif - #if defined(MY_GATEWAY_FEATURE) - _lastNetworkDiscovery = 0ul; - #endif - #if defined(MY_RAM_ROUTING_TABLE_ENABLED) - _lastRoutingTableSave = hwMillis(); - #endif +#if defined(MY_TRANSPORT_SANITY_CHECK) + _lastSanityCheck = hwMillis(); +#endif +#if defined(MY_GATEWAY_FEATURE) + _lastNetworkDiscovery = 0ul; +#endif +#if defined(MY_RAM_ROUTING_TABLE_ENABLED) + _lastRoutingTableSave = hwMillis(); +#endif // Read node settings (ID, parent ID, GW distance) from EEPROM - hwReadConfigBlock((void*)&_transportConfig, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(transportConfig_t)); + hwReadConfigBlock((void*)&_transportConfig, (void*)EEPROM_NODE_ID_ADDRESS, + sizeof(transportConfig_t)); } -void stInitUpdate(void) { +void stInitUpdate(void) +{ // initialise radio if (!transportInit()) { TRANSPORT_DEBUG(PSTR("!TSM:INIT:TSP FAIL\n")); setIndication(INDICATION_ERR_INIT_TRANSPORT); transportSwitchSM(stFailure); - } - else { + } else { TRANSPORT_DEBUG(PSTR("TSM:INIT:TSP OK\n")); _transportSM.transportActive = true; - #if defined(MY_GATEWAY_FEATURE) - // Set configuration for gateway - TRANSPORT_DEBUG(PSTR("TSM:INIT:GW MODE\n")); - _transportConfig.parentNodeId = GATEWAY_ADDRESS; - _transportConfig.distanceGW = 0u; - _transportConfig.nodeId = GATEWAY_ADDRESS; - transportSetAddress(GATEWAY_ADDRESS); - // GW mode: skip FPAR,ID,UPL states - transportSwitchSM(stReady); - #else - if (MY_NODE_ID != AUTO) { - TRANSPORT_DEBUG(PSTR("TSM:INIT:STATID=%d\n"),(uint8_t)MY_NODE_ID); - // Set static ID - _transportConfig.nodeId = (uint8_t)MY_NODE_ID; - // Save static ID to eeprom (for bootloader) - hwWriteConfig(EEPROM_NODE_ID_ADDRESS, (uint8_t)MY_NODE_ID); - } - // assign ID if set - if (_transportConfig.nodeId == AUTO || transportAssignNodeID(_transportConfig.nodeId)) { - // if node ID valid (>0 and <255), proceed to next state - transportSwitchSM(stParent); - } - else { - // ID invalid (0 or 255) - transportSwitchSM(stFailure); - } - #endif +#if defined(MY_GATEWAY_FEATURE) + // Set configuration for gateway + TRANSPORT_DEBUG(PSTR("TSM:INIT:GW MODE\n")); + _transportConfig.parentNodeId = GATEWAY_ADDRESS; + _transportConfig.distanceGW = 0u; + _transportConfig.nodeId = GATEWAY_ADDRESS; + transportSetAddress(GATEWAY_ADDRESS); + // GW mode: skip FPAR,ID,UPL states + transportSwitchSM(stReady); +#else + if (MY_NODE_ID != AUTO) { + TRANSPORT_DEBUG(PSTR("TSM:INIT:STATID=%d\n"),(uint8_t)MY_NODE_ID); + // Set static ID + _transportConfig.nodeId = (uint8_t)MY_NODE_ID; + // Save static ID to eeprom (for bootloader) + hwWriteConfig(EEPROM_NODE_ID_ADDRESS, (uint8_t)MY_NODE_ID); + } + // assign ID if set + if (_transportConfig.nodeId == AUTO || transportAssignNodeID(_transportConfig.nodeId)) { + // if node ID valid (>0 and <255), proceed to next state + transportSwitchSM(stParent); + } else { + // ID invalid (0 or 255) + transportSwitchSM(stFailure); + } +#endif } } // stParent: find parent -void stParentTransition(void) { +void stParentTransition(void) +{ TRANSPORT_DEBUG(PSTR("TSM:FPAR\n")); // find parent setIndication(INDICATION_FIND_PARENT); _transportSM.uplinkOk = false; _transportSM.preferredParentFound = false; - #if defined(MY_PARENT_NODE_IS_STATIC) - TRANSPORT_DEBUG(PSTR("TSM:FPAR:STATP=%d\n"), (uint8_t)MY_PARENT_NODE_ID); // static parent - _transportSM.findingParentNode = false; - _transportConfig.distanceGW = 1u; // assumption, CHKUPL:GWDC will update this variable - _transportConfig.parentNodeId = (uint8_t)MY_PARENT_NODE_ID; - // save parent ID to eeprom (for bootloader) - hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, (uint8_t)MY_PARENT_NODE_ID); - #else - _transportSM.findingParentNode = true; - _transportConfig.distanceGW = DISTANCE_INVALID; // Set distance to max and invalidate parent node ID - _transportConfig.parentNodeId = AUTO; - // Broadcast find parent request - (void)transportRouteMessage(build(_msgTmp, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_REQUEST).set("")); - #endif +#if defined(MY_PARENT_NODE_IS_STATIC) + TRANSPORT_DEBUG(PSTR("TSM:FPAR:STATP=%d\n"), (uint8_t)MY_PARENT_NODE_ID); // static parent + _transportSM.findingParentNode = false; + _transportConfig.distanceGW = 1u; // assumption, CHKUPL:GWDC will update this variable + _transportConfig.parentNodeId = (uint8_t)MY_PARENT_NODE_ID; + // save parent ID to eeprom (for bootloader) + hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, (uint8_t)MY_PARENT_NODE_ID); +#else + _transportSM.findingParentNode = true; + _transportConfig.distanceGW = DISTANCE_INVALID; // Set distance to max and invalidate parent node ID + _transportConfig.parentNodeId = AUTO; + // Broadcast find parent request + (void)transportRouteMessage(build(_msgTmp, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, + I_FIND_PARENT_REQUEST).set("")); +#endif } // stParentUpdate -void stParentUpdate(void) { - #if defined(MY_PARENT_NODE_IS_STATIC) - // skipping find parent - setIndication(INDICATION_GOT_PARENT); - transportSwitchSM(stID); - #else - if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS || _transportSM.preferredParentFound) { - // timeout or preferred parent found - if (_transportConfig.parentNodeId != AUTO) { - // parent assigned - TRANSPORT_DEBUG(PSTR("TSM:FPAR:OK\n")); // find parent ok - _transportSM.findingParentNode = false; - setIndication(INDICATION_GOT_PARENT); - // go to next state - transportSwitchSM(stID); - } - else { - // timeout w/o reply or valid parent - if (_transportSM.stateRetries < MY_TRANSPORT_STATE_RETRIES) { - // retries left - TRANSPORT_DEBUG(PSTR("!TSM:FPAR:NO REPLY\n")); // find parent, no reply - // reenter state - transportSwitchSM(stParent); - } - else { - // no retries left, finding parent failed - TRANSPORT_DEBUG(PSTR("!TSM:FPAR:FAIL\n")); - setIndication(INDICATION_ERR_FIND_PARENT); - transportSwitchSM(stFailure); - } +void stParentUpdate(void) +{ +#if defined(MY_PARENT_NODE_IS_STATIC) + // skipping find parent + setIndication(INDICATION_GOT_PARENT); + transportSwitchSM(stID); +#else + if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS || _transportSM.preferredParentFound) { + // timeout or preferred parent found + if (_transportConfig.parentNodeId != AUTO) { + // parent assigned + TRANSPORT_DEBUG(PSTR("TSM:FPAR:OK\n")); // find parent ok + _transportSM.findingParentNode = false; + setIndication(INDICATION_GOT_PARENT); + // go to next state + transportSwitchSM(stID); + } else { + // timeout w/o reply or valid parent + if (_transportSM.stateRetries < MY_TRANSPORT_STATE_RETRIES) { + // retries left + TRANSPORT_DEBUG(PSTR("!TSM:FPAR:NO REPLY\n")); // find parent, no reply + // reenter state + transportSwitchSM(stParent); + } else { + // no retries left, finding parent failed + TRANSPORT_DEBUG(PSTR("!TSM:FPAR:FAIL\n")); + setIndication(INDICATION_ERR_FIND_PARENT); + transportSwitchSM(stFailure); } } - #endif + } +#endif } // stID: verify and request ID if necessary -void stIDTransition(void) { +void stIDTransition(void) +{ TRANSPORT_DEBUG(PSTR("TSM:ID\n")); // verify/request node ID if (_transportConfig.nodeId == AUTO) { // send ID request setIndication(INDICATION_REQ_NODEID); TRANSPORT_DEBUG(PSTR("TSM:ID:REQ\n")); // request node ID - (void)transportRouteMessage(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_ID_REQUEST).set("")); + (void)transportRouteMessage(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, + I_ID_REQUEST).set("")); } } -void stIDUpdate(void) { +void stIDUpdate(void) +{ if (_transportConfig.nodeId != AUTO) { // current node ID is valid TRANSPORT_DEBUG(PSTR("TSM:ID:OK\n")); setIndication(INDICATION_GOT_NODEID); // proceed to next state transportSwitchSM(stUplink); - } - else if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS) { + } else if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS) { // timeout if (_transportSM.stateRetries < MY_TRANSPORT_STATE_RETRIES) { // retries left: reenter state transportSwitchSM(stID); - } - else { + } else { // no retries left TRANSPORT_DEBUG(PSTR("!TSM:ID:FAIL\n")); setIndication(INDICATION_ERR_GET_NODEID); @@ -210,51 +213,55 @@ void stIDUpdate(void) { } } -void stUplinkTransition(void) { - #if !defined(MY_TRANSPORT_UPLINK_CHECK_DISABLED) - TRANSPORT_DEBUG(PSTR("TSM:UPL\n")); - setIndication(INDICATION_CHECK_UPLINK); - _transportSM.pingResponse = INVALID_HOPS; - _transportSM.pingActive = true; - (void)transportRouteMessage(build(_msgTmp,GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_PING).set((uint8_t)0x01)); - #endif +void stUplinkTransition(void) +{ +#if !defined(MY_TRANSPORT_UPLINK_CHECK_DISABLED) + TRANSPORT_DEBUG(PSTR("TSM:UPL\n")); + setIndication(INDICATION_CHECK_UPLINK); + _transportSM.pingResponse = INVALID_HOPS; + _transportSM.pingActive = true; + (void)transportRouteMessage(build(_msgTmp,GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, + I_PING).set((uint8_t)0x01)); +#endif } -void stUplinkUpdate(void) { - #if !defined(MY_TRANSPORT_UPLINK_CHECK_DISABLED) - if (_transportSM.pingResponse != INVALID_HOPS) { - _transportSM.lastUplinkCheck = hwMillis(); - // uplink ok, i.e. GW replied - TRANSPORT_DEBUG(PSTR("TSM:UPL:OK\n")); // uplink ok - if (_transportSM.pingResponse != _transportConfig.distanceGW) { - TRANSPORT_DEBUG(PSTR("TSM:UPL:DGWC,O=%d,N=%d\n"), _transportConfig.distanceGW, _transportSM.pingResponse); // distance to GW changed - _transportConfig.distanceGW = _transportSM.pingResponse; - } - transportSwitchSM(stReady); // proceed to next state +void stUplinkUpdate(void) +{ +#if !defined(MY_TRANSPORT_UPLINK_CHECK_DISABLED) + if (_transportSM.pingResponse != INVALID_HOPS) { + _transportSM.lastUplinkCheck = hwMillis(); + // uplink ok, i.e. GW replied + TRANSPORT_DEBUG(PSTR("TSM:UPL:OK\n")); // uplink ok + if (_transportSM.pingResponse != _transportConfig.distanceGW) { + TRANSPORT_DEBUG(PSTR("TSM:UPL:DGWC,O=%d,N=%d\n"), _transportConfig.distanceGW, + _transportSM.pingResponse); // distance to GW changed + _transportConfig.distanceGW = _transportSM.pingResponse; } - else if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS) { - // timeout - if (_transportSM.stateRetries < MY_TRANSPORT_STATE_RETRIES) { - // retries left: reenter state - transportSwitchSM(stUplink); - } - else { - // no retries left - TRANSPORT_DEBUG(PSTR("!TSM:UPL:FAIL\n")); // uplink check failed - _transportSM.pingActive = false; - setIndication(INDICATION_ERR_CHECK_UPLINK); - transportSwitchSM(stParent); // go back to stParent - } + transportSwitchSM(stReady); // proceed to next state + } else if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS) { + // timeout + if (_transportSM.stateRetries < MY_TRANSPORT_STATE_RETRIES) { + // retries left: reenter state + transportSwitchSM(stUplink); + } else { + // no retries left + TRANSPORT_DEBUG(PSTR("!TSM:UPL:FAIL\n")); // uplink check failed + _transportSM.pingActive = false; + setIndication(INDICATION_ERR_CHECK_UPLINK); + transportSwitchSM(stParent); // go back to stParent } - #else - TRANSPORT_DEBUG(PSTR("TSM:UPL:DISABLED\n")); // uplink check disabled - transportSwitchSM(stReady); - #endif + } +#else + TRANSPORT_DEBUG(PSTR("TSM:UPL:DISABLED\n")); // uplink check disabled + transportSwitchSM(stReady); +#endif } -void stReadyTransition(void) { +void stReadyTransition(void) +{ // transport is ready and fully operational - TRANSPORT_DEBUG(PSTR("TSM:READY:ID=%d,PAR=%d,DIS=%d\n"), _transportConfig.nodeId, _transportConfig.parentNodeId, _transportConfig.distanceGW); + TRANSPORT_DEBUG(PSTR("TSM:READY:ID=%d,PAR=%d,DIS=%d\n"), _transportConfig.nodeId, + _transportConfig.parentNodeId, _transportConfig.distanceGW); _transportSM.uplinkOk = true; _transportSM.failureCounter = 0u; // reset failure counter _transportSM.failedUplinkTransmissions = 0u; // reset failed uplink TX counter @@ -265,37 +272,40 @@ void stReadyTransition(void) { } // stReadyUpdate: monitors link -void stReadyUpdate(void) { - #if defined(MY_GATEWAY_FEATURE) - if (hwMillis() - _lastNetworkDiscovery > MY_TRANSPORT_DISCOVERY_INTERVAL_MS) { - _lastNetworkDiscovery = hwMillis(); - TRANSPORT_DEBUG(PSTR("TSM:READY:NWD REQ\n")); // send transport network discovery - (void)transportRouteMessage(build(_msgTmp, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DISCOVER_REQUEST).set("")); - } - #else - if (_transportSM.failedUplinkTransmissions > MY_TRANSPORT_MAX_TX_FAILURES) { - // too many uplink transmissions failed, find new parent (if non-static) - #if !defined(MY_PARENT_NODE_IS_STATIC) - TRANSPORT_DEBUG(PSTR("!TSM:READY:UPL FAIL,SNP\n")); // uplink failed, search new parent - transportSwitchSM(stParent); - #else - TRANSPORT_DEBUG(PSTR("!TSM:READY:UPL FAIL,STATP\n")); // uplink failed, static parent - // reset counter - _transportSM.failedUplinkTransmissions = 0u; - #endif - } - #endif +void stReadyUpdate(void) +{ +#if defined(MY_GATEWAY_FEATURE) + if (hwMillis() - _lastNetworkDiscovery > MY_TRANSPORT_DISCOVERY_INTERVAL_MS) { + _lastNetworkDiscovery = hwMillis(); + TRANSPORT_DEBUG(PSTR("TSM:READY:NWD REQ\n")); // send transport network discovery + (void)transportRouteMessage(build(_msgTmp, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, + I_DISCOVER_REQUEST).set("")); + } +#else + if (_transportSM.failedUplinkTransmissions > MY_TRANSPORT_MAX_TX_FAILURES) { + // too many uplink transmissions failed, find new parent (if non-static) +#if !defined(MY_PARENT_NODE_IS_STATIC) + TRANSPORT_DEBUG(PSTR("!TSM:READY:UPL FAIL,SNP\n")); // uplink failed, search new parent + transportSwitchSM(stParent); +#else + TRANSPORT_DEBUG(PSTR("!TSM:READY:UPL FAIL,STATP\n")); // uplink failed, static parent + // reset counter + _transportSM.failedUplinkTransmissions = 0u; +#endif + } +#endif - #if defined(MY_RAM_ROUTING_TABLE_ENABLED) - if (hwMillis() - _lastRoutingTableSave > MY_ROUTING_TABLE_SAVE_INTERVAL_MS) { - _lastRoutingTableSave = hwMillis(); - transportSaveRoutingTable(); - } - #endif +#if defined(MY_RAM_ROUTING_TABLE_ENABLED) + if (hwMillis() - _lastRoutingTableSave > MY_ROUTING_TABLE_SAVE_INTERVAL_MS) { + _lastRoutingTableSave = hwMillis(); + transportSaveRoutingTable(); + } +#endif } // stFailure: entered upon HW init failure or max retries exceeded -void stFailureTransition(void) { +void stFailureTransition(void) +{ if (_transportSM.failureCounter < MY_TRANSPORT_MAX_TSM_FAILURES) { _transportSM.failureCounter++; // increment consecutive TSM failure counter } @@ -303,25 +313,27 @@ void stFailureTransition(void) { _transportSM.uplinkOk = false; // uplink nok _transportSM.transportActive = false; // transport inactive setIndication(INDICATION_ERR_INIT_TRANSPORT); - #if defined(MY_SENSOR_NETWORK) - TRANSPORT_DEBUG(PSTR("TSM:FAIL:PDT\n")); // power down transport, no need until re-init - transportPowerDown(); - #endif +#if defined(MY_SENSOR_NETWORK) + TRANSPORT_DEBUG(PSTR("TSM:FAIL:PDT\n")); // power down transport, no need until re-init + transportPowerDown(); +#endif } -void stFailureUpdate(void) { - if (transportTimeInState() > ( isTransportExtendedFailure()? MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE: MY_TRANSPORT_TIMEOUT_FAILURE_STATE) ) { +void stFailureUpdate(void) +{ + if (transportTimeInState() > ( isTransportExtendedFailure()? MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE: + MY_TRANSPORT_TIMEOUT_FAILURE_STATE) ) { TRANSPORT_DEBUG(PSTR("TSM:FAIL:RE-INIT\n")); // attempt to re-initialise transport transportSwitchSM(stInit); } } -void transportSwitchSM(transportState_t& newState) { +void transportSwitchSM(transportState_t& newState) +{ if (_transportSM.currentState != &newState) { _transportSM.stateRetries = 0u; // state change, reset retry counter _transportSM.currentState = &newState; // change state - } - else { + } else { _transportSM.stateRetries++; // increment retries } if (_transportSM.currentState->Transition) { @@ -330,38 +342,46 @@ void transportSwitchSM(transportState_t& newState) { _transportSM.stateEnter = hwMillis(); // save time } -uint32_t transportTimeInState(void) { +uint32_t transportTimeInState(void) +{ return hwMillis() - _transportSM.stateEnter; } -void transportUpdateSM(void) { +void transportUpdateSM(void) +{ if (_transportSM.currentState->Update) { _transportSM.currentState->Update(); } } -bool isTransportReady(void) { +bool isTransportReady(void) +{ return _transportSM.uplinkOk; } -bool isTransportExtendedFailure(void) { +bool isTransportExtendedFailure(void) +{ return _transportSM.failureCounter == MY_TRANSPORT_MAX_TSM_FAILURES; } -bool isTransportSearchingParent(void) { +bool isTransportSearchingParent(void) +{ return _transportSM.findingParentNode; } -bool isMessageReceived(void) { +bool isMessageReceived(void) +{ return _transportSM.msgReceived; } -void resetMessageReceived(void) { +void resetMessageReceived(void) +{ _transportSM.msgReceived = false; } -void transportInitialise(void) { +void transportInitialise(void) +{ _transportSM.failureCounter = 0u; // reset failure counter transportLoadRoutingTable(); // load routing table to RAM (if feature enabled) // intial state @@ -369,7 +389,8 @@ void transportInitialise(void) { transportSwitchSM(stInit); } -bool transportWaitUntilReady(const uint32_t waitingMS) { +bool transportWaitUntilReady(const uint32_t waitingMS) +{ // check if transport ready TRANSPORT_DEBUG(PSTR("TSF:WUR:MS=%lu\n"), waitingMS); // timeout uint32_t enterMS = hwMillis(); @@ -383,7 +404,8 @@ bool transportWaitUntilReady(const uint32_t waitingMS) { } // update TSM and process incoming messages -void transportProcess(void) { +void transportProcess(void) +{ // update state machine transportUpdateSM(); // process transport FIFO @@ -391,7 +413,8 @@ void transportProcess(void) { } -bool transportCheckUplink(const bool force) { +bool transportCheckUplink(const bool force) +{ if (!force && (hwMillis() - _transportSM.lastUplinkCheck) < MY_TRANSPORT_CHKUPL_INTERVAL_MS) { TRANSPORT_DEBUG(PSTR("TSF:CKU:OK,FCTRL\n")); // flood control return true; @@ -405,18 +428,19 @@ bool transportCheckUplink(const bool force) { TRANSPORT_DEBUG(PSTR("TSF:CKU:OK\n")); // did distance to GW change upstream, eg. re-routing of uplink nodes if (hopsCount != _transportConfig.distanceGW) { - TRANSPORT_DEBUG(PSTR("TSF:CKU:DGWC,O=%d,N=%d\n"), _transportConfig.distanceGW, hopsCount); // distance to GW changed + TRANSPORT_DEBUG(PSTR("TSF:CKU:DGWC,O=%d,N=%d\n"), _transportConfig.distanceGW, + hopsCount); // distance to GW changed _transportConfig.distanceGW = hopsCount; } return true; - } - else { + } else { TRANSPORT_DEBUG(PSTR("TSF:CKU:FAIL\n")); return false; } } -bool transportAssignNodeID(const uint8_t newNodeId) { +bool transportAssignNodeID(const uint8_t newNodeId) +{ // verify if ID valid if (newNodeId != GATEWAY_ADDRESS && newNodeId != AUTO) { _transportConfig.nodeId = newNodeId; @@ -425,8 +449,7 @@ bool transportAssignNodeID(const uint8_t newNodeId) { hwWriteConfig(EEPROM_NODE_ID_ADDRESS, newNodeId); TRANSPORT_DEBUG(PSTR("TSF:SID:OK,ID=%d\n"),newNodeId); // Node ID assigned return true; - } - else { + } else { TRANSPORT_DEBUG(PSTR("!TSF:SID:FAIL,ID=%d\n"),newNodeId); // ID is invalid, cannot assign ID setIndication(INDICATION_ERR_NET_FULL); _transportConfig.nodeId = AUTO; @@ -434,7 +457,8 @@ bool transportAssignNodeID(const uint8_t newNodeId) { } } -bool transportRouteMessage(MyMessage &message) { +bool transportRouteMessage(MyMessage &message) +{ const uint8_t destination = message.destination; uint8_t route = _transportConfig.parentNodeId; // by default, all traffic is routed via parent node @@ -446,60 +470,58 @@ bool transportRouteMessage(MyMessage &message) { if (destination == GATEWAY_ADDRESS) { route = _transportConfig.parentNodeId; // message to GW always routes via parent - } - else if (destination == BROADCAST_ADDRESS) { + } else if (destination == BROADCAST_ADDRESS) { route = BROADCAST_ADDRESS; // message to BC does not require routing - } - else { - #if defined(MY_REPEATER_FEATURE) - // destination not GW & not BC, get route - route = transportGetRoute(destination); - if (route == AUTO) { - TRANSPORT_DEBUG(PSTR("!TSF:RTE:%d UNKNOWN\n"), destination); // route unknown - #if !defined(MY_GATEWAY_FEATURE) - if (message.last != _transportConfig.parentNodeId) { - // message not from parent, i.e. child node - route it to parent - route = _transportConfig.parentNodeId; - } - else { - // route unknown and msg received from parent, send it to destination assuming in rx radius - route = destination; - } - #else - // if GW, all unknown destinations are directly addressed - route = destination; - #endif + } else { +#if defined(MY_REPEATER_FEATURE) + // destination not GW & not BC, get route + route = transportGetRoute(destination); + if (route == AUTO) { + TRANSPORT_DEBUG(PSTR("!TSF:RTE:%d UNKNOWN\n"), destination); // route unknown +#if !defined(MY_GATEWAY_FEATURE) + if (message.last != _transportConfig.parentNodeId) { + // message not from parent, i.e. child node - route it to parent + route = _transportConfig.parentNodeId; + } else { + // route unknown and msg received from parent, send it to destination assuming in rx radius + route = destination; } - #else - route = _transportConfig.parentNodeId; // not a repeater, all traffic routed via parent - #endif +#else + // if GW, all unknown destinations are directly addressed + route = destination; +#endif + } +#else + route = _transportConfig.parentNodeId; // not a repeater, all traffic routed via parent +#endif } // send message const bool result = transportSendWrite(route, message); - #if !defined(MY_GATEWAY_FEATURE) - // update counter - if (route == _transportConfig.parentNodeId) { - if (!result) { - setIndication(INDICATION_ERR_TX); - _transportSM.failedUplinkTransmissions++; - } - else _transportSM.failedUplinkTransmissions = 0u; - } - #else - if(!result) { +#if !defined(MY_GATEWAY_FEATURE) + // update counter + if (route == _transportConfig.parentNodeId) { + if (!result) { setIndication(INDICATION_ERR_TX); + _transportSM.failedUplinkTransmissions++; + } else { + _transportSM.failedUplinkTransmissions = 0u; } - #endif + } +#else + if(!result) { + setIndication(INDICATION_ERR_TX); + } +#endif return result; } -bool transportSendRoute(MyMessage &message) { +bool transportSendRoute(MyMessage &message) +{ bool result = false; if (isTransportReady()) { result = transportRouteMessage(message); - } - else { + } else { // TNR: transport not ready TRANSPORT_DEBUG(PSTR("!TSF:SND:TNR\n")); } @@ -507,7 +529,8 @@ bool transportSendRoute(MyMessage &message) { } // only be used inside transport -bool transportWait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType){ +bool transportWait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType) +{ const uint32_t enterMS = hwMillis(); // invalidate msg type _msg.type = !msgType; @@ -521,35 +544,37 @@ bool transportWait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t ms return expectedResponse; } -uint8_t transportPingNode(const uint8_t targetId) { - if(!_transportSM.pingActive){ +uint8_t transportPingNode(const uint8_t targetId) +{ + if(!_transportSM.pingActive) { TRANSPORT_DEBUG(PSTR("TSF:PNG:SEND,TO=%d\n"), targetId); if(targetId == _transportConfig.nodeId) { // pinging self _transportSM.pingResponse = 0u; - } - else { + } else { _transportSM.pingActive = true; _transportSM.pingResponse = INVALID_HOPS; - (void)transportRouteMessage(build(_msgTmp, targetId, NODE_SENSOR_ID, C_INTERNAL, I_PING).set((uint8_t)0x01)); + (void)transportRouteMessage(build(_msgTmp, targetId, NODE_SENSOR_ID, C_INTERNAL, + I_PING).set((uint8_t)0x01)); // Wait for ping reply or timeout (void)transportWait(2000, C_INTERNAL, I_PONG); } // make sure missing I_PONG msg does not block pinging function by leaving pignActive=true _transportSM.pingActive = false; return _transportSM.pingResponse; - } - else { + } else { TRANSPORT_DEBUG(PSTR("!TSF:PNG:ACTIVE\n")); // ping active, cannot start new ping return INVALID_HOPS; } } -uint32_t transportGetHeartbeat(void) { +uint32_t transportGetHeartbeat(void) +{ return transportTimeInState(); } -void transportProcessMessage(void) { +void transportProcessMessage(void) +{ // Manage signing timeout (void)signerCheckTimer(); // receive message @@ -560,7 +585,7 @@ void transportProcessMessage(void) { const uint8_t msgLength = min(mGetLength(_msg), (uint8_t)MAX_PAYLOAD); // calculate expected length const uint8_t expectedMessageLength = HEADER_SIZE + (mGetSigned(_msg) ? MAX_PAYLOAD : msgLength); -#if defined(MY_RF24_ENABLE_ENCRYPTION) +#if defined(MY_RF24_ENABLE_ENCRYPTION) // payload length = a multiple of blocksize length for decrypted messages, i.e. cannot be used for payload length check payloadLength = expectedMessageLength; #endif @@ -571,19 +596,22 @@ void transportProcessMessage(void) { const uint8_t destination = _msg.destination; TRANSPORT_DEBUG(PSTR("TSF:MSG:READ,%d-%d-%d,s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d:%s\n"), - sender, last, destination, _msg.sensor, command, type, mGetPayloadType(_msg), msgLength, mGetSigned(_msg), _msg.getString(_convBuf)); + sender, last, destination, _msg.sensor, command, type, mGetPayloadType(_msg), msgLength, + mGetSigned(_msg), _msg.getString(_convBuf)); // Reject payloads with incorrect length if (payloadLength != expectedMessageLength) { setIndication(INDICATION_ERR_LENGTH); - TRANSPORT_DEBUG(PSTR("!TSF:MSG:LEN,%d!=%d\n"), payloadLength, expectedMessageLength); // invalid payload length + TRANSPORT_DEBUG(PSTR("!TSF:MSG:LEN,%d!=%d\n"), payloadLength, + expectedMessageLength); // invalid payload length return; } // Reject messages with incorrect protocol version if (mGetVersion(_msg) != PROTOCOL_VERSION) { setIndication(INDICATION_ERR_VERSION); - TRANSPORT_DEBUG(PSTR("!TSF:MSG:PVER,%d=%d\n"), mGetVersion(_msg), PROTOCOL_VERSION); // protocol version mismatch + TRANSPORT_DEBUG(PSTR("!TSF:MSG:PVER,%d=%d\n"), mGetVersion(_msg), + PROTOCOL_VERSION); // protocol version mismatch return; } @@ -595,20 +623,20 @@ void transportProcessMessage(void) { } // update routing table if msg not from parent - #if defined(MY_REPEATER_FEATURE) - #if !defined(MY_GATEWAY_FEATURE) - if (last != getParentNodeId()) +#if defined(MY_REPEATER_FEATURE) +#if !defined(MY_GATEWAY_FEATURE) + if (last != getParentNodeId()) { +#else + // GW doesn't have parent + { +#endif + // Message is from one of the child nodes and not sent from this node. Add it to routing table. + if (sender != getNodeId()) { - #else - // GW doesn't have parent - { - #endif - // Message is from one of the child nodes and not sent from this node. Add it to routing table. - if (sender != getNodeId()) { - transportSetRoute(sender, last); - } + transportSetRoute(sender, last); } - #endif // MY_REPEATER_FEATURE + } +#endif // MY_REPEATER_FEATURE // set message received flag _transportSM.msgReceived = true; @@ -623,7 +651,8 @@ void transportProcessMessage(void) { if (mGetRequestAck(_msg)) { TRANSPORT_DEBUG(PSTR("TSF:MSG:ACK REQ\n")); // ACK requested _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 _msgTmp.sender = _transportConfig.nodeId; _msgTmp.destination = sender; @@ -637,49 +666,51 @@ void transportProcessMessage(void) { if (signerProcessInternal(_msg)) { return; // Signer processing indicated no further action needed } - #if !defined(MY_GATEWAY_FEATURE) - if (type == I_ID_RESPONSE) { - #if (MY_NODE_ID == AUTO) - // only active if node ID dynamic - (void)transportAssignNodeID(_msg.getByte()); - #endif - return; // no further processing required - } - if (type == I_FIND_PARENT_RESPONSE) { - #if !defined(MY_GATEWAY_FEATURE) && !defined(MY_PARENT_NODE_IS_STATIC) - if (_transportSM.findingParentNode) { // only process if find parent active - // Reply to a I_FIND_PARENT_REQUEST message. Check if the distance is shorter than we already have. - uint8_t distance = _msg.getByte(); - if (isValidDistance(distance)) { - distance++; // Distance to gateway is one more for us w.r.t. parent - // update settings if distance shorter or preferred parent found - if (((isValidDistance(distance) && distance < _transportConfig.distanceGW) || (!_autoFindParent && sender == (uint8_t)MY_PARENT_NODE_ID)) && !_transportSM.preferredParentFound) { - // Found a neighbor closer to GW than previously found - if (!_autoFindParent && sender == (uint8_t)MY_PARENT_NODE_ID) { - _transportSM.preferredParentFound = true; - TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR PREF\n")); // find parent, preferred parent found - } - _transportConfig.distanceGW = distance; - _transportConfig.parentNodeId = sender; - TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR OK,ID=%d,D=%d\n"), _transportConfig.parentNodeId, _transportConfig.distanceGW); - } +#if !defined(MY_GATEWAY_FEATURE) + if (type == I_ID_RESPONSE) { +#if (MY_NODE_ID == AUTO) + // only active if node ID dynamic + (void)transportAssignNodeID(_msg.getByte()); +#endif + return; // no further processing required + } + if (type == I_FIND_PARENT_RESPONSE) { +#if !defined(MY_GATEWAY_FEATURE) && !defined(MY_PARENT_NODE_IS_STATIC) + if (_transportSM.findingParentNode) { // only process if find parent active + // Reply to a I_FIND_PARENT_REQUEST message. Check if the distance is shorter than we already have. + uint8_t distance = _msg.getByte(); + if (isValidDistance(distance)) { + distance++; // Distance to gateway is one more for us w.r.t. parent + // update settings if distance shorter or preferred parent found + if (((isValidDistance(distance) && distance < _transportConfig.distanceGW) || (!_autoFindParent && + sender == (uint8_t)MY_PARENT_NODE_ID)) && !_transportSM.preferredParentFound) { + // Found a neighbor closer to GW than previously found + if (!_autoFindParent && sender == (uint8_t)MY_PARENT_NODE_ID) { + _transportSM.preferredParentFound = true; + TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR PREF\n")); // find parent, preferred parent found } + _transportConfig.distanceGW = distance; + _transportConfig.parentNodeId = sender; + TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR OK,ID=%d,D=%d\n"), _transportConfig.parentNodeId, + _transportConfig.distanceGW); } - else { - TRANSPORT_DEBUG(PSTR("!TSF:MSG:FPAR INACTIVE\n")); // find parent response received, but inactive - } - return; - #endif + } + } else { + TRANSPORT_DEBUG(PSTR("!TSF:MSG:FPAR INACTIVE\n")); // find parent response received, but inactive } - #endif + return; +#endif + } +#endif // general if (type == I_PING) { TRANSPORT_DEBUG(PSTR("TSF:MSG:PINGED,ID=%d,HP=%d\n"), sender, _msg.getByte()); // node pinged - #if defined(MY_GATEWAY_FEATURE) && (F_CPU>16000000) - // delay for fast GW and slow nodes - delay(5); - #endif - (void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, I_PONG).set((uint8_t)1)); +#if defined(MY_GATEWAY_FEATURE) && (F_CPU>16000000) + // delay for fast GW and slow nodes + delay(5); +#endif + (void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, + I_PONG).set((uint8_t)1)); return; // no further processing required } if (type == I_PONG) { @@ -687,8 +718,7 @@ void transportProcessMessage(void) { _transportSM.pingActive = false; _transportSM.pingResponse = _msg.getByte(); TRANSPORT_DEBUG(PSTR("TSF:MSG:PONG RECV,HP=%d\n"), _transportSM.pingResponse); // pong received - } - else { + } else { TRANSPORT_DEBUG(PSTR("!TSF:MSG:PONG RECV,INACTIVE\n")); // pong received, but !pingActive } return; // no further processing required @@ -697,32 +727,31 @@ void transportProcessMessage(void) { return; // no further processing required } } else if (command == C_STREAM) { - #if defined(MY_OTA_FIRMWARE_FEATURE) - if(firmwareOTAUpdateProcess()){ - return; // OTA FW update processing indicated no further action needed - } - #endif +#if defined(MY_OTA_FIRMWARE_FEATURE) + if(firmwareOTAUpdateProcess()) { + return; // OTA FW update processing indicated no further action needed + } +#endif } + } else { + TRANSPORT_DEBUG( + PSTR("TSF:MSG:ACK\n")); // received message is ACK, no internal processing, handover to msg callback } - else { - TRANSPORT_DEBUG(PSTR("TSF:MSG:ACK\n")); // received message is ACK, no internal processing, handover to msg callback - } - #if defined(MY_GATEWAY_FEATURE) - // Hand over message to controller - (void)gatewayTransportSend(_msg); - #endif +#if defined(MY_GATEWAY_FEATURE) + // Hand over message to controller + (void)gatewayTransportSend(_msg); +#endif // Call incoming message callback if available if (receive) { receive(_msg); } - } - else if (destination == BROADCAST_ADDRESS) { + } else if (destination == BROADCAST_ADDRESS) { TRANSPORT_DEBUG(PSTR("TSF:MSG:BC\n")); // broadcast msg if (command == C_INTERNAL) { if (isTransportReady()) { // only reply if node is fully operational if (type == I_FIND_PARENT_REQUEST) { - #if defined(MY_REPEATER_FEATURE) +#if defined(MY_REPEATER_FEATURE) if (sender != _transportConfig.parentNodeId) { // no circular reference TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR REQ,ID=%d\n"), sender); // FPAR: find parent request // check if uplink functional - node can only be parent node if link to GW functional @@ -732,60 +761,61 @@ void transportProcessMessage(void) { TRANSPORT_DEBUG(PSTR("TSF:MSG:GWL OK\n")); // GW uplink ok // random delay minimizes collisions delay(hwMillis() & 0x3ff); - (void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_RESPONSE).set(_transportConfig.distanceGW)); - } - else { + (void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, + I_FIND_PARENT_RESPONSE).set(_transportConfig.distanceGW)); + } else { TRANSPORT_DEBUG(PSTR("!TSF:MSG:GWL FAIL\n")); // GW uplink fail, do not respond to parent request } } - #endif +#endif return; // no further processing required, do not forward } } // isTransportReady if (type == I_FIND_PARENT_RESPONSE) { return; // no further processing required, do not forward } - #if !defined(MY_GATEWAY_FEATURE) - if (type == I_DISCOVER_REQUEST) { - if (last == _transportConfig.parentNodeId) { - // random wait to minimize collisions - delay(hwMillis() & 0x3ff); - (void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, I_DISCOVER_RESPONSE).set(_transportConfig.parentNodeId)); - // no return here (for fwd if repeater) - } +#if !defined(MY_GATEWAY_FEATURE) + if (type == I_DISCOVER_REQUEST) { + if (last == _transportConfig.parentNodeId) { + // random wait to minimize collisions + delay(hwMillis() & 0x3ff); + (void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, + I_DISCOVER_RESPONSE).set(_transportConfig.parentNodeId)); + // no return here (for fwd if repeater) } - #endif + } +#endif } // controlled BC relay - #if defined(MY_REPEATER_FEATURE) - // controlled BC repeating: forward only if message received from parent and sender not self to prevent circular fwds - if(last == _transportConfig.parentNodeId && sender != _transportConfig.nodeId && isTransportReady()){ - TRANSPORT_DEBUG(PSTR("TSF:MSG:FWD BC MSG\n")); // controlled broadcast msg forwarding - (void)transportRouteMessage(_msg); - } - #endif +#if defined(MY_REPEATER_FEATURE) + // controlled BC repeating: forward only if message received from parent and sender not self to prevent circular fwds + if(last == _transportConfig.parentNodeId && sender != _transportConfig.nodeId && + isTransportReady()) { + TRANSPORT_DEBUG(PSTR("TSF:MSG:FWD BC MSG\n")); // controlled broadcast msg forwarding + (void)transportRouteMessage(_msg); + } +#endif // Callback for BC, only for non-internal messages if (command != C_INTERNAL) { - #if !defined(MY_GATEWAY_FEATURE) - // only proceed if message received from parent - if (last != _transportConfig.parentNodeId) { - return; - } - #endif - #if defined(MY_GATEWAY_FEATURE) - // Hand over message to controller - (void)gatewayTransportSend(_msg); - #endif +#if !defined(MY_GATEWAY_FEATURE) + // only proceed if message received from parent + if (last != _transportConfig.parentNodeId) { + return; + } +#endif +#if defined(MY_GATEWAY_FEATURE) + // Hand over message to controller + (void)gatewayTransportSend(_msg); +#endif if (receive) { receive(_msg); } } - } - else { + } else { // msg not to us and not BC, relay msg - #if defined(MY_REPEATER_FEATURE) +#if defined(MY_REPEATER_FEATURE) if (isTransportReady()) { TRANSPORT_DEBUG(PSTR("TSF:MSG:REL MSG\n")); // relay msg if (command == C_INTERNAL) { @@ -801,49 +831,51 @@ void transportProcessMessage(void) { // Relay this message to another node (void)transportRouteMessage(_msg); } - #else - TRANSPORT_DEBUG(PSTR("!TSF:MSG:REL MSG,NREP\n")); // message relaying request, but not a repeater - #endif +#else + TRANSPORT_DEBUG(PSTR("!TSF:MSG:REL MSG,NREP\n")); // message relaying request, but not a repeater +#endif } } -void transportInvokeSanityCheck(void) { +void transportInvokeSanityCheck(void) +{ if (!transportSanityCheck()) { TRANSPORT_DEBUG(PSTR("!TSF:SNK:FAIL\n")); // sanity check fail transportSwitchSM(stFailure); - } - else { + } else { TRANSPORT_DEBUG(PSTR("TSF:SNK:OK\n")); // sanity check ok } } -void transportProcessFIFO(void) { +void transportProcessFIFO(void) +{ if (!_transportSM.transportActive) { // transport not active, no further processing required return; } - #if defined(MY_TRANSPORT_SANITY_CHECK) - if (hwMillis() - _lastSanityCheck > MY_TRANSPORT_SANITY_CHECK_INTERVAL_MS) { - _lastSanityCheck = hwMillis(); - transportInvokeSanityCheck(); - } - #endif +#if defined(MY_TRANSPORT_SANITY_CHECK) + if (hwMillis() - _lastSanityCheck > MY_TRANSPORT_SANITY_CHECK_INTERVAL_MS) { + _lastSanityCheck = hwMillis(); + transportInvokeSanityCheck(); + } +#endif uint8_t _processedMessages = MAX_SUBSEQ_MSGS; // process all msgs in FIFO or counter exit while (transportAvailable() && _processedMessages--) { transportProcessMessage(); } - #if defined(MY_OTA_FIRMWARE_FEATURE) - if (isTransportReady()) { - // only process if transport ok - firmwareOTAUpdateRequest(); - } - #endif +#if defined(MY_OTA_FIRMWARE_FEATURE) + if (isTransportReady()) { + // only process if transport ok + firmwareOTAUpdateRequest(); + } +#endif } -bool transportSendWrite(const uint8_t to, MyMessage &message) { +bool transportSendWrite(const uint8_t to, MyMessage &message) +{ message.last = _transportConfig.nodeId; // Update last // sign message if required if (!signerSignMsg(message)) { @@ -853,7 +885,8 @@ bool transportSendWrite(const uint8_t to, MyMessage &message) { } // msg length changes if signed - const uint8_t totalMsgLength = HEADER_SIZE + ( mGetSigned(message) ? MAX_PAYLOAD : mGetLength(message) ); + const uint8_t totalMsgLength = HEADER_SIZE + ( mGetSigned(message) ? MAX_PAYLOAD : mGetLength( + message) ); // send setIndication(INDICATION_TX); @@ -862,8 +895,10 @@ bool transportSendWrite(const uint8_t to, MyMessage &message) { result |= (to == BROADCAST_ADDRESS); TRANSPORT_DEBUG(PSTR("%sTSF:MSG:SEND,%d-%d-%d-%d,s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d,ft=%d,st=%s:%s\n"), - (result ? "" : "!"), message.sender, message.last, to, message.destination, message.sensor, mGetCommand(message), message.type, - mGetPayloadType(message), mGetLength(message), mGetSigned(message), _transportSM.failedUplinkTransmissions, (result ? "OK" : "NACK"), message.getString(_convBuf)); + (result ? "" : "!"), message.sender, message.last, to, message.destination, message.sensor, + mGetCommand(message), message.type, + mGetPayloadType(message), mGetLength(message), mGetSigned(message), + _transportSM.failedUplinkTransmissions, (result ? "OK" : "NACK"), message.getString(_convBuf)); return result; } @@ -887,7 +922,8 @@ uint8_t transportGetDistanceGW(void) } -void transportClearRoutingTable(void) { +void transportClearRoutingTable(void) +{ for (uint16_t i = 0; i < SIZE_ROUTES; i++) { transportSetRoute((uint8_t)i, BROADCAST_ADDRESS); } @@ -895,34 +931,38 @@ void transportClearRoutingTable(void) { TRANSPORT_DEBUG(PSTR("TSF:CRT:OK\n")); // clear routing table } -void transportLoadRoutingTable(void) { - #if defined(MY_RAM_ROUTING_TABLE_ENABLED) - hwReadConfigBlock((void*)&_transportRoutingTable.route, (void*)EEPROM_ROUTES_ADDRESS, SIZE_ROUTES); - TRANSPORT_DEBUG(PSTR("TSF:LRT:OK\n")); // load routing table - #endif +void transportLoadRoutingTable(void) +{ +#if defined(MY_RAM_ROUTING_TABLE_ENABLED) + hwReadConfigBlock((void*)&_transportRoutingTable.route, (void*)EEPROM_ROUTES_ADDRESS, SIZE_ROUTES); + TRANSPORT_DEBUG(PSTR("TSF:LRT:OK\n")); // load routing table +#endif } -void transportSaveRoutingTable(void) { - #if defined(MY_RAM_ROUTING_TABLE_ENABLED) - hwWriteConfigBlock((void*)&_transportRoutingTable.route, (void*)EEPROM_ROUTES_ADDRESS, SIZE_ROUTES); - TRANSPORT_DEBUG(PSTR("TSF:SRT:OK\n")); // save routing table - #endif +void transportSaveRoutingTable(void) +{ +#if defined(MY_RAM_ROUTING_TABLE_ENABLED) + hwWriteConfigBlock((void*)&_transportRoutingTable.route, (void*)EEPROM_ROUTES_ADDRESS, SIZE_ROUTES); + TRANSPORT_DEBUG(PSTR("TSF:SRT:OK\n")); // save routing table +#endif } -void transportSetRoute(const uint8_t node, const uint8_t route) { - #if defined(MY_RAM_ROUTING_TABLE_ENABLED) - _transportRoutingTable.route[node] = route; - #else - hwWriteConfig(EEPROM_ROUTES_ADDRESS + node, route); - #endif +void transportSetRoute(const uint8_t node, const uint8_t route) +{ +#if defined(MY_RAM_ROUTING_TABLE_ENABLED) + _transportRoutingTable.route[node] = route; +#else + hwWriteConfig(EEPROM_ROUTES_ADDRESS + node, route); +#endif } -uint8_t transportGetRoute(const uint8_t node) { +uint8_t transportGetRoute(const uint8_t node) +{ uint8_t result; - #if defined(MY_RAM_ROUTING_TABLE_ENABLED) - result = _transportRoutingTable.route[node]; - #else - result = hwReadConfig(EEPROM_ROUTES_ADDRESS + node); - #endif +#if defined(MY_RAM_ROUTING_TABLE_ENABLED) + result = _transportRoutingTable.route[node]; +#else + result = hwReadConfig(EEPROM_ROUTES_ADDRESS + node); +#endif return result; } diff --git a/core/MyTransport.h b/core/MyTransport.h index 4508cc9..52cdd48 100644 --- a/core/MyTransport.h +++ b/core/MyTransport.h @@ -17,166 +17,166 @@ * version 2 as published by the Free Software Foundation. */ - /** - * @file MyTransport.h - * - * @defgroup MyTransportgrp MyTransport - * @ingroup internals - * @{ - * - * Transport-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE - * - [!] Exclamation mark is prepended in case of error - * - SYSTEM: - * - TSM: messages emitted by the transport state machine - * - TSF: messages emitted by transport support functions - * - SUB SYSTEMS: - * - Transport state machine (TSM) - * - TSM:INIT from stInit Initialize transport and radio - * - TSM:FPAR from stParent Find parent - * - TSM:ID from stID Check/request node ID, if dynamic node ID set - * - TSM:UPL from stUplink Verify uplink connection by pinging GW - * - TSM:READY from stReady Transport is ready and fully operational - * - TSM:FAIL from stFailure Failure in transport link or transport HW - * - Transport support function (TSF) - * - TSF:CHKUPL from @ref transportCheckUplink(), checks connection to GW - * - TSF:ASID from @ref transportAssignNodeID(), assigns node ID - * - TSF:PING from @ref transportPingNode(), pings a node - * - TSF:WUR from @ref transportWaitUntilReady(), waits until transport is ready - * - TSF:CRT from @ref transportClearRoutingTable(), clears routing table stored in EEPROM - * - TSF:LRT from @ref transportLoadRoutingTable(), loads RAM routing table from EEPROM (only GW/repeaters) - * - TSF:SRT from @ref transportSaveRoutingTable(), saves RAM routing table to EEPROM (only GW/repeaters) - * - TSF:MSG from @ref transportProcessMessage(), processes incoming message - * - TSF:SANCHK from @ref transportInvokeSanityCheck(), calls transport-specific sanity check - * - TSF:ROUTE from @ref transportRouteMessage(), sends message - * - TSF:SEND from @ref transportSendRoute(), sends message if transport is ready (exposed) +/** +* @file MyTransport.h +* +* @defgroup MyTransportgrp MyTransport +* @ingroup internals +* @{ +* +* Transport-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE +* - [!] Exclamation mark is prepended in case of error +* - SYSTEM: +* - TSM: messages emitted by the transport state machine +* - TSF: messages emitted by transport support functions +* - SUB SYSTEMS: +* - Transport state machine (TSM) +* - TSM:INIT from stInit Initialize transport and radio +* - TSM:FPAR from stParent Find parent +* - TSM:ID from stID Check/request node ID, if dynamic node ID set +* - TSM:UPL from stUplink Verify uplink connection by pinging GW +* - TSM:READY from stReady Transport is ready and fully operational +* - TSM:FAIL from stFailure Failure in transport link or transport HW +* - Transport support function (TSF) +* - TSF:CHKUPL from @ref transportCheckUplink(), checks connection to GW +* - TSF:ASID from @ref transportAssignNodeID(), assigns node ID +* - TSF:PING from @ref transportPingNode(), pings a node +* - TSF:WUR from @ref transportWaitUntilReady(), waits until transport is ready +* - TSF:CRT from @ref transportClearRoutingTable(), clears routing table stored in EEPROM +* - TSF:LRT from @ref transportLoadRoutingTable(), loads RAM routing table from EEPROM (only GW/repeaters) +* - TSF:SRT from @ref transportSaveRoutingTable(), saves RAM routing table to EEPROM (only GW/repeaters) +* - TSF:MSG from @ref transportProcessMessage(), processes incoming message +* - TSF:SANCHK from @ref transportInvokeSanityCheck(), calls transport-specific sanity check +* - TSF:ROUTE from @ref transportRouteMessage(), sends message +* - TSF:SEND from @ref transportSendRoute(), sends message if transport is ready (exposed) - * - * Transport debug log messages: - * - * |E| SYS | SUB | Message | Comment - * |-|------|-----------|-----------------------|--------------------------------------------------------------------- - * | | TSM | INIT | | Transition to stInit state - * | | TSM | INIT | STATID=%%d | Node ID is static - * | | TSM | INIT | TSP OK | Transport device configured and fully operational - * | | TSM | INIT | GW MODE | Node is set up as GW, thus omitting ID and findParent states - * |!| TSM | INIT | TSP FAIL | Transport device initialization failed - * | | TSM | FPAR | | Transition to stParent state - * | | TSM | FPAR | STATP=%%d | Static parent set, skip finding parent - * | | TSM | FPAR | OK | Parent node identified - * |!| TSM | FPAR | NO REPLY | No potential parents replied to find parent request - * |!| TSM | FPAR | FAIL | Finding parent failed - * | | TSM | ID | | Transition to stID state - * | | TSM | ID | OK,ID=%%d | Node ID is valid - * | | TSM | ID | REQ | Request node ID from controller - * |!| TSM | ID | FAIL,ID=%%d | ID verification failed, ID invalid - * | | TSM | UPL | | Transition to stUplink state - * | | TSM | UPL | OK | Uplink OK, GW returned ping - * | | TSF | UPL | DGWC,O=%%d,N=%%d | Uplink check revealed changed network topology, old distance (O), new distance (N) - * |!| TSM | UPL | FAIL | Uplink check failed, i.e. GW could not be pinged - * | | TSM | READY | SRT | Save routing table - * | | TSM | READY | ID=%%d,PAR=%%d,DIS=%%d| Transition to stReady Transport ready, node ID (ID), parent node ID (PAR), distance to GW (DIS) - * |!| TSM | READY | UPL FAIL,SNP | Too many failed uplink transmissions, search new parent - * |!| TSM | READY | FAIL,STATP | Too many failed uplink transmissions, static parent enforced - * | | TSM | FAIL | CNT=%%d | Transition to stFailure state, consecutive failure counter (CNT) - * | | TSM | FAIL | PDT | Power-down transport - * | | TSM | FAIL | RE-INIT | Attempt to re-initialize transport - * | | TSF | CHKUPL | OK | Uplink OK - * | | TSF | CHKUPL | OK,FCTRL | Uplink OK, flood control prevents pinging GW in too short intervals - * | | TSF | CHKUPL | DGWC,O=%%d,N=%%d | Uplink check revealed changed network topology, old distance (O), new distance (N) - * | | TSF | CHKUPL | FAIL | No reply received when checking uplink - * | | TSF | ASID | OK,ID=%%d | Node ID assigned - * |!| TSF | ASID | FAIL,ID=%%d | Assigned ID is invalid - * | | TSF | PING | SEND,TO=%%d | Send ping to destination (TO) - * | | TSF | WUR | MS=%%lu | Wait until transport ready, timeout (MS) - * | | TSF | MSG | ACK REQ | ACK message requested - * | | TSF | MSG | ACK | ACK message, do not proceed but forward to callback - * | | TSF | MSG | FPAR RES,ID=%%d,D=%%d | Response to find parent received from node (ID) with distance (D) to GW - * | | TSF | MSG | FPAR PREF FOUND | Preferred parent found, i.e. parent defined via MY_PARENT_NODE_ID - * | | TSF | MSG | FPAR OK,ID=%%d,D=%%d | Find parent response from node (ID) is valid, distance (D) to GW - * | | TSF | MSG | FPAR INACTIVE | Find parent response received, but no find parent request active, skip response - * | | TSF | MSG | FPAR REQ,ID=%%d | Find parent request from node (ID) - * | | TSF | MSG | PINGED,ID=%%d,HP=%%d | Node pinged by node (ID) with (HP) hops - * | | TSF | MSG | PONG RECV,HP=%%d | Pinged node replied with (HP) hops - * | | TSF | MSG | BC | Broadcast message received - * | | TSF | MSG | GWL OK | Link to GW ok - * | | TSF | MSG | FWD BC MSG | Controlled broadcast message forwarding - * | | TSF | MSG | REL MSG | Relay message - * | | TSF | MSG | REL PxNG,HP=%%d | Relay PING/PONG message, increment hop counter (HP) - * |!| TSF | MSG | LEN,%%d!=%%d | Invalid message length, (actual!=expected) - * |!| TSF | MSG | PVER,%%d!=%%d | Message protocol version mismatch (actual!=expected) - * |!| TSF | MSG | SIGN VERIFY FAIL | Signing verification failed - * |!| TSF | MSG | REL MSG,NORP | Node received a message for relaying, but node is not a repeater, message skipped - * |!| TSF | MSG | SIGN FAIL | Signing message failed - * |!| TSF | MSG | GWL FAIL | GW uplink failed - * | | TSF | SANCHK | OK | Sanity check passed - * |!| TSF | SANCHK | FAIL | Sanity check failed, attempt to re-initialize radio - * | | TSF | CRT | OK | Clearing routing table successful - * | | TSF | LRT | OK | Loading routing table successful - * | | TSF | SRT | OK | Saving routing table successful - * |!| TSF | ROUTE | FPAR ACTIVE | Finding parent active, message not sent - * |!| TSF | ROUTE | DST %%d UNKNOWN | Routing for destination (DST) unknown, send message to parent - * |!| TSF | SEND | TNR | Transport not ready, message cannot be sent - * - * Incoming / outgoing messages: - * - * See here for more detail on the format and definitons. - * - * Receiving a message - * - TSF:MSG:READ,sender-last-destination,s=%%d,c=%%d,t=%%d,pt=%%d,l=%%d,sg=%%d:%%s - * - * Sending a message - * - [!]TSF:MSG:SEND,sender-last-next-destination,s=%%d,c=%%d,t=%%d,pt=%%d,l=%%d,sg=%%d,ft=%%d,st=%%s:%%s - * - * Message fields: - * - s=sensor ID - * - c=command - * - t=msg type - * - pt=payload type - * - l=length - * - sg=signing flag - * - ft=failed uplink transmission counter - * - st=send status, OK=success, NACK=no radio ACK received - * - * @brief API declaration for MyTransport - * - */ +* +* Transport debug log messages: +* +* |E| SYS | SUB | Message | Comment +* |-|------|-----------|-----------------------|--------------------------------------------------------------------- +* | | TSM | INIT | | Transition to stInit state +* | | TSM | INIT | STATID=%%d | Node ID is static +* | | TSM | INIT | TSP OK | Transport device configured and fully operational +* | | TSM | INIT | GW MODE | Node is set up as GW, thus omitting ID and findParent states +* |!| TSM | INIT | TSP FAIL | Transport device initialization failed +* | | TSM | FPAR | | Transition to stParent state +* | | TSM | FPAR | STATP=%%d | Static parent set, skip finding parent +* | | TSM | FPAR | OK | Parent node identified +* |!| TSM | FPAR | NO REPLY | No potential parents replied to find parent request +* |!| TSM | FPAR | FAIL | Finding parent failed +* | | TSM | ID | | Transition to stID state +* | | TSM | ID | OK,ID=%%d | Node ID is valid +* | | TSM | ID | REQ | Request node ID from controller +* |!| TSM | ID | FAIL,ID=%%d | ID verification failed, ID invalid +* | | TSM | UPL | | Transition to stUplink state +* | | TSM | UPL | OK | Uplink OK, GW returned ping +* | | TSF | UPL | DGWC,O=%%d,N=%%d | Uplink check revealed changed network topology, old distance (O), new distance (N) +* |!| TSM | UPL | FAIL | Uplink check failed, i.e. GW could not be pinged +* | | TSM | READY | SRT | Save routing table +* | | TSM | READY | ID=%%d,PAR=%%d,DIS=%%d| Transition to stReady Transport ready, node ID (ID), parent node ID (PAR), distance to GW (DIS) +* |!| TSM | READY | UPL FAIL,SNP | Too many failed uplink transmissions, search new parent +* |!| TSM | READY | FAIL,STATP | Too many failed uplink transmissions, static parent enforced +* | | TSM | FAIL | CNT=%%d | Transition to stFailure state, consecutive failure counter (CNT) +* | | TSM | FAIL | PDT | Power-down transport +* | | TSM | FAIL | RE-INIT | Attempt to re-initialize transport +* | | TSF | CHKUPL | OK | Uplink OK +* | | TSF | CHKUPL | OK,FCTRL | Uplink OK, flood control prevents pinging GW in too short intervals +* | | TSF | CHKUPL | DGWC,O=%%d,N=%%d | Uplink check revealed changed network topology, old distance (O), new distance (N) +* | | TSF | CHKUPL | FAIL | No reply received when checking uplink +* | | TSF | ASID | OK,ID=%%d | Node ID assigned +* |!| TSF | ASID | FAIL,ID=%%d | Assigned ID is invalid +* | | TSF | PING | SEND,TO=%%d | Send ping to destination (TO) +* | | TSF | WUR | MS=%%lu | Wait until transport ready, timeout (MS) +* | | TSF | MSG | ACK REQ | ACK message requested +* | | TSF | MSG | ACK | ACK message, do not proceed but forward to callback +* | | TSF | MSG | FPAR RES,ID=%%d,D=%%d | Response to find parent received from node (ID) with distance (D) to GW +* | | TSF | MSG | FPAR PREF FOUND | Preferred parent found, i.e. parent defined via MY_PARENT_NODE_ID +* | | TSF | MSG | FPAR OK,ID=%%d,D=%%d | Find parent response from node (ID) is valid, distance (D) to GW +* | | TSF | MSG | FPAR INACTIVE | Find parent response received, but no find parent request active, skip response +* | | TSF | MSG | FPAR REQ,ID=%%d | Find parent request from node (ID) +* | | TSF | MSG | PINGED,ID=%%d,HP=%%d | Node pinged by node (ID) with (HP) hops +* | | TSF | MSG | PONG RECV,HP=%%d | Pinged node replied with (HP) hops +* | | TSF | MSG | BC | Broadcast message received +* | | TSF | MSG | GWL OK | Link to GW ok +* | | TSF | MSG | FWD BC MSG | Controlled broadcast message forwarding +* | | TSF | MSG | REL MSG | Relay message +* | | TSF | MSG | REL PxNG,HP=%%d | Relay PING/PONG message, increment hop counter (HP) +* |!| TSF | MSG | LEN,%%d!=%%d | Invalid message length, (actual!=expected) +* |!| TSF | MSG | PVER,%%d!=%%d | Message protocol version mismatch (actual!=expected) +* |!| TSF | MSG | SIGN VERIFY FAIL | Signing verification failed +* |!| TSF | MSG | REL MSG,NORP | Node received a message for relaying, but node is not a repeater, message skipped +* |!| TSF | MSG | SIGN FAIL | Signing message failed +* |!| TSF | MSG | GWL FAIL | GW uplink failed +* | | TSF | SANCHK | OK | Sanity check passed +* |!| TSF | SANCHK | FAIL | Sanity check failed, attempt to re-initialize radio +* | | TSF | CRT | OK | Clearing routing table successful +* | | TSF | LRT | OK | Loading routing table successful +* | | TSF | SRT | OK | Saving routing table successful +* |!| TSF | ROUTE | FPAR ACTIVE | Finding parent active, message not sent +* |!| TSF | ROUTE | DST %%d UNKNOWN | Routing for destination (DST) unknown, send message to parent +* |!| TSF | SEND | TNR | Transport not ready, message cannot be sent +* +* Incoming / outgoing messages: +* +* See here for more detail on the format and definitons. +* +* Receiving a message +* - TSF:MSG:READ,sender-last-destination,s=%%d,c=%%d,t=%%d,pt=%%d,l=%%d,sg=%%d:%%s +* +* Sending a message +* - [!]TSF:MSG:SEND,sender-last-next-destination,s=%%d,c=%%d,t=%%d,pt=%%d,l=%%d,sg=%%d,ft=%%d,st=%%s:%%s +* +* Message fields: +* - s=sensor ID +* - c=command +* - t=msg type +* - pt=payload type +* - l=length +* - sg=signing flag +* - ft=failed uplink transmission counter +* - st=send status, OK=success, NACK=no radio ACK received +* +* @brief API declaration for MyTransport +* +*/ #ifndef MyTransport_h #define MyTransport_h #include "MySensorsCore.h" - // debug +// debug #if defined(MY_DEBUG) - #define TRANSPORT_DEBUG(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug - extern char _convBuf[MAX_PAYLOAD * 2 + 1]; +#define TRANSPORT_DEBUG(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug +extern char _convBuf[MAX_PAYLOAD * 2 + 1]; #else - #define TRANSPORT_DEBUG(x,...) //!< debug NULL +#define TRANSPORT_DEBUG(x,...) //!< debug NULL #endif #if defined(MY_REPEATER_FEATURE) - #define MY_TRANSPORT_MAX_TX_FAILURES (10u) //!< search for a new parent node after this many transmission failures, higher threshold for repeating nodes +#define MY_TRANSPORT_MAX_TX_FAILURES (10u) //!< search for a new parent node after this many transmission failures, higher threshold for repeating nodes #else - #define MY_TRANSPORT_MAX_TX_FAILURES (5u) //!< search for a new parent node after this many transmission failures, lower threshold for non-repeating nodes +#define MY_TRANSPORT_MAX_TX_FAILURES (5u) //!< search for a new parent node after this many transmission failures, lower threshold for non-repeating nodes #endif #define MY_TRANSPORT_MAX_TSM_FAILURES (7u) //!< Max. number of consecutive TSM failure state entries (3bits) #ifndef MY_TRANSPORT_TIMEOUT_FAILURE_STATE - #define MY_TRANSPORT_TIMEOUT_FAILURE_STATE (10*1000ul) //!< Duration failure state (in ms) +#define MY_TRANSPORT_TIMEOUT_FAILURE_STATE (10*1000ul) //!< Duration failure state (in ms) #endif #ifndef MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE - #define MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE (60*1000ul) //!< Duration extended failure state (in ms) +#define MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE (60*1000ul) //!< Duration extended failure state (in ms) #endif #ifndef MY_TRANSPORT_STATE_TIMEOUT_MS - #define MY_TRANSPORT_STATE_TIMEOUT_MS (2*1000ul) //!< general state timeout (in ms) +#define MY_TRANSPORT_STATE_TIMEOUT_MS (2*1000ul) //!< general state timeout (in ms) #endif #ifndef MY_TRANSPORT_CHKUPL_INTERVAL_MS - #define MY_TRANSPORT_CHKUPL_INTERVAL_MS (10*1000ul) //!< Interval to re-check uplink (in ms) +#define MY_TRANSPORT_CHKUPL_INTERVAL_MS (10*1000ul) //!< Interval to re-check uplink (in ms) #endif #ifndef MY_TRANSPORT_STATE_RETRIES - #define MY_TRANSPORT_STATE_RETRIES (3u) //!< retries before switching to FAILURE +#define MY_TRANSPORT_STATE_RETRIES (3u) //!< retries before switching to FAILURE #endif #define AUTO (255u) //!< ID 255 is reserved @@ -188,7 +188,7 @@ // parent node check #if defined(MY_PARENT_NODE_IS_STATIC) && !defined(MY_PARENT_NODE_ID) - #error MY_PARENT_NODE_IS_STATIC but no MY_PARENT_NODE_ID defined! +#error MY_PARENT_NODE_IS_STATIC but no MY_PARENT_NODE_ID defined! #endif #define _autoFindParent (bool)(MY_PARENT_NODE_ID == AUTO) //!< returns true if static parent id is undefined @@ -197,14 +197,14 @@ // RX queue #if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - #if defined(MY_RADIO_RFM69) - #error Receive message buffering not supported for RFM69! - #endif - #if defined(MY_RS485) - #error Receive message buffering not supported for RS485! - #endif +#if defined(MY_RADIO_RFM69) +#error Receive message buffering not supported for RFM69! +#endif +#if defined(MY_RS485) +#error Receive message buffering not supported for RS485! +#endif #elif !defined(MY_RX_MESSAGE_BUFFER_FEATURE) && defined(MY_RX_MESSAGE_BUFFER_SIZE) - #error Receive message buffering requires message buffering feature enabled! +#error Receive message buffering requires message buffering feature enabled! #endif /** @@ -237,7 +237,7 @@ typedef struct { * @brief Status variables and SM state * * This structure stores transport status and SM variables - */ + */ typedef struct { // SM variables transportState_t* currentState; //!< pointer to current fsm state @@ -252,7 +252,7 @@ typedef struct { bool transportActive : 1; //!< flag transport active uint8_t stateRetries : 3; //!< retries / state re-enter (max 7) // 8 bits - uint8_t failedUplinkTransmissions : 4; //!< counter failed uplink transmissions (max 15) + uint8_t failedUplinkTransmissions : 4; //!< counter failed uplink transmissions (max 15) uint8_t failureCounter : 3; //!< counter for TSM failures (max 7) bool msgReceived : 1; //!< flag message received // 8 bits @@ -309,7 +309,7 @@ void stReadyTransition(void); */ void stReadyUpdate(void); /** -* @brief Transport failure and power down radio +* @brief Transport failure and power down radio */ void stFailureTransition(void); /** @@ -352,7 +352,7 @@ bool transportAssignNodeID(const uint8_t newNodeId); * @brief Wait and process messages for a defined amount of time until specified message received * @param waitingMS Time to wait and process incoming messages in ms * @param cmd Specific command -* @param msgType Specific message type +* @param msgType Specific message type * @return true if specified command received within waiting time */ bool transportWait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType); @@ -364,7 +364,7 @@ bool transportWait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t ms uint8_t transportPingNode(const uint8_t targetId); /** * @brief Send and route message according to destination -* +* * This function is used in MyTransport and omits the transport state check, i.e. message can be sent even if transport is not ready * * @param message @@ -381,7 +381,7 @@ bool transportSendRoute(MyMessage &message); * @brief Send message to recipient * @param to Recipient of message * @param message -* @return true if message sent successfully +* @return true if message sent successfully */ bool transportSendWrite(const uint8_t to, MyMessage &message); /** @@ -501,7 +501,7 @@ bool transportSanityCheck(); * @brief Receive message from FIFO * @return length of recevied message (header + payload) */ -uint8_t transportReceive(void* data); +uint8_t transportReceive(void* data); /** * @brief Power down transport HW */ diff --git a/core/MyTransportNRF24.cpp b/core/MyTransportNRF24.cpp index e1d6ba4..65230da 100644 --- a/core/MyTransportNRF24.cpp +++ b/core/MyTransportNRF24.cpp @@ -30,33 +30,34 @@ #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 + 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 @@ -69,86 +70,86 @@ uint8_t _psk[16]; 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); + 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 ); + RF24_registerReceiveCallback( transportRxCallback ); #endif - return RF24_initialize(); + return RF24_initialize(); } void transportSetAddress(const uint8_t address) { - RF24_setNodeAddress(address); - RF24_startListening(); + RF24_setNodeAddress(address); + RF24_startListening(); } uint8_t transportGetAddress(void) { - return RF24_getNodeID(); + return RF24_getNodeID(); } 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); + // 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); + return RF24_sendMessage(recipient, data, len); #endif } bool transportAvailable(void) { #if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - (void)RF24_isDataAvailable; // Prevent 'defined but not used' warning - return !transportRxQueue.empty(); + (void)RF24_isDataAvailable; // Prevent 'defined but not used' warning + return !transportRxQueue.empty(); #else - return RF24_isDataAvailable(); + return RF24_isDataAvailable(); #endif } bool transportSanityCheck(void) { - return RF24_sanityCheck(); + return RF24_sanityCheck(); } uint8_t transportReceive(void* data) { - uint8_t len = 0; + 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(); - } + 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); + len = RF24_readMessage(data); #endif #if defined(MY_RF24_ENABLE_ENCRYPTION) - // has to be adjusted, WIP! - _aes.set_IV(0); - // decrypt data + // has to be adjusted, WIP! + _aes.set_IV(0); + // decrypt data if (_aes.cbc_decrypt((uint8_t*)(data), (uint8_t*)(data), len > 16 ? 2 : 1) != AES_SUCCESS) { len = 0; } #endif - return len; + return len; } void transportPowerDown(void) { - RF24_powerDown(); + RF24_powerDown(); } diff --git a/core/MyTransportRFM69.cpp b/core/MyTransportRFM69.cpp index 6ed7283..b5ff53f 100644 --- a/core/MyTransportRFM69.cpp +++ b/core/MyTransportRFM69.cpp @@ -26,43 +26,50 @@ RFM69 _radio(MY_RF69_SPI_CS, MY_RF69_IRQ_PIN, MY_RFM69HW, MY_RF69_IRQ_NUM); uint8_t _address; -bool transportInit() { +bool transportInit() +{ // Start up the radio library (_address will be set later by the MySensors library) if (_radio.initialize(MY_RFM69_FREQUENCY, _address, MY_RFM69_NETWORKID)) { - #ifdef MY_RFM69_ENABLE_ENCRYPTION - uint8_t _psk[16]; - hwReadConfigBlock((void*)_psk, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); - _radio.encrypt((const char*)_psk); - memset(_psk, 0, 16); // Make sure it is purged from memory when set - #endif +#ifdef MY_RFM69_ENABLE_ENCRYPTION + uint8_t _psk[16]; + hwReadConfigBlock((void*)_psk, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); + _radio.encrypt((const char*)_psk); + memset(_psk, 0, 16); // Make sure it is purged from memory when set +#endif return true; } return false; } -void transportSetAddress(uint8_t address) { +void transportSetAddress(uint8_t address) +{ _address = address; _radio.setAddress(address); } -uint8_t transportGetAddress() { +uint8_t transportGetAddress() +{ return _address; } -bool transportSend(uint8_t to, const void* data, uint8_t len) { +bool transportSend(uint8_t to, const void* data, uint8_t len) +{ return _radio.sendWithRetry(to,data,len); } -bool transportAvailable() { +bool transportAvailable() +{ return _radio.receiveDone(); } -bool transportSanityCheck() { +bool transportSanityCheck() +{ // not implemented yet return true; } -uint8_t transportReceive(void* data) { +uint8_t transportReceive(void* data) +{ memcpy(data,(const void *)_radio.DATA, _radio.DATALEN); // save payload length const uint8_t dataLen = _radio.DATALEN; @@ -71,8 +78,9 @@ uint8_t transportReceive(void* data) { _radio.sendACK(); } return dataLen; -} +} -void transportPowerDown() { +void transportPowerDown() +{ _radio.sleep(); } diff --git a/core/MyTransportRFM95.cpp b/core/MyTransportRFM95.cpp index 1d3ec33..8bdedf3 100644 --- a/core/MyTransportRFM95.cpp +++ b/core/MyTransportRFM95.cpp @@ -22,43 +22,52 @@ #include "MyTransport.h" #include "drivers/RFM95/RFM95.h" -bool transportInit(void) { +bool transportInit(void) +{ const bool result = RFM95_initialise(MY_RFM95_FREQUENCY); - #if !defined(MY_GATEWAY_FEATURE) && !defined(MY_RFM95_ATC_MODE_DISABLED) - // only enable ATC mode nodes - RFM95_ATCmode(true, MY_RFM95_ATC_TARGET_RSSI); - #endif +#if !defined(MY_GATEWAY_FEATURE) && !defined(MY_RFM95_ATC_MODE_DISABLED) + // only enable ATC mode nodes + RFM95_ATCmode(true, MY_RFM95_ATC_TARGET_RSSI); +#endif return result; } -void transportSetAddress(uint8_t address) { +void transportSetAddress(uint8_t address) +{ RFM95_setAddress(address); } -uint8_t transportGetAddress(void) { +uint8_t transportGetAddress(void) +{ return RFM95_getAddress(); } -bool transportSend(uint8_t to, const void* data, uint8_t len) { +bool transportSend(uint8_t to, const void* data, uint8_t len) +{ return RFM95_sendWithRetry(to, data, len); } -bool transportAvailable(void) { +bool transportAvailable(void) +{ return RFM95_available(); } -bool transportSanityCheck(void) { +bool transportSanityCheck(void) +{ return RFM95_sanityCheck(); } -uint8_t transportReceive(void* data) { +uint8_t transportReceive(void* data) +{ return RFM95_recv((uint8_t*)data); -} +} -void transportPowerDown(void) { +void transportPowerDown(void) +{ (void)RFM95_sleep(); } -int16_t transportGetSignalStrength(void) { +int16_t transportGetSignalStrength(void) +{ return RFM95_getRSSI(); } diff --git a/core/MyTransportRS485.cpp b/core/MyTransportRS485.cpp index 780301a..b865602 100644 --- a/core/MyTransportRS485.cpp +++ b/core/MyTransportRS485.cpp @@ -62,16 +62,16 @@ #include "MyTransport.h" #ifdef __linux__ - #include "SerialPort.h" +#include "SerialPort.h" #endif #if defined(MY_RS485_DE_PIN) - #define assertDE() hwDigitalWrite(MY_RS485_DE_PIN, HIGH); delayMicroseconds(5) - #define deassertDE() hwDigitalWrite(MY_RS485_DE_PIN, LOW) +#define assertDE() hwDigitalWrite(MY_RS485_DE_PIN, HIGH); delayMicroseconds(5) +#define deassertDE() hwDigitalWrite(MY_RS485_DE_PIN, LOW) #else - #define assertDE() - #define deassertDE() +#define assertDE() +#define deassertDE() #endif // We only use SYS_PACK in this application @@ -114,13 +114,14 @@ bool _packet_received; //Reset the state machine and release the data pointer -void _serialReset(){ - _recPhase = 0; - _recPos = 0; - _recLen = 0; - _recCommand = 0; - _recCS = 0; - _recCalcCS = 0; +void _serialReset() +{ + _recPhase = 0; + _recPos = 0; + _recLen = 0; + _recCommand = 0; + _recCS = 0; + _recCalcCS = 0; } // This is the main reception state machine. Progress through the states @@ -132,118 +133,118 @@ void _serialReset(){ // function. bool _serialProcess() { - char inch; - unsigned char i; - if (!_dev.available()) { - return false; + char inch; + unsigned char i; + if (!_dev.available()) { + return false; + } + + while(_dev.available()) { + inch = _dev.read(); + + switch(_recPhase) { + + // Case 0 looks for the header. Bytes arrive in the serial interface and get + // shifted through a header buffer. When the start and end characters in + // the buffer match the SOH/STX pair, and the destination station ID matches + // our ID, save the header information and progress to the next state. + case 0: + memcpy(&_header[0],&_header[1],5); + _header[5] = inch; + if ((_header[0] == SOH) && (_header[5] == STX) && (_header[1] != _header[2])) { + _recCalcCS = 0; + _recStation = _header[1]; + _recSender = _header[2]; + _recCommand = _header[3]; + _recLen = _header[4]; + + for (i=1; i<=4; i++) { + _recCalcCS += _header[i]; + } + _recPhase = 1; + _recPos = 0; + + //Check if we should process this message + //We reject the message if we are the sender + //We reject if we are not the receiver and message is not a broadcast + if ((_recSender == _nodeId) || + (_recStation != _nodeId && + _recStation != BROADCAST_ADDRESS)) { + _serialReset(); + break; + } + + if (_recLen == 0) { + _recPhase = 2; + } + + } + break; + + // Case 1 receives the data portion of the packet. Read in "_recLen" number + // of bytes and store them in the _data array. + case 1: + _data[_recPos++] = inch; + _recCalcCS += inch; + if (_recPos == _recLen) { + _recPhase = 2; + } + break; + + // After the data comes a single ETX character. Do we have it? If not, + // reset the state machine to default and start looking for a new header. + case 2: + // Packet properly terminated? + if (inch == ETX) { + _recPhase = 3; + } else { + _serialReset(); + } + break; + + // Next comes the checksum. We have already calculated it from the incoming + // data, so just store the incoming checksum byte for later. + case 3: + _recCS = inch; + _recPhase = 4; + break; + + // The final state - check the last character is EOT and that the checksum matches. + // If that test passes, then look for a valid command callback to execute. + // Execute it if found. + case 4: + if (inch == EOT) { + if (_recCS == _recCalcCS) { + // First, check for system level commands. It is possible + // to register your own callback as well for system level + // commands which will be called after the system default + // hook. + + switch (_recCommand) { + case ICSC_SYS_PACK: + _packet_from = _recSender; + _packet_len = _recLen; + _packet_received = true; + break; + } + } + } + //Clear the data + _serialReset(); + //Return true, we have processed one command + return true; + break; } - - while(_dev.available()) { - inch = _dev.read(); - - switch(_recPhase) { - - // Case 0 looks for the header. Bytes arrive in the serial interface and get - // shifted through a header buffer. When the start and end characters in - // the buffer match the SOH/STX pair, and the destination station ID matches - // our ID, save the header information and progress to the next state. - case 0: - memcpy(&_header[0],&_header[1],5); - _header[5] = inch; - if ((_header[0] == SOH) && (_header[5] == STX) && (_header[1] != _header[2])) { - _recCalcCS = 0; - _recStation = _header[1]; - _recSender = _header[2]; - _recCommand = _header[3]; - _recLen = _header[4]; - - for (i=1; i<=4; i++) { - _recCalcCS += _header[i]; - } - _recPhase = 1; - _recPos = 0; - - //Check if we should process this message - //We reject the message if we are the sender - //We reject if we are not the receiver and message is not a broadcast - if ((_recSender == _nodeId) || - (_recStation != _nodeId && - _recStation != BROADCAST_ADDRESS)) { - _serialReset(); - break; - } - - if (_recLen == 0) { - _recPhase = 2; - } - - } - break; - - // Case 1 receives the data portion of the packet. Read in "_recLen" number - // of bytes and store them in the _data array. - case 1: - _data[_recPos++] = inch; - _recCalcCS += inch; - if (_recPos == _recLen) { - _recPhase = 2; - } - break; - - // After the data comes a single ETX character. Do we have it? If not, - // reset the state machine to default and start looking for a new header. - case 2: - // Packet properly terminated? - if (inch == ETX) { - _recPhase = 3; - } else { - _serialReset(); - } - break; - - // Next comes the checksum. We have already calculated it from the incoming - // data, so just store the incoming checksum byte for later. - case 3: - _recCS = inch; - _recPhase = 4; - break; - - // The final state - check the last character is EOT and that the checksum matches. - // If that test passes, then look for a valid command callback to execute. - // Execute it if found. - case 4: - if (inch == EOT) { - if (_recCS == _recCalcCS) { - // First, check for system level commands. It is possible - // to register your own callback as well for system level - // commands which will be called after the system default - // hook. - - switch (_recCommand) { - case ICSC_SYS_PACK: - _packet_from = _recSender; - _packet_len = _recLen; - _packet_received = true; - break; - } - } - } - //Clear the data - _serialReset(); - //Return true, we have processed one command - return true; - break; - } - } - return true; + } + return true; } bool transportSend(uint8_t to, const void* data, uint8_t len) { const char *datap = static_cast(data); - unsigned char i; - unsigned char cs = 0; - unsigned char del; + unsigned char i; + unsigned char cs = 0; + unsigned char del; // This is how many times to try and transmit before failing. unsigned char timeout = 10; @@ -264,101 +265,107 @@ bool transportSend(uint8_t to, const void* data, uint8_t len) } } - #if defined(MY_RS485_DE_PIN) - hwDigitalWrite(MY_RS485_DE_PIN, HIGH); - delayMicroseconds(5); - #endif +#if defined(MY_RS485_DE_PIN) + hwDigitalWrite(MY_RS485_DE_PIN, HIGH); + delayMicroseconds(5); +#endif - // Start of header by writing multiple SOH - for(byte w=0;w<1;w++) { - _dev.write(SOH); - } - _dev.write(to); // Destination address - cs += to; - _dev.write(_nodeId); // Source address - cs += _nodeId; - _dev.write(ICSC_SYS_PACK); // Command code - cs += ICSC_SYS_PACK; - _dev.write(len); // Length of text - cs += len; - _dev.write(STX); // Start of text - for(i=0; i= 100 - #if ARDUINO >= 104 - // Arduino 1.0.4 and upwards does it right - _dev.flush(); - #else - // Between 1.0.0 and 1.0.3 it almost does it - need to compensate - // for the hardware buffer. Delay for 2 bytes worth of transmission. - _dev.flush(); - delayMicroseconds((20000000UL/9600)+1); - #endif - #elif defined(__linux__) - _dev.flush(); - #endif - #endif - hwDigitalWrite(MY_RS485_DE_PIN, LOW); - #endif - return true; +#if defined(MY_RS485_DE_PIN) +#ifdef __PIC32MX__ + // MPIDE has nothing yet for this. It uses the hardware buffer, which + // could be up to 8 levels deep. For now, let's just delay for 8 + // characters worth. + delayMicroseconds((F_CPU/9600)+1); +#else +#if defined(ARDUINO) && ARDUINO >= 100 +#if ARDUINO >= 104 + // Arduino 1.0.4 and upwards does it right + _dev.flush(); +#else + // Between 1.0.0 and 1.0.3 it almost does it - need to compensate + // for the hardware buffer. Delay for 2 bytes worth of transmission. + _dev.flush(); + delayMicroseconds((20000000UL/9600)+1); +#endif +#elif defined(__linux__) + _dev.flush(); +#endif +#endif + hwDigitalWrite(MY_RS485_DE_PIN, LOW); +#endif + return true; } -bool transportInit() { - // Reset the state machine +bool transportInit() +{ + // Reset the state machine _dev.begin(MY_RS485_BAUD_RATE); - _serialReset(); - #if defined(MY_RS485_DE_PIN) - hwPinMode(MY_RS485_DE_PIN, OUTPUT); - hwDigitalWrite(MY_RS485_DE_PIN, LOW); - #endif - return true; + _serialReset(); +#if defined(MY_RS485_DE_PIN) + hwPinMode(MY_RS485_DE_PIN, OUTPUT); + hwDigitalWrite(MY_RS485_DE_PIN, LOW); +#endif + return true; } -void transportSetAddress(uint8_t address) { +void transportSetAddress(uint8_t address) +{ _nodeId = address; } -uint8_t transportGetAddress() { +uint8_t transportGetAddress() +{ return _nodeId; } -bool transportAvailable() { +bool transportAvailable() +{ _serialProcess(); return _packet_received; } -bool transportSanityCheck() { +bool transportSanityCheck() +{ // not implemented yet return true; } -uint8_t transportReceive(void* data) { +uint8_t transportReceive(void* data) +{ if (_packet_received) { memcpy(data,_data,_packet_len); _packet_received = false; return _packet_len; - } - else { + } else { return (0); } } -void transportPowerDown() { +void transportPowerDown() +{ // Nothing to shut down here } diff --git a/drivers/AES/AES.cpp b/drivers/AES/AES.cpp index 02fbfd8..06af427 100644 --- a/drivers/AES/AES.cpp +++ b/drivers/AES/AES.cpp @@ -65,44 +65,42 @@ #define WPOLY 0x011B #define DPOLY 0x008D -const static byte s_fwd [0x100] PROGMEM = -{ - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, +const static byte s_fwd [0x100] PROGMEM = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, } ; -const static byte s_inv [0x100] PROGMEM = -{ - 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, - 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, - 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, - 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, - 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, - 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, - 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, - 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, - 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, - 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, - 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, - 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, - 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, - 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, - 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, +const static byte s_inv [0x100] PROGMEM = { + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, } ; // times 2 in the GF(2^8) @@ -111,38 +109,36 @@ const static byte s_inv [0x100] PROGMEM = static byte s_box (byte x) { - // return fwd_affine (pgm_read_byte (&inv [x])) ; - return pgm_read_byte (& s_fwd [x]) ; + // return fwd_affine (pgm_read_byte (&inv [x])) ; + return pgm_read_byte (& s_fwd [x]) ; } // Inverse Sbox static byte is_box (byte x) { - // return pgm_read_byte (&inv [inv_affine (x)]) ; - return pgm_read_byte (& s_inv [x]) ; + // return pgm_read_byte (&inv [inv_affine (x)]) ; + return pgm_read_byte (& s_inv [x]) ; } static void xor_block (byte * d, byte * s) { - for (byte i = 0 ; i < N_BLOCK ; i += 4) - { - *d++ ^= *s++ ; // some unrolling - *d++ ^= *s++ ; - *d++ ^= *s++ ; - *d++ ^= *s++ ; - } + for (byte i = 0 ; i < N_BLOCK ; i += 4) { + *d++ ^= *s++ ; // some unrolling + *d++ ^= *s++ ; + *d++ ^= *s++ ; + *d++ ^= *s++ ; + } } static void copy_and_key (byte * d, byte * s, byte * k) { - for (byte i = 0 ; i < N_BLOCK ; i += 4) - { - *d++ = *s++ ^ *k++ ; // some unrolling - *d++ = *s++ ^ *k++ ; - *d++ = *s++ ^ *k++ ; - *d++ = *s++ ^ *k++ ; - } + for (byte i = 0 ; i < N_BLOCK ; i += 4) { + *d++ = *s++ ^ *k++ ; // some unrolling + *d++ = *s++ ^ *k++ ; + *d++ = *s++ ^ *k++ ; + *d++ = *s++ ^ *k++ ; + } } // #define add_round_key(d, k) xor_block (d, k) @@ -151,88 +147,110 @@ static void copy_and_key (byte * d, byte * s, byte * k) static void shift_sub_rows (byte st [N_BLOCK]) { - st [0] = s_box (st [0]) ; st [4] = s_box (st [4]) ; - st [8] = s_box (st [8]) ; st [12] = s_box (st [12]) ; + st [0] = s_box (st [0]) ; + st [4] = s_box (st [4]) ; + st [8] = s_box (st [8]) ; + st [12] = s_box (st [12]) ; - byte tt = st [1] ; - st [1] = s_box (st [5]) ; st [5] = s_box (st [9]) ; - st [9] = s_box (st [13]) ; st [13] = s_box (tt) ; + byte tt = st [1] ; + st [1] = s_box (st [5]) ; + st [5] = s_box (st [9]) ; + st [9] = s_box (st [13]) ; + st [13] = s_box (tt) ; - tt = st[2] ; st [2] = s_box (st [10]) ; st [10] = s_box (tt) ; - tt = st[6] ; st [6] = s_box (st [14]) ; st [14] = s_box (tt) ; + tt = st[2] ; + st [2] = s_box (st [10]) ; + st [10] = s_box (tt) ; + tt = st[6] ; + st [6] = s_box (st [14]) ; + st [14] = s_box (tt) ; - tt = st[15] ; - st [15] = s_box (st [11]) ; st [11] = s_box (st [7]) ; - st [7] = s_box (st [3]) ; st [3] = s_box (tt) ; + tt = st[15] ; + st [15] = s_box (st [11]) ; + st [11] = s_box (st [7]) ; + st [7] = s_box (st [3]) ; + st [3] = s_box (tt) ; } static void inv_shift_sub_rows (byte st[N_BLOCK]) { - st [0] = is_box (st[0]) ; st [4] = is_box (st [4]); - st [8] = is_box (st[8]) ; st [12] = is_box (st [12]); + st [0] = is_box (st[0]) ; + st [4] = is_box (st [4]); + st [8] = is_box (st[8]) ; + st [12] = is_box (st [12]); - byte tt = st[13] ; - st [13] = is_box (st [9]) ; st [9] = is_box (st [5]) ; - st [5] = is_box (st [1]) ; st [1] = is_box (tt) ; + byte tt = st[13] ; + st [13] = is_box (st [9]) ; + st [9] = is_box (st [5]) ; + st [5] = is_box (st [1]) ; + st [1] = is_box (tt) ; - tt = st [2] ; st [2] = is_box (st [10]) ; st [10] = is_box (tt) ; - tt = st [6] ; st [6] = is_box (st [14]) ; st [14] = is_box (tt) ; + tt = st [2] ; + st [2] = is_box (st [10]) ; + st [10] = is_box (tt) ; + tt = st [6] ; + st [6] = is_box (st [14]) ; + st [14] = is_box (tt) ; - tt = st [3] ; - st [3] = is_box (st [7]) ; st [7] = is_box (st [11]) ; - st [11] = is_box (st [15]) ; st [15] = is_box (tt) ; + tt = st [3] ; + st [3] = is_box (st [7]) ; + st [7] = is_box (st [11]) ; + st [11] = is_box (st [15]) ; + st [15] = is_box (tt) ; } /* SUB COLUMNS PHASE */ static void mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK]) { - byte j = 5 ; - byte k = 10 ; - byte l = 15 ; - for (byte i = 0 ; i < N_BLOCK ; i += N_COL) - { - byte a = st [i] ; - byte b = st [j] ; j = (j+N_COL) & 15 ; - byte c = st [k] ; k = (k+N_COL) & 15 ; - byte d = st [l] ; l = (l+N_COL) & 15 ; - byte a1 = s_box (a), b1 = s_box (b), c1 = s_box (c), d1 = s_box (d) ; - byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ; - dt[i] = a2 ^ b2^b1 ^ c1 ^ d1 ; - dt[i+1] = a1 ^ b2 ^ c2^c1 ^ d1 ; - dt[i+2] = a1 ^ b1 ^ c2 ^ d2^d1 ; - dt[i+3] = a2^a1 ^ b1 ^ c1 ^ d2 ; - } + byte j = 5 ; + byte k = 10 ; + byte l = 15 ; + for (byte i = 0 ; i < N_BLOCK ; i += N_COL) { + byte a = st [i] ; + byte b = st [j] ; + j = (j+N_COL) & 15 ; + byte c = st [k] ; + k = (k+N_COL) & 15 ; + byte d = st [l] ; + l = (l+N_COL) & 15 ; + byte a1 = s_box (a), b1 = s_box (b), c1 = s_box (c), d1 = s_box (d) ; + byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ; + dt[i] = a2 ^ b2^b1 ^ c1 ^ d1 ; + dt[i+1] = a1 ^ b2 ^ c2^c1 ^ d1 ; + dt[i+2] = a1 ^ b1 ^ c2 ^ d2^d1 ; + dt[i+3] = a2^a1 ^ b1 ^ c1 ^ d2 ; + } } static void inv_mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK]) { - for (byte i = 0 ; i < N_BLOCK ; i += N_COL) - { - byte a1 = st [i] ; - byte b1 = st [i+1] ; - byte c1 = st [i+2] ; - byte d1 = st [i+3] ; - byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ; - byte a4 = f2(a2), b4 = f2(b2), c4 = f2(c2), d4 = f2(d2) ; - 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 ac = a8 ^ a4,bc = b8 ^ b4,cc = c8 ^ c4,dc = d8 ^ d4 ; + for (byte i = 0 ; i < N_BLOCK ; i += N_COL) { + byte a1 = st [i] ; + byte b1 = st [i+1] ; + byte c1 = st [i+2] ; + byte d1 = st [i+3] ; + byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ; + byte a4 = f2(a2), b4 = f2(b2), c4 = f2(c2), d4 = f2(d2) ; + 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 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+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+15)&15] = is_box (a9^a2 ^ bc^b1 ^ c9 ^ dc^d2) ; - } + 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+10)&15] = is_box (ac^a1 ^ b9 ^ cc^c2 ^ d9^d2) ; + dt[(i+15)&15] = is_box (a9^a2 ^ bc^b1 ^ c9 ^ dc^d2) ; + } } /******************************************************************************/ -AES::AES(){ +AES::AES() +{ byte ar_iv[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 }; memcpy(iv,ar_iv,8); memcpy(iv+8,ar_iv,8); - arr_pad[0] = 0x01; + arr_pad[0] = 0x01; arr_pad[1] = 0x02; arr_pad[2] = 0x03; arr_pad[3] = 0x04; @@ -253,208 +271,196 @@ AES::AES(){ byte AES::set_key (byte key [], int keylen) { - byte hi ; - switch (keylen) - { - case 16: - case 128: - keylen = 16; // 10 rounds - round = 10 ; - break; - case 24: - case 192: - keylen = 24; // 12 rounds - round = 12 ; - break; - case 32: - case 256: - keylen = 32; // 14 rounds - round = 14 ; - break; - default: - round = 0; - return AES_FAILURE; - } - hi = (round + 1) << 4 ; - copy_n_bytes (key_sched, key, keylen) ; - byte t[4] ; - byte next = keylen ; - for (byte cc = keylen, rc = 1 ; cc < hi ; cc += N_COL) - { - for (byte i = 0 ; i < N_COL ; i++) { - t[i] = key_sched [cc-4+i] ; - } - if (cc == next) - { - next += keylen ; - byte ttt = t[0] ; - t[0] = s_box (t[1]) ^ rc ; - t[1] = s_box (t[2]) ; - t[2] = s_box (t[3]) ; - t[3] = s_box (ttt) ; - rc = f2 (rc) ; - } - else if (keylen == 32 && (cc & 31) == 16) - { - for (byte i = 0 ; i < 4 ; i++) { - t[i] = s_box (t[i]) ; - } - } - byte tt = cc - keylen ; - for (byte i = 0 ; i < N_COL ; i++) { - key_sched [cc + i] = key_sched [tt + i] ^ t[i] ; - } - } - return AES_SUCCESS ; + byte hi ; + switch (keylen) { + case 16: + case 128: + keylen = 16; // 10 rounds + round = 10 ; + break; + case 24: + case 192: + keylen = 24; // 12 rounds + round = 12 ; + break; + case 32: + case 256: + keylen = 32; // 14 rounds + round = 14 ; + break; + default: + round = 0; + return AES_FAILURE; + } + hi = (round + 1) << 4 ; + copy_n_bytes (key_sched, key, keylen) ; + byte t[4] ; + byte next = keylen ; + for (byte cc = keylen, rc = 1 ; cc < hi ; cc += N_COL) { + for (byte i = 0 ; i < N_COL ; i++) { + t[i] = key_sched [cc-4+i] ; + } + if (cc == next) { + next += keylen ; + byte ttt = t[0] ; + t[0] = s_box (t[1]) ^ rc ; + t[1] = s_box (t[2]) ; + t[2] = s_box (t[3]) ; + t[3] = s_box (ttt) ; + rc = f2 (rc) ; + } else if (keylen == 32 && (cc & 31) == 16) { + for (byte i = 0 ; i < 4 ; i++) { + t[i] = s_box (t[i]) ; + } + } + byte tt = cc - keylen ; + for (byte i = 0 ; i < N_COL ; i++) { + key_sched [cc + i] = key_sched [tt + i] ^ t[i] ; + } + } + return AES_SUCCESS ; } /******************************************************************************/ void AES::clean () { - for (byte i = 0 ; i < KEY_SCHEDULE_BYTES ; i++) { - key_sched [i] = 0 ; - } - round = 0 ; + for (byte i = 0 ; i < KEY_SCHEDULE_BYTES ; i++) { + key_sched [i] = 0 ; + } + round = 0 ; } /******************************************************************************/ void AES::copy_n_bytes (byte * d, byte * s, byte nn) { - while (nn >= 4) - { - *d++ = *s++ ; // some unrolling - *d++ = *s++ ; - *d++ = *s++ ; - *d++ = *s++ ; - nn -= 4 ; - } - while (nn--) - *d++ = *s++ ; + while (nn >= 4) { + *d++ = *s++ ; // some unrolling + *d++ = *s++ ; + *d++ = *s++ ; + *d++ = *s++ ; + nn -= 4 ; + } + while (nn--) { + *d++ = *s++ ; + } } /******************************************************************************/ byte AES::encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK]) { - if (round) - { - byte s1 [N_BLOCK], r ; - copy_and_key (s1, plain, (byte*) (key_sched)) ; + if (round) { + byte s1 [N_BLOCK], r ; + copy_and_key (s1, plain, (byte*) (key_sched)) ; - for (r = 1 ; r < round ; r++) - { - byte s2 [N_BLOCK] ; - mix_sub_columns (s2, s1) ; - copy_and_key (s1, s2, (byte*) (key_sched + r * N_BLOCK)) ; - } - shift_sub_rows (s1) ; - copy_and_key (cipher, s1, (byte*) (key_sched + r * N_BLOCK)) ; - } - else - return AES_FAILURE ; - return AES_SUCCESS ; + for (r = 1 ; r < round ; r++) { + byte s2 [N_BLOCK] ; + mix_sub_columns (s2, s1) ; + copy_and_key (s1, s2, (byte*) (key_sched + r * N_BLOCK)) ; + } + shift_sub_rows (s1) ; + copy_and_key (cipher, s1, (byte*) (key_sched + r * N_BLOCK)) ; + } else { + return AES_FAILURE ; + } + return AES_SUCCESS ; } /******************************************************************************/ byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOCK]) { - while (n_block--) - { - xor_block (iv, plain) ; - if (encrypt (iv, iv) != AES_SUCCESS) { - return AES_FAILURE ; - } - copy_n_bytes (cipher, iv, N_BLOCK) ; - plain += N_BLOCK ; - cipher += N_BLOCK ; - } - return AES_SUCCESS ; + while (n_block--) { + xor_block (iv, plain) ; + if (encrypt (iv, iv) != AES_SUCCESS) { + return AES_FAILURE ; + } + copy_n_bytes (cipher, iv, N_BLOCK) ; + plain += N_BLOCK ; + cipher += N_BLOCK ; + } + return AES_SUCCESS ; } /******************************************************************************/ byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block) { - while (n_block--) - { - xor_block (iv, plain) ; - if (encrypt (iv, iv) != AES_SUCCESS) { - return AES_FAILURE ; - } - copy_n_bytes (cipher, iv, N_BLOCK) ; - plain += N_BLOCK ; - cipher += N_BLOCK ; - } - return AES_SUCCESS ; + while (n_block--) { + xor_block (iv, plain) ; + if (encrypt (iv, iv) != AES_SUCCESS) { + return AES_FAILURE ; + } + copy_n_bytes (cipher, iv, N_BLOCK) ; + plain += N_BLOCK ; + cipher += N_BLOCK ; + } + return AES_SUCCESS ; } /******************************************************************************/ byte AES::decrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK]) { - if (round) - { - byte s1 [N_BLOCK] ; - copy_and_key (s1, plain, (byte*) (key_sched + round * N_BLOCK)) ; - inv_shift_sub_rows (s1) ; + if (round) { + byte s1 [N_BLOCK] ; + copy_and_key (s1, plain, (byte*) (key_sched + round * N_BLOCK)) ; + inv_shift_sub_rows (s1) ; - for (byte r = round ; --r ; ) - { - byte s2 [N_BLOCK] ; - copy_and_key (s2, s1, (byte*) (key_sched + r * N_BLOCK)) ; - inv_mix_sub_columns (s1, s2) ; - } - copy_and_key (cipher, s1, (byte*) (key_sched)) ; - } - else - return AES_FAILURE ; - return AES_SUCCESS ; + for (byte r = round ; --r ; ) { + byte s2 [N_BLOCK] ; + copy_and_key (s2, s1, (byte*) (key_sched + r * N_BLOCK)) ; + inv_mix_sub_columns (s1, s2) ; + } + copy_and_key (cipher, s1, (byte*) (key_sched)) ; + } else { + return AES_FAILURE ; + } + return AES_SUCCESS ; } /******************************************************************************/ byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK]) { - while (n_block--) - { - byte tmp [N_BLOCK] ; - copy_n_bytes (tmp, cipher, N_BLOCK) ; - if (decrypt (cipher, plain) != AES_SUCCESS) { - return AES_FAILURE ; - } - xor_block (plain, iv) ; - copy_n_bytes (iv, tmp, N_BLOCK) ; - plain += N_BLOCK ; - cipher += N_BLOCK; - } - return AES_SUCCESS ; + while (n_block--) { + byte tmp [N_BLOCK] ; + copy_n_bytes (tmp, cipher, N_BLOCK) ; + if (decrypt (cipher, plain) != AES_SUCCESS) { + return AES_FAILURE ; + } + xor_block (plain, iv) ; + copy_n_bytes (iv, tmp, N_BLOCK) ; + plain += N_BLOCK ; + cipher += N_BLOCK; + } + return AES_SUCCESS ; } /******************************************************************************/ byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block) { - while (n_block--) - { - byte tmp [N_BLOCK] ; - copy_n_bytes (tmp, cipher, N_BLOCK) ; - if (decrypt (cipher, plain) != AES_SUCCESS) { - return AES_FAILURE ; - } - xor_block (plain, iv) ; - copy_n_bytes (iv, tmp, N_BLOCK) ; - plain += N_BLOCK ; - cipher += N_BLOCK; - } - return AES_SUCCESS ; + while (n_block--) { + byte tmp [N_BLOCK] ; + copy_n_bytes (tmp, cipher, N_BLOCK) ; + if (decrypt (cipher, plain) != AES_SUCCESS) { + return AES_FAILURE ; + } + xor_block (plain, iv) ; + copy_n_bytes (iv, tmp, N_BLOCK) ; + plain += N_BLOCK ; + cipher += N_BLOCK; + } + return AES_SUCCESS ; } /*****************************************************************************/ -void AES::set_IV(unsigned long long int IVCl){ +void AES::set_IV(unsigned long long int IVCl) +{ memcpy(iv,&IVCl,8); memcpy(iv+8,&IVCl,8); IVC = IVCl; @@ -462,7 +468,8 @@ void AES::set_IV(unsigned long long int IVCl){ /******************************************************************************/ -void AES::iv_inc(){ +void AES::iv_inc() +{ IVC += 1; memcpy(iv,&IVC,8); memcpy(iv+8,&IVC,8); @@ -470,31 +477,35 @@ void AES::iv_inc(){ /******************************************************************************/ -int AES::get_size(){ +int AES::get_size() +{ return size; } /******************************************************************************/ -void AES::set_size(int sizel){ +void AES::set_size(int sizel) +{ size = sizel; } /******************************************************************************/ -void AES::get_IV(byte *out){ +void AES::get_IV(byte *out) +{ memcpy(out,&IVC,8); memcpy(out+8,&IVC,8); } /******************************************************************************/ -void AES::calc_size_n_pad(int p_size){ +void AES::calc_size_n_pad(int p_size) +{ int s_of_p = p_size - 1; - if ( s_of_p % N_BLOCK == 0){ - size = s_of_p; - }else{ + if ( s_of_p % N_BLOCK == 0) { + size = s_of_p; + } else { size = s_of_p + (N_BLOCK-(s_of_p % N_BLOCK)); } pad = size - s_of_p; @@ -505,59 +516,63 @@ void AES::calc_size_n_pad(int p_size){ void AES::padPlaintext(void* in,byte* out) { memcpy(out,in,size); - for (int i = size-pad; i < size; i++){; + for (int i = size-pad; i < size; i++) { + ; out[i] = arr_pad[pad - 1]; } } /******************************************************************************/ -bool AES::CheckPad(byte* in,int lsize){ - if (in[lsize-1] <= 0x0f){ +bool AES::CheckPad(byte* in,int lsize) +{ + if (in[lsize-1] <= 0x0f) { int lpad = (int)in[lsize-1]; - for (int i = lsize - 1; i >= lsize-lpad; i--){ - if (arr_pad[lpad - 1] != in[i]){ + for (int i = lsize - 1; i >= lsize-lpad; i--) { + if (arr_pad[lpad - 1] != in[i]) { return false; } } - }else{ + } else { return true; } -return true; + return true; } /******************************************************************************/ void AES::printArray(byte output[],bool p_pad) { -uint8_t i,j; -uint8_t loops = size/N_BLOCK; -uint8_t outp = N_BLOCK; -for (j = 0; j < loops; j += 1){ - if (p_pad && (j == (loops - 1)) ) { outp = N_BLOCK - pad; } - for (i = 0; i < outp; i++) - { - printf_P(PSTR("%c"),output[j*N_BLOCK + i]); - } -} - printf_P(PSTR("\n")); + uint8_t i,j; + uint8_t loops = size/N_BLOCK; + uint8_t outp = N_BLOCK; + for (j = 0; j < loops; j += 1) { + if (p_pad && (j == (loops - 1)) ) { + outp = N_BLOCK - pad; + } + for (i = 0; i < outp; i++) { + printf_P(PSTR("%c"),output[j*N_BLOCK + i]); + } + } + printf_P(PSTR("\n")); } /******************************************************************************/ void AES::printArray(byte output[],int sizel) { - for (int i = 0; i < sizel; i++) - { - printf_P(PSTR("%x"),output[i]); - } - printf_P(PSTR("\n")); + for (int i = 0; i < sizel; i++) { + printf_P(PSTR("%x"),output[i]); + } + printf_P(PSTR("\n")); } /******************************************************************************/ -void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits, byte ivl [N_BLOCK]){ +void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits, + byte ivl [N_BLOCK]) +{ calc_size_n_pad(size_p); byte plain_p[get_size()]; padPlaintext(plain,plain_p); @@ -568,7 +583,8 @@ void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits /******************************************************************************/ -void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits){ +void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits) +{ calc_size_n_pad(size_p); byte plain_p[get_size()]; padPlaintext(plain,plain_p); @@ -579,7 +595,9 @@ void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits /******************************************************************************/ -void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits, byte ivl [N_BLOCK]){ +void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits, + byte ivl [N_BLOCK]) +{ set_size(size_c); int blocks = size_c / N_BLOCK; set_key (key, bits); @@ -588,7 +606,8 @@ void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits /******************************************************************************/ -void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits){ +void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits) +{ set_size(size_c); int blocks = size_c / N_BLOCK; set_key (key, bits); @@ -599,7 +618,8 @@ void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits /******************************************************************************/ #if defined(AES_LINUX) -double AES::millis(){ +double AES::millis() +{ gettimeofday(&tv, NULL); return (tv.tv_sec + 0.000001 * tv.tv_usec); } diff --git a/drivers/AES/AES.h b/drivers/AES/AES.h index 1d92c8c..7ba5731 100644 --- a/drivers/AES/AES.h +++ b/drivers/AES/AES.h @@ -31,44 +31,44 @@ This is an AES implementation that uses only 8-bit byte operations on the cipher state. */ - - /* code was modified by george spanos - * 16/12/14 - */ + +/* code was modified by george spanos +* 16/12/14 +*/ /** AES class */ class AES { - public: +public: -/* The following calls are for a precomputed key schedule + /* The following calls are for a precomputed key schedule - NOTE: If the length_type used for the key length is an - unsigned 8-bit character, a key length of 256 bits must - be entered as a length in bytes (valid inputs are hence - 128, 192, 16, 24 and 32). -*/ + NOTE: If the length_type used for the key length is an + unsigned 8-bit character, a key length of 256 bits must + be entered as a length in bytes (valid inputs are hence + 128, 192, 16, 24 and 32). + */ /** \fn AES() * \brief AES constructor - * + * * This function initialized an instance of AES. */ AES(); - - /** Set the cipher key for the pre-keyed version. + + /** Set the cipher key for the pre-keyed version. * @param key[] pointer to the key string. * @param keylen Integer that indicates the length of the key. - * @note NOTE: If the length_type used for the key length is an unsigned 8-bit character, - * a key length of 256 bits must be entered as a length in bytes + * @note NOTE: If the length_type used for the key length is an unsigned 8-bit character, + * a key length of 256 bits must be entered as a length in bytes * (valid inputs are hence 128, 192, 16, 24 and 32). * */ byte set_key (byte key[], int keylen) ; - + /** clean up subkeys after use. - * - */ + * + */ void clean () ; // delete key schedule after use - + /** copying and xoring utilities. * @param *AESt byte pointer of the AEStination array. * @param *src byte pointer of the source array. @@ -92,9 +92,9 @@ class AES * */ byte encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK]) ; - + /** CBC encrypt a number of blocks (input and return an IV). - * + * * @param *plain Pointer, points to the plaintex. * @param *cipher Pointer, points to the ciphertext that will be created. * @param n_block integer, indicated the number of blocks to be ciphered. @@ -103,9 +103,9 @@ class AES * */ byte cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOCK]) ; - + /** CBC encrypt a number of blocks (input and return an IV). - * + * * @param *plain Pointer, points to the plaintex. * @param *cipher Pointer, points to the ciphertext that will be created. * @param n_block integer, indicated the number of blocks to be ciphered. @@ -115,7 +115,7 @@ class AES byte cbc_encrypt (byte * plain, byte * cipher, int n_block) ; - /** Decrypt a single block of 16 bytes + /** Decrypt a single block of 16 bytes * @param cipher Array of the ciphertext. * @param plain Array of the plaintext. * @note The N_BLOCK is defined in AES_config.h as, @@ -128,9 +128,9 @@ class AES * */ byte decrypt (byte cipher [N_BLOCK], byte plain [N_BLOCK]) ; - - /** CBC decrypt a number of blocks (input and return an IV) - * + + /** CBC decrypt a number of blocks (input and return an IV) + * * @param *cipher Pointer, points to the ciphertext that will be created. * @param *plain Pointer, points to the plaintex. * @param n_block integer, indicated the number of blocks to be ciphered. @@ -139,9 +139,9 @@ class AES * */ byte cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK]) ; - - /** CBC decrypt a number of blocks (input and return an IV) - * + + /** CBC decrypt a number of blocks (input and return an IV) + * * @param *cipher Pointer, points to the ciphertext that will be created. * @param *plain Pointer, points to the plaintex. * @param n_block integer, indicated the number of blocks to be ciphered. @@ -149,7 +149,7 @@ class AES * */ byte cbc_decrypt (byte * cipher, byte * plain, int n_block) ; - + /** Sets IV (initialization vector) and IVC (IV counter). * This function changes the ivc and iv variables needed for AES. * @@ -158,62 +158,62 @@ class AES * @code unsigned long long int my_iv = 01234567; @endcode */ void set_IV(unsigned long long int IVCl); - + /** increase the iv (initialization vector) and IVC (IV counter) by 1 - * + * * This function increased the VI by one step in order to have a different IV each time - * + * */ void iv_inc(); - + /** Getter method for size - * + * * This function return the size * @return an integer, that is the size of the of the padded plaintext, * thus, the size of the ciphertext. */ int get_size(); - + /** Setter method for size * * This function sets the size of the plaintext+pad - * + * */ void set_size(int sizel); - + /** Getter method for IV - * + * * This function return the IV * @param out byte pointer that gets the IV. * @return none, the IV is writed to the out pointer. */ void get_IV(byte *out); - + /** Calculates the size of the plaintext and the padding. - * + * * Calculates the size of theplaintext with the padding * and the size of the padding needed. Moreover it stores them in their class variables. - * + * * @param p_size the size of the byte array ex sizeof(plaintext) */ void calc_size_n_pad(int p_size); - + /** Pads the plaintext - * - * This function pads the plaintext and returns an char array with the - * plaintext and the padding in order for the plaintext to be compatible with + * + * This function pads the plaintext and returns an char array with the + * plaintext and the padding in order for the plaintext to be compatible with * 16bit size blocks required by AES - * + * * @param in the string of the plaintext in a byte array * @param out The string of the out array. * @return no return, The padded plaintext is stored in the out pointer. */ void padPlaintext(void* in,byte* out); - + /** Check the if the padding is correct. - * + * * This functions checks the padding of the plaintext. - * + * * @param in the string of the plaintext in a byte array * @param size the size of the string * @return true if correct / false if not @@ -221,26 +221,26 @@ class AES bool CheckPad(byte* in,int size); /** Prints the array given. - * - * This function prints the given array and pad, + * + * This function prints the given array and pad, * It is mainlly used for debugging purpuses or to output the string. - * + * * @param output[] the string of the text in a byte array * @param p_pad optional, used to print with out the padding characters */ void printArray(byte output[],bool p_pad = true); - + /** Prints the array given. - * + * * This function prints the given array in Hexadecimal. - * + * * @param output[] the string of the text in a byte array * @param sizel the size of the array. */ void printArray(byte output[],int sizel); - + /** User friendly implementation of AES-CBC encryption. - * + * * @param *plain pointer to the plaintext * @param size_p size of the plaintext * @param *cipher pointer to the ciphertext @@ -250,9 +250,9 @@ class AES * @note The key will be stored in class variable. */ void do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits, byte ivl [N_BLOCK]); - + /** User friendly implementation of AES-CBC encryption. - * + * * @param *plain pointer to the plaintext * @param size_p size of the plaintext * @param *cipher pointer to the ciphertext @@ -261,9 +261,9 @@ class AES * @note The key will be stored in class variable. */ void do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits); - + /** User friendly implementation of AES-CBC decryption. - * + * * @param *cipher pointer to the ciphertext * @param size_c size of the ciphertext * @param *plain pointer to the plaintext @@ -273,9 +273,9 @@ class AES * @note The key will be stored in class variable. */ void do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits, byte ivl [N_BLOCK]); - + /** User friendly implementation of AES-CBC decryption. - * + * * @param *cipher pointer to the ciphertext * @param size_c size of the ciphertext * @param *plain pointer to the plaintext @@ -285,27 +285,28 @@ class AES */ void do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits); - #if defined(AES_LINUX) - /** - * used in linux in order to retrieve the time in milliseconds. - * - * @return returns the milliseconds in a double format. - */ - double millis(); - #endif - private: - int round ;/**< holds the number of rounds to be used. */ - byte key_sched [KEY_SCHEDULE_BYTES] ;/**< holds the pre-computed key for the encryption/decrpytion. */ - unsigned long long int IVC;/**< holds the initialization vector counter in numerical format. */ - byte iv[16];/**< holds the initialization vector that will be used in the cipher. */ - int pad;/**< holds the size of the padding. */ - int size;/**< hold the size of the plaintext to be ciphered */ - #if defined(AES_LINUX) +#if defined(AES_LINUX) + /** + * used in linux in order to retrieve the time in milliseconds. + * + * @return returns the milliseconds in a double format. + */ + double millis(); +#endif +private: + int round ;/**< holds the number of rounds to be used. */ + byte key_sched [KEY_SCHEDULE_BYTES] + ;/**< holds the pre-computed key for the encryption/decrpytion. */ + unsigned long long int IVC;/**< holds the initialization vector counter in numerical format. */ + byte iv[16];/**< holds the initialization vector that will be used in the cipher. */ + int pad;/**< holds the size of the padding. */ + int size;/**< hold the size of the plaintext to be ciphered */ +#if defined(AES_LINUX) timeval tv;/**< holds the time value on linux */ byte arr_pad[15];/**< holds the hexadecimal padding values on linux */ - #else +#else byte arr_pad[15];// = { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };/**< holds the hexadecimal padding values */ - #endif +#endif } ; @@ -319,33 +320,33 @@ class AES * This is an example of how to use AES in CBC mode easily. * The text and keys can be either in HEX or String format.
*/ - - /** - * @example aes.cpp - * For Rasberry pi
- * Updated: spaniakos 2015
- * - * This is an example of how to use AES in CBC mode easily. - * The text and keys can be either in HEX or String format.
- */ - - /** - * @example test_vectors.pde - * For Arduino
- * Updated: spaniakos 2015
- * - * This is an example of monte carlo test vectors, in order to justify the effectiveness of the algorithm.
- * plus is a classical approach to the AES encryption library with out the easy to use add-on modifications. - */ - - /** - * @example test_vectors.cpp - * For Rasberry pi
- * Updated: spaniakos 2015
- * - * This is an example of monte carlo test vectors, in order to justify the effectiveness of the algorithm.
- * plus is a classical approach to the AES encryption library with out the easy to use add-on modifications. - */ + +/** +* @example aes.cpp +* For Rasberry pi
+* Updated: spaniakos 2015
+* +* This is an example of how to use AES in CBC mode easily. +* The text and keys can be either in HEX or String format.
+*/ + +/** +* @example test_vectors.pde +* For Arduino
+* Updated: spaniakos 2015
+* +* This is an example of monte carlo test vectors, in order to justify the effectiveness of the algorithm.
+* plus is a classical approach to the AES encryption library with out the easy to use add-on modifications. +*/ + +/** +* @example test_vectors.cpp +* For Rasberry pi
+* Updated: spaniakos 2015
+* +* This is an example of monte carlo test vectors, in order to justify the effectiveness of the algorithm.
+* plus is a classical approach to the AES encryption library with out the easy to use add-on modifications. +*/ /** * @defgroup aeslib AES library for Arduino and Raspberry pi @@ -362,21 +363,21 @@ class AES * * @section Acknowledgements Acknowledgements * This is an AES library for the Arduino, based on tzikis's AES library, which you can find here:.
- * Tzikis library was based on scottmac`s library, which you can find here:
- * + * Tzikis library was based on scottmac`s library, which you can find here:
+ * * @section Installation Installation *

Arduino

- * Create a folder named _AES_ in the _libraries_ folder inside your Arduino sketch folder. If the + * Create a folder named _AES_ in the _libraries_ folder inside your Arduino sketch folder. If the * libraries folder doesn't exist, create it. Then copy everything inside. (re)launch the Arduino IDE.
* You're done. Time for a mojito - * + * *

Raspberry pi

* install

- * + * * sudo make install
* cd examples_Rpi
* make

- * + * * What to do after changes to the library

* sudo make clean
* sudo make install
@@ -392,7 +393,7 @@ class AES * How to start a sketch

* cd examples_Rpi
* sudo ./\

- * + * * @section AesNews News * * If issues are discovered with the documentation, please report them here @@ -411,6 +412,6 @@ class AES * - Arduino * - Intel Galileo support * - Raspberry Pi Support - * + * * - The library has not been tested to other boards, but it should suppport ATMega 328 based boards,Mega Boards,Arduino Due,ATTiny board */ diff --git a/drivers/AES/AES_config.h b/drivers/AES/AES_config.h index d0ae828..ab38489 100644 --- a/drivers/AES/AES_config.h +++ b/drivers/AES/AES_config.h @@ -7,34 +7,34 @@ #if (defined(__linux) || defined(linux)) && !defined(__ARDUINO_X86__) - #define AES_LINUX +#define AES_LINUX - #include - #include - #include - #include - #include - #include +#include +#include +#include +#include +#include +#include #else - #include +#include #endif #include #include #if defined(__ARDUINO_X86__) || (defined (__linux) || defined (linux)) - #undef PROGMEM - #define PROGMEM __attribute__(( section(".progmem.data") )) - #define pgm_read_byte(p) (*(p)) - typedef unsigned char byte; - #define printf_P printf - #define PSTR(x) (x) +#undef PROGMEM +#define PROGMEM __attribute__(( section(".progmem.data") )) +#define pgm_read_byte(p) (*(p)) +typedef unsigned char byte; +#define printf_P printf +#define PSTR(x) (x) #elif defined(ARDUINO_ARCH_ESP8266) - #include +#include #elif defined(ARDUINO_ARCH_SAMD) - #define printf_P printf +#define printf_P printf #else - #include +#include #endif #define N_ROW 4 diff --git a/drivers/AES/examples_Rpi/aes.cpp b/drivers/AES/examples_Rpi/aes.cpp index 7b6d8fe..c7d45ae 100644 --- a/drivers/AES/examples_Rpi/aes.cpp +++ b/drivers/AES/examples_Rpi/aes.cpp @@ -15,33 +15,33 @@ unsigned long long int my_iv = 01234567; int main(int argc, char** argv) { - printf("\n===testng mode\n") ; + printf("\n===testng mode\n") ; - for (int i=0;i<1;i++){ - prekey_test () ; - } + for (int i=0; i<1; i++) { + prekey_test () ; + } } void prekey (int bits) { - byte iv [N_BLOCK] ; - byte plain_p[sizeof(plain) + (N_BLOCK - (sizeof(plain) % 16)) - 1]; - byte cipher[sizeof(plain_p)]; - aes.do_aes_encrypt(plain,sizeof(plain),cipher,key,bits); - aes.get_IV(iv); - aes.do_aes_dencrypt(cipher,aes.get_size(),plain_p,key,bits,iv); - //normally u have sizeof(cipher) but if its in the same sketch you cannot determin it dynamically + byte iv [N_BLOCK] ; + byte plain_p[sizeof(plain) + (N_BLOCK - (sizeof(plain) % 16)) - 1]; + byte cipher[sizeof(plain_p)]; + aes.do_aes_encrypt(plain,sizeof(plain),cipher,key,bits); + aes.get_IV(iv); + aes.do_aes_dencrypt(cipher,aes.get_size(),plain_p,key,bits,iv); + //normally u have sizeof(cipher) but if its in the same sketch you cannot determin it dynamically - printf("\n\nPLAIN :"); - aes.printArray(plain); - printf("\nCIPHER:"); - aes.printArray(cipher); - printf("\nPlain2:"); - aes.printArray(plain_p); - printf("\n============================================================\n"); + printf("\n\nPLAIN :"); + aes.printArray(plain); + printf("\nCIPHER:"); + aes.printArray(cipher); + printf("\nPlain2:"); + aes.printArray(plain_p); + printf("\n============================================================\n"); } void prekey_test () { - prekey (128) ; + prekey (128) ; } diff --git a/drivers/AES/examples_Rpi/test_vectors.cpp b/drivers/AES/examples_Rpi/test_vectors.cpp index 334713d..d50b497 100644 --- a/drivers/AES/examples_Rpi/test_vectors.cpp +++ b/drivers/AES/examples_Rpi/test_vectors.cpp @@ -18,108 +18,113 @@ void monte_carlo (int bits); int main(int argc, char** argv) { - printf ("AES library test vectors") ; + printf ("AES library test vectors") ; - monte_carlo (128) ; + monte_carlo (128) ; - for (int keysize = 128 ; keysize <= 256 ; keysize += 64) - { - prekey_test_var_plaintext (keysize) ; - prekey_test_var_key (keysize) ; - } + for (int keysize = 128 ; keysize <= 256 ; keysize += 64) { + prekey_test_var_plaintext (keysize) ; + prekey_test_var_key (keysize) ; + } } void prekey_test_var_plaintext (int bits) { - printf ("\nECB Varying Plaintext %i bits\n",bits) ; - - byte succ ; - set_bits (bits, key, 0) ; // all zero key - succ = aes.set_key (key, bits) ; - if (succ != SUCCESS) - printf("Failure set_key\n") ; + printf ("\nECB Varying Plaintext %i bits\n",bits) ; + + byte succ ; + set_bits (bits, key, 0) ; // all zero key + succ = aes.set_key (key, bits) ; + if (succ != SUCCESS) { + printf("Failure set_key\n") ; + } - for (int bitcount = 1 ; bitcount <= 128 ; bitcount++) - { - printf ("COUNT = %i \n",bitcount-1); - print_value ("KEY = ", key, bits) ; - set_bits (128, plain, bitcount) ; - - print_value ("PLAINTEXT = ", plain, 128) ; - - succ = aes.encrypt (plain, cipher) ; - if (succ != SUCCESS) - printf ("Failure encrypt\n") ; + for (int bitcount = 1 ; bitcount <= 128 ; bitcount++) { + printf ("COUNT = %i \n",bitcount-1); + print_value ("KEY = ", key, bits) ; + set_bits (128, plain, bitcount) ; - print_value ("CIPHERTEXT = ", cipher, 128) ; - - succ = aes.decrypt (cipher, check) ; - if (succ != SUCCESS) - printf ("Failure decrypt\n") ; + print_value ("PLAINTEXT = ", plain, 128) ; - //print_value ("CHECK = ", check, 128) ; - check_same (plain, check, 128) ; - printf ("\n") ; - } + succ = aes.encrypt (plain, cipher) ; + if (succ != SUCCESS) { + printf ("Failure encrypt\n") ; + } + + print_value ("CIPHERTEXT = ", cipher, 128) ; + + succ = aes.decrypt (cipher, check) ; + if (succ != SUCCESS) { + printf ("Failure decrypt\n") ; + } + + //print_value ("CHECK = ", check, 128) ; + check_same (plain, check, 128) ; + printf ("\n") ; + } } void prekey_test_var_key (int bits) { - printf ("\nECB Varying key %i bits\n",bits); - - byte succ ; - set_bits (128, plain, 0) ; + printf ("\nECB Varying key %i bits\n",bits); - for (int bitcount = 1 ; bitcount <= bits ; bitcount++) - { - set_bits (bits, key, bitcount) ; // all zero key - succ = aes.set_key (key, bits) ; - if (succ != SUCCESS) - printf ("Failure set_key\n") ; - printf ("COUNT = %i\n",bitcount-1); - print_value ("KEY = ", key, bits) ; + byte succ ; + set_bits (128, plain, 0) ; - print_value ("PLAINTEXT = ", plain, 128) ; + for (int bitcount = 1 ; bitcount <= bits ; bitcount++) { + set_bits (bits, key, bitcount) ; // all zero key + succ = aes.set_key (key, bits) ; + if (succ != SUCCESS) { + printf ("Failure set_key\n") ; + } + printf ("COUNT = %i\n",bitcount-1); + print_value ("KEY = ", key, bits) ; - succ = aes.encrypt (plain, cipher) ; - if (succ != SUCCESS) - printf ("Failure encrypt\n") ; + print_value ("PLAINTEXT = ", plain, 128) ; - print_value ("CIPHERTEXT = ", cipher, 128) ; + succ = aes.encrypt (plain, cipher) ; + if (succ != SUCCESS) { + printf ("Failure encrypt\n") ; + } - succ = aes.decrypt (cipher, check) ; - if (succ != SUCCESS) - printf ("Failure decrypt\n") ; + print_value ("CIPHERTEXT = ", cipher, 128) ; - check_same (plain, check, 128) ; - printf("\n"); - } + succ = aes.decrypt (cipher, check) ; + if (succ != SUCCESS) { + printf ("Failure decrypt\n") ; + } + + check_same (plain, check, 128) ; + printf("\n"); + } } void set_bits (int bits, byte * a, int count) { - bits >>= 3 ; - byte bcount = count >> 3 ; - for (byte i = 0 ; i < bcount ; i++) - a [i] = 0xFF ; - if ((count & 7) != 0) - a [bcount++] = 0xFF & (0xFF00 >> (count & 7)) ; - for (byte i = bcount ; i < bits ; i++) - a [i] = 0x00 ; + bits >>= 3 ; + byte bcount = count >> 3 ; + for (byte i = 0 ; i < bcount ; i++) { + a [i] = 0xFF ; + } + if ((count & 7) != 0) { + a [bcount++] = 0xFF & (0xFF00 >> (count & 7)) ; + } + for (byte i = bcount ; i < bits ; i++) { + a [i] = 0x00 ; + } } void check_same (byte * a, byte * b, int bits) { - bits >>= 3 ; - for (byte i = 0 ; i < bits ; i++) - if (a[i] != b[i]) - { - printf ("Failure plain != check\n") ; - return ; - } + bits >>= 3 ; + for (byte i = 0 ; i < bits ; i++) + if (a[i] != b[i]) { + printf ("Failure plain != check\n") ; + return ; + } } char hex[] = "0123456789abcdef" ; @@ -127,57 +132,51 @@ char hex[] = "0123456789abcdef" ; void print_value (const char * str, byte * a, int bits) { - printf ("%s",str) ; - bits >>= 3 ; - for (int i = 0 ; i < bits ; i++) - { - byte b = a[i] ; - printf("%c%c",hex[b >> 4],hex [b & 15]); - //Serial.print (hex [b >> 4]) ; - //Serial.print (hex [b & 15]) ; - } - printf("\n") ; + printf ("%s",str) ; + bits >>= 3 ; + for (int i = 0 ; i < bits ; i++) { + byte b = a[i] ; + printf("%c%c",hex[b >> 4],hex [b & 15]); + //Serial.print (hex [b >> 4]) ; + //Serial.print (hex [b & 15]) ; + } + printf("\n") ; } -byte monteplain [] = - { 0xb9, 0x14, 0x5a, 0x76, 0x8b, 0x7d, 0xc4, 0x89, - 0xa0, 0x96, 0xb5, 0x46, 0xf4, 0x3b, 0x23, 0x1f } ; -byte montekey [] = - { 0x13, 0x9a, 0x35, 0x42, 0x2f, 0x1d, 0x61, 0xde, - 0x3c, 0x91, 0x78, 0x7f, 0xe0, 0x50, 0x7a, 0xfd } ; +byte monteplain [] = { + 0xb9, 0x14, 0x5a, 0x76, 0x8b, 0x7d, 0xc4, 0x89, + 0xa0, 0x96, 0xb5, 0x46, 0xf4, 0x3b, 0x23, 0x1f +} ; +byte montekey [] = { + 0x13, 0x9a, 0x35, 0x42, 0x2f, 0x1d, 0x61, 0xde, + 0x3c, 0x91, 0x78, 0x7f, 0xe0, 0x50, 0x7a, 0xfd +} ; void monte_carlo (int bits) { - printf ("\nMonte Carlo %i bits\n",bits); - byte succ; - for (int i = 0 ; i < 16 ; i++) - { - plain [i] = monteplain [i] ; - key [i] = montekey [i] ; - } - for (int i = 0 ; i < 100 ; i++) - { - printf ("COUNT = %i\n",i); - print_value ("KEY = ", key, bits) ; - print_value ("PLAINTEXT = ", plain, 128) ; - succ = aes.set_key (key, bits) ; - for (int j = 0 ; j < 1000 ; j++) - { - succ = aes.encrypt (plain, cipher) ; - aes.copy_n_bytes (plain, cipher, 16) ; - } - print_value ("CIPHERTEXT = ", cipher, 128) ; - printf("\n"); - if (bits == 128) - { - for (byte k = 0 ; k < 16 ; k++) - key [k] ^= cipher [k] ; - } - else if (bits == 192) - { - } - else - { - } - } + printf ("\nMonte Carlo %i bits\n",bits); + byte succ; + for (int i = 0 ; i < 16 ; i++) { + plain [i] = monteplain [i] ; + key [i] = montekey [i] ; + } + for (int i = 0 ; i < 100 ; i++) { + printf ("COUNT = %i\n",i); + print_value ("KEY = ", key, bits) ; + print_value ("PLAINTEXT = ", plain, 128) ; + succ = aes.set_key (key, bits) ; + for (int j = 0 ; j < 1000 ; j++) { + succ = aes.encrypt (plain, cipher) ; + aes.copy_n_bytes (plain, cipher, 16) ; + } + print_value ("CIPHERTEXT = ", cipher, 128) ; + printf("\n"); + if (bits == 128) { + for (byte k = 0 ; k < 16 ; k++) { + key [k] ^= cipher [k] ; + } + } else if (bits == 192) { + } else { + } + } } diff --git a/drivers/AES/printf.h b/drivers/AES/printf.h index d54e661..5d4935d 100644 --- a/drivers/AES/printf.h +++ b/drivers/AES/printf.h @@ -5,7 +5,7 @@ modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. */ - /* Galileo support from spaniakos */ +/* Galileo support from spaniakos */ /** * @file printf.h @@ -21,36 +21,36 @@ int serial_putc( char c, FILE * ) { - Serial.write( c ); + Serial.write( c ); - return c; + return c; } void printf_begin(void) { - fdevopen( &serial_putc, 0 ); + fdevopen( &serial_putc, 0 ); } #elif defined (__arm__) -void printf_begin(void){} +void printf_begin(void) {} #elif defined(__ARDUINO_X86__) int serial_putc( char c, FILE * ) { - Serial.write( c ); + Serial.write( c ); - return c; + return c; } void printf_begin(void) { - //JESUS - For reddirect stdout to /dev/ttyGS0 (Serial Monitor port) - stdout = freopen("/dev/ttyGS0","w",stdout); - delay(500); - printf("redirecting to Serial..."); - - //JESUS ----------------------------------------------------------- + //JESUS - For reddirect stdout to /dev/ttyGS0 (Serial Monitor port) + stdout = freopen("/dev/ttyGS0","w",stdout); + delay(500); + printf("redirecting to Serial..."); + + //JESUS ----------------------------------------------------------- } #else #error This example is only for use on Arduino. diff --git a/drivers/ATSHA204/ATSHA204.cpp b/drivers/ATSHA204/ATSHA204.cpp index ff7d250..9c6ad00 100644 --- a/drivers/ATSHA204/ATSHA204.cpp +++ b/drivers/ATSHA204/ATSHA204.cpp @@ -16,393 +16,361 @@ static uint8_t swi_send_byte(uint8_t value); static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response); static uint8_t sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, uint16_t address); static uint8_t sha204c_resync(uint8_t size, uint8_t *response); -static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, uint8_t execution_delay, uint8_t execution_timeout); +static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, + uint8_t execution_delay, uint8_t execution_timeout); /* SWI bit bang functions */ static void swi_set_signal_pin(uint8_t is_high) { - SHA204_SET_OUTPUT(); + SHA204_SET_OUTPUT(); - if (is_high) { - SHA204_POUT_HIGH(); - } - else { - SHA204_POUT_LOW(); - } + if (is_high) { + SHA204_POUT_HIGH(); + } else { + SHA204_POUT_LOW(); + } } static uint8_t swi_send_bytes(uint8_t count, uint8_t *buffer) { - uint8_t i, bit_mask; + uint8_t i, bit_mask; - // Disable interrupts while sending. - noInterrupts(); //swi_disable_interrupts(); + // Disable interrupts while sending. + noInterrupts(); //swi_disable_interrupts(); - // Set signal pin as output. - SHA204_POUT_HIGH(); - SHA204_SET_OUTPUT(); + // Set signal pin as output. + SHA204_POUT_HIGH(); + SHA204_SET_OUTPUT(); - // Wait turn around time. - delayMicroseconds(RX_TX_DELAY); //RX_TX_DELAY; + // Wait turn around time. + delayMicroseconds(RX_TX_DELAY); //RX_TX_DELAY; - for (i = 0; i < count; i++) - { - for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) - { - if (bit_mask & buffer[i]) - { - SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin; - delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; - SHA204_POUT_HIGH(); //*device_port_OUT |= device_pin; - delayMicroseconds(7*BIT_DELAY); //BIT_DELAY_7; - } - else - { - // Send a zero bit. - SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin; - delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; - SHA204_POUT_HIGH(); //*device_port_OUT |= device_pin; - delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; - SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin; - delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; - SHA204_POUT_HIGH(); //*device_port_OUT |= device_pin; - delayMicroseconds(5*BIT_DELAY); //BIT_DELAY_5; - } - } - } - interrupts(); //swi_enable_interrupts(); - return SWI_FUNCTION_RETCODE_SUCCESS; + for (i = 0; i < count; i++) { + for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) { + if (bit_mask & buffer[i]) { + SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin; + delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; + SHA204_POUT_HIGH(); //*device_port_OUT |= device_pin; + delayMicroseconds(7*BIT_DELAY); //BIT_DELAY_7; + } else { + // Send a zero bit. + SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin; + delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; + SHA204_POUT_HIGH(); //*device_port_OUT |= device_pin; + delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; + SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin; + delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; + SHA204_POUT_HIGH(); //*device_port_OUT |= device_pin; + delayMicroseconds(5*BIT_DELAY); //BIT_DELAY_5; + } + } + } + interrupts(); //swi_enable_interrupts(); + return SWI_FUNCTION_RETCODE_SUCCESS; } static uint8_t swi_send_byte(uint8_t value) { - return swi_send_bytes(1, &value); + return swi_send_bytes(1, &value); } static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer) { - uint8_t status = SWI_FUNCTION_RETCODE_SUCCESS; - uint8_t i; - uint8_t bit_mask; - uint8_t pulse_count; - uint8_t timeout_count; + uint8_t status = SWI_FUNCTION_RETCODE_SUCCESS; + uint8_t i; + uint8_t bit_mask; + uint8_t pulse_count; + uint8_t timeout_count; - // Disable interrupts while receiving. - noInterrupts(); //swi_disable_interrupts(); + // Disable interrupts while receiving. + noInterrupts(); //swi_disable_interrupts(); - // Configure signal pin as input. - SHA204_SET_INPUT(); + // Configure signal pin as input. + SHA204_SET_INPUT(); - // Receive bits and store in buffer. - for (i = 0; i < count; i++) - { - for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) - { - pulse_count = 0; + // Receive bits and store in buffer. + for (i = 0; i < count; i++) { + for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) { + pulse_count = 0; - // Make sure that the variable below is big enough. - // Change it to uint16_t if 255 is too small, but be aware that - // the loop resolution decreases on an 8-bit controller in that case. - timeout_count = START_PULSE_TIME_OUT; + // Make sure that the variable below is big enough. + // Change it to uint16_t if 255 is too small, but be aware that + // the loop resolution decreases on an 8-bit controller in that case. + timeout_count = START_PULSE_TIME_OUT; - // Detect start bit. - while (--timeout_count > 0) - { - // Wait for falling edge. - if (SHA204_PIN_READ() == 0) { - break; - } - } + // Detect start bit. + while (--timeout_count > 0) { + // Wait for falling edge. + if (SHA204_PIN_READ() == 0) { + break; + } + } - if (timeout_count == 0) - { - status = SWI_FUNCTION_RETCODE_TIMEOUT; - break; - } + if (timeout_count == 0) { + status = SWI_FUNCTION_RETCODE_TIMEOUT; + break; + } - do - { - // Wait for rising edge. - if (SHA204_PIN_READ() != 0) - { - // For an Atmel microcontroller this might be faster than "pulse_count++". - pulse_count = 1; - break; - } - } while (--timeout_count > 0); + do { + // Wait for rising edge. + if (SHA204_PIN_READ() != 0) { + // For an Atmel microcontroller this might be faster than "pulse_count++". + pulse_count = 1; + break; + } + } while (--timeout_count > 0); - if (pulse_count == 0) - { - status = SWI_FUNCTION_RETCODE_TIMEOUT; - break; - } + if (pulse_count == 0) { + status = SWI_FUNCTION_RETCODE_TIMEOUT; + break; + } - // Trying to measure the time of start bit and calculating the timeout - // for zero bit detection is not accurate enough for an 8 MHz 8-bit CPU. - // So let's just wait the maximum time for the falling edge of a zero bit - // to arrive after we have detected the rising edge of the start bit. - timeout_count = ZERO_PULSE_TIME_OUT; + // Trying to measure the time of start bit and calculating the timeout + // for zero bit detection is not accurate enough for an 8 MHz 8-bit CPU. + // So let's just wait the maximum time for the falling edge of a zero bit + // to arrive after we have detected the rising edge of the start bit. + timeout_count = ZERO_PULSE_TIME_OUT; - // Detect possible edge indicating zero bit. - do - { - if (SHA204_PIN_READ() == 0) - { - // For an Atmel microcontroller this might be faster than "pulse_count++". - pulse_count = 2; - break; - } - } while (--timeout_count > 0); + // Detect possible edge indicating zero bit. + do { + if (SHA204_PIN_READ() == 0) { + // For an Atmel microcontroller this might be faster than "pulse_count++". + pulse_count = 2; + break; + } + } while (--timeout_count > 0); - // Wait for rising edge of zero pulse before returning. Otherwise we might interpret - // its rising edge as the next start pulse. - if (pulse_count == 2) - { - do - { - if (SHA204_PIN_READ() != 0) { - break; - } - } while (timeout_count-- > 0); - } + // Wait for rising edge of zero pulse before returning. Otherwise we might interpret + // its rising edge as the next start pulse. + if (pulse_count == 2) { + do { + if (SHA204_PIN_READ() != 0) { + break; + } + } while (timeout_count-- > 0); + } - // Update byte at current buffer index. - else - buffer[i] |= bit_mask; // received "one" bit - } + // Update byte at current buffer index. + else { + buffer[i] |= bit_mask; // received "one" bit + } + } - if (status != SWI_FUNCTION_RETCODE_SUCCESS) { - break; - } - } - interrupts(); //swi_enable_interrupts(); + if (status != SWI_FUNCTION_RETCODE_SUCCESS) { + break; + } + } + interrupts(); //swi_enable_interrupts(); - if (status == SWI_FUNCTION_RETCODE_TIMEOUT) - { - if (i > 0) { - // Indicate that we timed out after having received at least one byte. - status = SWI_FUNCTION_RETCODE_RX_FAIL; - } - } - return status; + if (status == SWI_FUNCTION_RETCODE_TIMEOUT) { + if (i > 0) { + // Indicate that we timed out after having received at least one byte. + status = SWI_FUNCTION_RETCODE_RX_FAIL; + } + } + return status; } /* Physical functions */ static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response) { - uint8_t count_byte; - uint8_t i; - uint8_t ret_code; + uint8_t count_byte; + uint8_t i; + uint8_t ret_code; - for (i = 0; i < size; i++) { - response[i] = 0; - } + for (i = 0; i < size; i++) { + response[i] = 0; + } - (void) swi_send_byte(SHA204_SWI_FLAG_TX); + (void) swi_send_byte(SHA204_SWI_FLAG_TX); - ret_code = swi_receive_bytes(size, response); - if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) - { - count_byte = response[SHA204_BUFFER_POS_COUNT]; - if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) { - return SHA204_INVALID_SIZE; - } + ret_code = swi_receive_bytes(size, response); + if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) { + count_byte = response[SHA204_BUFFER_POS_COUNT]; + if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) { + return SHA204_INVALID_SIZE; + } - return SHA204_SUCCESS; - } + return SHA204_SUCCESS; + } - // Translate error so that the Communication layer - // can distinguish between a real error or the - // device being busy executing a command. - if (ret_code == SWI_FUNCTION_RETCODE_TIMEOUT) { - return SHA204_RX_NO_RESPONSE; - } - else { - return SHA204_RX_FAIL; - } + // Translate error so that the Communication layer + // can distinguish between a real error or the + // device being busy executing a command. + if (ret_code == SWI_FUNCTION_RETCODE_TIMEOUT) { + return SHA204_RX_NO_RESPONSE; + } else { + return SHA204_RX_FAIL; + } } /* Communication functions */ static uint8_t sha204c_resync(uint8_t size, uint8_t *response) { - // Try to re-synchronize without sending a Wake token - // (step 1 of the re-synchronization process). - delay(SHA204_SYNC_TIMEOUT); - uint8_t ret_code = sha204p_receive_response(size, response); - if (ret_code == SHA204_SUCCESS) { - return ret_code; - } + // Try to re-synchronize without sending a Wake token + // (step 1 of the re-synchronization process). + delay(SHA204_SYNC_TIMEOUT); + uint8_t ret_code = sha204p_receive_response(size, response); + if (ret_code == SHA204_SUCCESS) { + return ret_code; + } - // We lost communication. Send a Wake pulse and try - // to receive a response (steps 2 and 3 of the - // re-synchronization process). - atsha204_sleep(); - ret_code = atsha204_wakeup(response); + // We lost communication. Send a Wake pulse and try + // to receive a response (steps 2 and 3 of the + // re-synchronization process). + atsha204_sleep(); + ret_code = atsha204_wakeup(response); - // Translate a return value of success into one - // that indicates that the device had to be woken up - // and might have lost its TempKey. - return (ret_code == SHA204_SUCCESS ? SHA204_RESYNC_WITH_WAKEUP : ret_code); + // Translate a return value of success into one + // that indicates that the device had to be woken up + // and might have lost its TempKey. + return (ret_code == SHA204_SUCCESS ? SHA204_RESYNC_WITH_WAKEUP : ret_code); } -static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, uint8_t execution_delay, uint8_t execution_timeout) +static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, + uint8_t execution_delay, uint8_t execution_timeout) { - uint8_t ret_code = SHA204_FUNC_FAIL; - uint8_t ret_code_resync; - uint8_t n_retries_send; - uint8_t n_retries_receive; - uint8_t i; - uint8_t status_byte; - uint8_t count = tx_buffer[SHA204_BUFFER_POS_COUNT]; - uint8_t count_minus_crc = count - SHA204_CRC_SIZE; - uint16_t execution_timeout_us = (uint16_t) (execution_timeout * 1000) + SHA204_RESPONSE_TIMEOUT; - volatile uint16_t timeout_countdown; + uint8_t ret_code = SHA204_FUNC_FAIL; + uint8_t ret_code_resync; + uint8_t n_retries_send; + uint8_t n_retries_receive; + uint8_t i; + uint8_t status_byte; + uint8_t count = tx_buffer[SHA204_BUFFER_POS_COUNT]; + uint8_t count_minus_crc = count - SHA204_CRC_SIZE; + uint16_t execution_timeout_us = (uint16_t) (execution_timeout * 1000) + SHA204_RESPONSE_TIMEOUT; + volatile uint16_t timeout_countdown; - // Append CRC. - sha204c_calculate_crc(count_minus_crc, tx_buffer, tx_buffer + count_minus_crc); + // Append CRC. + sha204c_calculate_crc(count_minus_crc, tx_buffer, tx_buffer + count_minus_crc); - // Retry loop for sending a command and receiving a response. - n_retries_send = SHA204_RETRY_COUNT + 1; + // Retry loop for sending a command and receiving a response. + n_retries_send = SHA204_RETRY_COUNT + 1; - while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS)) - { - // Send command. - ret_code = swi_send_byte(SHA204_SWI_FLAG_CMD); - if (ret_code != SWI_FUNCTION_RETCODE_SUCCESS) { - ret_code = SHA204_COMM_FAIL; - } - else { - ret_code = swi_send_bytes(count, tx_buffer); - } + while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS)) { + // Send command. + ret_code = swi_send_byte(SHA204_SWI_FLAG_CMD); + if (ret_code != SWI_FUNCTION_RETCODE_SUCCESS) { + ret_code = SHA204_COMM_FAIL; + } else { + ret_code = swi_send_bytes(count, tx_buffer); + } - if (ret_code != SHA204_SUCCESS) - { - if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) { - return ret_code; // The device seems to be dead in the water. - } - else { - continue; - } - } + if (ret_code != SHA204_SUCCESS) { + if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) { + return ret_code; // The device seems to be dead in the water. + } else { + continue; + } + } - // Wait minimum command execution time and then start polling for a response. - delay(execution_delay); + // Wait minimum command execution time and then start polling for a response. + delay(execution_delay); - // Retry loop for receiving a response. - n_retries_receive = SHA204_RETRY_COUNT + 1; - while (n_retries_receive-- > 0) - { - // Reset response buffer. - for (i = 0; i < rx_size; i++) { - rx_buffer[i] = 0; - } + // Retry loop for receiving a response. + n_retries_receive = SHA204_RETRY_COUNT + 1; + while (n_retries_receive-- > 0) { + // Reset response buffer. + for (i = 0; i < rx_size; i++) { + rx_buffer[i] = 0; + } - // Poll for response. - timeout_countdown = execution_timeout_us; - do - { - ret_code = sha204p_receive_response(rx_size, rx_buffer); - timeout_countdown -= SHA204_RESPONSE_TIMEOUT; - } - while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (ret_code == SHA204_RX_NO_RESPONSE)); + // Poll for response. + timeout_countdown = execution_timeout_us; + do { + ret_code = sha204p_receive_response(rx_size, rx_buffer); + timeout_countdown -= SHA204_RESPONSE_TIMEOUT; + } while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (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. - if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) { - // The device seems to be dead in the water. - return ret_code; - } - else { - break; - } - } + if (ret_code == SHA204_RX_NO_RESPONSE) { + // We did not receive a response. Re-synchronize and send command again. + if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) { + // The device seems to be dead in the water. + return ret_code; + } else { + break; + } + } - // Check whether we received a valid response. - if (ret_code == SHA204_INVALID_SIZE) - { - // We see 0xFF for the count when communication got out of sync. - ret_code_resync = sha204c_resync(rx_size, rx_buffer); - if (ret_code_resync == SHA204_SUCCESS) { - // We did not have to wake up the device. Try receiving response again. - continue; - } - if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) { - // We could re-synchronize, but only after waking up the device. - // Re-send command. - break; - } - else { - // We failed to re-synchronize. - return ret_code; - } - } + // Check whether we received a valid response. + if (ret_code == SHA204_INVALID_SIZE) { + // We see 0xFF for the count when communication got out of sync. + ret_code_resync = sha204c_resync(rx_size, rx_buffer); + if (ret_code_resync == SHA204_SUCCESS) { + // We did not have to wake up the device. Try receiving response again. + continue; + } + if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) { + // We could re-synchronize, but only after waking up the device. + // Re-send command. + break; + } else { + // We failed to re-synchronize. + return ret_code; + } + } - // We received a response of valid size. - // Check the consistency of the response. - ret_code = sha204c_check_crc(rx_buffer); - if (ret_code == SHA204_SUCCESS) - { - // Received valid response. - if (rx_buffer[SHA204_BUFFER_POS_COUNT] > SHA204_RSP_SIZE_MIN) { - // Received non-status response. We are done. - return ret_code; - } + // We received a response of valid size. + // Check the consistency of the response. + ret_code = sha204c_check_crc(rx_buffer); + if (ret_code == SHA204_SUCCESS) { + // Received valid response. + if (rx_buffer[SHA204_BUFFER_POS_COUNT] > SHA204_RSP_SIZE_MIN) { + // Received non-status response. We are done. + return ret_code; + } - // Received status response. - status_byte = rx_buffer[SHA204_BUFFER_POS_STATUS]; + // Received status response. + status_byte = rx_buffer[SHA204_BUFFER_POS_STATUS]; - // Translate the three possible device status error codes - // into library return codes. - if (status_byte == SHA204_STATUS_BYTE_PARSE) { - return SHA204_PARSE_ERROR; - } - if (status_byte == SHA204_STATUS_BYTE_EXEC) { - return SHA204_CMD_FAIL; - } - if (status_byte == SHA204_STATUS_BYTE_COMM) - { - // In case of the device status byte indicating a communication - // error this function exits the retry loop for receiving a response - // and enters the overall retry loop - // (send command / receive response). - ret_code = SHA204_STATUS_CRC; - break; - } + // Translate the three possible device status error codes + // into library return codes. + if (status_byte == SHA204_STATUS_BYTE_PARSE) { + return SHA204_PARSE_ERROR; + } + if (status_byte == SHA204_STATUS_BYTE_EXEC) { + return SHA204_CMD_FAIL; + } + if (status_byte == SHA204_STATUS_BYTE_COMM) { + // In case of the device status byte indicating a communication + // error this function exits the retry loop for receiving a response + // and enters the overall retry loop + // (send command / receive response). + ret_code = SHA204_STATUS_CRC; + break; + } - // Received status response from CheckMAC, DeriveKey, GenDig, - // Lock, Nonce, Pause, UpdateExtra, or Write command. - return ret_code; - } + // Received status response from CheckMAC, DeriveKey, GenDig, + // Lock, Nonce, Pause, UpdateExtra, or Write command. + return ret_code; + } - else - { - // Received response with incorrect CRC. - ret_code_resync = sha204c_resync(rx_size, rx_buffer); - if (ret_code_resync == SHA204_SUCCESS) { - // We did not have to wake up the device. Try receiving response again. - continue; - } - if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) { - // We could re-synchronize, but only after waking up the device. - // Re-send command. - break; - } - else { - // We failed to re-synchronize. - return ret_code; - } - } // block end of check response consistency + else { + // Received response with incorrect CRC. + ret_code_resync = sha204c_resync(rx_size, rx_buffer); + if (ret_code_resync == SHA204_SUCCESS) { + // We did not have to wake up the device. Try receiving response again. + continue; + } + if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) { + // We could re-synchronize, but only after waking up the device. + // Re-send command. + break; + } else { + // We failed to re-synchronize. + return ret_code; + } + } // block end of check response consistency - } // block end of receive retry loop + } // block end of receive retry loop - } // block end of send and receive retry loop + } // block end of send and receive retry loop - return ret_code; + return ret_code; } @@ -410,60 +378,59 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin static uint8_t sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, uint16_t address) { - uint8_t rx_size; + uint8_t rx_size; - address >>= 2; + address >>= 2; - tx_buffer[SHA204_COUNT_IDX] = READ_COUNT; - tx_buffer[SHA204_OPCODE_IDX] = SHA204_READ; - tx_buffer[READ_ZONE_IDX] = zone; - tx_buffer[READ_ADDR_IDX] = (uint8_t) (address & SHA204_ADDRESS_MASK); - tx_buffer[READ_ADDR_IDX + 1] = 0; + tx_buffer[SHA204_COUNT_IDX] = READ_COUNT; + tx_buffer[SHA204_OPCODE_IDX] = SHA204_READ; + tx_buffer[READ_ZONE_IDX] = zone; + tx_buffer[READ_ADDR_IDX] = (uint8_t) (address & SHA204_ADDRESS_MASK); + tx_buffer[READ_ADDR_IDX + 1] = 0; - rx_size = (zone & SHA204_ZONE_COUNT_FLAG) ? READ_32_RSP_SIZE : READ_4_RSP_SIZE; + rx_size = (zone & SHA204_ZONE_COUNT_FLAG) ? READ_32_RSP_SIZE : READ_4_RSP_SIZE; - return sha204c_send_and_receive(&tx_buffer[0], rx_size, &rx_buffer[0], READ_DELAY, READ_EXEC_MAX - READ_DELAY); + return sha204c_send_and_receive(&tx_buffer[0], rx_size, &rx_buffer[0], READ_DELAY, + READ_EXEC_MAX - READ_DELAY); } /* CRC Calculator and Checker */ static void sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc) { - uint8_t counter; - uint16_t crc_register = 0; - uint16_t polynom = 0x8005; - uint8_t shift_register; - uint8_t data_bit, crc_bit; + uint8_t counter; + uint16_t crc_register = 0; + uint16_t polynom = 0x8005; + uint8_t shift_register; + uint8_t data_bit, crc_bit; - for (counter = 0; counter < length; counter++) - { - for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) - { - data_bit = (data[counter] & shift_register) ? 1 : 0; - crc_bit = crc_register >> 15; + for (counter = 0; counter < length; counter++) { + for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) { + data_bit = (data[counter] & shift_register) ? 1 : 0; + crc_bit = crc_register >> 15; - // Shift CRC to the left by 1. - crc_register <<= 1; + // Shift CRC to the left by 1. + crc_register <<= 1; - if ((data_bit ^ crc_bit) != 0) { - crc_register ^= polynom; - } - } - } - crc[0] = (uint8_t) (crc_register & 0x00FF); - crc[1] = (uint8_t) (crc_register >> 8); + if ((data_bit ^ crc_bit) != 0) { + crc_register ^= polynom; + } + } + } + crc[0] = (uint8_t) (crc_register & 0x00FF); + crc[1] = (uint8_t) (crc_register >> 8); } static uint8_t sha204c_check_crc(uint8_t *response) { - uint8_t crc[SHA204_CRC_SIZE]; - uint8_t count = response[SHA204_BUFFER_POS_COUNT]; + uint8_t crc[SHA204_CRC_SIZE]; + uint8_t count = response[SHA204_BUFFER_POS_COUNT]; - count -= SHA204_CRC_SIZE; - sha204c_calculate_crc(count, response, crc); + count -= SHA204_CRC_SIZE; + sha204c_calculate_crc(count, response, crc); - return (crc[0] == response[count] && crc[1] == response[count + 1]) - ? SHA204_SUCCESS : SHA204_BAD_CRC; + return (crc[0] == response[count] && crc[1] == response[count + 1]) + ? SHA204_SUCCESS : SHA204_BAD_CRC; } /* Public functions */ @@ -471,116 +438,113 @@ static uint8_t sha204c_check_crc(uint8_t *response) void atsha204_init(uint8_t pin) { #if defined(ARDUINO_ARCH_AVR) - device_pin = digitalPinToBitMask(pin); // Find the bit value of the pin - uint8_t port = digitalPinToPort(pin); // temoporarily used to get the next three registers + device_pin = digitalPinToBitMask(pin); // Find the bit value of the pin + uint8_t port = digitalPinToPort(pin); // temoporarily used to get the next three registers - // Point to data direction register port of pin - device_port_DDR = portModeRegister(port); - // Point to output register of pin - device_port_OUT = portOutputRegister(port); - // Point to input register of pin - device_port_IN = portInputRegister(port); + // Point to data direction register port of pin + device_port_DDR = portModeRegister(port); + // Point to output register of pin + device_port_OUT = portOutputRegister(port); + // Point to input register of pin + device_port_IN = portInputRegister(port); #else - device_pin = pin; + device_pin = pin; #endif } void atsha204_idle(void) { - swi_send_byte(SHA204_SWI_FLAG_IDLE); + swi_send_byte(SHA204_SWI_FLAG_IDLE); } void atsha204_sleep(void) { - swi_send_byte(SHA204_SWI_FLAG_SLEEP); + swi_send_byte(SHA204_SWI_FLAG_SLEEP); } uint8_t atsha204_wakeup(uint8_t *response) { - swi_set_signal_pin(0); - delayMicroseconds(10*SHA204_WAKEUP_PULSE_WIDTH); - swi_set_signal_pin(1); - delay(SHA204_WAKEUP_DELAY); + swi_set_signal_pin(0); + delayMicroseconds(10*SHA204_WAKEUP_PULSE_WIDTH); + swi_set_signal_pin(1); + delay(SHA204_WAKEUP_DELAY); - uint8_t ret_code = sha204p_receive_response(SHA204_RSP_SIZE_MIN, response); - if (ret_code != SHA204_SUCCESS) { - return ret_code; - } + uint8_t ret_code = sha204p_receive_response(SHA204_RSP_SIZE_MIN, response); + if (ret_code != SHA204_SUCCESS) { + return ret_code; + } - // Verify status response. - if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN) { - ret_code = SHA204_INVALID_SIZE; - } - else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP) { - ret_code = SHA204_COMM_FAIL; - } - else - { - if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33) - || (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43)) { - ret_code = SHA204_BAD_CRC; - } - } - if (ret_code != SHA204_SUCCESS) { - delay(SHA204_COMMAND_EXEC_MAX); - } + // Verify status response. + if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN) { + ret_code = SHA204_INVALID_SIZE; + } else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP) { + ret_code = SHA204_COMM_FAIL; + } else { + if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33) + || (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43)) { + ret_code = SHA204_BAD_CRC; + } + } + if (ret_code != SHA204_SUCCESS) { + delay(SHA204_COMMAND_EXEC_MAX); + } - return ret_code; + return ret_code; } uint8_t atsha204_execute(uint8_t op_code, uint8_t param1, uint16_t param2, - uint8_t datalen1, uint8_t *data1, uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer) + uint8_t datalen1, uint8_t *data1, uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, + uint8_t *rx_buffer) { uint8_t poll_delay, poll_timeout, response_size; uint8_t *p_buffer; uint8_t len; - (void)tx_size; + (void)tx_size; // Supply delays and response size. - switch (op_code) - { - case SHA204_GENDIG: - poll_delay = GENDIG_DELAY; - poll_timeout = GENDIG_EXEC_MAX - GENDIG_DELAY; - response_size = GENDIG_RSP_SIZE; - break; + switch (op_code) { + case SHA204_GENDIG: + poll_delay = GENDIG_DELAY; + poll_timeout = GENDIG_EXEC_MAX - GENDIG_DELAY; + response_size = GENDIG_RSP_SIZE; + break; - case SHA204_HMAC: - poll_delay = HMAC_DELAY; - poll_timeout = HMAC_EXEC_MAX - HMAC_DELAY; - response_size = HMAC_RSP_SIZE; - break; + case SHA204_HMAC: + poll_delay = HMAC_DELAY; + poll_timeout = HMAC_EXEC_MAX - HMAC_DELAY; + response_size = HMAC_RSP_SIZE; + break; - case SHA204_NONCE: - poll_delay = NONCE_DELAY; - poll_timeout = NONCE_EXEC_MAX - NONCE_DELAY; - response_size = param1 == NONCE_MODE_PASSTHROUGH - ? NONCE_RSP_SIZE_SHORT : NONCE_RSP_SIZE_LONG; - break; + case SHA204_NONCE: + poll_delay = NONCE_DELAY; + poll_timeout = NONCE_EXEC_MAX - NONCE_DELAY; + response_size = param1 == NONCE_MODE_PASSTHROUGH + ? NONCE_RSP_SIZE_SHORT : NONCE_RSP_SIZE_LONG; + break; - case SHA204_RANDOM: - poll_delay = RANDOM_DELAY; - poll_timeout = RANDOM_EXEC_MAX - RANDOM_DELAY; - response_size = RANDOM_RSP_SIZE; - break; + case SHA204_RANDOM: + poll_delay = RANDOM_DELAY; + poll_timeout = RANDOM_EXEC_MAX - RANDOM_DELAY; + response_size = RANDOM_RSP_SIZE; + break; - case SHA204_SHA: - poll_delay = SHA_DELAY; - poll_timeout = SHA_EXEC_MAX - SHA_DELAY; - response_size = param1 == SHA_INIT - ? SHA_RSP_SIZE_SHORT : SHA_RSP_SIZE_LONG; - break; + case SHA204_SHA: + poll_delay = SHA_DELAY; + poll_timeout = SHA_EXEC_MAX - SHA_DELAY; + response_size = param1 == SHA_INIT + ? SHA_RSP_SIZE_SHORT : SHA_RSP_SIZE_LONG; + break; - case SHA204_WRITE: - poll_delay = WRITE_DELAY; - poll_timeout = WRITE_EXEC_MAX - WRITE_DELAY; - response_size = WRITE_RSP_SIZE; - break; + case SHA204_WRITE: + poll_delay = WRITE_DELAY; + poll_timeout = WRITE_EXEC_MAX - WRITE_DELAY; + response_size = WRITE_RSP_SIZE; + break; - default: - poll_delay = 0; - poll_timeout = SHA204_COMMAND_EXEC_MAX; - response_size = rx_size; + default: + poll_delay = 0; + poll_timeout = SHA204_COMMAND_EXEC_MAX; + response_size = rx_size; } // Assemble command. @@ -601,35 +565,34 @@ uint8_t atsha204_execute(uint8_t op_code, uint8_t param1, uint16_t param2, // Send command and receive response. return sha204c_send_and_receive(&tx_buffer[0], response_size, - &rx_buffer[0], poll_delay, poll_timeout); + &rx_buffer[0], poll_delay, poll_timeout); } uint8_t atsha204_getSerialNumber(uint8_t * response) { - uint8_t readCommand[READ_COUNT]; - uint8_t readResponse[READ_4_RSP_SIZE]; + uint8_t readCommand[READ_COUNT]; + uint8_t readResponse[READ_4_RSP_SIZE]; - /* read from bytes 0->3 of config zone */ - uint8_t returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN03); - if (!returnCode) - { - for (int i=0; i<4; i++) {// store bytes 0-3 into respones array - response[i] = readResponse[SHA204_BUFFER_POS_DATA+i]; - } + /* read from bytes 0->3 of config zone */ + uint8_t returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN03); + if (!returnCode) { + for (int i=0; i<4; i++) {// store bytes 0-3 into respones array + response[i] = readResponse[SHA204_BUFFER_POS_DATA+i]; + } - /* read from bytes 8->11 of config zone */ - returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN47); + /* read from bytes 8->11 of config zone */ + 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 - response[i] = readResponse[SHA204_BUFFER_POS_DATA+(i-4)]; - } + 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)]; + } - if (!returnCode) - { /* Finally if last two reads were successful, read byte 8 of the SN */ - returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN8); - response[8] = readResponse[SHA204_BUFFER_POS_DATA]; // Byte 8 of SN should always be 0xEE - } - } + if (!returnCode) { + /* Finally if last two reads were successful, read byte 8 of the SN */ + returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN8); + response[8] = readResponse[SHA204_BUFFER_POS_DATA]; // Byte 8 of SN should always be 0xEE + } + } - return returnCode; + return returnCode; } diff --git a/drivers/ATSHA204/ATSHA204.h b/drivers/ATSHA204/ATSHA204.h index aefa644..94b4171 100644 --- a/drivers/ATSHA204/ATSHA204.h +++ b/drivers/ATSHA204/ATSHA204.h @@ -244,8 +244,8 @@ void atsha204_idle(void); void atsha204_sleep(void); uint8_t atsha204_wakeup(uint8_t *response); uint8_t atsha204_execute(uint8_t op_code, uint8_t param1, uint16_t param2, - uint8_t datalen1, uint8_t *data1, uint8_t tx_size, - uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer); + uint8_t datalen1, uint8_t *data1, uint8_t tx_size, + uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer); uint8_t atsha204_getSerialNumber(uint8_t *response); #endif diff --git a/drivers/ATSHA204/sha256.cpp b/drivers/ATSHA204/sha256.cpp index ac89f8e..b085e72 100644 --- a/drivers/ATSHA204/sha256.cpp +++ b/drivers/ATSHA204/sha256.cpp @@ -1,7 +1,7 @@ #include #if defined(__AVR__) - #include - #define PRIPSTR "%S" +#include +#define PRIPSTR "%S" #elif defined(ESP8266) #include #endif @@ -9,132 +9,146 @@ const uint32_t sha256K[] PROGMEM = { - 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, - 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, - 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, - 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, - 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, - 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, - 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, - 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, + 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, + 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, + 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, + 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, + 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, + 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, + 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 }; #define BUFFER_SIZE 64 const uint8_t sha256InitState[] PROGMEM = { - 0x67,0xe6,0x09,0x6a, // H0 - 0x85,0xae,0x67,0xbb, // H1 - 0x72,0xf3,0x6e,0x3c, // H2 - 0x3a,0xf5,0x4f,0xa5, // H3 - 0x7f,0x52,0x0e,0x51, // H4 - 0x8c,0x68,0x05,0x9b, // H5 - 0xab,0xd9,0x83,0x1f, // H6 - 0x19,0xcd,0xe0,0x5b // H7 + 0x67,0xe6,0x09,0x6a, // H0 + 0x85,0xae,0x67,0xbb, // H1 + 0x72,0xf3,0x6e,0x3c, // H2 + 0x3a,0xf5,0x4f,0xa5, // H3 + 0x7f,0x52,0x0e,0x51, // H4 + 0x8c,0x68,0x05,0x9b, // H5 + 0xab,0xd9,0x83,0x1f, // H6 + 0x19,0xcd,0xe0,0x5b // H7 }; -void Sha256Class::init(void) { - memcpy_P(state.b,sha256InitState,32); - byteCount = 0; - bufferOffset = 0; +void Sha256Class::init(void) +{ + memcpy_P(state.b,sha256InitState,32); + byteCount = 0; + bufferOffset = 0; } -uint32_t Sha256Class::ror32(uint32_t number, uint8_t bits) { - return ((number << (32-bits)) | (number >> bits)); +uint32_t Sha256Class::ror32(uint32_t number, uint8_t bits) +{ + return ((number << (32-bits)) | (number >> bits)); } -void Sha256Class::hashBlock() { - uint8_t i; - uint32_t a,b,c,d,e,f,g,h,t1,t2; +void Sha256Class::hashBlock() +{ + uint8_t i; + uint32_t a,b,c,d,e,f,g,h,t1,t2; - a=state.w[0]; - b=state.w[1]; - c=state.w[2]; - d=state.w[3]; - e=state.w[4]; - f=state.w[5]; - g=state.w[6]; - h=state.w[7]; + a=state.w[0]; + b=state.w[1]; + c=state.w[2]; + d=state.w[3]; + e=state.w[4]; + f=state.w[5]; + g=state.w[6]; + h=state.w[7]; - for (i=0; i<64; i++) { - if (i>=16) { - t1 = buffer.w[i&15] + buffer.w[(i-7)&15]; - t2 = buffer.w[(i-2)&15]; - t1 += ror32(t2,17) ^ ror32(t2,19) ^ (t2>>10); - t2 = buffer.w[(i-15)&15]; - t1 += ror32(t2,7) ^ ror32(t2,18) ^ (t2>>3); - buffer.w[i&15] = t1; - } - t1 = h; - t1 += ror32(e,6) ^ ror32(e,11) ^ ror32(e,25); // ∑1(e) - t1 += g ^ (e & (g ^ f)); // Ch(e,f,g) - t1 += pgm_read_dword(sha256K+i); // Ki - t1 += buffer.w[i&15]; // Wi - t2 = ror32(a,2) ^ ror32(a,13) ^ ror32(a,22); // ∑0(a) - t2 += ((b & c) | (a & (b | c))); // Maj(a,b,c) - h=g; g=f; f=e; e=d+t1; d=c; c=b; b=a; a=t1+t2; - } - state.w[0] += a; - state.w[1] += b; - state.w[2] += c; - state.w[3] += d; - state.w[4] += e; - state.w[5] += f; - state.w[6] += g; - state.w[7] += h; + for (i=0; i<64; i++) { + if (i>=16) { + t1 = buffer.w[i&15] + buffer.w[(i-7)&15]; + t2 = buffer.w[(i-2)&15]; + t1 += ror32(t2,17) ^ ror32(t2,19) ^ (t2>>10); + t2 = buffer.w[(i-15)&15]; + t1 += ror32(t2,7) ^ ror32(t2,18) ^ (t2>>3); + buffer.w[i&15] = t1; + } + t1 = h; + t1 += ror32(e,6) ^ ror32(e,11) ^ ror32(e,25); // ∑1(e) + t1 += g ^ (e & (g ^ f)); // Ch(e,f,g) + t1 += pgm_read_dword(sha256K+i); // Ki + t1 += buffer.w[i&15]; // Wi + t2 = ror32(a,2) ^ ror32(a,13) ^ ror32(a,22); // ∑0(a) + t2 += ((b & c) | (a & (b | c))); // Maj(a,b,c) + h=g; + g=f; + f=e; + e=d+t1; + d=c; + c=b; + b=a; + a=t1+t2; + } + state.w[0] += a; + state.w[1] += b; + state.w[2] += c; + state.w[3] += d; + state.w[4] += e; + state.w[5] += f; + state.w[6] += g; + state.w[7] += h; } -void Sha256Class::addUncounted(uint8_t data) { - buffer.b[bufferOffset ^ 3] = data; - bufferOffset++; - if (bufferOffset == BUFFER_SIZE) { - hashBlock(); - bufferOffset = 0; - } +void Sha256Class::addUncounted(uint8_t data) +{ + buffer.b[bufferOffset ^ 3] = data; + bufferOffset++; + if (bufferOffset == BUFFER_SIZE) { + hashBlock(); + bufferOffset = 0; + } } -void Sha256Class::write(uint8_t data) { - ++byteCount; - addUncounted(data); +void Sha256Class::write(uint8_t data) +{ + ++byteCount; + addUncounted(data); } -void Sha256Class::pad() { - // Implement SHA-256 padding (fips180-2 §5.1.1) +void Sha256Class::pad() +{ + // Implement SHA-256 padding (fips180-2 §5.1.1) - // Pad with 0x80 followed by 0x00 until the end of the block - addUncounted(0x80); - while (bufferOffset != 56) { + // Pad with 0x80 followed by 0x00 until the end of the block + addUncounted(0x80); + while (bufferOffset != 56) { addUncounted(0x00); } - // Append length in the last 8 bytes - addUncounted(0); // We're only using 32 bit lengths - addUncounted(0); // But SHA-1 supports 64 bit lengths - addUncounted(0); // So zero pad the top bits - addUncounted(byteCount >> 29); // Shifting to multiply by 8 - addUncounted(byteCount >> 21); // as SHA-1 supports bitstreams as well as - addUncounted(byteCount >> 13); // byte. - addUncounted(byteCount >> 5); - addUncounted(byteCount << 3); + // Append length in the last 8 bytes + addUncounted(0); // We're only using 32 bit lengths + addUncounted(0); // But SHA-1 supports 64 bit lengths + addUncounted(0); // So zero pad the top bits + addUncounted(byteCount >> 29); // Shifting to multiply by 8 + addUncounted(byteCount >> 21); // as SHA-1 supports bitstreams as well as + addUncounted(byteCount >> 13); // byte. + addUncounted(byteCount >> 5); + addUncounted(byteCount << 3); } -uint8_t* Sha256Class::result(void) { - // Pad to complete the last block - pad(); +uint8_t* Sha256Class::result(void) +{ + // Pad to complete the last block + pad(); - // Swap byte order back - for (int i=0; i<8; i++) { - uint32_t a,b; - a=state.w[i]; - b=a<<24; - b|=(a<<8) & 0x00ff0000; - b|=(a>>8) & 0x0000ff00; - b|=a>>24; - state.w[i]=b; - } + // Swap byte order back + for (int i=0; i<8; i++) { + uint32_t a,b; + a=state.w[i]; + b=a<<24; + b|=(a<<8) & 0x00ff0000; + b|=(a>>8) & 0x0000ff00; + b|=a>>24; + state.w[i]=b; + } - // Return pointer to hash (20 characters) - return state.b; + // Return pointer to hash (20 characters) + return state.b; } #define HMAC_IPAD 0x36 @@ -143,38 +157,40 @@ uint8_t* Sha256Class::result(void) { uint8_t keyBuffer[BLOCK_LENGTH]; // K0 in FIPS-198a uint8_t innerHash[HASH_LENGTH]; -void Sha256Class::initHmac(const uint8_t* key, int keyLength) { - uint8_t i; - memset(keyBuffer,0,BLOCK_LENGTH); - if (keyLength > BLOCK_LENGTH) { - // Hash long keys - init(); - for (;keyLength--;) { +void Sha256Class::initHmac(const uint8_t* key, int keyLength) +{ + uint8_t i; + memset(keyBuffer,0,BLOCK_LENGTH); + if (keyLength > BLOCK_LENGTH) { + // Hash long keys + init(); + for (; keyLength--;) { write(*key++); } - memcpy(keyBuffer,result(),HASH_LENGTH); - } else { - // Block length keys are used as is - memcpy(keyBuffer,key,keyLength); - } - // Start inner hash - init(); - for (i=0; i= digitalPinCount) { - badPinNumber(); - } +static ALWAYS_INLINE void badPinCheck(uint8_t pin) +{ + if (!__builtin_constant_p(pin) || pin >= digitalPinCount) { + badPinNumber(); + } } //------------------------------------------------------------------------------ /** fast write helper @@ -413,29 +414,31 @@ static ALWAYS_INLINE void badPinCheck(uint8_t pin) { * @param[in] bit bit number to write * @param[in] level value for bit */ -static ALWAYS_INLINE void fastBitWriteSafe(volatile uint8_t* address, uint8_t bit, bool level) { - uint8_t oldSREG; - if (address > (uint8_t*)0X5F) { - oldSREG = SREG; - cli(); - } - if (level) { - *address |= 1 << bit; - } else { - *address &= ~(1 << bit); - } - if (address > (uint8_t*)0X5F) { - SREG = oldSREG; - } +static ALWAYS_INLINE void fastBitWriteSafe(volatile uint8_t* address, uint8_t bit, bool level) +{ + uint8_t oldSREG; + if (address > (uint8_t*)0X5F) { + oldSREG = SREG; + cli(); + } + if (level) { + *address |= 1 << bit; + } else { + *address &= ~(1 << bit); + } + if (address > (uint8_t*)0X5F) { + SREG = oldSREG; + } } //------------------------------------------------------------------------------ /** read pin value * @param[in] pin Arduino pin number * @return value read */ -static ALWAYS_INLINE bool fastDigitalRead(uint8_t pin) { - badPinCheck(pin); - return (*pinMap[pin].pin >> pinMap[pin].bit) & 1; +static ALWAYS_INLINE bool fastDigitalRead(uint8_t pin) +{ + badPinCheck(pin); + return (*pinMap[pin].pin >> pinMap[pin].bit) & 1; } //------------------------------------------------------------------------------ /** toggle a pin @@ -444,24 +447,26 @@ static ALWAYS_INLINE bool fastDigitalRead(uint8_t pin) { * If the pin is in output mode toggle the pin level. * If the pin is in input mode toggle the state of the 20K pullup. */ -static ALWAYS_INLINE void fastDigitalToggle(uint8_t pin) { - badPinCheck(pin); - if (pinMap[pin].pin > (uint8_t*)0X5F) { - // must write bit to high address port - *pinMap[pin].pin = 1 << pinMap[pin].bit; - } else { - // will compile to sbi and PIN register will not be read. - *pinMap[pin].pin |= 1 << pinMap[pin].bit; - } +static ALWAYS_INLINE void fastDigitalToggle(uint8_t pin) +{ + badPinCheck(pin); + if (pinMap[pin].pin > (uint8_t*)0X5F) { + // must write bit to high address port + *pinMap[pin].pin = 1 << pinMap[pin].bit; + } else { + // will compile to sbi and PIN register will not be read. + *pinMap[pin].pin |= 1 << pinMap[pin].bit; + } } //------------------------------------------------------------------------------ /** Set pin value * @param[in] pin Arduino pin number * @param[in] level value to write */ -static ALWAYS_INLINE void fastDigitalWrite(uint8_t pin, bool level) { - badPinCheck(pin); - fastBitWriteSafe(pinMap[pin].port, pinMap[pin].bit, level); +static ALWAYS_INLINE void fastDigitalWrite(uint8_t pin, bool level) +{ + badPinCheck(pin); + fastBitWriteSafe(pinMap[pin].port, pinMap[pin].bit, level); } //------------------------------------------------------------------------------ /** set pin mode @@ -470,9 +475,10 @@ static ALWAYS_INLINE void fastDigitalWrite(uint8_t pin, bool level) { * * fastPinMode does not enable or disable the 20K pullup for input mode. */ -static ALWAYS_INLINE void fastPinMode(uint8_t pin, bool mode) { - badPinCheck(pin); - fastBitWriteSafe(pinMap[pin].ddr, pinMap[pin].bit, mode); +static ALWAYS_INLINE void fastPinMode(uint8_t pin, bool mode) +{ + badPinCheck(pin); + fastBitWriteSafe(pinMap[pin].ddr, pinMap[pin].bit, mode); } //------------------------------------------------------------------------------ /** set pin configuration @@ -481,9 +487,10 @@ static ALWAYS_INLINE void fastPinMode(uint8_t pin, bool mode) { * @param[in] level If mode is output, set level high/low. * If mode is input, enable or disable the pin's 20K pullup. */ -static ALWAYS_INLINE void fastPinConfig(uint8_t pin, bool mode, bool level) { - fastPinMode(pin, mode); - fastDigitalWrite(pin, level); +static ALWAYS_INLINE void fastPinConfig(uint8_t pin, bool mode, bool level) +{ + fastPinMode(pin, mode); + fastDigitalWrite(pin, level); } //============================================================================== /** @@ -491,96 +498,112 @@ static ALWAYS_INLINE void fastPinConfig(uint8_t pin, bool mode, bool level) { * @brief Fast AVR digital port I/O */ template -class DigitalPin { - public: - //---------------------------------------------------------------------------- - /** Constructor */ - DigitalPin() {} - //---------------------------------------------------------------------------- - /** Constructor - * @param[in] pinMode if true set output mode else input mode. - */ - explicit DigitalPin(bool pinMode) { - mode(pinMode); - } - //---------------------------------------------------------------------------- - /** Constructor - * @param[in] mode If true set output mode else input mode - * @param[in] level If mode is output, set level high/low. - * If mode is input, enable or disable the pin's 20K pullup. - */ - DigitalPin(bool mode, bool level) { - config(mode, level); - } - //---------------------------------------------------------------------------- - /** Asignment operator - * @param[in] value If true set the pin's level high else set the - * pin's level low. - * - * @return This DigitalPin instance. - */ - inline DigitalPin & operator = (bool value) __attribute__((always_inline)) { - write(value); - return *this; - } - //---------------------------------------------------------------------------- - /** Parenthesis operator - * @return Pin's level - */ - inline operator bool () const __attribute__((always_inline)) { - return read(); - } - //---------------------------------------------------------------------------- - /** set pin configuration - * @param[in] mode If true set output mode else input mode - * @param[in] level If mode is output, set level high/low. - * If mode is input, enable or disable the pin's 20K pullup. - */ - ALWAYS_INLINE void config(bool mode, bool level) { - fastPinConfig(PinNumber, mode, level); - } - //---------------------------------------------------------------------------- - /** - * Set pin level high if output mode or enable 20K pullup if input mode. - */ - ALWAYS_INLINE void high() {write(true);} - //---------------------------------------------------------------------------- - /** - * Set pin level low if output mode or disable 20K pullup if input mode. - */ - ALWAYS_INLINE void low() {write(false);} - //---------------------------------------------------------------------------- - /** - * Set pin mode - * @param[in] pinMode if true set output mode else input mode. - * - * mode() does not enable or disable the 20K pullup for input mode. - */ - ALWAYS_INLINE void mode(bool pinMode) { - fastPinMode(PinNumber, pinMode); - } - //---------------------------------------------------------------------------- - /** @return Pin's level */ - ALWAYS_INLINE bool read() const { - return fastDigitalRead(PinNumber); - } - //---------------------------------------------------------------------------- - /** toggle a pin - * - * If the pin is in output mode toggle the pin's level. - * If the pin is in input mode toggle the state of the 20K pullup. - */ - ALWAYS_INLINE void toggle() { - fastDigitalToggle(PinNumber); - } - //---------------------------------------------------------------------------- - /** Write the pin's level. - * @param[in] value If true set the pin's level high else set the - * pin's level low. - */ - ALWAYS_INLINE void write(bool value) { - fastDigitalWrite(PinNumber, value); - } +class DigitalPin +{ +public: + //---------------------------------------------------------------------------- + /** Constructor */ + DigitalPin() {} + //---------------------------------------------------------------------------- + /** Constructor + * @param[in] pinMode if true set output mode else input mode. + */ + explicit DigitalPin(bool pinMode) + { + mode(pinMode); + } + //---------------------------------------------------------------------------- + /** Constructor + * @param[in] mode If true set output mode else input mode + * @param[in] level If mode is output, set level high/low. + * If mode is input, enable or disable the pin's 20K pullup. + */ + DigitalPin(bool mode, bool level) + { + config(mode, level); + } + //---------------------------------------------------------------------------- + /** Asignment operator + * @param[in] value If true set the pin's level high else set the + * pin's level low. + * + * @return This DigitalPin instance. + */ + inline DigitalPin & operator = (bool value) __attribute__((always_inline)) + { + write(value); + return *this; + } + //---------------------------------------------------------------------------- + /** Parenthesis operator + * @return Pin's level + */ + inline operator bool () const __attribute__((always_inline)) + { + return read(); + } + //---------------------------------------------------------------------------- + /** set pin configuration + * @param[in] mode If true set output mode else input mode + * @param[in] level If mode is output, set level high/low. + * If mode is input, enable or disable the pin's 20K pullup. + */ + ALWAYS_INLINE void config(bool mode, bool level) + { + fastPinConfig(PinNumber, mode, level); + } + //---------------------------------------------------------------------------- + /** + * Set pin level high if output mode or enable 20K pullup if input mode. + */ + ALWAYS_INLINE void high() + { + write(true); + } + //---------------------------------------------------------------------------- + /** + * Set pin level low if output mode or disable 20K pullup if input mode. + */ + ALWAYS_INLINE void low() + { + write(false); + } + //---------------------------------------------------------------------------- + /** + * Set pin mode + * @param[in] pinMode if true set output mode else input mode. + * + * mode() does not enable or disable the 20K pullup for input mode. + */ + ALWAYS_INLINE void mode(bool pinMode) + { + fastPinMode(PinNumber, pinMode); + } + //---------------------------------------------------------------------------- + /** @return Pin's level */ + ALWAYS_INLINE bool read() const + { + return fastDigitalRead(PinNumber); + } + //---------------------------------------------------------------------------- + /** toggle a pin + * + * If the pin is in output mode toggle the pin's level. + * If the pin is in input mode toggle the state of the 20K pullup. + */ + ALWAYS_INLINE void toggle() + { + fastDigitalToggle(PinNumber); + } + //---------------------------------------------------------------------------- + /** Write the pin's level. + * @param[in] value If true set the pin's level high else set the + * pin's level low. + */ + ALWAYS_INLINE void write(bool value) + { + fastDigitalWrite(PinNumber, value); + } }; #endif // DigitalPin_h /** @} */ \ No newline at end of file diff --git a/drivers/AVR/DigitalIO/PinIO.cpp b/drivers/AVR/DigitalIO/PinIO.cpp index 5f1ff52..e2b842b 100644 --- a/drivers/AVR/DigitalIO/PinIO.cpp +++ b/drivers/AVR/DigitalIO/PinIO.cpp @@ -32,22 +32,26 @@ /** Constructor * @param[in] pin Pin assigned to this object. */ -PinIO::PinIO(uint8_t pin) { - begin(pin); +PinIO::PinIO(uint8_t pin) +{ + begin(pin); } //------------------------------------------------------------------------------ /** Initialize pin bit mask and port address. * @param[in] pin Arduino board pin number. * @return true for success or false if invalid pin number. */ -bool PinIO::begin(uint8_t pin) { - if (pin >= NUM_DIGITAL_PINS) return false; - uint8_t port = digitalPinToPort(pin); - pinReg_ = portInputRegister(port); - bit_ = digitalPinToBitMask(pin); - mask_ = ~bit_; - portReg_ = pinReg_ + 2; - return true; +bool PinIO::begin(uint8_t pin) +{ + if (pin >= NUM_DIGITAL_PINS) { + return false; + } + uint8_t port = digitalPinToPort(pin); + pinReg_ = portInputRegister(port); + bit_ = digitalPinToBitMask(pin); + mask_ = ~bit_; + portReg_ = pinReg_ + 2; + return true; } //------------------------------------------------------------------------------ /** Configure the pin @@ -59,10 +63,11 @@ bool PinIO::begin(uint8_t pin) { * This function may be used with interrupts enabled or disabled. * The previous interrupt state will be restored. */ -void PinIO::config(bool mode, bool data) { - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { - modeI(mode); - writeI(data); - } +void PinIO::config(bool mode, bool data) +{ + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + modeI(mode); + writeI(data); + } } /** @} */ diff --git a/drivers/AVR/DigitalIO/PinIO.h b/drivers/AVR/DigitalIO/PinIO.h index c861d13..cd9e35d 100644 --- a/drivers/AVR/DigitalIO/PinIO.h +++ b/drivers/AVR/DigitalIO/PinIO.h @@ -37,118 +37,153 @@ * @class PinIO * @brief AVR port I/O with runtime pin numbers. */ -class PinIO { - public: - /** Create a PinIO object with no assigned pin. */ - PinIO() : bit_(0), mask_(0XFF) {} - /** Constructor - * @param[in] pin Pin assigned to this object. - */ - explicit PinIO(uint8_t pin); - /** Initialize pin bit mask and port address. - * @param[in] pin Arduino board pin number. - * @return true for success or false if invalid pin number. - */ - bool begin(uint8_t pin); - /** Configure the pin - * - * @param[in] mode Configure as output mode if true else input mode. - * @param[in] data For output mode set pin high if true else low. - * For input mode enable 20K pullup if true else Hi-Z. - * - * This function may be used with interrupts enabled or disabled. - * The previous interrupt state will be restored. - */ - void config(bool mode, bool data); - //---------------------------------------------------------------------------- - /** @return Pin's level */ - ALWAYS_INLINE bool read() {return *pinReg_ & bit_;} - //---------------------------------------------------------------------------- - /** toggle a pin - * - * If the pin is in output mode toggle the pin's level. - * If the pin is in input mode toggle the state of the 20K pullup. - */ - ALWAYS_INLINE void toggle() {*pinReg_ = bit_;} - //============================================================================ - /** - * Set pin high if output mode or enable 20K pullup if input mode. - * - * This function must be called with interrupts disabled. - * This function will not change the interrupt state. - */ - ALWAYS_INLINE void highI() {writeI(1);} - /** - * Set pin low if output mode or disable 20K pullup if input mode. - * - * This function must be called with interrupts disabled. - * This function will not change the interrupt state. - */ - ALWAYS_INLINE void lowI() {writeI(0);} - /** - * Set pin mode - * @param[in] mode if true set output mode else input mode. - * - * mode() does not enable or disable the 20K pullup for input mode. - * - * This function must be called with interrupts disabled. - * This function will not change the interrupt state. - */ - ALWAYS_INLINE void modeI(bool mode) { - volatile uint8_t* ddrReg = pinReg_ + 1; - *ddrReg = mode ? *ddrReg | bit_ : *ddrReg & mask_; - } - /** Write pin. - * - * @param[in] level If output mode set pin high if true else low. - * If input mode enable 20K pullup if true else disable pullup. - * - * This function must be called with interrupts disabled. - * This function will not change the interrupt state. - */ - ALWAYS_INLINE void writeI(bool level) { - *portReg_ = level ? *portReg_ | bit_ : *portReg_ & mask_; - } - //============================================================================ - /** - * Set pin level high if output mode or enable 20K pullup if input mode. - * - * This function will enable interrupts. This function should not be - * called in an ISR or where interrupts are disabled. - */ - ALWAYS_INLINE void high() {ATOMIC_BLOCK(ATOMIC_FORCEON) {highI();}} - /** - * Set pin level low if output mode or disable 20K pullup if input mode. - * - * This function will enable interrupts. This function should not be - * called in an ISR or where interrupts are disabled. - */ - ALWAYS_INLINE void low() {ATOMIC_BLOCK(ATOMIC_FORCEON) {lowI();}} - /** - * Set pin mode - * @param[in] pinMode if true set output mode else input mode. - * - * mode() does not enable or disable the 20K pullup for input mode. - * - * This function will enable interrupts. This function should not be - * called in an ISR or where interrupts are disabled. - */ - ALWAYS_INLINE void mode(bool pinMode) {ATOMIC_BLOCK(ATOMIC_FORCEON) {modeI(pinMode);}} - /** Write pin. - * - * @param[in] level If output mode set pin high if true else low. - * If input mode enable 20K pullup if true else disable pullup. - * - * This function will enable interrupts. This function should not be - * called in an ISR or where interrupts are disabled. - */ - ALWAYS_INLINE void write(bool level) {ATOMIC_BLOCK(ATOMIC_FORCEON) {writeI(level);}} - //---------------------------------------------------------------------------- - private: - uint8_t bit_; - uint8_t mask_; - volatile uint8_t* pinReg_; - volatile uint8_t* portReg_; +class PinIO +{ +public: + /** Create a PinIO object with no assigned pin. */ + PinIO() : bit_(0), mask_(0XFF) {} + /** Constructor + * @param[in] pin Pin assigned to this object. + */ + explicit PinIO(uint8_t pin); + /** Initialize pin bit mask and port address. + * @param[in] pin Arduino board pin number. + * @return true for success or false if invalid pin number. + */ + bool begin(uint8_t pin); + /** Configure the pin + * + * @param[in] mode Configure as output mode if true else input mode. + * @param[in] data For output mode set pin high if true else low. + * For input mode enable 20K pullup if true else Hi-Z. + * + * This function may be used with interrupts enabled or disabled. + * The previous interrupt state will be restored. + */ + void config(bool mode, bool data); + //---------------------------------------------------------------------------- + /** @return Pin's level */ + ALWAYS_INLINE bool read() + { + return *pinReg_ & bit_; + } + //---------------------------------------------------------------------------- + /** toggle a pin + * + * If the pin is in output mode toggle the pin's level. + * If the pin is in input mode toggle the state of the 20K pullup. + */ + ALWAYS_INLINE void toggle() + { + *pinReg_ = bit_; + } + //============================================================================ + /** + * Set pin high if output mode or enable 20K pullup if input mode. + * + * This function must be called with interrupts disabled. + * This function will not change the interrupt state. + */ + ALWAYS_INLINE void highI() + { + writeI(1); + } + /** + * Set pin low if output mode or disable 20K pullup if input mode. + * + * This function must be called with interrupts disabled. + * This function will not change the interrupt state. + */ + ALWAYS_INLINE void lowI() + { + writeI(0); + } + /** + * Set pin mode + * @param[in] mode if true set output mode else input mode. + * + * mode() does not enable or disable the 20K pullup for input mode. + * + * This function must be called with interrupts disabled. + * This function will not change the interrupt state. + */ + ALWAYS_INLINE void modeI(bool mode) + { + volatile uint8_t* ddrReg = pinReg_ + 1; + *ddrReg = mode ? *ddrReg | bit_ : *ddrReg & mask_; + } + /** Write pin. + * + * @param[in] level If output mode set pin high if true else low. + * If input mode enable 20K pullup if true else disable pullup. + * + * This function must be called with interrupts disabled. + * This function will not change the interrupt state. + */ + ALWAYS_INLINE void writeI(bool level) + { + *portReg_ = level ? *portReg_ | bit_ : *portReg_ & mask_; + } + //============================================================================ + /** + * Set pin level high if output mode or enable 20K pullup if input mode. + * + * This function will enable interrupts. This function should not be + * called in an ISR or where interrupts are disabled. + */ + ALWAYS_INLINE void high() + { + ATOMIC_BLOCK(ATOMIC_FORCEON) { + highI(); + } + } + /** + * Set pin level low if output mode or disable 20K pullup if input mode. + * + * This function will enable interrupts. This function should not be + * called in an ISR or where interrupts are disabled. + */ + ALWAYS_INLINE void low() + { + ATOMIC_BLOCK(ATOMIC_FORCEON) { + lowI(); + } + } + /** + * Set pin mode + * @param[in] pinMode if true set output mode else input mode. + * + * mode() does not enable or disable the 20K pullup for input mode. + * + * This function will enable interrupts. This function should not be + * called in an ISR or where interrupts are disabled. + */ + ALWAYS_INLINE void mode(bool pinMode) + { + ATOMIC_BLOCK(ATOMIC_FORCEON) { + modeI(pinMode); + } + } + /** Write pin. + * + * @param[in] level If output mode set pin high if true else low. + * If input mode enable 20K pullup if true else disable pullup. + * + * This function will enable interrupts. This function should not be + * called in an ISR or where interrupts are disabled. + */ + ALWAYS_INLINE void write(bool level) + { + ATOMIC_BLOCK(ATOMIC_FORCEON) { + writeI(level); + } + } + //---------------------------------------------------------------------------- +private: + uint8_t bit_; + uint8_t mask_; + volatile uint8_t* pinReg_; + volatile uint8_t* portReg_; }; #endif // PinIO_h /** @} */ \ No newline at end of file diff --git a/drivers/AVR/DigitalIO/SoftI2cMaster.cpp b/drivers/AVR/DigitalIO/SoftI2cMaster.cpp index d02b2bb..e504d3f 100644 --- a/drivers/AVR/DigitalIO/SoftI2cMaster.cpp +++ b/drivers/AVR/DigitalIO/SoftI2cMaster.cpp @@ -49,16 +49,17 @@ * @return true for success else false. */ bool I2cMasterBase::transfer(uint8_t addrRW, - void *buf, size_t nbytes, uint8_t option) { - if (_state != STATE_REP_START) { - start(); - } - if (!write(addrRW)) { - _state = addrRW & I2C_READ ? STATE_RX_ADDR_NACK : STATE_TX_ADDR_NACK; - return false; - } - _state = addrRW & I2C_READ ? STATE_RX_DATA : STATE_TX_DATA; - return transferContinue(buf, nbytes, option); + void *buf, size_t nbytes, uint8_t option) +{ + if (_state != STATE_REP_START) { + start(); + } + if (!write(addrRW)) { + _state = addrRW & I2C_READ ? STATE_RX_ADDR_NACK : STATE_TX_ADDR_NACK; + return false; + } + _state = addrRW & I2C_READ ? STATE_RX_DATA : STATE_TX_DATA; + return transferContinue(buf, nbytes, option); } //------------------------------------------------------------------------------ /** @@ -76,30 +77,31 @@ bool I2cMasterBase::transfer(uint8_t addrRW, * . * @return true for success else false. */ -bool I2cMasterBase::transferContinue(void *buf, size_t nbytes, uint8_t option) { - uint8_t* p = reinterpret_cast(buf); - if (_state == STATE_RX_DATA) { - for (size_t i = 0; i < nbytes; i++) { - p[i] = read(i == (nbytes - 1) && option != I2C_CONTINUE); - } - } else if (_state == STATE_TX_DATA) { - for (size_t i = 0; i < nbytes; i++) { - if (!write(p[i])) { - _state = STATE_TX_DATA_NACK; - return false; - } - } - } else { - return false; - } - if (option == I2C_STOP) { - stop(); - _state = STATE_STOP; - } else if (option == I2C_REP_START) { - start(); - _state = STATE_STOP; - } - return true; +bool I2cMasterBase::transferContinue(void *buf, size_t nbytes, uint8_t option) +{ + uint8_t* p = reinterpret_cast(buf); + if (_state == STATE_RX_DATA) { + for (size_t i = 0; i < nbytes; i++) { + p[i] = read(i == (nbytes - 1) && option != I2C_CONTINUE); + } + } else if (_state == STATE_TX_DATA) { + for (size_t i = 0; i < nbytes; i++) { + if (!write(p[i])) { + _state = STATE_TX_DATA_NACK; + return false; + } + } + } else { + return false; + } + if (option == I2C_STOP) { + stop(); + _state = STATE_STOP; + } else if (option == I2C_REP_START) { + start(); + _state = STATE_STOP; + } + return true; } //============================================================================== // WARNING don't change SoftI2cMaster unless you verify the change with a scope @@ -111,8 +113,9 @@ bool I2cMasterBase::transferContinue(void *buf, size_t nbytes, uint8_t option) { * * @param[in] sclPin The software SCL pin number. */ -SoftI2cMaster::SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin) { - begin(sclPin, sdaPin); +SoftI2cMaster::SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin) +{ + begin(sclPin, sdaPin); } //------------------------------------------------------------------------------ /** @@ -122,32 +125,33 @@ SoftI2cMaster::SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin) { * * @param[in] sclPin The software SCL pin number. */ -void SoftI2cMaster::begin(uint8_t sclPin, uint8_t sdaPin) { - uint8_t port; +void SoftI2cMaster::begin(uint8_t sclPin, uint8_t sdaPin) +{ + uint8_t port; - // Get bit mask and address of scl registers. - _sclBit = digitalPinToBitMask(sclPin); - port = digitalPinToPort(sclPin); - _sclDDR = portModeRegister(port); - volatile uint8_t* sclOutReg = portOutputRegister(port); + // Get bit mask and address of scl registers. + _sclBit = digitalPinToBitMask(sclPin); + port = digitalPinToPort(sclPin); + _sclDDR = portModeRegister(port); + volatile uint8_t* sclOutReg = portOutputRegister(port); - // Get bit mask and address of sda registers. - _sdaBit = digitalPinToBitMask(sdaPin); - port = digitalPinToPort(sdaPin); - _sdaDDR = portModeRegister(port); - _sdaInReg = portInputRegister(port); - volatile uint8_t* sdaOutReg = portOutputRegister(port); + // Get bit mask and address of sda registers. + _sdaBit = digitalPinToBitMask(sdaPin); + port = digitalPinToPort(sdaPin); + _sdaDDR = portModeRegister(port); + _sdaInReg = portInputRegister(port); + volatile uint8_t* sdaOutReg = portOutputRegister(port); - // Clear PORT bit for scl and sda. - uint8_t s = SREG; - noInterrupts(); - *sclOutReg &= ~_sclBit; - *sdaOutReg &= ~_sdaBit; - SREG = s; + // Clear PORT bit for scl and sda. + uint8_t s = SREG; + noInterrupts(); + *sclOutReg &= ~_sclBit; + *sdaOutReg &= ~_sdaBit; + SREG = s; - // Set scl and sda high. - writeScl(HIGH); - writeSda(HIGH); + // Set scl and sda high. + writeScl(HIGH); + writeSda(HIGH); } //------------------------------------------------------------------------------ /* Read a byte and send ACK if more reads follow else NACK to terminate read. @@ -156,51 +160,56 @@ void SoftI2cMaster::begin(uint8_t sclPin, uint8_t sdaPin) { * * @return The byte read from the I2C bus. */ -uint8_t SoftI2cMaster::read(uint8_t last) { - uint8_t b = 0; +uint8_t SoftI2cMaster::read(uint8_t last) +{ + uint8_t b = 0; - // Set sda to high Z mode for read. - writeSda(HIGH); - // Read a byte. - for (uint8_t i = 0; i < 8; i++) { - // Don't change this loop unless you verify the change with a scope. - b <<= 1; - sclDelay(16); - writeScl(HIGH); - sclDelay(12); - if (readSda()) b |= 1; - writeScl(LOW); - } - // send ACK or NACK - writeSda(last); - sclDelay(12); - writeScl(HIGH); - sclDelay(18); - writeScl(LOW); - writeSda(LOW); - return b; + // Set sda to high Z mode for read. + writeSda(HIGH); + // Read a byte. + for (uint8_t i = 0; i < 8; i++) { + // Don't change this loop unless you verify the change with a scope. + b <<= 1; + sclDelay(16); + writeScl(HIGH); + sclDelay(12); + if (readSda()) { + b |= 1; + } + writeScl(LOW); + } + // send ACK or NACK + writeSda(last); + sclDelay(12); + writeScl(HIGH); + sclDelay(18); + writeScl(LOW); + writeSda(LOW); + return b; } //------------------------------------------------------------------------------ /* Issue a start condition. */ -void SoftI2cMaster::start() { - if (!readSda()) { - writeSda(HIGH); - writeScl(HIGH); - sclDelay(20); - } - writeSda(LOW); - sclDelay(20); - writeScl(LOW); +void SoftI2cMaster::start() +{ + if (!readSda()) { + writeSda(HIGH); + writeScl(HIGH); + sclDelay(20); + } + writeSda(LOW); + sclDelay(20); + writeScl(LOW); } //------------------------------------------------------------------------------ - /* Issue a stop condition. */ -void SoftI2cMaster::stop(void) { - writeSda(LOW); - sclDelay(20); - writeScl(HIGH); - sclDelay(20); - writeSda(HIGH); - sclDelay(20); +/* Issue a stop condition. */ +void SoftI2cMaster::stop(void) +{ + writeSda(LOW); + sclDelay(20); + writeScl(HIGH); + sclDelay(20); + writeSda(HIGH); + sclDelay(20); } //------------------------------------------------------------------------------ /* @@ -210,30 +219,31 @@ void SoftI2cMaster::stop(void) { * * @return The value true, 1, if the slave returned an ACK or false for NACK. */ -bool SoftI2cMaster::write(uint8_t data) { - // write byte - for (uint8_t m = 0X80; m != 0; m >>= 1) { - // don't change this loop unless you verify the change with a scope - writeSda(m & data); - sclDelay(8); - writeScl(HIGH); - sclDelay(18); - writeScl(LOW); - } - sclDelay(8); - // Go to sda high Z mode for input. - writeSda(HIGH); - writeScl(HIGH); - sclDelay(16); +bool SoftI2cMaster::write(uint8_t data) +{ + // write byte + for (uint8_t m = 0X80; m != 0; m >>= 1) { + // don't change this loop unless you verify the change with a scope + writeSda(m & data); + sclDelay(8); + writeScl(HIGH); + sclDelay(18); + writeScl(LOW); + } + sclDelay(8); + // Go to sda high Z mode for input. + writeSda(HIGH); + writeScl(HIGH); + sclDelay(16); - // Get ACK or NACK. - uint8_t rtn = readSda(); + // Get ACK or NACK. + uint8_t rtn = readSda(); - // pull scl low. - writeScl(LOW); + // pull scl low. + writeScl(LOW); - // Pull sda low. - writeSda(LOW); - return rtn == 0; + // Pull sda low. + writeSda(LOW); + return rtn == 0; } /** @} */ diff --git a/drivers/AVR/DigitalIO/SoftI2cMaster.h b/drivers/AVR/DigitalIO/SoftI2cMaster.h index dd4bbf0..dd250eb 100644 --- a/drivers/AVR/DigitalIO/SoftI2cMaster.h +++ b/drivers/AVR/DigitalIO/SoftI2cMaster.h @@ -63,151 +63,161 @@ const uint8_t STATE_TX_DATA_NACK = 6; * @class I2cMasterBase * @brief Base class for FastI2cMaster, SoftI2cMaster */ -class I2cMasterBase { - public: - I2cMasterBase() : _state(STATE_STOP) {} - /** Read a byte - * - * @note This function should only be used by experts. Data should be - * accessed by calling transfer() and transferContinue() - * - * @param[in] last send a NACK to terminate read if last is true else - * send an ACK to continue the read. - * - * @return byte read from I2C bus - */ - virtual uint8_t read(uint8_t last) = 0; +class I2cMasterBase +{ +public: + I2cMasterBase() : _state(STATE_STOP) {} + /** Read a byte + * + * @note This function should only be used by experts. Data should be + * accessed by calling transfer() and transferContinue() + * + * @param[in] last send a NACK to terminate read if last is true else + * send an ACK to continue the read. + * + * @return byte read from I2C bus + */ + virtual uint8_t read(uint8_t last) = 0; - /** Issue a start condition - * - * @note This function should only be used by experts. Data should be - * accessed by calling transfer() and transferContinue() - */ - virtual void start() = 0; - /** Issue a stop condition. - * - * @note This function should only be used by experts. Data should be - * accessed by calling transfer() and transferContinue() - */ - virtual void stop() = 0; + /** Issue a start condition + * + * @note This function should only be used by experts. Data should be + * accessed by calling transfer() and transferContinue() + */ + virtual void start() = 0; + /** Issue a stop condition. + * + * @note This function should only be used by experts. Data should be + * accessed by calling transfer() and transferContinue() + */ + virtual void stop() = 0; -/** - * Start an I2C transfer with possible continuation. - * - * @param[in] addressRW I2C slave address plus R/W bit. - * The I2C slave address is in the high seven bits - * and is ORed with on of the following: - * - I2C_READ for a read transfer. - * - I2C_WRITE for a write transfer. - * . - * @param[in,out] buf Source or destination for transfer. - * @param[in] nbyte Number of bytes to transfer (may be zero). - * @param[in] option Option for ending the transfer, one of: - * - I2C_STOP end the transfer with an I2C stop - * condition. - * - I2C_REP_START end the transfer with an I2C - * repeated start condition. - * - I2C_CONTINUE allow additional transferContinue() - * calls. - * . - * @return true for success else false. - */ - bool transfer(uint8_t addressRW, void *buf, - size_t nbyte, uint8_t option = I2C_STOP); + /** + * Start an I2C transfer with possible continuation. + * + * @param[in] addressRW I2C slave address plus R/W bit. + * The I2C slave address is in the high seven bits + * and is ORed with on of the following: + * - I2C_READ for a read transfer. + * - I2C_WRITE for a write transfer. + * . + * @param[in,out] buf Source or destination for transfer. + * @param[in] nbyte Number of bytes to transfer (may be zero). + * @param[in] option Option for ending the transfer, one of: + * - I2C_STOP end the transfer with an I2C stop + * condition. + * - I2C_REP_START end the transfer with an I2C + * repeated start condition. + * - I2C_CONTINUE allow additional transferContinue() + * calls. + * . + * @return true for success else false. + */ + bool transfer(uint8_t addressRW, void *buf, + size_t nbyte, uint8_t option = I2C_STOP); -/** - * Continue an I2C transfer. - * - * @param[in,out] buf Source or destination for transfer. - * @param[in] nbyte Number of bytes to transfer (may be zero). - * @param[in] option Option for ending the transfer, one of: - * - I2C_STOP end the transfer with an I2C stop - * condition. - * - I2C_REP_START end the transfer with an I2C - * repeated start condition. - * - I2C_CONTINUE allow additional transferContinue() - * calls. - * . - * @return true for success else false. - */ - bool transferContinue(void *buf, size_t nbyte, uint8_t option = I2C_STOP); - /** Write a byte - * - * @note This function should only be used by experts. Data should be - * accessed by calling transfer() and transferContinue() - * - * @param[in] data byte to write - * @return true for ACK or false for NACK */ - virtual bool write(uint8_t data) = 0; + /** + * Continue an I2C transfer. + * + * @param[in,out] buf Source or destination for transfer. + * @param[in] nbyte Number of bytes to transfer (may be zero). + * @param[in] option Option for ending the transfer, one of: + * - I2C_STOP end the transfer with an I2C stop + * condition. + * - I2C_REP_START end the transfer with an I2C + * repeated start condition. + * - I2C_CONTINUE allow additional transferContinue() + * calls. + * . + * @return true for success else false. + */ + bool transferContinue(void *buf, size_t nbyte, uint8_t option = I2C_STOP); + /** Write a byte + * + * @note This function should only be used by experts. Data should be + * accessed by calling transfer() and transferContinue() + * + * @param[in] data byte to write + * @return true for ACK or false for NACK */ + virtual bool write(uint8_t data) = 0; - private: - uint8_t _state; +private: + uint8_t _state; }; //============================================================================== /** * @class SoftI2cMaster * @brief Software I2C master class */ -class SoftI2cMaster : public I2cMasterBase { - public: - SoftI2cMaster() {} - /** - * Constructor, initialize SCL/SDA pins and set the bus high. - * - * @param[in] sdaPin The software SDA pin number. - * - * @param[in] sclPin The software SCL pin number. - */ - SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin); - /** - * Initialize SCL/SDA pins and set the bus high. - * - * @param[in] sdaPin The software SDA pin number. - * - * @param[in] sclPin The software SCL pin number. - */ - void begin(uint8_t sclPin, uint8_t sdaPin); - uint8_t read(uint8_t last); - void start(); - void stop(void); - bool write(uint8_t b); +class SoftI2cMaster : public I2cMasterBase +{ +public: + SoftI2cMaster() {} + /** + * Constructor, initialize SCL/SDA pins and set the bus high. + * + * @param[in] sdaPin The software SDA pin number. + * + * @param[in] sclPin The software SCL pin number. + */ + SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin); + /** + * Initialize SCL/SDA pins and set the bus high. + * + * @param[in] sdaPin The software SDA pin number. + * + * @param[in] sclPin The software SCL pin number. + */ + void begin(uint8_t sclPin, uint8_t sdaPin); + uint8_t read(uint8_t last); + void start(); + void stop(void); + bool write(uint8_t b); - private: - uint8_t _sclBit; - uint8_t _sdaBit; - volatile uint8_t* _sclDDR; - volatile uint8_t* _sdaDDR; - volatile uint8_t* _sdaInReg; - //---------------------------------------------------------------------------- - bool readSda() {return *_sdaInReg & _sdaBit;} - //---------------------------------------------------------------------------- - void sclDelay(uint8_t n) {_delay_loop_1(n);} - //---------------------------------------------------------------------------- - void writeScl(bool value) { - uint8_t s = SREG; - noInterrupts(); - if (value == LOW) { - // Pull scl low. - *_sclDDR |= _sclBit; - } else { - // Put scl in high Z input mode. - *_sclDDR &= ~_sclBit; - } - SREG = s; - } - //---------------------------------------------------------------------------- - void writeSda(bool value) { - uint8_t s = SREG; - noInterrupts(); - if (value == LOW) { - // Pull sda low. - *_sdaDDR |= _sdaBit; - } else { - // Put sda in high Z input mode. - *_sdaDDR &= ~_sdaBit; - } - SREG = s; - } +private: + uint8_t _sclBit; + uint8_t _sdaBit; + volatile uint8_t* _sclDDR; + volatile uint8_t* _sdaDDR; + volatile uint8_t* _sdaInReg; + //---------------------------------------------------------------------------- + bool readSda() + { + return *_sdaInReg & _sdaBit; + } + //---------------------------------------------------------------------------- + void sclDelay(uint8_t n) + { + _delay_loop_1(n); + } + //---------------------------------------------------------------------------- + void writeScl(bool value) + { + uint8_t s = SREG; + noInterrupts(); + if (value == LOW) { + // Pull scl low. + *_sclDDR |= _sclBit; + } else { + // Put scl in high Z input mode. + *_sclDDR &= ~_sclBit; + } + SREG = s; + } + //---------------------------------------------------------------------------- + void writeSda(bool value) + { + uint8_t s = SREG; + noInterrupts(); + if (value == LOW) { + // Pull sda low. + *_sdaDDR |= _sdaBit; + } else { + // Put sda in high Z input mode. + *_sdaDDR &= ~_sdaBit; + } + SREG = s; + } }; //============================================================================== // Template based fast software I2C @@ -217,118 +227,140 @@ class SoftI2cMaster : public I2cMasterBase { * @brief Fast software I2C master class. */ template -class FastI2cMaster : public I2cMasterBase { - public: - //---------------------------------------------------------------------------- - FastI2cMaster() { - begin(); - } - //---------------------------------------------------------------------------- - /** Initialize I2C bus pins. */ - void begin() { - fastDigitalWrite(sclPin, LOW); - fastDigitalWrite(sdaPin, LOW); +class FastI2cMaster : public I2cMasterBase +{ +public: + //---------------------------------------------------------------------------- + FastI2cMaster() + { + begin(); + } + //---------------------------------------------------------------------------- + /** Initialize I2C bus pins. */ + void begin() + { + fastDigitalWrite(sclPin, LOW); + fastDigitalWrite(sdaPin, LOW); - sclWrite(HIGH); - sdaWrite(HIGH); - } - //---------------------------------------------------------------------------- - uint8_t read(uint8_t last) { - uint8_t data = 0; - sdaWrite(HIGH); + sclWrite(HIGH); + sdaWrite(HIGH); + } + //---------------------------------------------------------------------------- + uint8_t read(uint8_t last) + { + uint8_t data = 0; + sdaWrite(HIGH); - readBit(7, &data); - readBit(6, &data); - readBit(5, &data); - readBit(4, &data); - readBit(3, &data); - readBit(2, &data); - readBit(1, &data); - readBit(0, &data); + readBit(7, &data); + readBit(6, &data); + readBit(5, &data); + readBit(4, &data); + readBit(3, &data); + readBit(2, &data); + readBit(1, &data); + readBit(0, &data); - // send ACK or NACK - sdaWrite(last); - sclDelay(4); - sclWrite(HIGH); - sclDelay(6); - sclWrite(LOW); - sdaWrite(LOW); - return data; - } - //---------------------------------------------------------------------------- - void start() { - if (!fastDigitalRead(sdaPin)) { - // It's a repeat start. - sdaWrite(HIGH); - sclDelay(8); - sclWrite(HIGH); - sclDelay(8); - } - sdaWrite(LOW); - sclDelay(8); - sclWrite(LOW); - sclDelay(8); - } - //---------------------------------------------------------------------------- - void stop(void) { - sdaWrite(LOW); - sclDelay(8); - sclWrite(HIGH); - sclDelay(8); - sdaWrite(HIGH); - sclDelay(8); - } - //---------------------------------------------------------------------------- - bool write(uint8_t data) { - // write byte - writeBit(7, data); - writeBit(6, data); - writeBit(5, data); - writeBit(4, data); - writeBit(3, data); - writeBit(2, data); - writeBit(1, data); - writeBit(0, data); + // send ACK or NACK + sdaWrite(last); + sclDelay(4); + sclWrite(HIGH); + sclDelay(6); + sclWrite(LOW); + sdaWrite(LOW); + return data; + } + //---------------------------------------------------------------------------- + void start() + { + if (!fastDigitalRead(sdaPin)) { + // It's a repeat start. + sdaWrite(HIGH); + sclDelay(8); + sclWrite(HIGH); + sclDelay(8); + } + sdaWrite(LOW); + sclDelay(8); + sclWrite(LOW); + sclDelay(8); + } + //---------------------------------------------------------------------------- + void stop(void) + { + sdaWrite(LOW); + sclDelay(8); + sclWrite(HIGH); + sclDelay(8); + sdaWrite(HIGH); + sclDelay(8); + } + //---------------------------------------------------------------------------- + bool write(uint8_t data) + { + // write byte + writeBit(7, data); + writeBit(6, data); + writeBit(5, data); + writeBit(4, data); + writeBit(3, data); + writeBit(2, data); + writeBit(1, data); + writeBit(0, data); - // get ACK or NACK - sdaWrite(HIGH); + // get ACK or NACK + sdaWrite(HIGH); - sclWrite(HIGH); - sclDelay(5); - bool rtn = fastDigitalRead(sdaPin); - sclWrite(LOW); - sdaWrite(LOW); - return rtn == 0; - } + sclWrite(HIGH); + sclDelay(5); + bool rtn = fastDigitalRead(sdaPin); + sclWrite(LOW); + sdaWrite(LOW); + return rtn == 0; + } - private: - //---------------------------------------------------------------------------- - inline __attribute__((always_inline)) - void sclWrite(bool value) {fastPinMode(sclPin, !value);} - //---------------------------------------------------------------------------- - inline __attribute__((always_inline)) - void sdaWrite(bool value) {fastPinMode(sdaPin, !value);} - //---------------------------------------------------------------------------- - inline __attribute__((always_inline)) - void readBit(uint8_t bit, uint8_t* data) { - sclWrite(HIGH); - sclDelay(5); - if (fastDigitalRead(sdaPin)) *data |= 1 << bit; - sclWrite(LOW); - if (bit) sclDelay(6); - } - //---------------------------------------------------------------------------- - void sclDelay(uint8_t n) {_delay_loop_1(n);} - //---------------------------------------------------------------------------- - inline __attribute__((always_inline)) - void writeBit(uint8_t bit, uint8_t data) { - uint8_t mask = 1 << bit; - sdaWrite(data & mask); - sclWrite(HIGH); - sclDelay(5); - sclWrite(LOW); - sclDelay(5); - } +private: + //---------------------------------------------------------------------------- + inline __attribute__((always_inline)) + void sclWrite(bool value) + { + fastPinMode(sclPin, !value); + } + //---------------------------------------------------------------------------- + inline __attribute__((always_inline)) + void sdaWrite(bool value) + { + fastPinMode(sdaPin, !value); + } + //---------------------------------------------------------------------------- + inline __attribute__((always_inline)) + void readBit(uint8_t bit, uint8_t* data) + { + sclWrite(HIGH); + sclDelay(5); + if (fastDigitalRead(sdaPin)) { + *data |= 1 << bit; + } + sclWrite(LOW); + if (bit) { + sclDelay(6); + } + } + //---------------------------------------------------------------------------- + void sclDelay(uint8_t n) + { + _delay_loop_1(n); + } + //---------------------------------------------------------------------------- + inline __attribute__((always_inline)) + void writeBit(uint8_t bit, uint8_t data) + { + uint8_t mask = 1 << bit; + sdaWrite(data & mask); + sclWrite(HIGH); + sclDelay(5); + sclWrite(LOW); + sclDelay(5); + } }; #endif // SOFT_I2C_MASTER_H /** @} */ diff --git a/drivers/AVR/DigitalIO/SoftSPI.h b/drivers/AVR/DigitalIO/SoftSPI.h index 86f9d94..d714055 100644 --- a/drivers/AVR/DigitalIO/SoftSPI.h +++ b/drivers/AVR/DigitalIO/SoftSPI.h @@ -18,7 +18,7 @@ * . */ /** - * @file + * @file * @brief Software SPI. * * @defgroup softSPI Software SPI @@ -48,108 +48,126 @@ const bool SCK_MODE = true; * @brief Fast software SPI. */ template -class SoftSPI { - public: - //---------------------------------------------------------------------------- - /** Initialize SoftSPI pins. */ - void begin() { - fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL); - fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode)); - fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode)); - } - //---------------------------------------------------------------------------- - /** Soft SPI receive byte. - * @return Data byte received. - */ - ALWAYS_INLINE uint8_t receive() { - uint8_t data = 0; - receiveBit(7, &data); - receiveBit(6, &data); - receiveBit(5, &data); - receiveBit(4, &data); - receiveBit(3, &data); - receiveBit(2, &data); - receiveBit(1, &data); - receiveBit(0, &data); - return data; - } - //---------------------------------------------------------------------------- - /** Soft SPI send byte. - * @param[in] data Data byte to send. - */ - ALWAYS_INLINE void send(uint8_t data) { - sendBit(7, data); - sendBit(6, data); - sendBit(5, data); - sendBit(4, data); - sendBit(3, data); - sendBit(2, data); - sendBit(1, data); - sendBit(0, data); - } - //---------------------------------------------------------------------------- - /** Soft SPI transfer byte. - * @param[in] txData Data byte to send. - * @return Data byte received. - */ - ALWAYS_INLINE uint8_t transfer(uint8_t txData) { - uint8_t rxData = 0; - transferBit(7, &rxData, txData); - transferBit(6, &rxData, txData); - transferBit(5, &rxData, txData); - transferBit(4, &rxData, txData); - transferBit(3, &rxData, txData); - transferBit(2, &rxData, txData); - transferBit(1, &rxData, txData); - transferBit(0, &rxData, txData); - return rxData; - } +class SoftSPI +{ +public: + //---------------------------------------------------------------------------- + /** Initialize SoftSPI pins. */ + void begin() + { + fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL); + fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode)); + fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode)); + } + //---------------------------------------------------------------------------- + /** Soft SPI receive byte. + * @return Data byte received. + */ + ALWAYS_INLINE uint8_t receive() + { + uint8_t data = 0; + receiveBit(7, &data); + receiveBit(6, &data); + receiveBit(5, &data); + receiveBit(4, &data); + receiveBit(3, &data); + receiveBit(2, &data); + receiveBit(1, &data); + receiveBit(0, &data); + return data; + } + //---------------------------------------------------------------------------- + /** Soft SPI send byte. + * @param[in] data Data byte to send. + */ + ALWAYS_INLINE void send(uint8_t data) + { + sendBit(7, data); + sendBit(6, data); + sendBit(5, data); + sendBit(4, data); + sendBit(3, data); + sendBit(2, data); + sendBit(1, data); + sendBit(0, data); + } + //---------------------------------------------------------------------------- + /** Soft SPI transfer byte. + * @param[in] txData Data byte to send. + * @return Data byte received. + */ + ALWAYS_INLINE uint8_t transfer(uint8_t txData) + { + uint8_t rxData = 0; + transferBit(7, &rxData, txData); + transferBit(6, &rxData, txData); + transferBit(5, &rxData, txData); + transferBit(4, &rxData, txData); + transferBit(3, &rxData, txData); + transferBit(2, &rxData, txData); + transferBit(1, &rxData, txData); + transferBit(0, &rxData, txData); + return rxData; + } - private: - //---------------------------------------------------------------------------- - ALWAYS_INLINE bool MODE_CPHA(uint8_t mode) {return (mode & 1) != 0;} - ALWAYS_INLINE bool MODE_CPOL(uint8_t mode) {return (mode & 2) != 0;} - ALWAYS_INLINE void receiveBit(uint8_t bit, uint8_t* data) { - if (MODE_CPHA(Mode)) { - fastDigitalWrite(SckPin, !MODE_CPOL(Mode)); - } - nop; - nop; - fastDigitalWrite(SckPin, - MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode)); - if (fastDigitalRead(MisoPin)) *data |= 1 << bit; - if (!MODE_CPHA(Mode)) { - fastDigitalWrite(SckPin, MODE_CPOL(Mode)); - } - } - //---------------------------------------------------------------------------- - ALWAYS_INLINE void sendBit(uint8_t bit, uint8_t data) { - if (MODE_CPHA(Mode)) { - fastDigitalWrite(SckPin, !MODE_CPOL(Mode)); - } - fastDigitalWrite(MosiPin, data & (1 << bit)); - fastDigitalWrite(SckPin, - MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode)); - nop; - nop; - if (!MODE_CPHA(Mode)) { - fastDigitalWrite(SckPin, MODE_CPOL(Mode)); - } - } - //---------------------------------------------------------------------------- - ALWAYS_INLINE void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData) { - if (MODE_CPHA(Mode)) { - fastDigitalWrite(SckPin, !MODE_CPOL(Mode)); - } - fastDigitalWrite(MosiPin, txData & (1 << bit)); - fastDigitalWrite(SckPin, - MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode)); - if (fastDigitalRead(MisoPin)) *rxData |= 1 << bit; - if (!MODE_CPHA(Mode)) { - fastDigitalWrite(SckPin, MODE_CPOL(Mode)); - } - } - //---------------------------------------------------------------------------- +private: + //---------------------------------------------------------------------------- + ALWAYS_INLINE bool MODE_CPHA(uint8_t mode) + { + return (mode & 1) != 0; + } + ALWAYS_INLINE bool MODE_CPOL(uint8_t mode) + { + return (mode & 2) != 0; + } + ALWAYS_INLINE void receiveBit(uint8_t bit, uint8_t* data) + { + if (MODE_CPHA(Mode)) { + fastDigitalWrite(SckPin, !MODE_CPOL(Mode)); + } + nop; + nop; + fastDigitalWrite(SckPin, + MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode)); + if (fastDigitalRead(MisoPin)) { + *data |= 1 << bit; + } + if (!MODE_CPHA(Mode)) { + fastDigitalWrite(SckPin, MODE_CPOL(Mode)); + } + } + //---------------------------------------------------------------------------- + ALWAYS_INLINE void sendBit(uint8_t bit, uint8_t data) + { + if (MODE_CPHA(Mode)) { + fastDigitalWrite(SckPin, !MODE_CPOL(Mode)); + } + fastDigitalWrite(MosiPin, data & (1 << bit)); + fastDigitalWrite(SckPin, + MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode)); + nop; + nop; + if (!MODE_CPHA(Mode)) { + fastDigitalWrite(SckPin, MODE_CPOL(Mode)); + } + } + //---------------------------------------------------------------------------- + ALWAYS_INLINE void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData) + { + if (MODE_CPHA(Mode)) { + fastDigitalWrite(SckPin, !MODE_CPOL(Mode)); + } + fastDigitalWrite(MosiPin, txData & (1 << bit)); + fastDigitalWrite(SckPin, + MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode)); + if (fastDigitalRead(MisoPin)) { + *rxData |= 1 << bit; + } + if (!MODE_CPHA(Mode)) { + fastDigitalWrite(SckPin, MODE_CPOL(Mode)); + } + } + //---------------------------------------------------------------------------- }; #endif // SoftSPI_h /** @} */ diff --git a/drivers/AVR/DigitalIO/attic/ADS7818.h b/drivers/AVR/DigitalIO/attic/ADS7818.h index eb64fb5..4e6f5d8 100644 --- a/drivers/AVR/DigitalIO/attic/ADS7818.h +++ b/drivers/AVR/DigitalIO/attic/ADS7818.h @@ -9,118 +9,132 @@ //------------------------------------------------------------------------------ template /** ADS7818 class */ -class ADS7818 { - public: - //---------------------------------------------------------------------------- - /** Set pin modes and initial levels. */ - void begin() { - fastPinMode(ClkPin, 1); - fastDigitalWrite(ClkPin, 0); - fastPinMode(ConvPin, 1); - fastDigitalWrite(ConvPin, 1); - fastPinMode(DataPin, 0); - } - //---------------------------------------------------------------------------- - /** Read ADS7818 12-bit ADC - * \return 16-bit value read. - */ - inline __attribute__((always_inline)) - uint16_t read() { - uint16_t v = 0; - fastDigitalWrite(ConvPin, 0); - fastDigitalWrite(ClkPin, 1); - fastDigitalWrite(ClkPin, 0); - fastDigitalWrite(ConvPin, 1); - fastDigitalWrite(ClkPin, 1); - fastDigitalWrite(ClkPin, 0); +class ADS7818 +{ +public: + //---------------------------------------------------------------------------- + /** Set pin modes and initial levels. */ + void begin() + { + fastPinMode(ClkPin, 1); + fastDigitalWrite(ClkPin, 0); + fastPinMode(ConvPin, 1); + fastDigitalWrite(ConvPin, 1); + fastPinMode(DataPin, 0); + } + //---------------------------------------------------------------------------- + /** Read ADS7818 12-bit ADC + * \return 16-bit value read. + */ + inline __attribute__((always_inline)) + uint16_t read() + { + uint16_t v = 0; + fastDigitalWrite(ConvPin, 0); + fastDigitalWrite(ClkPin, 1); + fastDigitalWrite(ClkPin, 0); + fastDigitalWrite(ConvPin, 1); + fastDigitalWrite(ClkPin, 1); + fastDigitalWrite(ClkPin, 0); - readBitFast16(v, 11); - readBitFast16(v, 10); - readBitFast16(v, 9); - readBitFast16(v, 8); - readBitFast16(v, 7); - readBitFast16(v, 6); - readBitFast16(v, 5); - readBitFast16(v, 4); - readBitFast16(v, 3); - readBitFast16(v, 2); - readBitFast16(v, 1); - readBitFast16(v, 0); - return v; - } - private: - //---------------------------------------------------------------------------- - inline __attribute__((always_inline)) - void readBitFast16(uint16_t &v, uint8_t b) { - fastDigitalWrite(ClkPin, 1); - if (fastDigitalRead(DataPin)) v |= (1 << b); - fastDigitalWrite(ClkPin, 0); - } + readBitFast16(v, 11); + readBitFast16(v, 10); + readBitFast16(v, 9); + readBitFast16(v, 8); + readBitFast16(v, 7); + readBitFast16(v, 6); + readBitFast16(v, 5); + readBitFast16(v, 4); + readBitFast16(v, 3); + readBitFast16(v, 2); + readBitFast16(v, 1); + readBitFast16(v, 0); + return v; + } +private: + //---------------------------------------------------------------------------- + inline __attribute__((always_inline)) + void readBitFast16(uint16_t &v, uint8_t b) + { + fastDigitalWrite(ClkPin, 1); + if (fastDigitalRead(DataPin)) { + v |= (1 << b); + } + fastDigitalWrite(ClkPin, 0); + } }; #if 0 /** initialize I/O ports */ -STATIC_ALWAYS_INLINE void adcBegin() { - fastPinMode(ADC_CLK_PIN, 1); - fastDigitalWrite(ADC_CLK_PIN, 0); - fastPinMode(ADC_CONV_PIN, 1); - fastDigitalWrite(ADC_CONV_PIN, 1); - fastPinMode(ADC_DATA_PIN, 0); +STATIC_ALWAYS_INLINE void adcBegin() +{ + fastPinMode(ADC_CLK_PIN, 1); + fastDigitalWrite(ADC_CLK_PIN, 0); + fastPinMode(ADC_CONV_PIN, 1); + fastDigitalWrite(ADC_CONV_PIN, 1); + fastPinMode(ADC_DATA_PIN, 0); } //------------------------------------------------------------------------------ /** clock for don't care bits *\param[in] delayBefore if true, delay before raising clock*/ -STATIC_ALWAYS_INLINE void fastDummy(bool first) { - if (!first) nop; - fastDigitalWrite(ADC_CLK_PIN, 1); - nop; - fastDigitalWrite(ADC_CLK_PIN, 0); +STATIC_ALWAYS_INLINE void fastDummy(bool first) +{ + if (!first) { + nop; + } + fastDigitalWrite(ADC_CLK_PIN, 1); + nop; + fastDigitalWrite(ADC_CLK_PIN, 0); } //------------------------------------------------------------------------------ /** read next bit fast as possible * \param[in] v word to receive bit * \param[in] b bit number to be set. v |= (1 << b) if next bit is high. */ -STATIC_ALWAYS_INLINE void readBitFast16(uint16_t &v, uint8_t b) { - fastDigitalWrite(ADC_CLK_PIN, 1); - if (fastDigitalRead(ADC_DATA_PIN)) v |= (1 << b); - fastDigitalWrite(ADC_CLK_PIN, 0); +STATIC_ALWAYS_INLINE void readBitFast16(uint16_t &v, uint8_t b) +{ + fastDigitalWrite(ADC_CLK_PIN, 1); + if (fastDigitalRead(ADC_DATA_PIN)) { + v |= (1 << b); + } + fastDigitalWrite(ADC_CLK_PIN, 0); } //------------------------------------------------------------------------------ /** Read AD7680 16-bit ADC in less than 8 microseconds * cs is chip select pin */ -STATIC_ALWAYS_INLINE uint16_t adcRead(bool centered = false) { - uint16_t v = 0; - fastDigitalWrite(ADC_CONV_PIN, 0); - fastDigitalWrite(ADC_CLK_PIN, 1); - fastDigitalWrite(ADC_CLK_PIN, 0); - fastDigitalWrite(ADC_CONV_PIN, 1); - fastDigitalWrite(ADC_CLK_PIN, 1); - fastDigitalWrite(ADC_CLK_PIN, 0); -// uint16_t v = 0; +STATIC_ALWAYS_INLINE uint16_t adcRead(bool centered = false) +{ + uint16_t v = 0; + fastDigitalWrite(ADC_CONV_PIN, 0); + fastDigitalWrite(ADC_CLK_PIN, 1); + fastDigitalWrite(ADC_CLK_PIN, 0); + fastDigitalWrite(ADC_CONV_PIN, 1); + fastDigitalWrite(ADC_CLK_PIN, 1); + fastDigitalWrite(ADC_CLK_PIN, 0); + // uint16_t v = 0; -// fastDummy(1); -// fastDummy(0); -// fastDummy(0); - // fastDummy(0); - -// readBitFast16(v, 15); -// readBitFast16(v, 14); -// readBitFast16(v, 13); -// readBitFast16(v, 12); - readBitFast16(v, 11); - readBitFast16(v, 10); - readBitFast16(v, 9); - readBitFast16(v, 8); - readBitFast16(v, 7); - readBitFast16(v, 6); - readBitFast16(v, 5); - readBitFast16(v, 4); - readBitFast16(v, 3); - readBitFast16(v, 2); - readBitFast16(v, 1); - readBitFast16(v, 0); - return centered ? v ^ 0X8000 : v; + // fastDummy(1); + // fastDummy(0); + // fastDummy(0); + // fastDummy(0); + + // readBitFast16(v, 15); + // readBitFast16(v, 14); + // readBitFast16(v, 13); + // readBitFast16(v, 12); + readBitFast16(v, 11); + readBitFast16(v, 10); + readBitFast16(v, 9); + readBitFast16(v, 8); + readBitFast16(v, 7); + readBitFast16(v, 6); + readBitFast16(v, 5); + readBitFast16(v, 4); + readBitFast16(v, 3); + readBitFast16(v, 2); + readBitFast16(v, 1); + readBitFast16(v, 0); + return centered ? v ^ 0X8000 : v; } #endif // 0 #endif // ADS7818_h \ No newline at end of file diff --git a/drivers/AVR/DigitalIO/attic/MCP320X.h b/drivers/AVR/DigitalIO/attic/MCP320X.h index 741bbee..9da32dc 100644 --- a/drivers/AVR/DigitalIO/attic/MCP320X.h +++ b/drivers/AVR/DigitalIO/attic/MCP320X.h @@ -4,259 +4,302 @@ //============================================================================== template /** MCP3201 class */ -class MCP3201 { - public: - //---------------------------------------------------------------------------- - /** Set pin modes and initial levels. */ - void begin() { - fastPinMode(ClkPin, 1); - fastDigitalWrite(ClkPin, 0); - fastPinMode(CsPin, 1); - fastDigitalWrite(CsPin, 1); - fastPinMode(DoutPin, 0); - } - //---------------------------------------------------------------------------- - /** Read MCP3201 12-bit ADC - * \return 16-bit value read. - */ - inline __attribute__((always_inline)) - uint16_t read() { - fastDigitalWrite(CsPin, 0); - // Start sample. - mcpAdcDummy(3); - // Extra sample time. - if (UsecDelay){ - delayMicroseconds(UsecDelay); - } - // End sample. - mcpAdcDummy(3); - // Null bit. - mcpAdcDummy(3); - uint16_t v = 0; - readBit(v, 11); - readBit(v, 10); - readBit(v, 9); - readBit(v, 8); - readBit(v, 7); - readBit(v, 6); - readBit(v, 5); - readBit(v, 4); - readBit(v, 3); - readBit(v, 2); - readBit(v, 1); - readBit(v, 0); - fastDigitalWrite(CsPin, 1); - return v; - } - private: - //---------------------------------------------------------------------------- - /** delay n nops - * \param[in] n nops to delay, must be a constant so compiler optimizes if(). - */ - inline __attribute__((always_inline)) - void delayCycles(uint8_t n) { - if (n & 1) asm volatile("nop\n\t"); - if (n & 2) asm volatile("nop\n\t" "nop\n\t"); - if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); - } - //---------------------------------------------------------------------------- - /** clock for don't care bits - *\param[in] delayBefore if true, delay before raising clock*/ - inline __attribute__((always_inline)) - void mcpAdcDummy(uint8_t delayBefore) { - delayCycles(delayBefore); - fastDigitalWrite(ClkPin, 1); - delayCycles(3); - fastDigitalWrite(ClkPin, 0); - } - //---------------------------------------------------------------------------- - inline __attribute__((always_inline)) - void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 2) { - delayCycles(3); - fastDigitalWrite(ClkPin, 1); - delayCycles(delayRead); - if (fastDigitalRead(DoutPin)) v |= (1 << b); - fastDigitalWrite(ClkPin, 0); - } +class MCP3201 +{ +public: + //---------------------------------------------------------------------------- + /** Set pin modes and initial levels. */ + void begin() + { + fastPinMode(ClkPin, 1); + fastDigitalWrite(ClkPin, 0); + fastPinMode(CsPin, 1); + fastDigitalWrite(CsPin, 1); + fastPinMode(DoutPin, 0); + } + //---------------------------------------------------------------------------- + /** Read MCP3201 12-bit ADC + * \return 16-bit value read. + */ + inline __attribute__((always_inline)) + uint16_t read() + { + fastDigitalWrite(CsPin, 0); + // Start sample. + mcpAdcDummy(3); + // Extra sample time. + if (UsecDelay) { + delayMicroseconds(UsecDelay); + } + // End sample. + mcpAdcDummy(3); + // Null bit. + mcpAdcDummy(3); + uint16_t v = 0; + readBit(v, 11); + readBit(v, 10); + readBit(v, 9); + readBit(v, 8); + readBit(v, 7); + readBit(v, 6); + readBit(v, 5); + readBit(v, 4); + readBit(v, 3); + readBit(v, 2); + readBit(v, 1); + readBit(v, 0); + fastDigitalWrite(CsPin, 1); + return v; + } +private: + //---------------------------------------------------------------------------- + /** delay n nops + * \param[in] n nops to delay, must be a constant so compiler optimizes if(). + */ + inline __attribute__((always_inline)) + void delayCycles(uint8_t n) + { + if (n & 1) { + asm volatile("nop\n\t"); + } + if (n & 2) { + asm volatile("nop\n\t" "nop\n\t"); + } + if (n & 4) { + asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); + } + } + //---------------------------------------------------------------------------- + /** clock for don't care bits + *\param[in] delayBefore if true, delay before raising clock*/ + inline __attribute__((always_inline)) + void mcpAdcDummy(uint8_t delayBefore) + { + delayCycles(delayBefore); + fastDigitalWrite(ClkPin, 1); + delayCycles(3); + fastDigitalWrite(ClkPin, 0); + } + //---------------------------------------------------------------------------- + inline __attribute__((always_inline)) + void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 2) + { + delayCycles(3); + fastDigitalWrite(ClkPin, 1); + delayCycles(delayRead); + if (fastDigitalRead(DoutPin)) { + v |= (1 << b); + } + fastDigitalWrite(ClkPin, 0); + } }; //============================================================================== template /** MCP3202 class */ -class MCP3202 { - public: - //---------------------------------------------------------------------------- - /** Set pin modes and initial levels. */ - void begin() { - fastPinMode(ClkPin, 1); - fastDigitalWrite(ClkPin, 0); - fastPinMode(CsPin, 1); - fastDigitalWrite(CsPin, 1); - fastPinMode(DoutPin, 0); - fastPinMode(DinPin, 1); - } - //---------------------------------------------------------------------------- - /** Read MCP3202 12-bit ADC - * \return 16-bit value read. - */ - inline __attribute__((always_inline)) - uint16_t read(uint8_t config) { - uint16_t v = 0; - fastDigitalWrite(CsPin, 0); - // Start bit. - writeBit(true); - // Mode bit. - writeBit(config & 2); - // Channel Selection and start sample. - writeBit(config & 1); - // Extra sample time. - if (UsecDelay){ - delayMicroseconds(UsecDelay); - } - // MSB first format and end sample. - writeBit(true); - // Null bit. - writeBit(true); - // Data bits. - readBit(v, 11); - readBit(v, 10); - readBit(v, 9); - readBit(v, 8); - readBit(v, 7); - readBit(v, 6); - readBit(v, 5); - readBit(v, 4); - readBit(v, 3); - readBit(v, 2); - readBit(v, 1); - readBit(v, 0); - fastDigitalWrite(CsPin, 1); - return v; - } - private: - //---------------------------------------------------------------------------- - /** delay n nops - * \param[in] n nops to delay, must be a constant so compiler optimizes if(). - */ - inline __attribute__((always_inline)) - void delayCycles(uint8_t n) { - if (n & 1) asm volatile("nop\n\t"); - if (n & 2) asm volatile("nop\n\t" "nop\n\t"); - if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); - } - //---------------------------------------------------------------------------- - /** clock for don't care bits - *\param[in] delayBefore if true, delay before raising clock*/ - inline __attribute__((always_inline)) - void writeBit(bool value) { - fastDigitalWrite(DinPin, value); - fastDigitalWrite(ClkPin, 1); - delayCycles(2); - fastDigitalWrite(ClkPin, 0); - } - //---------------------------------------------------------------------------- - inline __attribute__((always_inline)) - void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1) { - delayCycles(2); - fastDigitalWrite(ClkPin, 1); - delayCycles(delayRead); - if (fastDigitalRead(DoutPin)) v |= (1 << b); - fastDigitalWrite(ClkPin, 0); - } +class MCP3202 +{ +public: + //---------------------------------------------------------------------------- + /** Set pin modes and initial levels. */ + void begin() + { + fastPinMode(ClkPin, 1); + fastDigitalWrite(ClkPin, 0); + fastPinMode(CsPin, 1); + fastDigitalWrite(CsPin, 1); + fastPinMode(DoutPin, 0); + fastPinMode(DinPin, 1); + } + //---------------------------------------------------------------------------- + /** Read MCP3202 12-bit ADC + * \return 16-bit value read. + */ + inline __attribute__((always_inline)) + uint16_t read(uint8_t config) + { + uint16_t v = 0; + fastDigitalWrite(CsPin, 0); + // Start bit. + writeBit(true); + // Mode bit. + writeBit(config & 2); + // Channel Selection and start sample. + writeBit(config & 1); + // Extra sample time. + if (UsecDelay) { + delayMicroseconds(UsecDelay); + } + // MSB first format and end sample. + writeBit(true); + // Null bit. + writeBit(true); + // Data bits. + readBit(v, 11); + readBit(v, 10); + readBit(v, 9); + readBit(v, 8); + readBit(v, 7); + readBit(v, 6); + readBit(v, 5); + readBit(v, 4); + readBit(v, 3); + readBit(v, 2); + readBit(v, 1); + readBit(v, 0); + fastDigitalWrite(CsPin, 1); + return v; + } +private: + //---------------------------------------------------------------------------- + /** delay n nops + * \param[in] n nops to delay, must be a constant so compiler optimizes if(). + */ + inline __attribute__((always_inline)) + void delayCycles(uint8_t n) + { + if (n & 1) { + asm volatile("nop\n\t"); + } + if (n & 2) { + asm volatile("nop\n\t" "nop\n\t"); + } + if (n & 4) { + asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); + } + } + //---------------------------------------------------------------------------- + /** clock for don't care bits + *\param[in] delayBefore if true, delay before raising clock*/ + inline __attribute__((always_inline)) + void writeBit(bool value) + { + fastDigitalWrite(DinPin, value); + fastDigitalWrite(ClkPin, 1); + delayCycles(2); + fastDigitalWrite(ClkPin, 0); + } + //---------------------------------------------------------------------------- + inline __attribute__((always_inline)) + void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1) + { + delayCycles(2); + fastDigitalWrite(ClkPin, 1); + delayCycles(delayRead); + if (fastDigitalRead(DoutPin)) { + v |= (1 << b); + } + fastDigitalWrite(ClkPin, 0); + } }; //============================================================================== template /** MCP3204 class */ -class MCP3204 { - public: - //---------------------------------------------------------------------------- - /** Set pin modes and initial levels. */ - void begin() { - fastPinMode(ClkPin, 1); - fastDigitalWrite(ClkPin, 0); - fastPinMode(CsPin, 1); - fastDigitalWrite(CsPin, 1); - fastPinMode(DoutPin, 0); - fastPinMode(DinPin, 1); - } - //---------------------------------------------------------------------------- - /** Read MCP3204 12-bit ADC - * \return 16-bit value read. - */ - inline __attribute__((always_inline)) - uint16_t read(uint8_t config) { - uint16_t v = 0; - fastDigitalWrite(CsPin, 0); - // Start bit. - writeBit(true); - // Mode bit. - writeBit(config & 8); - // D2 channel bit. - writeBit(config & 4); - // D1 channel bit. - writeBit(config & 2); - // D0 channel bit and start sample. - writeBit(config & 1); - // Extra sample time. - if (UsecDelay){ - delayMicroseconds(UsecDelay); - } - // End sample cycle. - writeBit(true); - // Null bit. - writeBit(true); - // Data bits. - readBit(v, 11); - readBit(v, 10); - readBit(v, 9); - readBit(v, 8); - readBit(v, 7); - readBit(v, 6); - readBit(v, 5); - readBit(v, 4); - readBit(v, 3); - readBit(v, 2); - readBit(v, 1); - readBit(v, 0); - fastDigitalWrite(CsPin, 1); - return v; - } - private: - //---------------------------------------------------------------------------- - /** delay n nops - * \param[in] n nops to delay, must be a constant so compiler optimizes if(). - */ - inline __attribute__((always_inline)) - void delayCycles(uint8_t n) { - if (n & 1) asm volatile("nop\n\t"); - if (n & 2) asm volatile("nop\n\t" "nop\n\t"); - if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); - } - //---------------------------------------------------------------------------- - /** clock for don't care bits - *\param[in] delayBefore if true, delay before raising clock*/ - inline __attribute__((always_inline)) - void writeBit(bool value) { - fastDigitalWrite(DinPin, value); - fastDigitalWrite(ClkPin, 1); - delayCycles(2); - fastDigitalWrite(ClkPin, 0); - } - //---------------------------------------------------------------------------- - inline __attribute__((always_inline)) - void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1) { - delayCycles(2); - fastDigitalWrite(ClkPin, 1); - delayCycles(delayRead); - if (fastDigitalRead(DoutPin)) v |= (1 << b); - fastDigitalWrite(ClkPin, 0); - } +class MCP3204 +{ +public: + //---------------------------------------------------------------------------- + /** Set pin modes and initial levels. */ + void begin() + { + fastPinMode(ClkPin, 1); + fastDigitalWrite(ClkPin, 0); + fastPinMode(CsPin, 1); + fastDigitalWrite(CsPin, 1); + fastPinMode(DoutPin, 0); + fastPinMode(DinPin, 1); + } + //---------------------------------------------------------------------------- + /** Read MCP3204 12-bit ADC + * \return 16-bit value read. + */ + inline __attribute__((always_inline)) + uint16_t read(uint8_t config) + { + uint16_t v = 0; + fastDigitalWrite(CsPin, 0); + // Start bit. + writeBit(true); + // Mode bit. + writeBit(config & 8); + // D2 channel bit. + writeBit(config & 4); + // D1 channel bit. + writeBit(config & 2); + // D0 channel bit and start sample. + writeBit(config & 1); + // Extra sample time. + if (UsecDelay) { + delayMicroseconds(UsecDelay); + } + // End sample cycle. + writeBit(true); + // Null bit. + writeBit(true); + // Data bits. + readBit(v, 11); + readBit(v, 10); + readBit(v, 9); + readBit(v, 8); + readBit(v, 7); + readBit(v, 6); + readBit(v, 5); + readBit(v, 4); + readBit(v, 3); + readBit(v, 2); + readBit(v, 1); + readBit(v, 0); + fastDigitalWrite(CsPin, 1); + return v; + } +private: + //---------------------------------------------------------------------------- + /** delay n nops + * \param[in] n nops to delay, must be a constant so compiler optimizes if(). + */ + inline __attribute__((always_inline)) + void delayCycles(uint8_t n) + { + if (n & 1) { + asm volatile("nop\n\t"); + } + if (n & 2) { + asm volatile("nop\n\t" "nop\n\t"); + } + if (n & 4) { + asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); + } + } + //---------------------------------------------------------------------------- + /** clock for don't care bits + *\param[in] delayBefore if true, delay before raising clock*/ + inline __attribute__((always_inline)) + void writeBit(bool value) + { + fastDigitalWrite(DinPin, value); + fastDigitalWrite(ClkPin, 1); + delayCycles(2); + fastDigitalWrite(ClkPin, 0); + } + //---------------------------------------------------------------------------- + inline __attribute__((always_inline)) + void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1) + { + delayCycles(2); + fastDigitalWrite(ClkPin, 1); + delayCycles(delayRead); + if (fastDigitalRead(DoutPin)) { + v |= (1 << b); + } + fastDigitalWrite(ClkPin, 0); + } }; //============================================================================== // MCP3204 and MCP3208 use the same code. template -class MCP3208 : public MCP3204 { +class MCP3208 : public MCP3204 +{ }; #endif // MCP320X_h \ No newline at end of file diff --git a/drivers/AVR/DigitalIO/attic/MCP355X.h b/drivers/AVR/DigitalIO/attic/MCP355X.h index daa2911..fb66d4a 100644 --- a/drivers/AVR/DigitalIO/attic/MCP355X.h +++ b/drivers/AVR/DigitalIO/attic/MCP355X.h @@ -9,119 +9,145 @@ const uint8_t MCP355X_TO_MS = 100; //============================================================================== template /** MCP355X class */ -class MCP355X { - public: - //---------------------------------------------------------------------------- - /** Set pin modes and initial levels. */ - void begin(bool singleMode = true) { - m_singleMode = singleMode; - fastPinMode(SdoPin, 0); - fastPinMode(SckPin, 1); - fastDigitalWrite(SckPin, 1); - fastPinMode(CsPin, 1); - fastDigitalWrite(CsPin, 1); - if (!m_singleMode) { - // Wait for conversion to complete. - delay(100); - // Start continuous conversion mode. - fastDigitalWrite(CsPin, 0); - } - } - //---------------------------------------------------------------------------- - /** Read MCP355X 22-bit ADC - * \return 22-bit value. - */ - inline __attribute__((always_inline)) - int32_t read() { - uint8_t t = 0; - uint8_t v3 = 0; - if (m_singleMode) { - // Start conversion. - fastDigitalWrite(CsPin, 0); - // Delay at least 10 usec to avoid RDY glitch on exit from Shutdown. - delay(1); - // Toggle CsPin to indicate single conversion mode. - fastDigitalWrite(CsPin, 1); - // Wait for conversion to complete. - while (1) { - delay(1); - fastDigitalWrite(CsPin, 0); - // Delay while RDY settles. - delayCycles(4); - if (!fastDigitalRead(SdoPin)) break; - fastDigitalWrite(CsPin, 1); - if (t++ > MCP355X_TO_MS) return MCP355X_ERR; - } - } else { - while (1) { - if (!fastDigitalRead(SdoPin)) break; - delay(1); - if (t++ > MCP355X_TO_MS) return MCP355X_ERR; - } - } - uint8_t v2 = readByte(); - uint8_t v1 = readByte(); - uint8_t v0 = readByte(); - - // The 25th falling edge of SCK changes SDO/RDY from Data mode to RDY mode. - uint8_t dummy = 0; - readBit(dummy, 0); +class MCP355X +{ +public: + //---------------------------------------------------------------------------- + /** Set pin modes and initial levels. */ + void begin(bool singleMode = true) + { + m_singleMode = singleMode; + fastPinMode(SdoPin, 0); + fastPinMode(SckPin, 1); + fastDigitalWrite(SckPin, 1); + fastPinMode(CsPin, 1); + fastDigitalWrite(CsPin, 1); + if (!m_singleMode) { + // Wait for conversion to complete. + delay(100); + // Start continuous conversion mode. + fastDigitalWrite(CsPin, 0); + } + } + //---------------------------------------------------------------------------- + /** Read MCP355X 22-bit ADC + * \return 22-bit value. + */ + inline __attribute__((always_inline)) + int32_t read() + { + uint8_t t = 0; + uint8_t v3 = 0; + if (m_singleMode) { + // Start conversion. + fastDigitalWrite(CsPin, 0); + // Delay at least 10 usec to avoid RDY glitch on exit from Shutdown. + delay(1); + // Toggle CsPin to indicate single conversion mode. + fastDigitalWrite(CsPin, 1); + // Wait for conversion to complete. + while (1) { + delay(1); + fastDigitalWrite(CsPin, 0); + // Delay while RDY settles. + delayCycles(4); + if (!fastDigitalRead(SdoPin)) { + break; + } + fastDigitalWrite(CsPin, 1); + if (t++ > MCP355X_TO_MS) { + return MCP355X_ERR; + } + } + } else { + while (1) { + if (!fastDigitalRead(SdoPin)) { + break; + } + delay(1); + if (t++ > MCP355X_TO_MS) { + return MCP355X_ERR; + } + } + } + uint8_t v2 = readByte(); + uint8_t v1 = readByte(); + uint8_t v0 = readByte(); - if (m_singleMode) { - fastDigitalWrite(CsPin, 1); - } - if ((v2 & 0XE0) == 0X20) { - // Negative in range so extend sign bit. - v2 |= 0XC0; - v3 = 0XFF; - } else if (v2 & 0X40) { - // Overflow high. Cause value to be >= MCP355X_OVH. - if (v2 & 0X20) v2 &= 0X3F; - } else if (v2 & 0X80) { - // Overflow low. Cause value to be <= MCP355X_OVH. - if ((v2 & 0X20) == 0) v2 |= 0X40; - v3 = 0XFF; - } - uint16_t v_high = (v3 << 8) | v2; - uint16_t v_low = (v1 << 8) | v0; - return ((uint32_t)v_high << 16) | v_low; - } - private: - //---------------------------------------------------------------------------- - /** delay n nops - * \param[in] n nops to delay, must be a constant so compiler optimizes if(). - */ - inline __attribute__((always_inline)) - void delayCycles(uint8_t n) { - if (n & 1) asm volatile("nop\n\t"); - if (n & 2) asm volatile("nop\n\t" "nop\n\t"); - if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); - } - //---------------------------------------------------------------------------- - // Default delay yields about 2 MHz clock. - inline __attribute__((always_inline)) - void readBit(uint8_t &v, uint8_t b, uint8_t delayRead = 0) { - fastDigitalWrite(SckPin, 0); - delayCycles(2 + delayRead); - fastDigitalWrite(SckPin, 1); - if (fastDigitalRead(SdoPin)) v |= (1 << b); - delayCycles(delayRead); - } - //---------------------------------------------------------------------------- - inline __attribute__((always_inline)) - uint8_t readByte() { - uint8_t v = 0; - readBit(v, 7); - readBit(v, 6); - readBit(v, 5); - readBit(v, 4); - readBit(v, 3); - readBit(v, 2); - readBit(v, 1); - readBit(v, 0); - return v; - } - //---------------------------------------------------------------------------- - bool m_singleMode; + // The 25th falling edge of SCK changes SDO/RDY from Data mode to RDY mode. + uint8_t dummy = 0; + readBit(dummy, 0); + + if (m_singleMode) { + fastDigitalWrite(CsPin, 1); + } + if ((v2 & 0XE0) == 0X20) { + // Negative in range so extend sign bit. + v2 |= 0XC0; + v3 = 0XFF; + } else if (v2 & 0X40) { + // Overflow high. Cause value to be >= MCP355X_OVH. + if (v2 & 0X20) { + v2 &= 0X3F; + } + } else if (v2 & 0X80) { + // Overflow low. Cause value to be <= MCP355X_OVH. + if ((v2 & 0X20) == 0) { + v2 |= 0X40; + } + v3 = 0XFF; + } + uint16_t v_high = (v3 << 8) | v2; + uint16_t v_low = (v1 << 8) | v0; + return ((uint32_t)v_high << 16) | v_low; + } +private: + //---------------------------------------------------------------------------- + /** delay n nops + * \param[in] n nops to delay, must be a constant so compiler optimizes if(). + */ + inline __attribute__((always_inline)) + void delayCycles(uint8_t n) + { + if (n & 1) { + asm volatile("nop\n\t"); + } + if (n & 2) { + asm volatile("nop\n\t" "nop\n\t"); + } + if (n & 4) { + asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); + } + } + //---------------------------------------------------------------------------- + // Default delay yields about 2 MHz clock. + inline __attribute__((always_inline)) + void readBit(uint8_t &v, uint8_t b, uint8_t delayRead = 0) + { + fastDigitalWrite(SckPin, 0); + delayCycles(2 + delayRead); + fastDigitalWrite(SckPin, 1); + if (fastDigitalRead(SdoPin)) { + v |= (1 << b); + } + delayCycles(delayRead); + } + //---------------------------------------------------------------------------- + inline __attribute__((always_inline)) + uint8_t readByte() + { + uint8_t v = 0; + readBit(v, 7); + readBit(v, 6); + readBit(v, 5); + readBit(v, 4); + readBit(v, 3); + readBit(v, 2); + readBit(v, 1); + readBit(v, 0); + return v; + } + //---------------------------------------------------------------------------- + bool m_singleMode; }; #endif // MCP355X_h \ No newline at end of file diff --git a/drivers/AVR/DigitalIO/examples/DigitalPinBlink/DigitalPinBlink.ino b/drivers/AVR/DigitalIO/examples/DigitalPinBlink/DigitalPinBlink.ino index 4a698ba..d8fd19f 100644 --- a/drivers/AVR/DigitalIO/examples/DigitalPinBlink/DigitalPinBlink.ino +++ b/drivers/AVR/DigitalIO/examples/DigitalPinBlink/DigitalPinBlink.ino @@ -4,9 +4,10 @@ DigitalPin<13> pin13(OUTPUT); void setup() {} -void loop() { - // toggle is a two byte instruction that executes - // in two cycles or 125 ns on a 16 MHz CPU - pin13.toggle(); - delay(250); +void loop() +{ + // toggle is a two byte instruction that executes + // in two cycles or 125 ns on a 16 MHz CPU + pin13.toggle(); + delay(250); } \ No newline at end of file diff --git a/drivers/AVR/DigitalIO/examples/DigitalPinConfigToggle/DigitalPinConfigToggle.ino b/drivers/AVR/DigitalIO/examples/DigitalPinConfigToggle/DigitalPinConfigToggle.ino index 06ad860..78a75c9 100644 --- a/drivers/AVR/DigitalIO/examples/DigitalPinConfigToggle/DigitalPinConfigToggle.ino +++ b/drivers/AVR/DigitalIO/examples/DigitalPinConfigToggle/DigitalPinConfigToggle.ino @@ -4,15 +4,17 @@ // Class with compile time pin number. DigitalPin<13> pin13; -void setup() { - // Set mode to OUTPUT and level LOW. - pin13.config(OUTPUT, LOW); +void setup() +{ + // Set mode to OUTPUT and level LOW. + pin13.config(OUTPUT, LOW); } -void loop() { - // toggle is a two byte instruction that executes - // in two cycles or 125 ns on a 16 MHz CPU - pin13.toggle(); - delay(100); - pin13.toggle(); - delay(400); +void loop() +{ + // toggle is a two byte instruction that executes + // in two cycles or 125 ns on a 16 MHz CPU + pin13.toggle(); + delay(100); + pin13.toggle(); + delay(400); } \ No newline at end of file diff --git a/drivers/AVR/DigitalIO/examples/DigitalPinReadWrite/DigitalPinReadWrite.ino b/drivers/AVR/DigitalIO/examples/DigitalPinReadWrite/DigitalPinReadWrite.ino index 57be1fa..09fb8d2 100644 --- a/drivers/AVR/DigitalIO/examples/DigitalPinReadWrite/DigitalPinReadWrite.ino +++ b/drivers/AVR/DigitalIO/examples/DigitalPinReadWrite/DigitalPinReadWrite.ino @@ -6,6 +6,7 @@ DigitalPin<13> pin13(OUTPUT); void setup() {} -void loop() { - pin13 = pin12; +void loop() +{ + pin13 = pin12; } \ No newline at end of file diff --git a/drivers/AVR/DigitalIO/examples/DigitalPinShiftOut/DigitalPinShiftOut.ino b/drivers/AVR/DigitalIO/examples/DigitalPinShiftOut/DigitalPinShiftOut.ino index 98682bb..6a31ee6 100644 --- a/drivers/AVR/DigitalIO/examples/DigitalPinShiftOut/DigitalPinShiftOut.ino +++ b/drivers/AVR/DigitalIO/examples/DigitalPinShiftOut/DigitalPinShiftOut.ino @@ -10,30 +10,34 @@ DigitalPin<13> dataPin(OUTPUT, HIGH); //------------------------------------------------------------------------------ // Time to send one bit is ten cycles or 625 ns for 16 MHz CPU. inline __attribute__((always_inline)) -void sendBit(uint8_t bit, uint8_t data) { - dataPin = data & (1 << bit); - clockPin = 1; - // may want a nop here - clock pulse is 125 ns wide - clockPin = 0; +void sendBit(uint8_t bit, uint8_t data) +{ + dataPin = data & (1 << bit); + clockPin = 1; + // may want a nop here - clock pulse is 125 ns wide + clockPin = 0; } //------------------------------------------------------------------------------ // Time to send one byte is 5 usec. -void shiftOut(uint8_t bits) { - sendBit(7, bits); - sendBit(6, bits); - sendBit(5, bits); - sendBit(4, bits); - sendBit(3, bits); - sendBit(2, bits); - sendBit(1, bits); - sendBit(0, bits); +void shiftOut(uint8_t bits) +{ + sendBit(7, bits); + sendBit(6, bits); + sendBit(5, bits); + sendBit(4, bits); + sendBit(3, bits); + sendBit(2, bits); + sendBit(1, bits); + sendBit(0, bits); } //------------------------------------------------------------------------------ -void setup() { - // Not used. +void setup() +{ + // Not used. } //------------------------------------------------------------------------------ -void loop() { - shiftOut(0X55); - delay(2); +void loop() +{ + shiftOut(0X55); + delay(2); } diff --git a/drivers/AVR/DigitalIO/examples/PinIOBegin/PinIOBegin.ino b/drivers/AVR/DigitalIO/examples/PinIOBegin/PinIOBegin.ino index 5f7e124..0ddcb1e 100644 --- a/drivers/AVR/DigitalIO/examples/PinIOBegin/PinIOBegin.ino +++ b/drivers/AVR/DigitalIO/examples/PinIOBegin/PinIOBegin.ino @@ -6,19 +6,21 @@ PinIO readPin; PinIO writePin; //------------------------------------------------------------------------------ -void setup() { - // Assign pin 12 to readPin. - readPin.begin(12); - - // input mode with pull-ups disabled - readPin.config(INPUT, LOW); +void setup() +{ + // Assign pin 12 to readPin. + readPin.begin(12); - // Assign pin 13 to writePin and set mode to output. - writePin.begin(13); - writePin.mode(OUTPUT); + // input mode with pull-ups disabled + readPin.config(INPUT, LOW); + + // Assign pin 13 to writePin and set mode to output. + writePin.begin(13); + writePin.mode(OUTPUT); } //------------------------------------------------------------------------------ -void loop() { - // Copy the value read from readPin to writePin. - writePin.write(readPin.read()); +void loop() +{ + // Copy the value read from readPin to writePin. + writePin.write(readPin.read()); } \ No newline at end of file diff --git a/drivers/AVR/DigitalIO/examples/PinIOConfigToggle/PinIOConfigToggle.ino b/drivers/AVR/DigitalIO/examples/PinIOConfigToggle/PinIOConfigToggle.ino index 3bf3e00..b9b9818 100644 --- a/drivers/AVR/DigitalIO/examples/PinIOConfigToggle/PinIOConfigToggle.ino +++ b/drivers/AVR/DigitalIO/examples/PinIOConfigToggle/PinIOConfigToggle.ino @@ -4,13 +4,15 @@ // Set runtime pin number. PinIO pin13(13); -void setup() { - // set mode to OUTPUT and level LOW - pin13.config(OUTPUT, LOW); +void setup() +{ + // set mode to OUTPUT and level LOW + pin13.config(OUTPUT, LOW); } -void loop() { - pin13.toggle(); - delay(100); - pin13.toggle(); - delay(400); +void loop() +{ + pin13.toggle(); + delay(100); + pin13.toggle(); + delay(400); } \ No newline at end of file diff --git a/drivers/AVR/DigitalIO/examples/PinIOReadWrite/PinIOReadWrite.ino b/drivers/AVR/DigitalIO/examples/PinIOReadWrite/PinIOReadWrite.ino index 8b225d5..3019a05 100644 --- a/drivers/AVR/DigitalIO/examples/PinIOReadWrite/PinIOReadWrite.ino +++ b/drivers/AVR/DigitalIO/examples/PinIOReadWrite/PinIOReadWrite.ino @@ -4,13 +4,15 @@ PinIO readPin(12); PinIO writePin(13); -void setup() { - // Set input mode and disable pull-up. - readPin.config(INPUT, LOW); +void setup() +{ + // Set input mode and disable pull-up. + readPin.config(INPUT, LOW); - // set output mode - writePin.mode(OUTPUT); + // set output mode + writePin.mode(OUTPUT); } -void loop() { - writePin.write(readPin.read()); +void loop() +{ + writePin.write(readPin.read()); } \ No newline at end of file diff --git a/drivers/AVR/DigitalIO/examples/ScanI2cBus/ScanI2cBus.ino b/drivers/AVR/DigitalIO/examples/ScanI2cBus/ScanI2cBus.ino index 6132a3f..18e5b6e 100644 --- a/drivers/AVR/DigitalIO/examples/ScanI2cBus/ScanI2cBus.ino +++ b/drivers/AVR/DigitalIO/examples/ScanI2cBus/ScanI2cBus.ino @@ -26,52 +26,59 @@ const uint8_t SCL_PIN = A5; SoftI2cMaster i2c(SCL_PIN, SDA_PIN); //FastI2cMaster i2c; //------------------------------------------------------------------------------ -void setup() { +void setup() +{ - Serial.begin(9600); - while (!Serial); - - if (!digitalRead(SDA_PIN) && !digitalRead(SCL_PIN)) { - Serial.println("External pull-up resistors appear to be missing."); - Serial.println("Many false responses may be detected."); - Serial.println("Type any character to continue."); + Serial.begin(9600); + while (!Serial); - while (!Serial.available()); - Serial.println(); + if (!digitalRead(SDA_PIN) && !digitalRead(SCL_PIN)) { + Serial.println("External pull-up resistors appear to be missing."); + Serial.println("Many false responses may be detected."); + Serial.println("Type any character to continue."); - } - uint8_t add = 0; - bool found = false; - do { - bool wr = i2c.transfer(add | I2C_WRITE, 0, 0); - bool rd = i2c.transfer(add | I2C_READ, 0, 0, I2C_CONTINUE); - if (rd) { - uint8_t dummy; - // Must read byte, send NACK, and issue STOP. - i2c.transferContinue(&dummy, 1); - } - if (rd || wr) { - found = true; - Serial.print("Device at address: 0X"); - Serial.print(add, HEX); - Serial.print(" responds to "); - if (rd) Serial.print("Read"); - if (rd && wr) Serial.print(" and "); - if (wr) Serial.print("Write"); - Serial.println('.'); - } - add += 2; - } - while (add); + while (!Serial.available()); + Serial.println(); - if (!found) { - Serial.println("No devices found."); - } - Serial.println("Done"); + } + uint8_t add = 0; + bool found = false; + do { + bool wr = i2c.transfer(add | I2C_WRITE, 0, 0); + bool rd = i2c.transfer(add | I2C_READ, 0, 0, I2C_CONTINUE); + if (rd) { + uint8_t dummy; + // Must read byte, send NACK, and issue STOP. + i2c.transferContinue(&dummy, 1); + } + if (rd || wr) { + found = true; + Serial.print("Device at address: 0X"); + Serial.print(add, HEX); + Serial.print(" responds to "); + if (rd) { + Serial.print("Read"); + } + if (rd && wr) { + Serial.print(" and "); + } + if (wr) { + Serial.print("Write"); + } + Serial.println('.'); + } + add += 2; + } while (add); + + if (!found) { + Serial.println("No devices found."); + } + Serial.println("Done"); } //------------------------------------------------------------------------------ -void loop() { - // Not used. +void loop() +{ + // Not used. } diff --git a/drivers/AVR/DigitalIO/examples/SoftDS1307Utility/SoftDS1307Utility.ino b/drivers/AVR/DigitalIO/examples/SoftDS1307Utility/SoftDS1307Utility.ino index 3747b96..aecb9e9 100644 --- a/drivers/AVR/DigitalIO/examples/SoftDS1307Utility/SoftDS1307Utility.ino +++ b/drivers/AVR/DigitalIO/examples/SoftDS1307Utility/SoftDS1307Utility.ino @@ -16,30 +16,35 @@ FastI2cMaster rtc; /* * Read 'count' bytes from the DS1307 starting at 'address'. */ -uint8_t readDS1307(uint8_t address, uint8_t *buf, uint8_t count) { +uint8_t readDS1307(uint8_t address, uint8_t *buf, uint8_t count) +{ - // Send address of data. - if (!rtc.transfer(DS1307ADDR | I2C_WRITE, &address, 1)) return false; + // Send address of data. + if (!rtc.transfer(DS1307ADDR | I2C_WRITE, &address, 1)) { + return false; + } - // Read data. - return rtc.transfer(DS1307ADDR | I2C_READ, buf, count); + // Read data. + return rtc.transfer(DS1307ADDR | I2C_READ, buf, count); } //------------------------------------------------------------------------------ /* * write 'count' bytes to DS1307 starting at 'address'. */ -uint8_t writeDS1307(uint8_t address, uint8_t *buf, uint8_t count) { +uint8_t writeDS1307(uint8_t address, uint8_t *buf, uint8_t count) +{ - // Write address and continue transfer for write of data. - if (!rtc.transfer(DS1307ADDR | I2C_WRITE, &address, 1, I2C_CONTINUE)) { - return false; - } - // Write data. - return rtc.transferContinue(buf, count); + // Write address and continue transfer for write of data. + if (!rtc.transfer(DS1307ADDR | I2C_WRITE, &address, 1, I2C_CONTINUE)) { + return false; + } + // Write data. + return rtc.transferContinue(buf, count); } //------------------------------------------------------------------------------ -void setup(void) { - Serial.begin(9600); +void setup(void) +{ + Serial.begin(9600); } //------------------------------------------------------------------------------ /** Store and print a string in flash memory.*/ @@ -50,134 +55,142 @@ void setup(void) { // Day of week U.S. convention. char *Ddd[] = {"Bad", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; //------------------------------------------------------------------------------ -void hexPrint(uint8_t v) { - Serial.print(v >> 4, HEX); - Serial.print(v & 0XF, HEX); +void hexPrint(uint8_t v) +{ + Serial.print(v >> 4, HEX); + Serial.print(v & 0XF, HEX); } //------------------------------------------------------------------------------ -void hexPrintln(uint8_t v) { - hexPrint(v); - Serial.println(); +void hexPrintln(uint8_t v) +{ + hexPrint(v); + Serial.println(); } //------------------------------------------------------------------------------ // read hex input -uint8_t hexRead(uint16_t* v) { - bool valid = false; - uint16_t n = 0; - while (!Serial.available()); - while (Serial.available()) { - uint8_t c = Serial.read(); - // Exit if end-of-line. - if (c == '\n' || c == '\r') { - delay(10); - // If CR/LF. - Serial.read(); - break; - } - n <<= 4; - if ('a' <= c && c <= 'f') { - n += c - ('a' - 10); - } - else if ('A' <= c && c <= 'F') { - n += c - ('A' - 10); - } - else if ('0' <= c && c <= '9') { - n += c - '0'; - } - else { - valid = false; - break; - } - delay(10); - valid = true; - } - if (!valid) { - PgmPrintln("Invalid entry"); - return false; - } - *v = n; - return true; +uint8_t hexRead(uint16_t* v) +{ + bool valid = false; + uint16_t n = 0; + while (!Serial.available()); + while (Serial.available()) { + uint8_t c = Serial.read(); + // Exit if end-of-line. + if (c == '\n' || c == '\r') { + delay(10); + // If CR/LF. + Serial.read(); + break; + } + n <<= 4; + if ('a' <= c && c <= 'f') { + n += c - ('a' - 10); + } else if ('A' <= c && c <= 'F') { + n += c - ('A' - 10); + } else if ('0' <= c && c <= '9') { + n += c - '0'; + } else { + valid = false; + break; + } + delay(10); + valid = true; + } + if (!valid) { + PgmPrintln("Invalid entry"); + return false; + } + *v = n; + return true; } //------------------------------------------------------------------------------ -uint8_t bcdRead(uint8_t min, uint8_t max, uint8_t* n) { - uint16_t v; - if (!hexRead(&v)) return false; - uint8_t d = 10 * (v >> 4) + (v & 0XF); - if ((v >> 4) > 9 || (v & 0XF) > 9 || d < min || d > max) { - PgmPrintln("Invalid"); - return false; - } - *n = v; - return true; +uint8_t bcdRead(uint8_t min, uint8_t max, uint8_t* n) +{ + uint16_t v; + if (!hexRead(&v)) { + return false; + } + uint8_t d = 10 * (v >> 4) + (v & 0XF); + if ((v >> 4) > 9 || (v & 0XF) > 9 || d < min || d > max) { + PgmPrintln("Invalid"); + return false; + } + *n = v; + return true; } //------------------------------------------------------------------------------ -void displayTime(void) { - uint8_t r[8]; - if (!readDS1307(0, r, 8)) { - PgmPrintln("Read Failed for display time"); - return; - } - PgmPrint("The current time is 20"); - // year - hexPrint(r[6]); - Serial.write('-'); +void displayTime(void) +{ + uint8_t r[8]; + if (!readDS1307(0, r, 8)) { + PgmPrintln("Read Failed for display time"); + return; + } + PgmPrint("The current time is 20"); + // year + hexPrint(r[6]); + Serial.write('-'); - // month - hexPrint(r[5]); - Serial.write('-'); + // month + hexPrint(r[5]); + Serial.write('-'); - // day - hexPrint(r[4]); - Serial.write(' '); + // day + hexPrint(r[4]); + Serial.write(' '); - Serial.print(Ddd[r[3] < 8 ? r[3] : 0]); - Serial.write(' '); + Serial.print(Ddd[r[3] < 8 ? r[3] : 0]); + Serial.write(' '); - // hour - hexPrint(r[2]); - Serial.write(':'); + // hour + hexPrint(r[2]); + Serial.write(':'); - // minute - hexPrint(r[1]); - Serial.write(':'); + // minute + hexPrint(r[1]); + Serial.write(':'); - // second - hexPrintln(r[0]); + // second + hexPrintln(r[0]); - // Control register. - PgmPrint("Control Register: "); - hexPrintln(r[7]); + // Control register. + PgmPrint("Control Register: "); + hexPrintln(r[7]); } //------------------------------------------------------------------------------ // dump registers and 56 bytes of RAM -void dumpAll(void) { - uint8_t buf[8]; - for (uint8_t a = 0; a < 64; a += 8) { - hexPrint(a); - Serial.write(' '); - if (!readDS1307(a, buf, 8)) { - PgmPrint("read failed for dumpAll"); - return; - } - for (uint8_t i = 0; i < 8; i++) { - Serial.write(' '); - hexPrint(buf[i]); - } - Serial.println(); - } +void dumpAll(void) +{ + uint8_t buf[8]; + for (uint8_t a = 0; a < 64; a += 8) { + hexPrint(a); + Serial.write(' '); + if (!readDS1307(a, buf, 8)) { + PgmPrint("read failed for dumpAll"); + return; + } + for (uint8_t i = 0; i < 8; i++) { + Serial.write(' '); + hexPrint(buf[i]); + } + Serial.println(); + } } //------------------------------------------------------------------------------ -void fillNvRam(void) { - uint8_t buf[8]; - PgmPrint("Enter HEX value for all NV RAM locations (00-FF): "); - uint16_t v; - if (!hexRead(&v)) return; - hexPrint(v); - for (uint8_t a = 8; a < 64; a ++) { - if (!writeDS1307(a, (uint8_t *)&v, 1)) { - PgmPrintln("write failed for fillNvRam"); - } - } +void fillNvRam(void) +{ + uint8_t buf[8]; + PgmPrint("Enter HEX value for all NV RAM locations (00-FF): "); + uint16_t v; + if (!hexRead(&v)) { + return; + } + hexPrint(v); + for (uint8_t a = 8; a < 64; a ++) { + if (!writeDS1307(a, (uint8_t *)&v, 1)) { + PgmPrintln("write failed for fillNvRam"); + } + } } //------------------------------------------------------------------------------ // set control register @@ -205,120 +218,149 @@ RS1 RS0 FREQUENCY 1 0 8.192kHz 1 1 32.768kHz */ -void setControl(void) { - PgmPrintln("SQW/OUT pin: "); - PgmPrintln("(00) Low"); - PgmPrintln("(10) 1Hz"); - PgmPrintln("(11) 4.096kHz"); - PgmPrintln("(12) 8.192kHz"); - PgmPrintln("(13) 32.768kHz"); - PgmPrintln("(80) High"); - PgmPrint("Enter control: "); - uint16_t r; - if (!hexRead(&r)) return; - hexPrintln(r); - if (!writeDS1307(7, (uint8_t *)&r, 1)) { - PgmPrint("Write Failed for setControl"); - } +void setControl(void) +{ + PgmPrintln("SQW/OUT pin: "); + PgmPrintln("(00) Low"); + PgmPrintln("(10) 1Hz"); + PgmPrintln("(11) 4.096kHz"); + PgmPrintln("(12) 8.192kHz"); + PgmPrintln("(13) 32.768kHz"); + PgmPrintln("(80) High"); + PgmPrint("Enter control: "); + uint16_t r; + if (!hexRead(&r)) { + return; + } + hexPrintln(r); + if (!writeDS1307(7, (uint8_t *)&r, 1)) { + PgmPrint("Write Failed for setControl"); + } } //------------------------------------------------------------------------------ -void setDate(void) { - uint8_t r[4]; - PgmPrint("Enter year (00-99): "); - if (!bcdRead(0, 99, &r[3])) return; - hexPrintln(r[3]); - PgmPrint("Enter month (01-12): "); - if (!bcdRead(1, 12, &r[2])) return; - hexPrintln(r[2]); - PgmPrint("Enter day (01-31): "); - if (!bcdRead(1, 31, &r[1])) return; - hexPrintln(r[1]); - PgmPrint("Enter day of week (01-07, Sun-Sat): "); - if (!bcdRead(1, 7, &r[0])) return; - hexPrintln(r[0]); +void setDate(void) +{ + uint8_t r[4]; + PgmPrint("Enter year (00-99): "); + if (!bcdRead(0, 99, &r[3])) { + return; + } + hexPrintln(r[3]); + PgmPrint("Enter month (01-12): "); + if (!bcdRead(1, 12, &r[2])) { + return; + } + hexPrintln(r[2]); + PgmPrint("Enter day (01-31): "); + if (!bcdRead(1, 31, &r[1])) { + return; + } + hexPrintln(r[1]); + PgmPrint("Enter day of week (01-07, Sun-Sat): "); + if (!bcdRead(1, 7, &r[0])) { + return; + } + hexPrintln(r[0]); - if (!writeDS1307(3, r, 4)) { - PgmPrintln("Write failed for setDate"); - } + if (!writeDS1307(3, r, 4)) { + PgmPrintln("Write failed for setDate"); + } } //------------------------------------------------------------------------------ -void setNvRam() { - uint8_t u; - uint16_t a, v; - while (true) { - PgmPrint("Enter zero to quit or Hex address (8-3F):"); - if (!hexRead(&a) || a == 0) return; - if (a < 8 || a > 0X3F) { - PgmPrintln("Invalid address"); - return; - } - hexPrintln(a); - if (!readDS1307(a, &u, 1)) { - PgmPrintln("Read failed"); - return; - } - PgmPrint("Current value: "); - hexPrintln(u); - PgmPrint("Enter new HEX value (00-FF): "); - if (!hexRead(&v)) return; - hexPrintln(v); - if (!writeDS1307(a, (uint8_t *)&v, 1)) { - PgmPrint("Write Failed"); - return; - } - } +void setNvRam() +{ + uint8_t u; + uint16_t a, v; + while (true) { + PgmPrint("Enter zero to quit or Hex address (8-3F):"); + if (!hexRead(&a) || a == 0) { + return; + } + if (a < 8 || a > 0X3F) { + PgmPrintln("Invalid address"); + return; + } + hexPrintln(a); + if (!readDS1307(a, &u, 1)) { + PgmPrintln("Read failed"); + return; + } + PgmPrint("Current value: "); + hexPrintln(u); + PgmPrint("Enter new HEX value (00-FF): "); + if (!hexRead(&v)) { + return; + } + hexPrintln(v); + if (!writeDS1307(a, (uint8_t *)&v, 1)) { + PgmPrint("Write Failed"); + return; + } + } } //------------------------------------------------------------------------------ -void setTime(void) { - uint8_t r[3]; - PgmPrint("Enter hours (00-23): "); - if (!bcdRead(0, 23, &r[2])) return; - hexPrintln(r[2]); - PgmPrint("Enter minutes (00-59): "); - if (!bcdRead(0, 59, &r[1])) return; - hexPrintln(r[1]); - PgmPrint("Enter seconds (00-59): "); - if (!bcdRead(0, 59, &r[0])) return; - hexPrintln(r[0]); +void setTime(void) +{ + uint8_t r[3]; + PgmPrint("Enter hours (00-23): "); + if (!bcdRead(0, 23, &r[2])) { + return; + } + hexPrintln(r[2]); + PgmPrint("Enter minutes (00-59): "); + if (!bcdRead(0, 59, &r[1])) { + return; + } + hexPrintln(r[1]); + PgmPrint("Enter seconds (00-59): "); + if (!bcdRead(0, 59, &r[0])) { + return; + } + hexPrintln(r[0]); - if (!writeDS1307(0, r, 3)) { - PgmPrintln("write failed in setTime"); - return; - } + if (!writeDS1307(0, r, 3)) { + PgmPrintln("write failed in setTime"); + return; + } } //------------------------------------------------------------------------------ -void loop(void) { - Serial.println(); - displayTime(); - while (Serial.read() >= 0) {} - PgmPrintln("\nOptions are:"); - PgmPrintln("(0) Display date and time"); - PgmPrintln("(1) Set time"); - PgmPrintln("(2) Set date"); - PgmPrintln("(3) Set Control"); - PgmPrintln("(4) Dump all"); - PgmPrintln("(5) Fill NV RAM"); - PgmPrintln("(6) Set NV RAM value"); - PgmPrint("Enter option: "); +void loop(void) +{ + Serial.println(); + displayTime(); + while (Serial.read() >= 0) {} + PgmPrintln("\nOptions are:"); + PgmPrintln("(0) Display date and time"); + PgmPrintln("(1) Set time"); + PgmPrintln("(2) Set date"); + PgmPrintln("(3) Set Control"); + PgmPrintln("(4) Dump all"); + PgmPrintln("(5) Fill NV RAM"); + PgmPrintln("(6) Set NV RAM value"); + PgmPrint("Enter option: "); - uint16_t n; - if (!hexRead(&n)) return; - Serial.println(n, DEC); - if (n == 0) return; - Serial.println(); - if (n == 1) { - setTime(); - } else if (n == 2) { - setDate(); - } else if (n == 3) { - setControl(); - } else if (n == 4) { - dumpAll(); - } else if (n == 5) { - fillNvRam(); - } else if (n == 6) { - setNvRam(); - } else { - PgmPrintln("Invalid option"); - } + uint16_t n; + if (!hexRead(&n)) { + return; + } + Serial.println(n, DEC); + if (n == 0) { + return; + } + Serial.println(); + if (n == 1) { + setTime(); + } else if (n == 2) { + setDate(); + } else if (n == 3) { + setControl(); + } else if (n == 4) { + dumpAll(); + } else if (n == 5) { + fillNvRam(); + } else if (n == 6) { + setNvRam(); + } else { + PgmPrintln("Invalid option"); + } } \ No newline at end of file diff --git a/drivers/AVR/DigitalIO/examples/testArduino/testArduino.ino b/drivers/AVR/DigitalIO/examples/testArduino/testArduino.ino index 13afe04..144c7fb 100644 --- a/drivers/AVR/DigitalIO/examples/testArduino/testArduino.ino +++ b/drivers/AVR/DigitalIO/examples/testArduino/testArduino.ino @@ -1,14 +1,16 @@ // Scope test for write timing with Arduino digitaWrite(). const uint8_t PIN13 = 13; -void setup() { - // Set mode to OUTPUT. - pinMode(PIN13, OUTPUT); +void setup() +{ + // Set mode to OUTPUT. + pinMode(PIN13, OUTPUT); } -void loop() { - digitalWrite(PIN13, HIGH); - digitalWrite(PIN13, LOW); - digitalWrite(PIN13, HIGH); - digitalWrite(PIN13, LOW); - delay(1); +void loop() +{ + digitalWrite(PIN13, HIGH); + digitalWrite(PIN13, LOW); + digitalWrite(PIN13, HIGH); + digitalWrite(PIN13, LOW); + delay(1); } \ No newline at end of file diff --git a/drivers/AVR/DigitalIO/examples/testDigitalPin/testDigitalPin.ino b/drivers/AVR/DigitalIO/examples/testDigitalPin/testDigitalPin.ino index 1ac0c02..5b4f562 100644 --- a/drivers/AVR/DigitalIO/examples/testDigitalPin/testDigitalPin.ino +++ b/drivers/AVR/DigitalIO/examples/testDigitalPin/testDigitalPin.ino @@ -4,16 +4,18 @@ // Class with compile time pin number. DigitalPin<13> pin13; -void setup() { - // set mode to OUTPUT - pin13.mode(OUTPUT); +void setup() +{ + // set mode to OUTPUT + pin13.mode(OUTPUT); } -void loop() { - pin13.high(); - pin13.low(); - pin13.write(1); - pin13.write(0); - pin13.toggle(); - pin13.toggle(); - delay(1); +void loop() +{ + pin13.high(); + pin13.low(); + pin13.write(1); + pin13.write(0); + pin13.toggle(); + pin13.toggle(); + delay(1); } \ No newline at end of file diff --git a/drivers/AVR/DigitalIO/examples/testFastDigital/testFastDigital.ino b/drivers/AVR/DigitalIO/examples/testFastDigital/testFastDigital.ino index 03f38d5..6fca39a 100644 --- a/drivers/AVR/DigitalIO/examples/testFastDigital/testFastDigital.ino +++ b/drivers/AVR/DigitalIO/examples/testFastDigital/testFastDigital.ino @@ -1,13 +1,15 @@ // Test fastDigital function timing with a scope. #include const uint8_t PIN = 13; -void setup() { - fastPinMode(PIN, OUTPUT); +void setup() +{ + fastPinMode(PIN, OUTPUT); } -void loop() { - fastDigitalWrite(PIN, HIGH); - fastDigitalWrite(PIN, LOW); - fastDigitalToggle(PIN); - fastDigitalToggle(PIN); - delay(1); +void loop() +{ + fastDigitalWrite(PIN, HIGH); + fastDigitalWrite(PIN, LOW); + fastDigitalToggle(PIN); + fastDigitalToggle(PIN); + delay(1); } \ No newline at end of file diff --git a/drivers/AVR/DigitalIO/examples/testPinIO/testPinIO.ino b/drivers/AVR/DigitalIO/examples/testPinIO/testPinIO.ino index 4f72823..3cf8a85 100644 --- a/drivers/AVR/DigitalIO/examples/testPinIO/testPinIO.ino +++ b/drivers/AVR/DigitalIO/examples/testPinIO/testPinIO.ino @@ -4,16 +4,18 @@ // Class with runtime pin numbers. PinIO pin(13); -void setup() { - // Set mode to OUTPUT. - pin.mode(OUTPUT); +void setup() +{ + // Set mode to OUTPUT. + pin.mode(OUTPUT); } -void loop() { - pin.high(); - pin.low(); - pin.write(1); - pin.write(0); - pin.toggle(); - pin.toggle(); - delay(1); +void loop() +{ + pin.high(); + pin.low(); + pin.write(1); + pin.write(0); + pin.toggle(); + pin.toggle(); + delay(1); } \ No newline at end of file diff --git a/drivers/AVR/DigitalIO/examples/testSoftSPI/testSoftSPI.ino b/drivers/AVR/DigitalIO/examples/testSoftSPI/testSoftSPI.ino index 7b9544f..f457a3f 100644 --- a/drivers/AVR/DigitalIO/examples/testSoftSPI/testSoftSPI.ino +++ b/drivers/AVR/DigitalIO/examples/testSoftSPI/testSoftSPI.ino @@ -9,29 +9,35 @@ const uint8_t SPI_MODE = 0; SoftSPI spi; int test; -void setup() { - Serial.begin(9600); - spi.begin(); - while(1) { - Serial.println("Enter:"); - Serial.println("R - Receive"); - Serial.println("S - Send"); - Serial.println("T - Transfer"); - while ((test = Serial.read()) <= 0) {} - test = toupper(test); - if (strchr("RST", test)) break; - Serial.println("Invalid entry"); - }; - Serial.print("Starting test "); - Serial.println((char)test); +void setup() +{ + Serial.begin(9600); + spi.begin(); + while(1) { + Serial.println("Enter:"); + Serial.println("R - Receive"); + Serial.println("S - Send"); + Serial.println("T - Transfer"); + while ((test = Serial.read()) <= 0) {} + test = toupper(test); + if (strchr("RST", test)) { + break; + } + Serial.println("Invalid entry"); + }; + Serial.print("Starting test "); + Serial.println((char)test); } -void loop() { - if (test == 'S') spi.send(0X55); - if (test == 'R') { - Serial.println(spi.receive(), HEX); - } - if (test == 'T') { - Serial.println(spi.transfer(0XAA), HEX); - } - delay(10); +void loop() +{ + if (test == 'S') { + spi.send(0X55); + } + if (test == 'R') { + Serial.println(spi.receive(), HEX); + } + if (test == 'T') { + Serial.println(spi.transfer(0XAA), HEX); + } + delay(10); } \ No newline at end of file diff --git a/drivers/AVR/DigitalWriteFast/digitalWriteFast.h b/drivers/AVR/DigitalWriteFast/digitalWriteFast.h index f90b4f6..54ee961 100644 --- a/drivers/AVR/DigitalWriteFast/digitalWriteFast.h +++ b/drivers/AVR/DigitalWriteFast/digitalWriteFast.h @@ -7,92 +7,92 @@ #define __digitalWriteFast_h_ #if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA1280) || defined(ARDUINO_AVR_MEGA2560) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) - #define __digitalPinToPortReg(__pin) \ - (((__pin) >= 22 && (__pin) <= 29) ? &PORTA : \ - ((((__pin) >= 10 && (__pin) <= 13) || ((__pin) >= 50 && (__pin) <= 53)) ? &PORTB : \ - (((__pin) >= 30 && (__pin) <= 37) ? &PORTC : \ - ((((__pin) >= 18 && (__pin) <= 21) || (__pin) == 38) ? &PORTD : \ - ((((__pin) <= 3) || (__pin) == 5) ? &PORTE : \ - (((__pin) >= 54 && (__pin) <= 61) ? &PORTF : \ - ((((__pin) >= 39 && (__pin) <= 41) || (__pin) == 4) ? &PORTG : \ - ((((__pin) >= 6 && (__pin) <= 9) || (__pin) == 16 || (__pin) == 17) ? &PORTH : \ - (((__pin) == 14 || (__pin) == 15) ? &PORTJ : \ - (((__pin) >= 62 && (__pin) <= 69) ? &PORTK : &PORTL)))))))))) - #define __digitalPinToDDRReg(__pin) \ - (((__pin) >= 22 && (__pin) <= 29) ? &DDRA : \ - ((((__pin) >= 10 && (__pin) <= 13) || ((__pin) >= 50 && (__pin) <= 53)) ? &DDRB : \ - (((__pin) >= 30 && (__pin) <= 37) ? &DDRC : \ - ((((__pin) >= 18 && (__pin) <= 21) || (__pin) == 38) ? &DDRD : \ - ((((__pin) <= 3) || (__pin) == 5) ? &DDRE : \ - (((__pin) >= 54 && (__pin) <= 61) ? &DDRF : \ - ((((__pin) >= 39 && (__pin) <= 41) || (__pin) == 4) ? &DDRG : \ - ((((__pin) >= 6 && (__pin) <= 9) || (__pin) == 16 || (__pin) == 17) ? &DDRH : \ - (((__pin) == 14 || (__pin) == 15) ? &DDRJ : \ - (((__pin) >= 62 && (__pin) <= 69) ? &DDRK : &DDRL)))))))))) - #define __digitalPinToPINReg(__pin) \ - (((__pin) >= 22 && (__pin) <= 29) ? &PINA : \ - ((((__pin) >= 10 && (__pin) <= 13) || ((__pin) >= 50 && (__pin) <= 53)) ? &PINB : \ - (((__pin) >= 30 && (__pin) <= 37) ? &PINC : \ - ((((__pin) >= 18 && (__pin) <= 21) || (__pin) == 38) ? &PIND : \ - ((((__pin) <= 3) || (__pin) == 5) ? &PINE : \ - (((__pin) >= 54 && (__pin) <= 61) ? &PINF : \ - ((((__pin) >= 39 && (__pin) <= 41) || (__pin) == 4) ? &PING : \ - ((((__pin) >= 6 && (__pin) <= 9) || (__pin) == 16 || (__pin) == 17) ? &PINH : \ - (((__pin) == 14 || (__pin) == 15) ? &PINJ : \ - (((__pin) >= 62 && (__pin) <= 69) ? &PINK : &PINL)))))))))) - #define __digitalPinToBit(__pin) \ - (((__pin) >= 7 && (__pin) <= 9) ? (__pin) - 3 : \ - (((__pin) >= 10 && (__pin) <= 13) ? (__pin) - 6 : \ - (((__pin) >= 22 && (__pin) <= 29) ? (__pin) - 22 : \ - (((__pin) >= 30 && (__pin) <= 37) ? 37 - (__pin) : \ - (((__pin) >= 39 && (__pin) <= 41) ? 41 - (__pin) : \ - (((__pin) >= 42 && (__pin) <= 49) ? 49 - (__pin) : \ - (((__pin) >= 50 && (__pin) <= 53) ? 53 - (__pin) : \ - (((__pin) >= 54 && (__pin) <= 61) ? (__pin) - 54 : \ - (((__pin) >= 62 && (__pin) <= 69) ? (__pin) - 62 : \ - (((__pin) == 0 || (__pin) == 15 || (__pin) == 17 || (__pin) == 21) ? 0 : \ - (((__pin) == 1 || (__pin) == 14 || (__pin) == 16 || (__pin) == 20) ? 1 : \ - (((__pin) == 19) ? 2 : \ - (((__pin) == 5 || (__pin) == 6 || (__pin) == 18) ? 3 : \ - (((__pin) == 2) ? 4 : \ - (((__pin) == 3 || (__pin) == 4) ? 5 : 7))))))))))))))) +#define __digitalPinToPortReg(__pin) \ + (((__pin) >= 22 && (__pin) <= 29) ? &PORTA : \ + ((((__pin) >= 10 && (__pin) <= 13) || ((__pin) >= 50 && (__pin) <= 53)) ? &PORTB : \ + (((__pin) >= 30 && (__pin) <= 37) ? &PORTC : \ + ((((__pin) >= 18 && (__pin) <= 21) || (__pin) == 38) ? &PORTD : \ + ((((__pin) <= 3) || (__pin) == 5) ? &PORTE : \ + (((__pin) >= 54 && (__pin) <= 61) ? &PORTF : \ + ((((__pin) >= 39 && (__pin) <= 41) || (__pin) == 4) ? &PORTG : \ + ((((__pin) >= 6 && (__pin) <= 9) || (__pin) == 16 || (__pin) == 17) ? &PORTH : \ + (((__pin) == 14 || (__pin) == 15) ? &PORTJ : \ + (((__pin) >= 62 && (__pin) <= 69) ? &PORTK : &PORTL)))))))))) +#define __digitalPinToDDRReg(__pin) \ + (((__pin) >= 22 && (__pin) <= 29) ? &DDRA : \ + ((((__pin) >= 10 && (__pin) <= 13) || ((__pin) >= 50 && (__pin) <= 53)) ? &DDRB : \ + (((__pin) >= 30 && (__pin) <= 37) ? &DDRC : \ + ((((__pin) >= 18 && (__pin) <= 21) || (__pin) == 38) ? &DDRD : \ + ((((__pin) <= 3) || (__pin) == 5) ? &DDRE : \ + (((__pin) >= 54 && (__pin) <= 61) ? &DDRF : \ + ((((__pin) >= 39 && (__pin) <= 41) || (__pin) == 4) ? &DDRG : \ + ((((__pin) >= 6 && (__pin) <= 9) || (__pin) == 16 || (__pin) == 17) ? &DDRH : \ + (((__pin) == 14 || (__pin) == 15) ? &DDRJ : \ + (((__pin) >= 62 && (__pin) <= 69) ? &DDRK : &DDRL)))))))))) +#define __digitalPinToPINReg(__pin) \ + (((__pin) >= 22 && (__pin) <= 29) ? &PINA : \ + ((((__pin) >= 10 && (__pin) <= 13) || ((__pin) >= 50 && (__pin) <= 53)) ? &PINB : \ + (((__pin) >= 30 && (__pin) <= 37) ? &PINC : \ + ((((__pin) >= 18 && (__pin) <= 21) || (__pin) == 38) ? &PIND : \ + ((((__pin) <= 3) || (__pin) == 5) ? &PINE : \ + (((__pin) >= 54 && (__pin) <= 61) ? &PINF : \ + ((((__pin) >= 39 && (__pin) <= 41) || (__pin) == 4) ? &PING : \ + ((((__pin) >= 6 && (__pin) <= 9) || (__pin) == 16 || (__pin) == 17) ? &PINH : \ + (((__pin) == 14 || (__pin) == 15) ? &PINJ : \ + (((__pin) >= 62 && (__pin) <= 69) ? &PINK : &PINL)))))))))) +#define __digitalPinToBit(__pin) \ + (((__pin) >= 7 && (__pin) <= 9) ? (__pin) - 3 : \ + (((__pin) >= 10 && (__pin) <= 13) ? (__pin) - 6 : \ + (((__pin) >= 22 && (__pin) <= 29) ? (__pin) - 22 : \ + (((__pin) >= 30 && (__pin) <= 37) ? 37 - (__pin) : \ + (((__pin) >= 39 && (__pin) <= 41) ? 41 - (__pin) : \ + (((__pin) >= 42 && (__pin) <= 49) ? 49 - (__pin) : \ + (((__pin) >= 50 && (__pin) <= 53) ? 53 - (__pin) : \ + (((__pin) >= 54 && (__pin) <= 61) ? (__pin) - 54 : \ + (((__pin) >= 62 && (__pin) <= 69) ? (__pin) - 62 : \ + (((__pin) == 0 || (__pin) == 15 || (__pin) == 17 || (__pin) == 21) ? 0 : \ + (((__pin) == 1 || (__pin) == 14 || (__pin) == 16 || (__pin) == 20) ? 1 : \ + (((__pin) == 19) ? 2 : \ + (((__pin) == 5 || (__pin) == 6 || (__pin) == 18) ? 3 : \ + (((__pin) == 2) ? 4 : \ + (((__pin) == 3 || (__pin) == 4) ? 5 : 7))))))))))))))) #elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) - #define __digitalPinToPortReg(__pin) (((__pin) <= 7) ? &PORTB : (((__pin) >= 8 && (__pin) <= 15) ? &PORTD : (((__pin) >= 16 && (__pin) <= 23) ? &PORTC : &PORTA))) - #define __digitalPinToDDRReg(__pin) (((__pin) <= 7) ? &DDRB : (((__pin) >= 8 && (__pin) <= 15) ? &DDRD : (((__pin) >= 8 && (__pin) <= 15) ? &DDRC : &DDRA))) - #define __digitalPinToPINReg(__pin) (((__pin) <= 7) ? &PINB : (((__pin) >= 8 && (__pin) <= 15) ? &PIND : (((__pin) >= 8 && (__pin) <= 15) ? &PINC : &PINA))) - #define __digitalPinToBit(__pin) (((__pin) <= 7) ? (__pin) : (((__pin) >= 8 && (__pin) <= 15) ? (__pin) - 8 : (((__pin) >= 16 && (__pin) <= 23) ? (__pin) - 16 : (__pin) - 24))) +#define __digitalPinToPortReg(__pin) (((__pin) <= 7) ? &PORTB : (((__pin) >= 8 && (__pin) <= 15) ? &PORTD : (((__pin) >= 16 && (__pin) <= 23) ? &PORTC : &PORTA))) +#define __digitalPinToDDRReg(__pin) (((__pin) <= 7) ? &DDRB : (((__pin) >= 8 && (__pin) <= 15) ? &DDRD : (((__pin) >= 8 && (__pin) <= 15) ? &DDRC : &DDRA))) +#define __digitalPinToPINReg(__pin) (((__pin) <= 7) ? &PINB : (((__pin) >= 8 && (__pin) <= 15) ? &PIND : (((__pin) >= 8 && (__pin) <= 15) ? &PINC : &PINA))) +#define __digitalPinToBit(__pin) (((__pin) <= 7) ? (__pin) : (((__pin) >= 8 && (__pin) <= 15) ? (__pin) - 8 : (((__pin) >= 16 && (__pin) <= 23) ? (__pin) - 16 : (__pin) - 24))) #elif defined(ARDUINO_AVR_LEONARDO) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) - #define __digitalPinToPortReg(__pin) ((((__pin) <= 4) || (__pin) == 6 || (__pin) == 12 || (__pin) == 24 || (__pin) == 25 || (__pin) == 29) ? &PORTD : (((__pin) == 5 || (__pin) == 13) ? &PORTC : (((__pin) >= 18 && (__pin) <= 23)) ? &PORTF : (((__pin) == 7) ? &PORTE : &PORTB))) - #define __digitalPinToDDRReg(__pin) ((((__pin) <= 4) || (__pin) == 6 || (__pin) == 12 || (__pin) == 24 || (__pin) == 25 || (__pin) == 29) ? &DDRD : (((__pin) == 5 || (__pin) == 13) ? &DDRC : (((__pin) >= 18 && (__pin) <= 23)) ? &DDRF : (((__pin) == 7) ? &DDRE : &DDRB))) - #define __digitalPinToPINReg(__pin) ((((__pin) <= 4) || (__pin) == 6 || (__pin) == 12 || (__pin) == 24 || (__pin) == 25 || (__pin) == 29) ? &PIND : (((__pin) == 5 || (__pin) == 13) ? &PINC : (((__pin) >= 18 && (__pin) <= 23)) ? &PINF : (((__pin) == 7) ? &PINE : &PINB))) - #define __digitalPinToBit(__pin) (((__pin) >= 8 && (__pin) <= 11) ? (__pin) - 4 : (((__pin) >= 18 && (__pin) <= 21) ? 25 - (__pin) : (((__pin) == 0) ? 2 : (((__pin) == 1) ? 3 : (((__pin) == 2) ? 1 : (((__pin) == 3) ? 0 : (((__pin) == 4) ? 4 : (((__pin) == 6) ? 7 : (((__pin) == 13) ? 7 : (((__pin) == 14) ? 3 : (((__pin) == 15) ? 1 : (((__pin) == 16) ? 2 : (((__pin) == 17) ? 0 : (((__pin) == 22) ? 1 : (((__pin) == 23) ? 0 : (((__pin) == 24) ? 4 : (((__pin) == 25) ? 7 : (((__pin) == 26) ? 4 : (((__pin) == 27) ? 5 : 6 ))))))))))))))))))) +#define __digitalPinToPortReg(__pin) ((((__pin) <= 4) || (__pin) == 6 || (__pin) == 12 || (__pin) == 24 || (__pin) == 25 || (__pin) == 29) ? &PORTD : (((__pin) == 5 || (__pin) == 13) ? &PORTC : (((__pin) >= 18 && (__pin) <= 23)) ? &PORTF : (((__pin) == 7) ? &PORTE : &PORTB))) +#define __digitalPinToDDRReg(__pin) ((((__pin) <= 4) || (__pin) == 6 || (__pin) == 12 || (__pin) == 24 || (__pin) == 25 || (__pin) == 29) ? &DDRD : (((__pin) == 5 || (__pin) == 13) ? &DDRC : (((__pin) >= 18 && (__pin) <= 23)) ? &DDRF : (((__pin) == 7) ? &DDRE : &DDRB))) +#define __digitalPinToPINReg(__pin) ((((__pin) <= 4) || (__pin) == 6 || (__pin) == 12 || (__pin) == 24 || (__pin) == 25 || (__pin) == 29) ? &PIND : (((__pin) == 5 || (__pin) == 13) ? &PINC : (((__pin) >= 18 && (__pin) <= 23)) ? &PINF : (((__pin) == 7) ? &PINE : &PINB))) +#define __digitalPinToBit(__pin) (((__pin) >= 8 && (__pin) <= 11) ? (__pin) - 4 : (((__pin) >= 18 && (__pin) <= 21) ? 25 - (__pin) : (((__pin) == 0) ? 2 : (((__pin) == 1) ? 3 : (((__pin) == 2) ? 1 : (((__pin) == 3) ? 0 : (((__pin) == 4) ? 4 : (((__pin) == 6) ? 7 : (((__pin) == 13) ? 7 : (((__pin) == 14) ? 3 : (((__pin) == 15) ? 1 : (((__pin) == 16) ? 2 : (((__pin) == 17) ? 0 : (((__pin) == 22) ? 1 : (((__pin) == 23) ? 0 : (((__pin) == 24) ? 4 : (((__pin) == 25) ? 7 : (((__pin) == 26) ? 4 : (((__pin) == 27) ? 5 : 6 ))))))))))))))))))) #elif defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_DUEMILANOVE) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) - #if defined(__AVR_ATmega328PB__) - #define __digitalPinToPortReg(__pin) (((__pin) <= 7) ? &PORTD : (((__pin) >= 8 && (__pin) <= 13) ? &PORTB : (((__pin) >= 14 && (__pin) <= 19) ? &PORTC : &PORTE))) - #define __digitalPinToDDRReg(__pin) (((__pin) <= 7) ? &DDRD : (((__pin) >= 8 && (__pin) <= 13) ? &DDRB : (((__pin) >= 14 && (__pin) <= 19) ? &DDRC : &DDRE))) - #define __digitalPinToPINReg(__pin) (((__pin) <= 7) ? &PIND : (((__pin) >= 8 && (__pin) <= 13) ? &PINB : (((__pin) >= 14 && (__pin) <= 19) ? &PINC : &PINE))) - #define __digitalPinToBit(__pin) (((__pin) <= 7) ? (__pin) : (((__pin) >= 8 && (__pin) <= 13) ? (__pin) - 8 : (((__pin) >= 14 && (__pin) <= 19) ? (__pin) - 14 : (((__pin) >= 20 && (__pin) <= 21) ? (__pin) - 18 : (__pin) - 22)))) - #else - #define __digitalPinToPortReg(__pin) (((__pin) <= 7) ? &PORTD : (((__pin) >= 8 && (__pin) <= 13) ? &PORTB : &PORTC)) - #define __digitalPinToDDRReg(__pin) (((__pin) <= 7) ? &DDRD : (((__pin) >= 8 && (__pin) <= 13) ? &DDRB : &DDRC)) - #define __digitalPinToPINReg(__pin) (((__pin) <= 7) ? &PIND : (((__pin) >= 8 && (__pin) <= 13) ? &PINB : &PINC)) - #define __digitalPinToBit(__pin) (((__pin) <= 7) ? (__pin) : (((__pin) >= 8 && (__pin) <= 13) ? (__pin) - 8 : (__pin) - 14)) - #endif +#if defined(__AVR_ATmega328PB__) +#define __digitalPinToPortReg(__pin) (((__pin) <= 7) ? &PORTD : (((__pin) >= 8 && (__pin) <= 13) ? &PORTB : (((__pin) >= 14 && (__pin) <= 19) ? &PORTC : &PORTE))) +#define __digitalPinToDDRReg(__pin) (((__pin) <= 7) ? &DDRD : (((__pin) >= 8 && (__pin) <= 13) ? &DDRB : (((__pin) >= 14 && (__pin) <= 19) ? &DDRC : &DDRE))) +#define __digitalPinToPINReg(__pin) (((__pin) <= 7) ? &PIND : (((__pin) >= 8 && (__pin) <= 13) ? &PINB : (((__pin) >= 14 && (__pin) <= 19) ? &PINC : &PINE))) +#define __digitalPinToBit(__pin) (((__pin) <= 7) ? (__pin) : (((__pin) >= 8 && (__pin) <= 13) ? (__pin) - 8 : (((__pin) >= 14 && (__pin) <= 19) ? (__pin) - 14 : (((__pin) >= 20 && (__pin) <= 21) ? (__pin) - 18 : (__pin) - 22)))) +#else +#define __digitalPinToPortReg(__pin) (((__pin) <= 7) ? &PORTD : (((__pin) >= 8 && (__pin) <= 13) ? &PORTB : &PORTC)) +#define __digitalPinToDDRReg(__pin) (((__pin) <= 7) ? &DDRD : (((__pin) >= 8 && (__pin) <= 13) ? &DDRB : &DDRC)) +#define __digitalPinToPINReg(__pin) (((__pin) <= 7) ? &PIND : (((__pin) >= 8 && (__pin) <= 13) ? &PINB : &PINC)) +#define __digitalPinToBit(__pin) (((__pin) <= 7) ? (__pin) : (((__pin) >= 8 && (__pin) <= 13) ? (__pin) - 8 : (__pin) - 14)) +#endif #endif #if defined(ARDUINO_ARCH_AVR) - #if !defined(__atomicWrite) - #define __atomicWrite(A,P,V) do { if ((A) < 0x40) {bitWrite((A), (P), (V) );} else {uint8_t register saveSreg = SREG;cli();bitWrite((A), (P), (V));SREG = saveSreg;}} while(0) - #endif - #if !defined(digitalWriteFast) - #define digitalWriteFast(__pin, __value) do { if (__builtin_constant_p(__pin) && __builtin_constant_p(__value)) { bitWrite(*__digitalPinToPortReg(__pin), __digitalPinToBit(__pin), (__value)); } else { digitalWrite((__pin), (__value)); } } while (0) - #endif - #if !defined(pinModeFast) - #define pinModeFast(__pin, __mode) do { if (__builtin_constant_p(__pin) && __builtin_constant_p(__mode) && (__mode!=INPUT_PULLUP)) { bitWrite(*__digitalPinToDDRReg(__pin), __digitalPinToBit(__pin), (__mode)); } else { pinMode((__pin), (__mode)); } } while (0) - #endif - #if !defined(digitalReadFast) - #define digitalReadFast(__pin) ( (bool) (__builtin_constant_p(__pin) ) ? (( bitRead(*__digitalPinToPINReg(__pin), __digitalPinToBit(__pin))) ) : digitalRead((__pin)) ) - #endif +#if !defined(__atomicWrite) +#define __atomicWrite(A,P,V) do { if ((A) < 0x40) {bitWrite((A), (P), (V) );} else {uint8_t register saveSreg = SREG;cli();bitWrite((A), (P), (V));SREG = saveSreg;}} while(0) +#endif +#if !defined(digitalWriteFast) +#define digitalWriteFast(__pin, __value) do { if (__builtin_constant_p(__pin) && __builtin_constant_p(__value)) { bitWrite(*__digitalPinToPortReg(__pin), __digitalPinToBit(__pin), (__value)); } else { digitalWrite((__pin), (__value)); } } while (0) +#endif +#if !defined(pinModeFast) +#define pinModeFast(__pin, __mode) do { if (__builtin_constant_p(__pin) && __builtin_constant_p(__mode) && (__mode!=INPUT_PULLUP)) { bitWrite(*__digitalPinToDDRReg(__pin), __digitalPinToBit(__pin), (__mode)); } else { pinMode((__pin), (__mode)); } } while (0) +#endif +#if !defined(digitalReadFast) +#define digitalReadFast(__pin) ( (bool) (__builtin_constant_p(__pin) ) ? (( bitRead(*__digitalPinToPINReg(__pin), __digitalPinToBit(__pin))) ) : digitalRead((__pin)) ) +#endif #endif #endif \ No newline at end of file diff --git a/drivers/AltSoftSerial/AltSoftSerial.h b/drivers/AltSoftSerial/AltSoftSerial.h index 5333903..4bb1fda 100644 --- a/drivers/AltSoftSerial/AltSoftSerial.h +++ b/drivers/AltSoftSerial/AltSoftSerial.h @@ -1,17 +1,17 @@ /* An Alternative Software Serial Library * http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html * Copyright (c) 2014 PJRC.COM, LLC, Paul Stoffregen, paul@pjrc.com - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -44,28 +44,61 @@ class AltSoftSerial : public Stream { public: AltSoftSerial() { } //!< Constructor - ~AltSoftSerial() { end(); } //!< Destructor - static void begin(uint32_t baud) { init((ALTSS_BASE_FREQ + baud / 2) / baud); } //!< begin + ~AltSoftSerial() + { + end(); //!< Destructor + } + static void begin(uint32_t baud) + { + init((ALTSS_BASE_FREQ + baud / 2) / baud); //!< begin + } static void end(); //!< end int peek(); //!< peek int read(); //!< read int available(); //!< available #if ARDUINO >= 100 - size_t write(uint8_t byte) { writeByte(byte); return 1; } //!< write - void flush() { flushOutput(); } //!< flush + size_t write(uint8_t byte) + { + writeByte(byte); //!< write + return 1; + } + void flush() + { + flushOutput(); //!< flush + } #else - void write(uint8_t byte) { writeByte(byte); } //!< write - void flush() { flushInput(); } //!< flush + void write(uint8_t byte) + { + writeByte(byte); //!< write + } + void flush() + { + flushInput(); //!< flush + } #endif using Print::write; static void flushInput(); //!< flushInput static void flushOutput(); //!< flushOutput // for drop-in compatibility with NewSoftSerial, rxPin & txPin ignored //AltSoftSerial(uint8_t rxPin, uint8_t txPin, bool inverse = false) { } - bool listen() { return false; } //!< listen - bool isListening() { return true; } //!< isListening - bool overflow() { bool r = timing_error; timing_error = false; return r; } //!< overflow - static int library_version() { return 1; } //!< library_version + bool listen() + { + return false; //!< listen + } + bool isListening() + { + return true; //!< isListening + } + bool overflow() + { + bool r = timing_error; //!< overflow + timing_error = false; + return r; + } + static int library_version() + { + return 1; //!< library_version + } static void enable_timer0(bool) { } //!< enable_timer0 static bool timing_error; //!< timing_error private: diff --git a/drivers/AltSoftSerial/config/AltSoftSerial_Boards.h b/drivers/AltSoftSerial/config/AltSoftSerial_Boards.h index 1ccbf68..51e1f18 100644 --- a/drivers/AltSoftSerial/config/AltSoftSerial_Boards.h +++ b/drivers/AltSoftSerial/config/AltSoftSerial_Boards.h @@ -1,17 +1,17 @@ /* An Alternative Software Serial Library * http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html * Copyright (c) 2014 PJRC.COM, LLC, Paul Stoffregen, paul@pjrc.com - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -26,15 +26,15 @@ // #if defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY) - //#define ALTSS_USE_TIMER1 - //#define INPUT_CAPTURE_PIN 22 // receive - //#define OUTPUT_COMPARE_A_PIN 14 // transmit - //#define OUTPUT_COMPARE_B_PIN 15 // unusable PWM - //#define OUTPUT_COMPARE_C_PIN 4 // unusable PWM +//#define ALTSS_USE_TIMER1 +//#define INPUT_CAPTURE_PIN 22 // receive +//#define OUTPUT_COMPARE_A_PIN 14 // transmit +//#define OUTPUT_COMPARE_B_PIN 15 // unusable PWM +//#define OUTPUT_COMPARE_C_PIN 4 // unusable PWM - #define ALTSS_USE_TIMER3 - #define INPUT_CAPTURE_PIN 10 // receive - #define OUTPUT_COMPARE_A_PIN 9 // transmit +#define ALTSS_USE_TIMER3 +#define INPUT_CAPTURE_PIN 10 // receive +#define OUTPUT_COMPARE_A_PIN 9 // transmit @@ -42,41 +42,41 @@ // #elif defined(__AVR_AT90USB1286__) && defined(CORE_TEENSY) - #define ALTSS_USE_TIMER1 - #define INPUT_CAPTURE_PIN 4 // receive - #define OUTPUT_COMPARE_A_PIN 25 // transmit - #define OUTPUT_COMPARE_B_PIN 26 // unusable PWM - #define OUTPUT_COMPARE_C_PIN 27 // unusable PWM +#define ALTSS_USE_TIMER1 +#define INPUT_CAPTURE_PIN 4 // receive +#define OUTPUT_COMPARE_A_PIN 25 // transmit +#define OUTPUT_COMPARE_B_PIN 26 // unusable PWM +#define OUTPUT_COMPARE_C_PIN 27 // unusable PWM - //#define ALTSS_USE_TIMER3 - //#define INPUT_CAPTURE_PIN 17 // receive - //#define OUTPUT_COMPARE_A_PIN 16 // transmit - //#define OUTPUT_COMPARE_B_PIN 15 // unusable PWM - //#define OUTPUT_COMPARE_C_PIN 14 // unusable PWM +//#define ALTSS_USE_TIMER3 +//#define INPUT_CAPTURE_PIN 17 // receive +//#define OUTPUT_COMPARE_A_PIN 16 // transmit +//#define OUTPUT_COMPARE_B_PIN 15 // unusable PWM +//#define OUTPUT_COMPARE_C_PIN 14 // unusable PWM // Teensy 3.0 & 3.1 // #elif defined(__MK20DX128__) || defined(__MK20DX256__) - #define ALTSS_USE_FTM0 - #define INPUT_CAPTURE_PIN 20 // receive (FTM0_CH5) - #define OUTPUT_COMPARE_A_PIN 21 // transmit (FTM0_CH6) - #define OUTPUT_COMPARE_B_PIN 22 // unusable PWM (FTM0_CH0) - #define OUTPUT_COMPARE_C_PIN 23 // PWM usable fixed freq - #define OUTPUT_COMPARE_D_PIN 5 // PWM usable fixed freq - #define OUTPUT_COMPARE_E_PIN 6 // PWM usable fixed freq - #define OUTPUT_COMPARE_F_PIN 9 // PWM usable fixed freq - #define OUTPUT_COMPARE_G_PIN 10 // PWM usable fixed freq +#define ALTSS_USE_FTM0 +#define INPUT_CAPTURE_PIN 20 // receive (FTM0_CH5) +#define OUTPUT_COMPARE_A_PIN 21 // transmit (FTM0_CH6) +#define OUTPUT_COMPARE_B_PIN 22 // unusable PWM (FTM0_CH0) +#define OUTPUT_COMPARE_C_PIN 23 // PWM usable fixed freq +#define OUTPUT_COMPARE_D_PIN 5 // PWM usable fixed freq +#define OUTPUT_COMPARE_E_PIN 6 // PWM usable fixed freq +#define OUTPUT_COMPARE_F_PIN 9 // PWM usable fixed freq +#define OUTPUT_COMPARE_G_PIN 10 // PWM usable fixed freq // Wiring-S // #elif defined(__AVR_ATmega644P__) && defined(WIRING) - #define ALTSS_USE_TIMER1 - #define INPUT_CAPTURE_PIN 6 // receive - #define OUTPUT_COMPARE_A_PIN 5 // transmit - #define OUTPUT_COMPARE_B_PIN 4 // unusable PWM +#define ALTSS_USE_TIMER1 +#define INPUT_CAPTURE_PIN 6 // receive +#define OUTPUT_COMPARE_A_PIN 5 // transmit +#define OUTPUT_COMPARE_B_PIN 4 // unusable PWM @@ -84,51 +84,51 @@ // #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) - #define ALTSS_USE_TIMER1 - #define INPUT_CAPTURE_PIN 8 // receive - #define OUTPUT_COMPARE_A_PIN 9 // transmit - #define OUTPUT_COMPARE_B_PIN 10 // unusable PWM +#define ALTSS_USE_TIMER1 +#define INPUT_CAPTURE_PIN 8 // receive +#define OUTPUT_COMPARE_A_PIN 9 // transmit +#define OUTPUT_COMPARE_B_PIN 10 // unusable PWM // Arduino Leonardo & Yun (from Cristian Maglie) // #elif defined(ARDUINO_AVR_YUN) || defined(ARDUINO_AVR_LEONARDO) || defined(__AVR_ATmega32U4__) - //#define ALTSS_USE_TIMER1 - //#define INPUT_CAPTURE_PIN 4 // receive - //#define OUTPUT_COMPARE_A_PIN 9 // transmit - //#define OUTPUT_COMPARE_B_PIN 10 // unusable PWM - //#define OUTPUT_COMPARE_C_PIN 11 // unusable PWM +//#define ALTSS_USE_TIMER1 +//#define INPUT_CAPTURE_PIN 4 // receive +//#define OUTPUT_COMPARE_A_PIN 9 // transmit +//#define OUTPUT_COMPARE_B_PIN 10 // unusable PWM +//#define OUTPUT_COMPARE_C_PIN 11 // unusable PWM - #define ALTSS_USE_TIMER3 - #define INPUT_CAPTURE_PIN 13 // receive - #define OUTPUT_COMPARE_A_PIN 5 // transmit +#define ALTSS_USE_TIMER3 +#define INPUT_CAPTURE_PIN 13 // receive +#define OUTPUT_COMPARE_A_PIN 5 // transmit // Arduino Mega // #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - //#define ALTSS_USE_TIMER4 - //#define INPUT_CAPTURE_PIN 49 // receive - //#define OUTPUT_COMPARE_A_PIN 6 // transmit - //#define OUTPUT_COMPARE_B_PIN 7 // unusable PWM - //#define OUTPUT_COMPARE_C_PIN 8 // unusable PWM +//#define ALTSS_USE_TIMER4 +//#define INPUT_CAPTURE_PIN 49 // receive +//#define OUTPUT_COMPARE_A_PIN 6 // transmit +//#define OUTPUT_COMPARE_B_PIN 7 // unusable PWM +//#define OUTPUT_COMPARE_C_PIN 8 // unusable PWM - #define ALTSS_USE_TIMER5 - #define INPUT_CAPTURE_PIN 48 // receive - #define OUTPUT_COMPARE_A_PIN 46 // transmit - #define OUTPUT_COMPARE_B_PIN 45 // unusable PWM - #define OUTPUT_COMPARE_C_PIN 44 // unusable PWM +#define ALTSS_USE_TIMER5 +#define INPUT_CAPTURE_PIN 48 // receive +#define OUTPUT_COMPARE_A_PIN 46 // transmit +#define OUTPUT_COMPARE_B_PIN 45 // unusable PWM +#define OUTPUT_COMPARE_C_PIN 44 // unusable PWM // Sanguino #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) - #define ALTSS_USE_TIMER1 - #define INPUT_CAPTURE_PIN 14 // receive - #define OUTPUT_COMPARE_A_PIN 13 // transmit - #define OUTPUT_COMPARE_B_PIN 12 // unusable PWM +#define ALTSS_USE_TIMER1 +#define INPUT_CAPTURE_PIN 14 // receive +#define OUTPUT_COMPARE_A_PIN 13 // transmit +#define OUTPUT_COMPARE_B_PIN 12 // unusable PWM // Unknown board diff --git a/drivers/AltSoftSerial/config/AltSoftSerial_Timers.h b/drivers/AltSoftSerial/config/AltSoftSerial_Timers.h index 4270cd8..3f8c96f 100644 --- a/drivers/AltSoftSerial/config/AltSoftSerial_Timers.h +++ b/drivers/AltSoftSerial/config/AltSoftSerial_Timers.h @@ -1,17 +1,17 @@ /* An Alternative Software Serial Library * http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html * Copyright (c) 2014 PJRC.COM, LLC, Paul Stoffregen, paul@pjrc.com - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -22,153 +22,153 @@ */ #if defined(ALTSS_USE_TIMER1) - #define CONFIG_TIMER_NOPRESCALE() (TIMSK1 = 0, TCCR1A = 0, TCCR1B = (1< 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(); - } +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) - { - MY_CRITICAL_SECTION - { - m_front = 0; - m_fill = 0; - } - } + /** + * Clear all entries in the circular buffer. + */ + void clear(void) + { + MY_CRITICAL_SECTION { + m_front = 0; + m_fill = 0; + } + } - /** - * Test if the circular buffer is empty. - * @return True, when empty. - */ - inline bool empty(void) const - { - bool empty; - MY_CRITICAL_SECTION - { - empty = !m_fill; - } - return empty; - } + /** + * Test if the circular buffer is empty. + * @return True, when empty. + */ + inline bool empty(void) const + { + bool empty; + MY_CRITICAL_SECTION { + empty = !m_fill; + } + return empty; + } - /** - * Test if the circular buffer is full. - * @return True, when full. - */ - inline bool full(void) const - { - bool full; - MY_CRITICAL_SECTION - { - full = m_fill == m_size; - } - return full; - } + /** + * Test if the circular buffer is full. + * @return True, when full. + */ + inline bool full(void) const + { + bool full; + MY_CRITICAL_SECTION { + full = m_fill == m_size; + } + return full; + } - /** - * Return the number of records stored in the buffer. - * @return number of records. - */ - inline uint8_t available(void) const - { - MY_CRITICAL_SECTION - { - return m_fill; - } - } - - /** - * Aquire unused 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 - { - MY_CRITICAL_SECTION - { - if (!full()) return get(m_front); - } - return static_cast(NULL); - } - - /** - * 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) - { - MY_CRITICAL_SECTION - { - if (!full()) - { - T* f = get(m_front); - if (f != record) - *f = *record; - m_front = (m_front+1) % m_size; - m_fill++; - return true; - } - } - return false; - } + /** + * Return the number of records stored in the buffer. + * @return number of records. + */ + inline uint8_t available(void) const + { + MY_CRITICAL_SECTION { + return m_fill; + } + } - /** - * 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 - { - MY_CRITICAL_SECTION - { - if (!empty()) return get(back()); - } - return static_cast(NULL); - } + /** + * Aquire unused 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 + { + MY_CRITICAL_SECTION { + if (!full()) + { + return get(m_front); + } + } + return static_cast(NULL); + } - /** - * Remove record from back of the buffer. - * @return True, when record was pop'ed successfully. - */ - bool popBack(void) - { - MY_CRITICAL_SECTION - { - if (!empty()) - { - m_fill--; - return true; - } - } - return false; - } - - protected: - /** - * Internal getter for records. - * @param idx Record index in buffer. - * @return Ptr to record. - */ - inline T * get(const uint8_t idx) const - { - return &(m_buff[idx]); - } + /** + * 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) + { + MY_CRITICAL_SECTION { + if (!full()) + { + T* f = get(m_front); + if (f != record) { + *f = *record; + } + m_front = (m_front+1) % m_size; + m_fill++; + return true; + } + } + return false; + } - /** - * Internal getter for index of last used record in buffer. - * @return Index of last record. - */ - inline uint8_t back(void) const - { - return (m_front - m_fill + m_size) % m_size; - } + /** + * 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 + { + MY_CRITICAL_SECTION { + if (!empty()) + { + return get(back()); + } + } + return static_cast(NULL); + } - 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. + /** + * Remove record from back of the buffer. + * @return True, when record was pop'ed successfully. + */ + bool popBack(void) + { + MY_CRITICAL_SECTION { + if (!empty()) + { + m_fill--; + return true; + } + } + return false; + } + +protected: + /** + * Internal getter for records. + * @param idx Record index in buffer. + * @return Ptr to record. + */ + inline T * get(const uint8_t idx) const + { + return &(m_buff[idx]); + } + + /** + * Internal getter for index of last used record in buffer. + * @return Index of last record. + */ + 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 diff --git a/drivers/Linux/Arduino.h b/drivers/Linux/Arduino.h index 71bca23..1446b98 100644 --- a/drivers/Linux/Arduino.h +++ b/drivers/Linux/Arduino.h @@ -14,8 +14,8 @@ #include "stdlib_noniso.h" #ifdef LINUX_ARCH_RASPBERRYPI - #include "rpi_util.h" - using namespace rpi_util; +#include "rpi_util.h" +using namespace rpi_util; #endif #undef PSTR @@ -57,7 +57,7 @@ #define random(...) GET_MACRO(_0, ##__VA_ARGS__, randMinMax, randMax, rand)(__VA_ARGS__) #ifndef delay - #define delay _delay_ms +#define delay _delay_ms #endif using std::string; diff --git a/drivers/Linux/Client.h b/drivers/Linux/Client.h index 4f38ac2..6550f3d 100644 --- a/drivers/Linux/Client.h +++ b/drivers/Linux/Client.h @@ -26,7 +26,8 @@ #include "IPAddress.h" #if !DOXYGEN -class Client : public Stream { +class Client : public Stream +{ public: virtual int connect(IPAddress ip, uint16_t port) = 0; @@ -43,7 +44,10 @@ public: virtual operator bool() = 0; protected: - uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; + uint8_t* rawIPAddress(IPAddress& addr) + { + return addr.raw_address(); + }; }; #endif diff --git a/drivers/Linux/EthernetClient.cpp b/drivers/Linux/EthernetClient.cpp index ea69014..1b2f093 100644 --- a/drivers/Linux/EthernetClient.cpp +++ b/drivers/Linux/EthernetClient.cpp @@ -32,13 +32,16 @@ #include "log.h" #include "EthernetClient.h" -EthernetClient::EthernetClient() : _sock(-1) { +EthernetClient::EthernetClient() : _sock(-1) +{ } -EthernetClient::EthernetClient(int sock) : _sock(sock) { +EthernetClient::EthernetClient(int sock) : _sock(sock) +{ } -int EthernetClient::connect(const char* host, uint16_t port) { +int EthernetClient::connect(const char* host, uint16_t port) +{ int sockfd; struct addrinfo hints, *servinfo, *p; int rv; @@ -51,14 +54,14 @@ int EthernetClient::connect(const char* host, uint16_t port) { sprintf(port_str, "%hu", port); if ((rv = getaddrinfo(host, port_str, &hints, &servinfo)) != 0) { - logError("getaddrinfo: %s\n", gai_strerror(rv)); + logError("getaddrinfo: %s\n", gai_strerror(rv)); return -1; } // loop through all the results and connect to the first we can for (p = servinfo; p != NULL; p = p->ai_next) { if ((sockfd = socket(p->ai_family, p->ai_socktype, - p->ai_protocol)) == -1) { + p->ai_protocol)) == -1) { logError("socket: %s\n", strerror(errno)); continue; } @@ -88,15 +91,18 @@ int EthernetClient::connect(const char* host, uint16_t port) { return 1; } -int EthernetClient::connect(IPAddress ip, uint16_t port) { +int EthernetClient::connect(IPAddress ip, uint16_t port) +{ return connect(ip.toString().c_str(), port); } -size_t EthernetClient::write(uint8_t b) { +size_t EthernetClient::write(uint8_t b) +{ return write(&b, 1); } -size_t EthernetClient::write(const uint8_t *buf, size_t size) { +size_t EthernetClient::write(const uint8_t *buf, size_t size) +{ int rc = 0; int bytes = 0; @@ -119,17 +125,20 @@ size_t EthernetClient::write(const uint8_t *buf, size_t size) { return bytes; } -size_t EthernetClient::write(const char *str) { +size_t EthernetClient::write(const char *str) +{ if (str == NULL) { return 0; } return write((const uint8_t *)str, strlen(str)); } -size_t EthernetClient::write(const char *buffer, size_t size) { +size_t EthernetClient::write(const char *buffer, size_t size) +{ return write((const uint8_t *)buffer, size); } -int EthernetClient::available() { +int EthernetClient::available() +{ int count = 0; if (_sock != -1) { @@ -139,10 +148,10 @@ int EthernetClient::available() { return 0; } -int EthernetClient::read() { +int EthernetClient::read() +{ uint8_t b; - if ( recv(_sock, &b, 1, 0) > 0 ) - { + if ( recv(_sock, &b, 1, 0) > 0 ) { // recv worked return b; } else { @@ -151,22 +160,26 @@ int EthernetClient::read() { } } -int EthernetClient::read(uint8_t *buf, size_t size) { +int EthernetClient::read(uint8_t *buf, size_t size) +{ return recv(_sock, buf, size, 0); } -int EthernetClient::peek() { +int EthernetClient::peek() +{ uint8_t b; return recv(_sock, &b, 1, MSG_PEEK | MSG_DONTWAIT); } -void EthernetClient::flush() { +void EthernetClient::flush() +{ // There isn't much we can do here return; } -void EthernetClient::stop() { +void EthernetClient::stop() +{ if (_sock == -1) { return; } @@ -186,7 +199,8 @@ void EthernetClient::stop() { } usleep(1000); 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 (s != ETHERNETCLIENT_W5100_CLOSED) { @@ -195,7 +209,8 @@ void EthernetClient::stop() { _sock = -1; } -uint8_t EthernetClient::status() { +uint8_t EthernetClient::status() +{ if (_sock == -1) { return ETHERNETCLIENT_W5100_CLOSED; } @@ -203,36 +218,38 @@ uint8_t EthernetClient::status() { struct tcp_info tcp_info; int tcp_info_length = sizeof(tcp_info); - if ( getsockopt( _sock, SOL_TCP, TCP_INFO, (void *)&tcp_info, (socklen_t *)&tcp_info_length ) == 0 ) { + if ( getsockopt( _sock, SOL_TCP, TCP_INFO, (void *)&tcp_info, + (socklen_t *)&tcp_info_length ) == 0 ) { switch (tcp_info.tcpi_state) { - case TCP_ESTABLISHED: - return ETHERNETCLIENT_W5100_ESTABLISHED; - case TCP_SYN_SENT: - return ETHERNETCLIENT_W5100_SYNSENT; - case TCP_SYN_RECV: - return ETHERNETCLIENT_W5100_SYNRECV; - case TCP_FIN_WAIT1: - case TCP_FIN_WAIT2: - return ETHERNETCLIENT_W5100_FIN_WAIT; - case TCP_TIME_WAIT: - return TCP_TIME_WAIT; - case TCP_CLOSE: - return ETHERNETCLIENT_W5100_CLOSED; - case TCP_CLOSE_WAIT: - return ETHERNETCLIENT_W5100_CLOSING; - case TCP_LAST_ACK: - return ETHERNETCLIENT_W5100_LAST_ACK; - case TCP_LISTEN: - return ETHERNETCLIENT_W5100_LISTEN; - case TCP_CLOSING: - return ETHERNETCLIENT_W5100_CLOSING; + case TCP_ESTABLISHED: + return ETHERNETCLIENT_W5100_ESTABLISHED; + case TCP_SYN_SENT: + return ETHERNETCLIENT_W5100_SYNSENT; + case TCP_SYN_RECV: + return ETHERNETCLIENT_W5100_SYNRECV; + case TCP_FIN_WAIT1: + case TCP_FIN_WAIT2: + return ETHERNETCLIENT_W5100_FIN_WAIT; + case TCP_TIME_WAIT: + return TCP_TIME_WAIT; + case TCP_CLOSE: + return ETHERNETCLIENT_W5100_CLOSED; + case TCP_CLOSE_WAIT: + return ETHERNETCLIENT_W5100_CLOSING; + case TCP_LAST_ACK: + return ETHERNETCLIENT_W5100_LAST_ACK; + case TCP_LISTEN: + return ETHERNETCLIENT_W5100_LISTEN; + case TCP_CLOSING: + return ETHERNETCLIENT_W5100_CLOSING; } } return ETHERNETCLIENT_W5100_CLOSED; } -uint8_t EthernetClient::connected() { +uint8_t EthernetClient::connected() +{ if (_sock == -1) { return 0; } @@ -246,17 +263,20 @@ uint8_t EthernetClient::connected() { return 1; } -int EthernetClient::getSocketNumber() { +int EthernetClient::getSocketNumber() +{ return _sock; } // the next function allows us to use the client returned by // EthernetServer::available() as the condition in an if-statement. -EthernetClient::operator bool() { +EthernetClient::operator bool() +{ return _sock != -1; } -bool EthernetClient::operator==(const EthernetClient& rhs) { +bool EthernetClient::operator==(const EthernetClient& rhs) +{ return _sock == rhs._sock && _sock != -1 && rhs._sock != -1; } diff --git a/drivers/Linux/EthernetClient.h b/drivers/Linux/EthernetClient.h index 2cbaca9..6297ec0 100644 --- a/drivers/Linux/EthernetClient.h +++ b/drivers/Linux/EthernetClient.h @@ -40,7 +40,8 @@ /** * EthernetClient class */ -class EthernetClient : public Client { +class EthernetClient : public Client +{ private: int _sock; //!< @brief Network socket. @@ -168,12 +169,18 @@ public: * @brief Overloaded cast operators. * */ - virtual bool operator==(const bool value) { return bool() == value; } + virtual bool operator==(const bool value) + { + return bool() == value; + } /** * @brief Overloaded cast operators. * */ - virtual bool operator!=(const bool value) { return bool() != value; } + virtual bool operator!=(const bool value) + { + return bool() != value; + } /** * @brief Overloaded cast operators. * @@ -183,7 +190,10 @@ public: * @brief Overloaded cast operators. * */ - virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); }; + virtual bool operator!=(const EthernetClient& rhs) + { + return !this->operator==(rhs); + }; friend class EthernetServer; }; diff --git a/drivers/Linux/EthernetServer.cpp b/drivers/Linux/EthernetServer.cpp index 311f315..e92f097 100644 --- a/drivers/Linux/EthernetServer.cpp +++ b/drivers/Linux/EthernetServer.cpp @@ -32,7 +32,8 @@ #include "EthernetClient.h" #include "EthernetServer.h" -EthernetServer::EthernetServer(uint16_t port, uint16_t max_clients) : port(port), max_clients(max_clients) +EthernetServer::EthernetServer(uint16_t port, uint16_t max_clients) : port(port), + max_clients(max_clients) { clients.reserve(max_clients); } diff --git a/drivers/Linux/EthernetServer.h b/drivers/Linux/EthernetServer.h index 4240e96..376f3d7 100644 --- a/drivers/Linux/EthernetServer.h +++ b/drivers/Linux/EthernetServer.h @@ -28,10 +28,10 @@ #include "IPAddress.h" #ifdef ETHERNETSERVER_MAX_CLIENTS - #define ETHERNETSERVER_BACKLOG ETHERNETSERVER_MAX_CLIENTS //!< Maximum length to which the queue of pending connections may grow. +#define ETHERNETSERVER_BACKLOG ETHERNETSERVER_MAX_CLIENTS //!< Maximum length to which the queue of pending connections may grow. #else - #define ETHERNETSERVER_MAX_CLIENTS 10 //!< Default value for max_clients. - #define ETHERNETSERVER_BACKLOG 10 //!< Maximum length to which the queue of pending connections may grow. +#define ETHERNETSERVER_MAX_CLIENTS 10 //!< Default value for max_clients. +#define ETHERNETSERVER_BACKLOG 10 //!< Maximum length to which the queue of pending connections may grow. #endif class EthernetClient; @@ -39,7 +39,8 @@ class EthernetClient; /** * @brief EthernetServer class */ -class EthernetServer : public Server { +class EthernetServer : public Server +{ private: uint16_t port; //!< @brief Port number for the network socket. diff --git a/drivers/Linux/IPAddress.cpp b/drivers/Linux/IPAddress.cpp index dd67b59..963f7e2 100644 --- a/drivers/Linux/IPAddress.cpp +++ b/drivers/Linux/IPAddress.cpp @@ -24,53 +24,53 @@ #include #include "IPAddress.h" -IPAddress::IPAddress() { +IPAddress::IPAddress() +{ _address.dword = 0; } -IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) { +IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, + uint8_t fourth_octet) +{ _address.bytes[0] = first_octet; _address.bytes[1] = second_octet; _address.bytes[2] = third_octet; _address.bytes[3] = fourth_octet; } -IPAddress::IPAddress(uint32_t address) { +IPAddress::IPAddress(uint32_t address) +{ _address.dword = address; } -IPAddress::IPAddress(const uint8_t *address) { +IPAddress::IPAddress(const uint8_t *address) +{ memcpy(_address.bytes, address, sizeof(_address.bytes)); } -bool IPAddress::fromString(const char *address) { +bool IPAddress::fromString(const char *address) +{ // TODO: add support for "a", "a.b", "a.b.c" formats uint16_t acc = 0; // Accumulator uint8_t dots = 0; - while (*address) - { + while (*address) { char c = *address++; - if (c >= '0' && c <= '9') - { + if (c >= '0' && c <= '9') { acc = acc * 10 + (c - '0'); if (acc > 255) { // Value out of [0..255] range return false; } - } - else if (c == '.') - { + } else if (c == '.') { if (dots == 3) { // Too much dots (there must be 3 dots) return false; } _address.bytes[dots++] = acc; acc = 0; - } - else - { + } else { // Invalid char return false; } @@ -84,23 +84,27 @@ bool IPAddress::fromString(const char *address) { return true; } -IPAddress& IPAddress::operator=(const uint8_t *address) { +IPAddress& IPAddress::operator=(const uint8_t *address) +{ memcpy(_address.bytes, address, sizeof(_address.bytes)); return *this; } -IPAddress& IPAddress::operator=(uint32_t address) { +IPAddress& IPAddress::operator=(uint32_t address) +{ _address.dword = address; return *this; } -bool IPAddress::operator==(const uint8_t* addr) const { +bool IPAddress::operator==(const uint8_t* addr) const +{ return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0; } std::string IPAddress::toString() { char szRet[16]; - sprintf(szRet,"%u.%u.%u.%u", _address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3]); + sprintf(szRet,"%u.%u.%u.%u", _address.bytes[0], _address.bytes[1], _address.bytes[2], + _address.bytes[3]); return std::string(szRet); } diff --git a/drivers/Linux/IPAddress.h b/drivers/Linux/IPAddress.h index c8e336c..68b9fb2 100644 --- a/drivers/Linux/IPAddress.h +++ b/drivers/Linux/IPAddress.h @@ -29,127 +29,137 @@ /** * @brief A class to make it easier to handle and pass around IP addresses */ -class IPAddress { - private: - union { - uint8_t bytes[4]; //!< IPv4 address as an array - uint32_t dword; //!< IPv4 address in 32 bits format - } _address; +class IPAddress +{ +private: + union { + uint8_t bytes[4]; //!< IPv4 address as an array + uint32_t dword; //!< IPv4 address in 32 bits format + } _address; - /** - * @brief Access the raw byte array containing the address. - * - * Because this returns a pointer to the internal structure rather than a copy of the address - * this function should only be used when you know that the usage of the returned uint8_t* will - * be transient and not stored. - * - * @return pointer to the internal structure. - */ - uint8_t* raw_address() { - return _address.bytes; - } + /** + * @brief Access the raw byte array containing the address. + * + * Because this returns a pointer to the internal structure rather than a copy of the address + * this function should only be used when you know that the usage of the returned uint8_t* will + * be transient and not stored. + * + * @return pointer to the internal structure. + */ + uint8_t* raw_address() + { + return _address.bytes; + } - public: - /** - * @brief IPAddress constructor. - */ - IPAddress(); - /** - * @brief IPAddress constructor. - * - * @param first_octet first octet of the IPv4 address. - * @param second_octet second octet of the IPv4 address. - * @param third_octet third octet of the IPv4 address. - * @param fourth_octet fourth octet of the IPv4 address. - */ - IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); - /** - * @brief IPAddress constructor. - * - * @param address to be set from a 32 bits integer. - */ - IPAddress(uint32_t address); - /** - * @brief IPAddress constructor. - * - * @param address to be set from a byte array. - */ - IPAddress(const uint8_t *address); - /** - * @brief Set the IP from a array of characters. - * - * @param address to be set. - */ - bool fromString(const char *address); - /** - * @brief Set the IP from a string class type. - * - * @param address to be set. - */ - bool fromString(const std::string &address) { return fromString(address.c_str()); } - /** - * @brief Overloaded cast operator - * - * Allow IPAddress objects to be used where a pointer to a four-byte uint8_t array is expected - */ - operator uint32_t() const { - return _address.dword; - } - /** - * @brief Overloaded cast operator - * - */ - bool operator==(const IPAddress& addr) const { - return _address.dword == addr._address.dword; - } - /** - * @brief Overloaded cast operator - * - */ - bool operator==(uint32_t addr) const { - return _address.dword == addr; - } - /** - * @brief Overloaded cast operator - * - */ - bool operator==(const uint8_t* addr) const; - /** - * @brief Overloaded index operator. - * - * Allow getting and setting individual octets of the address. - * - */ - uint8_t operator[](int index) const { - return _address.bytes[index]; - } - /** - * @brief Overloaded index operator - * - */ - uint8_t& operator[](int index) { - return _address.bytes[index]; - } - /** - * @brief Overloaded copy operators. - * - * Allow initialisation of IPAddress objects from byte array. - */ - IPAddress& operator=(const uint8_t *address); - /** - * @brief Overloaded copy operator. - * - * Allow initialisation of IPAddress objects from a 32 bits integer. - */ - IPAddress& operator=(uint32_t address); - /** - * @brief Convert the IP address to a string. - * - * @return A stringified IP address - */ - std::string toString(); +public: + /** + * @brief IPAddress constructor. + */ + IPAddress(); + /** + * @brief IPAddress constructor. + * + * @param first_octet first octet of the IPv4 address. + * @param second_octet second octet of the IPv4 address. + * @param third_octet third octet of the IPv4 address. + * @param fourth_octet fourth octet of the IPv4 address. + */ + IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); + /** + * @brief IPAddress constructor. + * + * @param address to be set from a 32 bits integer. + */ + IPAddress(uint32_t address); + /** + * @brief IPAddress constructor. + * + * @param address to be set from a byte array. + */ + IPAddress(const uint8_t *address); + /** + * @brief Set the IP from a array of characters. + * + * @param address to be set. + */ + bool fromString(const char *address); + /** + * @brief Set the IP from a string class type. + * + * @param address to be set. + */ + bool fromString(const std::string &address) + { + return fromString(address.c_str()); + } + /** + * @brief Overloaded cast operator + * + * Allow IPAddress objects to be used where a pointer to a four-byte uint8_t array is expected + */ + operator uint32_t() const + { + return _address.dword; + } + /** + * @brief Overloaded cast operator + * + */ + bool operator==(const IPAddress& addr) const + { + return _address.dword == addr._address.dword; + } + /** + * @brief Overloaded cast operator + * + */ + bool operator==(uint32_t addr) const + { + return _address.dword == addr; + } + /** + * @brief Overloaded cast operator + * + */ + bool operator==(const uint8_t* addr) const; + /** + * @brief Overloaded index operator. + * + * Allow getting and setting individual octets of the address. + * + */ + uint8_t operator[](int index) const + { + return _address.bytes[index]; + } + /** + * @brief Overloaded index operator + * + */ + uint8_t& operator[](int index) + { + return _address.bytes[index]; + } + /** + * @brief Overloaded copy operators. + * + * Allow initialisation of IPAddress objects from byte array. + */ + IPAddress& operator=(const uint8_t *address); + /** + * @brief Overloaded copy operator. + * + * Allow initialisation of IPAddress objects from a 32 bits integer. + */ + IPAddress& operator=(uint32_t address); + /** + * @brief Convert the IP address to a string. + * + * @return A stringified IP address + */ + std::string toString(); - friend class Client; + friend class Client; }; #endif diff --git a/drivers/Linux/Print.cpp b/drivers/Linux/Print.cpp index 4c8d670..86c0e20 100644 --- a/drivers/Linux/Print.cpp +++ b/drivers/Linux/Print.cpp @@ -30,7 +30,8 @@ // Public Methods ////////////////////////////////////////////////////////////// -size_t Print::write(const uint8_t *buffer, size_t size) { +size_t Print::write(const uint8_t *buffer, size_t size) +{ size_t n = 0; while(size--) { n += write(*buffer++); @@ -42,7 +43,8 @@ size_t #ifdef __GNUC__ __attribute__((format(printf, 2, 3))) #endif -Print::printf(const char *format, ...) { +Print::printf(const char *format, ...) +{ va_list arg; va_start(arg, format); char temp[64]; @@ -65,31 +67,38 @@ Print::printf(const char *format, ...) { return len; } -size_t Print::print(const std::string &s) { +size_t Print::print(const std::string &s) +{ return write(s.c_str(), s.length()); } -size_t Print::print(const char str[]) { +size_t Print::print(const char str[]) +{ return write(str); } -size_t Print::print(char c) { +size_t Print::print(char c) +{ return write(c); } -size_t Print::print(unsigned char b, int base) { +size_t Print::print(unsigned char b, int base) +{ return print((unsigned long) b, base); } -size_t Print::print(int n, int base) { +size_t Print::print(int n, int base) +{ return print((long) n, base); } -size_t Print::print(unsigned int n, int base) { +size_t Print::print(unsigned int n, int base) +{ return print((unsigned long) n, base); } -size_t Print::print(long n, int base) { +size_t Print::print(long n, int base) +{ if(base == 0) { return write(n); } else if(base == 10) { @@ -104,72 +113,83 @@ size_t Print::print(long n, int base) { } } -size_t Print::print(unsigned long n, int base) { +size_t Print::print(unsigned long n, int base) +{ if(base == 0) { return write(n); - } - else { + } else { return printNumber(n, base); } } -size_t Print::print(double n, int digits) { +size_t Print::print(double n, int digits) +{ return printFloat(n, digits); } -size_t Print::println(void) { +size_t Print::println(void) +{ return print("\r\n"); } -size_t Print::println(const std::string &s) { +size_t Print::println(const std::string &s) +{ size_t n = print(s); n += println(); return n; } -size_t Print::println(const char c[]) { +size_t Print::println(const char c[]) +{ size_t n = print(c); n += println(); return n; } -size_t Print::println(char c) { +size_t Print::println(char c) +{ size_t n = print(c); n += println(); return n; } -size_t Print::println(unsigned char b, int base) { +size_t Print::println(unsigned char b, int base) +{ size_t n = print(b, base); n += println(); return n; } -size_t Print::println(int num, int base) { +size_t Print::println(int num, int base) +{ size_t n = print(num, base); n += println(); return n; } -size_t Print::println(unsigned int num, int base) { +size_t Print::println(unsigned int num, int base) +{ size_t n = print(num, base); n += println(); return n; } -size_t Print::println(long num, int base) { +size_t Print::println(long num, int base) +{ size_t n = print(num, base); n += println(); return n; } -size_t Print::println(unsigned long num, int base) { +size_t Print::println(unsigned long num, int base) +{ size_t n = print(num, base); n += println(); return n; } -size_t Print::println(double num, int digits) { +size_t Print::println(double num, int digits) +{ size_t n = print(num, digits); n += println(); return n; @@ -177,7 +197,8 @@ size_t Print::println(double num, int digits) { // Private Methods ///////////////////////////////////////////////////////////// -size_t Print::printNumber(unsigned long n, uint8_t base) { +size_t Print::printNumber(unsigned long n, uint8_t base) +{ char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. char *str = &buf[sizeof(buf) - 1]; @@ -198,7 +219,8 @@ size_t Print::printNumber(unsigned long n, uint8_t base) { return write(str); } -size_t Print::printFloat(double number, uint8_t digits) { +size_t Print::printFloat(double number, uint8_t digits) +{ size_t n = 0; if(std::isnan(number)) { diff --git a/drivers/Linux/Print.h b/drivers/Linux/Print.h index e59900e..ff8f695 100644 --- a/drivers/Linux/Print.h +++ b/drivers/Linux/Print.h @@ -32,54 +32,67 @@ #define OCT 8 #define BIN 2 -class Print { - private: - int write_error; - size_t printNumber(unsigned long n, uint8_t base); - size_t printFloat(double number, uint8_t digits); +class Print +{ +private: + int write_error; + size_t printNumber(unsigned long n, uint8_t base); + size_t printFloat(double number, uint8_t digits); - protected: - void setWriteError(int err = 1) { write_error = err; } +protected: + void setWriteError(int err = 1) + { + write_error = err; + } - public: - Print() : write_error(0) {} +public: + Print() : write_error(0) {} - int getWriteError() { return write_error; } - void clearWriteError() { setWriteError(0); } + int getWriteError() + { + return write_error; + } + void clearWriteError() + { + setWriteError(0); + } - virtual size_t write(uint8_t) = 0; - size_t write(const char *str) { - if (str == NULL) - return 0; - return write((const uint8_t *) str, strlen(str)); - } - virtual size_t write(const uint8_t *buffer, size_t size); - size_t write(const char *buffer, size_t size) { - return write((const uint8_t *) buffer, size); + virtual size_t write(uint8_t) = 0; + size_t write(const char *str) + { + if (str == NULL) { + return 0; } + return write((const uint8_t *) str, strlen(str)); + } + virtual size_t write(const uint8_t *buffer, size_t size); + size_t write(const char *buffer, size_t size) + { + return write((const uint8_t *) buffer, size); + } - size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3))); - size_t print(const std::string &); - size_t print(const char[]); - size_t print(char); - size_t print(unsigned char, int = DEC); - size_t print(int, int = DEC); - size_t print(unsigned int, int = DEC); - size_t print(long, int = DEC); - size_t print(unsigned long, int = DEC); - size_t print(double, int = 2); + size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3))); + size_t print(const std::string &); + size_t print(const char[]); + size_t print(char); + size_t print(unsigned char, int = DEC); + size_t print(int, int = DEC); + size_t print(unsigned int, int = DEC); + size_t print(long, int = DEC); + size_t print(unsigned long, int = DEC); + size_t print(double, int = 2); - size_t println(const std::string &s); - size_t println(const char[]); - size_t println(char); - size_t println(unsigned char, int = DEC); - size_t println(int, int = DEC); - size_t println(unsigned int, int = DEC); - size_t println(long, int = DEC); - size_t println(unsigned long, int = DEC); - size_t println(double, int = 2); - size_t println(void); - }; + size_t println(const std::string &s); + size_t println(const char[]); + size_t println(char); + size_t println(unsigned char, int = DEC); + size_t println(int, int = DEC); + size_t println(unsigned int, int = DEC); + size_t println(long, int = DEC); + size_t println(unsigned long, int = DEC); + size_t println(double, int = 2); + size_t println(void); +}; #endif #endif diff --git a/drivers/Linux/SerialPort.cpp b/drivers/Linux/SerialPort.cpp index 0c9f1bb..5adca05 100644 --- a/drivers/Linux/SerialPort.cpp +++ b/drivers/Linux/SerialPort.cpp @@ -69,7 +69,8 @@ bool SerialPort::open(int bauds) /* create a symlink with predictable name to the PTY device */ unlink(serialPort.c_str()); // remove the symlink if it already exists if (symlink(ptsname(sd), serialPort.c_str()) != 0) { - logError("Couldn't create a symlink '%s' to PTY! (%d) %s\n", serialPort.c_str(), errno, strerror(errno)); + logError("Couldn't create a symlink '%s' to PTY! (%d) %s\n", serialPort.c_str(), errno, + strerror(errno)); return false; } } else { @@ -83,23 +84,57 @@ bool SerialPort::open(int bauds) } switch (bauds) { - case 50: speed = B50 ; break ; - case 75: speed = B75 ; break ; - case 110: speed = B110 ; break ; - case 134: speed = B134 ; break ; - case 150: speed = B150 ; break ; - case 200: speed = B200 ; break ; - case 300: speed = B300 ; break ; - case 600: speed = B600 ; break ; - case 1200: speed = B1200 ; break ; - case 1800: speed = B1800 ; break ; - case 2400: speed = B2400 ; break ; - case 9600: speed = B9600 ; break ; - case 19200: speed = B19200 ; break ; - case 38400: speed = B38400 ; break ; - case 57600: speed = B57600 ; break ; - case 115200: speed = B115200 ; break ; - default: speed = B115200 ; break ; + case 50: + speed = B50 ; + break ; + case 75: + speed = B75 ; + break ; + case 110: + speed = B110 ; + break ; + case 134: + speed = B134 ; + break ; + case 150: + speed = B150 ; + break ; + case 200: + speed = B200 ; + break ; + case 300: + speed = B300 ; + break ; + case 600: + speed = B600 ; + break ; + case 1200: + speed = B1200 ; + break ; + case 1800: + speed = B1800 ; + break ; + case 2400: + speed = B2400 ; + break ; + case 9600: + speed = B9600 ; + break ; + case 19200: + speed = B19200 ; + break ; + case 38400: + speed = B38400 ; + break ; + case 57600: + speed = B57600 ; + break ; + case 115200: + speed = B115200 ; + break ; + default: + speed = B115200 ; + break ; } // Get the current options of the port diff --git a/drivers/Linux/SerialPort.h b/drivers/Linux/SerialPort.h index e0f77bb..4279b3c 100644 --- a/drivers/Linux/SerialPort.h +++ b/drivers/Linux/SerialPort.h @@ -28,7 +28,8 @@ * SerialPort Class * Class that provides the functionality of arduino Serial library */ -class SerialPort : public Stream { +class SerialPort : public Stream +{ private: int sd; //!< @brief file descriptor number. diff --git a/drivers/Linux/Server.h b/drivers/Linux/Server.h index c637f7a..61b14a0 100644 --- a/drivers/Linux/Server.h +++ b/drivers/Linux/Server.h @@ -23,9 +23,10 @@ #include "Print.h" #if !DOXYGEN -class Server : public Print { - public: - virtual void begin() =0; +class Server : public Print +{ +public: + virtual void begin() =0; }; #endif diff --git a/drivers/Linux/SoftEeprom.cpp b/drivers/Linux/SoftEeprom.cpp index bc1b497..46e4b81 100644 --- a/drivers/Linux/SoftEeprom.cpp +++ b/drivers/Linux/SoftEeprom.cpp @@ -52,7 +52,8 @@ SoftEeprom::SoftEeprom(const char *fileName, size_t length) myFile.write((const char*)_values, _length); myFile.close(); } else if (fileInfo.st_size < 0 || (size_t)fileInfo.st_size != _length) { - logError("Config file %s is not the correct size of %zu. Please remove the file and a new one will be created.\n", _fileName, _length); + logError("Config file %s is not the correct size of %zu. Please remove the file and a new one will be created.\n", + _fileName, _length); exit(1); } else { //Read config into local memory. @@ -98,10 +99,10 @@ void SoftEeprom::readBlock(void* buf, void* addr, size_t length) void SoftEeprom::writeBlock(void* buf, void* addr, size_t length) { unsigned long int offs = reinterpret_cast(addr); - + if (length && offs + length <= _length) { memcpy(_values+offs, buf, length); - + std::ofstream myFile(_fileName, std::ios::out | std::ios::in | std::ios::binary); if (!myFile) { logError("Unable to write config to file %s.\n", _fileName); diff --git a/drivers/Linux/SoftEeprom.h b/drivers/Linux/SoftEeprom.h index e623773..70ad72c 100644 --- a/drivers/Linux/SoftEeprom.h +++ b/drivers/Linux/SoftEeprom.h @@ -30,7 +30,8 @@ /** * SoftEeprom class */ -class SoftEeprom { +class SoftEeprom +{ private: size_t _length; //!< @brief Eeprom max size. diff --git a/drivers/Linux/Stream.cpp b/drivers/Linux/Stream.cpp index 62f9f61..b07826e 100644 --- a/drivers/Linux/Stream.cpp +++ b/drivers/Linux/Stream.cpp @@ -28,50 +28,53 @@ #define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field // private method to read stream with timeout -int Stream::timedRead() { - int c; - _startMillis = millis(); - do { - c = read(); - if(c >= 0) { - return c; - } - yield(); - } while(millis() - _startMillis < _timeout); - return -1; // -1 indicates timeout +int Stream::timedRead() +{ + int c; + _startMillis = millis(); + do { + c = read(); + if(c >= 0) { + return c; + } + yield(); + } while(millis() - _startMillis < _timeout); + return -1; // -1 indicates timeout } // private method to peek stream with timeout -int Stream::timedPeek() { - int c; - _startMillis = millis(); - do { - c = peek(); - if(c >= 0) { - return c; - } - yield(); - } while(millis() - _startMillis < _timeout); - return -1; // -1 indicates timeout +int Stream::timedPeek() +{ + int c; + _startMillis = millis(); + do { + c = peek(); + if(c >= 0) { + return c; + } + yield(); + } while(millis() - _startMillis < _timeout); + return -1; // -1 indicates timeout } // returns peek of the next digit in the stream or -1 if timeout // discards non-numeric characters -int Stream::peekNextDigit() { - int c; - while(1) { - c = timedPeek(); - if(c < 0) { - return c; // timeout - } - if(c == '-') { - return c; - } - if(c >= '0' && c <= '9') { - return c; - } - read(); // discard non-numeric - } +int Stream::peekNextDigit() +{ + int c; + while(1) { + c = timedPeek(); + if(c < 0) { + return c; // timeout + } + if(c == '-') { + return c; + } + if(c >= '0' && c <= '9') { + return c; + } + read(); // discard non-numeric + } } // Public Methods @@ -79,148 +82,151 @@ int Stream::peekNextDigit() { void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait { - _timeout = timeout; + _timeout = timeout; } // find returns true if the target string is found -bool Stream::find(const char *target) { - return findUntil(target, (char*) ""); +bool Stream::find(const char *target) +{ + return findUntil(target, (char*) ""); } // reads data from the stream until the target string of given length is found // returns true if target string is found, false if timed out -bool Stream::find(const char *target, size_t length) { - return findUntil(target, length, NULL, 0); +bool Stream::find(const char *target, size_t length) +{ + return findUntil(target, length, NULL, 0); } // as find but search ends if the terminator string is found -bool Stream::findUntil(const char *target, const char *terminator) { - return findUntil(target, strlen(target), terminator, strlen(terminator)); +bool Stream::findUntil(const char *target, const char *terminator) +{ + return findUntil(target, strlen(target), terminator, strlen(terminator)); } // reads data from the stream until the target string of the given length is found // search terminated if the terminator string is found // returns true if target string is found, false if terminated or timed out -bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen) { - size_t index = 0; // maximum target string length is 64k bytes! - size_t termIndex = 0; - int c; +bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, + size_t termLen) +{ + size_t index = 0; // maximum target string length is 64k bytes! + size_t termIndex = 0; + int c; - if(*target == 0) { - return true; // return true if target is a null string - } - while((c = timedRead()) > 0) { + if(*target == 0) { + return true; // return true if target is a null string + } + while((c = timedRead()) > 0) { - if(c != target[index]) { - index = 0; // reset index if any char does not match - } - if(c == target[index]) { - //////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 - return true; - } - } + if(c != target[index]) { + index = 0; // reset index if any char does not match + } + if(c == target[index]) { + //////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 + return true; + } + } - if(termLen > 0 && c == terminator[termIndex]) { - if(++termIndex >= termLen) { - return false; // return false if terminate string found before target string - } - } else { - termIndex = 0; - } - } - return false; + if(termLen > 0 && c == terminator[termIndex]) { + if(++termIndex >= termLen) { + return false; // return false if terminate string found before target string + } + } else { + termIndex = 0; + } + } + return false; } // returns the first valid (long) integer value from the current position. // initial characters that are not digits (or the minus sign) are skipped // function is terminated by the first character that is not a digit. -long Stream::parseInt() { - return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout) +long Stream::parseInt() +{ + return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout) } // as above but a given skipChar is ignored // this allows format characters (typically commas) in values to be ignored -long Stream::parseInt(char skipChar) { - boolean isNegative = false; - long value = 0; - int c; +long Stream::parseInt(char skipChar) +{ + boolean isNegative = false; + long value = 0; + int c; - c = peekNextDigit(); - // ignore non numeric leading characters - if(c < 0) { - return 0; // zero returned if timeout - } + c = peekNextDigit(); + // ignore non numeric leading characters + if(c < 0) { + return 0; // zero returned if timeout + } - do { - if(c == skipChar) { - // ignore this charactor - } - else if(c == '-') { - isNegative = true; - } - else if(c >= '0' && c <= '9') { // is c a digit? - value = value * 10 + c - '0'; - } - read(); // consume the character we got with peek - c = timedPeek(); - } while((c >= '0' && c <= '9') || c == skipChar); + do { + if(c == skipChar) { + // ignore this charactor + } else if(c == '-') { + isNegative = true; + } else if(c >= '0' && c <= '9') { // is c a digit? + value = value * 10 + c - '0'; + } + read(); // consume the character we got with peek + c = timedPeek(); + } while((c >= '0' && c <= '9') || c == skipChar); - if(isNegative) { - value = -value; - } - return value; + if(isNegative) { + value = -value; + } + return value; } // as parseInt but returns a floating point value -float Stream::parseFloat() { - return parseFloat(NO_SKIP_CHAR); +float Stream::parseFloat() +{ + return parseFloat(NO_SKIP_CHAR); } // as above but the given skipChar is ignored // this allows format characters (typically commas) in values to be ignored -float Stream::parseFloat(char skipChar) { - boolean isNegative = false; - boolean isFraction = false; - long value = 0; - int c; - float fraction = 1.0; +float Stream::parseFloat(char skipChar) +{ + boolean isNegative = false; + boolean isFraction = false; + long value = 0; + int c; + float fraction = 1.0; - c = peekNextDigit(); - // ignore non numeric leading characters - if(c < 0) { - return 0; // zero returned if timeout - } + c = peekNextDigit(); + // ignore non numeric leading characters + if(c < 0) { + return 0; // zero returned if timeout + } - do { - if(c == skipChar) { - // ignore - } - else if(c == '-') { - isNegative = true; - } - else if(c == '.') { - isFraction = true; - } - else if(c >= '0' && c <= '9') { // is c a digit? - value = value * 10 + c - '0'; - if(isFraction) { - fraction *= 0.1; - } - } - read(); // consume the character we got with peek - c = timedPeek(); - } while((c >= '0' && c <= '9') || c == '.' || c == skipChar); + do { + if(c == skipChar) { + // ignore + } else if(c == '-') { + isNegative = true; + } else if(c == '.') { + isFraction = true; + } else if(c >= '0' && c <= '9') { // is c a digit? + value = value * 10 + c - '0'; + if(isFraction) { + fraction *= 0.1; + } + } + read(); // consume the character we got with peek + c = timedPeek(); + } while((c >= '0' && c <= '9') || c == '.' || c == skipChar); - if(isNegative) { - value = -value; - } - if(isFraction) { - return value * fraction; - } - else { - return value; - } + if(isNegative) { + value = -value; + } + if(isFraction) { + return value * fraction; + } else { + return value; + } } // read characters from stream into buffer @@ -228,55 +234,59 @@ float Stream::parseFloat(char skipChar) { // returns the number of characters placed in the buffer // the buffer is NOT null terminated. // -size_t Stream::readBytes(char *buffer, size_t length) { - size_t count = 0; - while(count < length) { - int c = timedRead(); - if(c < 0) { - break; - } - *buffer++ = (char) c; - count++; - } - return count; +size_t Stream::readBytes(char *buffer, size_t length) +{ + size_t count = 0; + while(count < length) { + int c = timedRead(); + if(c < 0) { + break; + } + *buffer++ = (char) c; + count++; + } + return count; } // as readBytes with terminator character // terminates if length characters have been read, timeout, or if the terminator character detected // returns the number of characters placed in the buffer (0 means no valid data found) -size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) { - if(length < 1) { - return 0; - } - size_t index = 0; - while(index < length) { - int c = timedRead(); - if(c < 0 || c == terminator) { - break; - } - *buffer++ = (char) c; - index++; - } - return index; // return number of characters, not including null terminator +size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) +{ + if(length < 1) { + return 0; + } + size_t index = 0; + while(index < length) { + int c = timedRead(); + if(c < 0 || c == terminator) { + break; + } + *buffer++ = (char) c; + index++; + } + return index; // return number of characters, not including null terminator } -std::string Stream::readString() { - std::string ret; - int c = timedRead(); - while(c >= 0) { - ret += (char) c; - c = timedRead(); - } - return ret; +std::string Stream::readString() +{ + std::string ret; + int c = timedRead(); + while(c >= 0) { + ret += (char) c; + c = timedRead(); + } + return ret; } -std::string Stream::readStringUntil(char terminator) { - std::string ret; - int c = timedRead(); - while(c >= 0 && c != terminator) { - ret += (char) c; - c = timedRead(); - } - return ret; +std::string Stream::readStringUntil(char terminator) +{ + std::string ret; + int c = timedRead(); + while(c >= 0 && c != terminator) { + ret += (char) c; + c = timedRead(); + } + return ret; } diff --git a/drivers/Linux/Stream.h b/drivers/Linux/Stream.h index dff2074..8bacd50 100644 --- a/drivers/Linux/Stream.h +++ b/drivers/Linux/Stream.h @@ -38,82 +38,99 @@ */ #if !DOXYGEN -class Stream: public Print { - protected: - unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read - unsigned long _startMillis; // used for timeout measurement - int timedRead(); // private method to read stream with timeout - int timedPeek(); // private method to peek stream with timeout - int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout +class Stream: public Print +{ +protected: + unsigned long + _timeout; // number of milliseconds to wait for the next char before aborting timed read + unsigned long _startMillis; // used for timeout measurement + int timedRead(); // private method to read stream with timeout + int timedPeek(); // private method to peek stream with timeout + int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout - public: - virtual int available() = 0; - virtual int read() = 0; - virtual int peek() = 0; - virtual void flush() = 0; +public: + virtual int available() = 0; + virtual int read() = 0; + virtual int peek() = 0; + virtual void flush() = 0; - Stream() { - _timeout = 1000; - } + Stream() + { + _timeout = 1000; + } -// parsing methods + // parsing methods - void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second + void setTimeout(unsigned long + timeout); // sets maximum milliseconds to wait for stream data, default is 1 second - bool find(const char *target); // reads data from the stream until the target string is found - bool find(uint8_t *target) { - return find((char *) target); - } - // returns true if target string is found, false if timed out (see setTimeout) + bool find(const char *target); // reads data from the stream until the target string is found + bool find(uint8_t *target) + { + return find((char *) target); + } + // returns true if target string is found, false if timed out (see setTimeout) - bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found - bool find(const uint8_t *target, size_t length) { - return find((char *) target, length); - } - // returns true if target string is found, false if timed out + bool find(const char *target, size_t + length); // reads data from the stream until the target string of given length is found + bool find(const uint8_t *target, size_t length) + { + return find((char *) target, length); + } + // returns true if target string is found, false if timed out - bool find(char target) { return find (&target, 1); } + bool find(char target) + { + return find (&target, 1); + } - bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found - bool findUntil(const uint8_t *target, const char *terminator) { - return findUntil((char *) target, terminator); - } + bool findUntil(const char *target, + const char *terminator); // as find but search ends if the terminator string is found + bool findUntil(const uint8_t *target, const char *terminator) + { + return findUntil((char *) target, terminator); + } - bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found - bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) { - return findUntil((char *) target, targetLen, terminate, termLen); - } + bool findUntil(const char *target, size_t targetLen, const char *terminate, + size_t termLen); // as above but search ends if the terminate string is found + bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) + { + return findUntil((char *) target, targetLen, terminate, termLen); + } - long parseInt(); // returns the first valid (long) integer value from the current position. - // initial characters that are not digits (or the minus sign) are skipped - // integer is terminated by the first character that is not a digit. + long parseInt(); // returns the first valid (long) integer value from the current position. + // initial characters that are not digits (or the minus sign) are skipped + // integer is terminated by the first character that is not a digit. - float parseFloat(); // float version of parseInt + float parseFloat(); // float version of parseInt - virtual size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer - virtual size_t readBytes(uint8_t *buffer, size_t length) { - return readBytes((char *) buffer, length); - } - // terminates if length characters have been read or timeout (see setTimeout) - // returns the number of characters placed in the buffer (0 means no valid data found) + virtual size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer + virtual size_t readBytes(uint8_t *buffer, size_t length) + { + return readBytes((char *) buffer, length); + } + // terminates if length characters have been read or timeout (see setTimeout) + // returns the number of characters placed in the buffer (0 means no valid data found) - size_t readBytesUntil(char terminator, char *buffer, size_t length); // as readBytes with terminator character - size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) { - return readBytesUntil(terminator, (char *) buffer, length); - } - // terminates if length characters have been read, timeout, or if the terminator character detected - // returns the number of characters placed in the buffer (0 means no valid data found) + size_t readBytesUntil(char terminator, char *buffer, + size_t length); // as readBytes with terminator character + size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) + { + return readBytesUntil(terminator, (char *) buffer, length); + } + // terminates if length characters have been read, timeout, or if the terminator character detected + // returns the number of characters placed in the buffer (0 means no valid data found) - // Arduino String functions to be added here - std::string readString(); - std::string readStringUntil(char terminator); + // Arduino String functions to be added here + std::string readString(); + std::string readStringUntil(char terminator); - protected: - long parseInt(char skipChar); // as above but the given skipChar is ignored - // as above but the given skipChar is ignored - // this allows format characters (typically commas) in values to be ignored +protected: + long parseInt(char skipChar); // as above but the given skipChar is ignored + // as above but the given skipChar is ignored + // this allows format characters (typically commas) in values to be ignored - float parseFloat(char skipChar); // as above but the given skipChar is ignored + float parseFloat(char skipChar); // as above but the given skipChar is ignored }; #endif diff --git a/drivers/Linux/compatibility.cpp b/drivers/Linux/compatibility.cpp index a19ce54..1f8f748 100644 --- a/drivers/Linux/compatibility.cpp +++ b/drivers/Linux/compatibility.cpp @@ -23,46 +23,46 @@ unsigned long millis(void) unsigned long micros() { - timeval curTime; + timeval curTime; - if (millis_at_start == 0) { - gettimeofday(&curTime, NULL); - millis_at_start = curTime.tv_sec; - } + if (millis_at_start == 0) { + gettimeofday(&curTime, NULL); + millis_at_start = curTime.tv_sec; + } - gettimeofday(&curTime, NULL); - return ((curTime.tv_sec - millis_at_start) * 1000000) + (curTime.tv_usec); + gettimeofday(&curTime, NULL); + return ((curTime.tv_sec - millis_at_start) * 1000000) + (curTime.tv_usec); } void _delay_ms(unsigned int millis) { - struct timespec sleeper; - - sleeper.tv_sec = (time_t)(millis / 1000); - sleeper.tv_nsec = (long)(millis % 1000) * 1000000; - nanosleep(&sleeper, NULL); + struct timespec sleeper; + + sleeper.tv_sec = (time_t)(millis / 1000); + sleeper.tv_nsec = (long)(millis % 1000) * 1000000; + nanosleep(&sleeper, NULL); } void randomSeed(unsigned long seed) { - if (seed != 0) { - srand(seed); - } + if (seed != 0) { + srand(seed); + } } long randMax(long howbig) { - if (howbig == 0) { - return 0; - } - return rand() % howbig; + if (howbig == 0) { + return 0; + } + return rand() % howbig; } long randMinMax(long howsmall, long howbig) { - if (howsmall >= howbig) { - return howsmall; - } - long diff = howbig - howsmall; - return randMax(diff) + howsmall; + if (howsmall >= howbig) { + return howsmall; + } + long diff = howbig - howsmall; + return randMax(diff) + howsmall; } diff --git a/drivers/Linux/noniso.cpp b/drivers/Linux/noniso.cpp index 04ee6f3..f751bb3 100644 --- a/drivers/Linux/noniso.cpp +++ b/drivers/Linux/noniso.cpp @@ -23,127 +23,136 @@ #include #include "stdlib_noniso.h" -char* utoa(unsigned value, char* result, int base) { - if(base < 2 || base > 16) { - *result = 0; - return result; - } +char* utoa(unsigned value, char* result, int base) +{ + if(base < 2 || base > 16) { + *result = 0; + return result; + } - char* out = result; - unsigned quotient = value; + char* out = result; + unsigned quotient = value; - do { - const unsigned tmp = quotient / base; - *out = "0123456789abcdef"[quotient - (tmp * base)]; - ++out; - quotient = tmp; - } while(quotient); + do { + const unsigned tmp = quotient / base; + *out = "0123456789abcdef"[quotient - (tmp * base)]; + ++out; + quotient = tmp; + } while(quotient); - reverse(result, out); - *out = 0; - return result; + reverse(result, out); + *out = 0; + return result; } -char* itoa(int value, char* result, int base) { - if(base < 2 || base > 16) { - *result = 0; - return result; - } +char* itoa(int value, char* result, int base) +{ + if(base < 2 || base > 16) { + *result = 0; + return result; + } - char* out = result; - int quotient = abs(value); + char* out = result; + int quotient = abs(value); - do { - const int tmp = quotient / base; - *out = "0123456789abcdef"[quotient - (tmp * base)]; - ++out; - quotient = tmp; - } while(quotient); + do { + const int tmp = quotient / base; + *out = "0123456789abcdef"[quotient - (tmp * base)]; + ++out; + quotient = tmp; + } while(quotient); - // Apply negative sign - if(value < 0) { - *out++ = '-'; - } + // Apply negative sign + if(value < 0) { + *out++ = '-'; + } - reverse(result, out); - *out = 0; - return result; + reverse(result, out); + *out = 0; + return result; } -int atoi(const char* s) { - return (int) atol(s); +int atoi(const char* s) +{ + return (int) atol(s); } -long atol(const char* s) { - char * tmp; - return strtol(s, &tmp, 10); +long atol(const char* s) +{ + char * tmp; + return strtol(s, &tmp, 10); } -double atof(const char* s) { - char * tmp; - return strtod(s, &tmp); +double atof(const char* s) +{ + char * tmp; + return strtod(s, &tmp); } -void reverse(char* begin, char* end) { - char *is = begin; - char *ie = end - 1; - while(is < ie) { - char tmp = *ie; - *ie = *is; - *is = tmp; - ++is; - --ie; - } +void reverse(char* begin, char* end) +{ + char *is = begin; + char *ie = end - 1; + while(is < ie) { + char tmp = *ie; + *ie = *is; + *is = tmp; + ++is; + --ie; + } } -char* ltoa(long value, char* result, int base) { - if(base < 2 || base > 16) { - *result = 0; - return result; - } +char* ltoa(long value, char* result, int base) +{ + if(base < 2 || base > 16) { + *result = 0; + return result; + } - char* out = result; - long quotient = abs(value); + char* out = result; + long quotient = abs(value); - do { - const long tmp = quotient / base; - *out = "0123456789abcdef"[quotient - (tmp * base)]; - ++out; - quotient = tmp; - } while(quotient); + do { + const long tmp = quotient / base; + *out = "0123456789abcdef"[quotient - (tmp * base)]; + ++out; + quotient = tmp; + } while(quotient); - // Apply negative sign - if(value < 0) { - *out++ = '-'; - } + // Apply negative sign + if(value < 0) { + *out++ = '-'; + } - reverse(result, out); - *out = 0; - return result; + reverse(result, out); + *out = 0; + return result; } -char* ultoa(unsigned long value, char* result, int base) { - if(base < 2 || base > 16) { - *result = 0; - return result; - } +char* ultoa(unsigned long value, char* result, int base) +{ + if(base < 2 || base > 16) { + *result = 0; + return result; + } - char* out = result; - unsigned long quotient = value; + char* out = result; + unsigned long quotient = value; - do { - const unsigned long tmp = quotient / base; - *out = "0123456789abcdef"[quotient - (tmp * base)]; - ++out; - quotient = tmp; - } while(quotient); + do { + const unsigned long tmp = quotient / base; + *out = "0123456789abcdef"[quotient - (tmp * base)]; + ++out; + quotient = tmp; + } while(quotient); - reverse(result, out); - *out = 0; - return result; + reverse(result, out); + *out = 0; + return result; } -char* dtostrf (double val, signed char width, unsigned char prec, char *s) { - sprintf(s,"%*.*f", width, prec, val); - return s; +char* dtostrf (double val, signed char width, unsigned char prec, char *s) +{ + sprintf(s,"%*.*f", width, prec, val); + return s; } diff --git a/drivers/Linux/stdlib_noniso.h b/drivers/Linux/stdlib_noniso.h index 636cbf4..ddbb920 100644 --- a/drivers/Linux/stdlib_noniso.h +++ b/drivers/Linux/stdlib_noniso.h @@ -1,9 +1,9 @@ -/* +/* stdlib_noniso.h - nonstandard (but usefull) conversion functions Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. This file is part of the esp8266 core for Arduino environment. - + 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 @@ -23,7 +23,7 @@ #define STDLIB_NONISO_H #ifdef __cplusplus -extern "C"{ +extern "C" { #endif int atoi(const char *s); @@ -39,7 +39,7 @@ char* ltoa (long val, char *s, int radix); char* utoa (unsigned int val, char *s, int radix); char* ultoa (unsigned long val, char *s, int radix); - + char* dtostrf (double val, signed char width, unsigned char prec, char *s); void reverse(char* begin, char* end); diff --git a/drivers/PubSubClient/PubSubClient.cpp b/drivers/PubSubClient/PubSubClient.cpp index d4a86c5..989b73f 100644 --- a/drivers/PubSubClient/PubSubClient.cpp +++ b/drivers/PubSubClient/PubSubClient.cpp @@ -7,595 +7,644 @@ #include "PubSubClient.h" #include "Arduino.h" -PubSubClient::PubSubClient() { - this->_state = MQTT_DISCONNECTED; - this->_client = NULL; - this->stream = NULL; - setCallback(NULL); +PubSubClient::PubSubClient() +{ + this->_state = MQTT_DISCONNECTED; + this->_client = NULL; + this->stream = NULL; + setCallback(NULL); } -PubSubClient::PubSubClient(Client& client) { - this->_state = MQTT_DISCONNECTED; - setClient(client); - this->stream = NULL; +PubSubClient::PubSubClient(Client& client) +{ + this->_state = MQTT_DISCONNECTED; + setClient(client); + this->stream = NULL; } -PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) { - this->_state = MQTT_DISCONNECTED; - setServer(addr, port); - setClient(client); - this->stream = NULL; +PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) +{ + this->_state = MQTT_DISCONNECTED; + setServer(addr, port); + setClient(client); + this->stream = NULL; } -PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client, Stream& stream) { - this->_state = MQTT_DISCONNECTED; - setServer(addr,port); - setClient(client); - setStream(stream); +PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client, Stream& stream) +{ + this->_state = MQTT_DISCONNECTED; + setServer(addr,port); + setClient(client); + setStream(stream); } -PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { - this->_state = MQTT_DISCONNECTED; - setServer(addr, port); - setCallback(callback); - setClient(client); - this->stream = NULL; +PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) +{ + this->_state = MQTT_DISCONNECTED; + setServer(addr, port); + setCallback(callback); + setClient(client); + this->stream = NULL; } -PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { - this->_state = MQTT_DISCONNECTED; - setServer(addr,port); - setCallback(callback); - setClient(client); - setStream(stream); +PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, + Stream& stream) +{ + this->_state = MQTT_DISCONNECTED; + setServer(addr,port); + setCallback(callback); + setClient(client); + setStream(stream); } -PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client) { - this->_state = MQTT_DISCONNECTED; - setServer(ip, port); - setClient(client); - this->stream = NULL; +PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client) +{ + this->_state = MQTT_DISCONNECTED; + setServer(ip, port); + setClient(client); + this->stream = NULL; } -PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client, Stream& stream) { - this->_state = MQTT_DISCONNECTED; - setServer(ip,port); - setClient(client); - setStream(stream); +PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client, Stream& stream) +{ + this->_state = MQTT_DISCONNECTED; + setServer(ip,port); + setClient(client); + setStream(stream); } -PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { - this->_state = MQTT_DISCONNECTED; - setServer(ip, port); - setCallback(callback); - setClient(client); - this->stream = NULL; +PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) +{ + this->_state = MQTT_DISCONNECTED; + setServer(ip, port); + setCallback(callback); + setClient(client); + this->stream = NULL; } -PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { - this->_state = MQTT_DISCONNECTED; - setServer(ip,port); - setCallback(callback); - setClient(client); - setStream(stream); +PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, + Stream& stream) +{ + this->_state = MQTT_DISCONNECTED; + setServer(ip,port); + setCallback(callback); + setClient(client); + setStream(stream); } -PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client) { - this->_state = MQTT_DISCONNECTED; - setServer(domain,port); - setClient(client); - this->stream = NULL; +PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client) +{ + this->_state = MQTT_DISCONNECTED; + setServer(domain,port); + setClient(client); + this->stream = NULL; } -PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client, Stream& stream) { - this->_state = MQTT_DISCONNECTED; - setServer(domain,port); - setClient(client); - setStream(stream); +PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client, Stream& stream) +{ + this->_state = MQTT_DISCONNECTED; + setServer(domain,port); + setClient(client); + setStream(stream); } -PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { - this->_state = MQTT_DISCONNECTED; - setServer(domain,port); - setCallback(callback); - setClient(client); - this->stream = NULL; +PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, + Client& client) +{ + this->_state = MQTT_DISCONNECTED; + setServer(domain,port); + setCallback(callback); + setClient(client); + this->stream = NULL; } -PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { - this->_state = MQTT_DISCONNECTED; - setServer(domain,port); - setCallback(callback); - setClient(client); - setStream(stream); +PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, + Client& client, Stream& stream) +{ + this->_state = MQTT_DISCONNECTED; + setServer(domain,port); + setCallback(callback); + setClient(client); + setStream(stream); } -boolean PubSubClient::connect(const char *id) { - return connect(id,NULL,NULL,0,0,0,0); +boolean PubSubClient::connect(const char *id) +{ + return connect(id,NULL,NULL,0,0,0,0); } -boolean PubSubClient::connect(const char *id, const char *user, const char *pass) { - return connect(id,user,pass,0,0,0,0); +boolean PubSubClient::connect(const char *id, const char *user, const char *pass) +{ + return connect(id,user,pass,0,0,0,0); } -boolean PubSubClient::connect(const char *id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) { - return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage); +boolean PubSubClient::connect(const char *id, const char* willTopic, uint8_t willQos, + boolean willRetain, const char* willMessage) +{ + return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage); } -boolean PubSubClient::connect(const char *id, const char *user, const char *pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) { - if (!connected()) { - int result = 0; +boolean PubSubClient::connect(const char *id, const char *user, const char *pass, + const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) +{ + if (!connected()) { + int result = 0; - if (domain != NULL) { - result = _client->connect(this->domain, this->port); - } else { - result = _client->connect(this->ip, this->port); - } - if (result == 1) { - nextMsgId = 1; - // Leave room in the buffer for header and variable length field - uint16_t length = 5; - unsigned int j; + if (domain != NULL) { + result = _client->connect(this->domain, this->port); + } else { + result = _client->connect(this->ip, this->port); + } + if (result == 1) { + nextMsgId = 1; + // Leave room in the buffer for header and variable length field + uint16_t length = 5; + unsigned int j; #if MQTT_VERSION == MQTT_VERSION_3_1 - uint8_t d[9] = {0x00,0x06,'M','Q','I','s','d','p', MQTT_VERSION}; + uint8_t d[9] = {0x00,0x06,'M','Q','I','s','d','p', MQTT_VERSION}; #define MQTT_HEADER_VERSION_LENGTH 9 #elif MQTT_VERSION == MQTT_VERSION_3_1_1 - uint8_t d[7] = {0x00,0x04,'M','Q','T','T',MQTT_VERSION}; + uint8_t d[7] = {0x00,0x04,'M','Q','T','T',MQTT_VERSION}; #define MQTT_HEADER_VERSION_LENGTH 7 #endif - for (j = 0;j>1); - } - } + if(pass != NULL) { + v = v|(0x80>>1); + } + } - buffer[length++] = v; + buffer[length++] = v; - buffer[length++] = ((MQTT_KEEPALIVE) >> 8); - buffer[length++] = ((MQTT_KEEPALIVE) & 0xFF); - length = writeString(id,buffer,length); - if (willTopic) { - length = writeString(willTopic,buffer,length); - length = writeString(willMessage,buffer,length); - } + buffer[length++] = ((MQTT_KEEPALIVE) >> 8); + buffer[length++] = ((MQTT_KEEPALIVE) & 0xFF); + length = writeString(id,buffer,length); + if (willTopic) { + length = writeString(willTopic,buffer,length); + length = writeString(willMessage,buffer,length); + } - if(user != NULL) { - length = writeString(user,buffer,length); - if(pass != NULL) { - length = writeString(pass,buffer,length); - } - } + if(user != NULL) { + length = writeString(user,buffer,length); + if(pass != NULL) { + length = writeString(pass,buffer,length); + } + } - write(MQTTCONNECT,buffer,length-5); + write(MQTTCONNECT,buffer,length-5); - lastInActivity = lastOutActivity = millis(); + lastInActivity = lastOutActivity = millis(); - while (!_client->available()) { - unsigned long t = millis(); - if (t-lastInActivity >= ((int32_t) MQTT_SOCKET_TIMEOUT*1000UL)) { - _state = MQTT_CONNECTION_TIMEOUT; - _client->stop(); - return false; - } - } - uint8_t llen; - uint16_t len = readPacket(&llen); + while (!_client->available()) { + unsigned long t = millis(); + if (t-lastInActivity >= ((int32_t) MQTT_SOCKET_TIMEOUT*1000UL)) { + _state = MQTT_CONNECTION_TIMEOUT; + _client->stop(); + return false; + } + } + uint8_t llen; + uint16_t len = readPacket(&llen); - if (len == 4) { - if (buffer[3] == 0) { - lastInActivity = millis(); - pingOutstanding = false; - _state = MQTT_CONNECTED; - return true; - } else { - _state = buffer[3]; - } - } - _client->stop(); - } else { - _state = MQTT_CONNECT_FAILED; - } - return false; - } - return true; + if (len == 4) { + if (buffer[3] == 0) { + lastInActivity = millis(); + pingOutstanding = false; + _state = MQTT_CONNECTED; + return true; + } else { + _state = buffer[3]; + } + } + _client->stop(); + } else { + _state = MQTT_CONNECT_FAILED; + } + return false; + } + return true; } // reads a byte into result -boolean PubSubClient::readByte(uint8_t * result) { - uint32_t previousMillis = millis(); - while(!_client->available()) { - uint32_t currentMillis = millis(); - if(currentMillis - previousMillis >= ((int32_t) MQTT_SOCKET_TIMEOUT * 1000)){ - return false; - } - } - *result = _client->read(); - return true; +boolean PubSubClient::readByte(uint8_t * result) +{ + uint32_t previousMillis = millis(); + while(!_client->available()) { + uint32_t currentMillis = millis(); + if(currentMillis - previousMillis >= ((int32_t) MQTT_SOCKET_TIMEOUT * 1000)) { + return false; + } + } + *result = _client->read(); + return true; } // reads a byte into result[*index] and increments index -boolean PubSubClient::readByte(uint8_t * result, uint16_t * index){ - uint16_t current_index = *index; - uint8_t * write_address = &(result[current_index]); - if(readByte(write_address)){ - *index = current_index + 1; - return true; - } - return false; +boolean PubSubClient::readByte(uint8_t * result, uint16_t * index) +{ + uint16_t current_index = *index; + uint8_t * write_address = &(result[current_index]); + if(readByte(write_address)) { + *index = current_index + 1; + return true; + } + return false; } -uint16_t PubSubClient::readPacket(uint8_t* lengthLength) { - uint16_t len = 0; - if(!readByte(buffer, &len)) { - return 0; - } - bool isPublish = (buffer[0]&0xF0) == MQTTPUBLISH; - uint32_t multiplier = 1; - uint16_t length = 0; - uint8_t digit = 0; - uint16_t skip = 0; - uint8_t start = 0; +uint16_t PubSubClient::readPacket(uint8_t* lengthLength) +{ + uint16_t len = 0; + if(!readByte(buffer, &len)) { + return 0; + } + bool isPublish = (buffer[0]&0xF0) == MQTTPUBLISH; + uint32_t multiplier = 1; + uint16_t length = 0; + uint8_t digit = 0; + uint16_t skip = 0; + uint8_t start = 0; - do { - if(!readByte(&digit)) { - return 0; - } - buffer[len++] = digit; - length += (digit & 127) * multiplier; - multiplier *= 128; - } while ((digit & 128) != 0); - *lengthLength = len-1; + do { + if(!readByte(&digit)) { + return 0; + } + buffer[len++] = digit; + length += (digit & 127) * multiplier; + multiplier *= 128; + } while ((digit & 128) != 0); + *lengthLength = len-1; - if (isPublish) { - // Read in topic length to calculate bytes to skip over for Stream writing - if(!readByte(buffer, &len)) { - return 0; - } - if(!readByte(buffer, &len)) { - return 0; - } - skip = (buffer[*lengthLength+1]<<8)+buffer[*lengthLength+2]; - start = 2; - if (buffer[0]&MQTTQOS1) { - // skip message id - skip += 2; - } - } + if (isPublish) { + // Read in topic length to calculate bytes to skip over for Stream writing + if(!readByte(buffer, &len)) { + return 0; + } + if(!readByte(buffer, &len)) { + return 0; + } + skip = (buffer[*lengthLength+1]<<8)+buffer[*lengthLength+2]; + start = 2; + if (buffer[0]&MQTTQOS1) { + // skip message id + skip += 2; + } + } - for (uint16_t i = start;istream) { - if (isPublish && len-*lengthLength-2>skip) { - this->stream->write(digit); - } - } - if (len < MQTT_MAX_PACKET_SIZE) { - buffer[len] = digit; - } - len++; - } + for (uint16_t i = start; istream) { + if (isPublish && len-*lengthLength-2>skip) { + this->stream->write(digit); + } + } + if (len < MQTT_MAX_PACKET_SIZE) { + buffer[len] = digit; + } + len++; + } - if (!this->stream && len > MQTT_MAX_PACKET_SIZE) { - len = 0; // This will cause the packet to be ignored. - } + if (!this->stream && len > MQTT_MAX_PACKET_SIZE) { + len = 0; // This will cause the packet to be ignored. + } - return len; + return len; } -boolean PubSubClient::loop() { - if (connected()) { - unsigned long t = millis(); - if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) { - if (pingOutstanding) { - this->_state = MQTT_CONNECTION_TIMEOUT; - _client->stop(); - return false; - } else { - buffer[0] = MQTTPINGREQ; - buffer[1] = 0; - _client->write(buffer,2); - lastOutActivity = t; - lastInActivity = t; - pingOutstanding = true; - } - } - if (_client->available()) { - uint8_t llen; - uint16_t len = readPacket(&llen); - uint16_t msgId = 0; - uint8_t *payload; - if (len > 0) { - lastInActivity = t; - uint8_t type = buffer[0]&0xF0; - if (type == MQTTPUBLISH) { - if (callback) { - uint16_t tl = (buffer[llen+1]<<8)+buffer[llen+2]; - char topic[tl+1]; - for (uint16_t i=0;i0 - if ((buffer[0]&0x06) == MQTTQOS1) { - msgId = (buffer[llen+3+tl]<<8)+buffer[llen+3+tl+1]; - payload = buffer+llen+3+tl+2; - callback(topic,payload,len-llen-3-tl-2); +boolean PubSubClient::loop() +{ + if (connected()) { + unsigned long t = millis(); + if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) { + if (pingOutstanding) { + this->_state = MQTT_CONNECTION_TIMEOUT; + _client->stop(); + return false; + } else { + buffer[0] = MQTTPINGREQ; + buffer[1] = 0; + _client->write(buffer,2); + lastOutActivity = t; + lastInActivity = t; + pingOutstanding = true; + } + } + if (_client->available()) { + uint8_t llen; + uint16_t len = readPacket(&llen); + uint16_t msgId = 0; + uint8_t *payload; + if (len > 0) { + lastInActivity = t; + uint8_t type = buffer[0]&0xF0; + if (type == MQTTPUBLISH) { + if (callback) { + uint16_t tl = (buffer[llen+1]<<8)+buffer[llen+2]; + char topic[tl+1]; + for (uint16_t i=0; i0 + if ((buffer[0]&0x06) == MQTTQOS1) { + msgId = (buffer[llen+3+tl]<<8)+buffer[llen+3+tl+1]; + payload = buffer+llen+3+tl+2; + callback(topic,payload,len-llen-3-tl-2); - buffer[0] = MQTTPUBACK; - buffer[1] = 2; - buffer[2] = (msgId >> 8); - buffer[3] = (msgId & 0xFF); - _client->write(buffer,4); - lastOutActivity = t; + buffer[0] = MQTTPUBACK; + buffer[1] = 2; + buffer[2] = (msgId >> 8); + buffer[3] = (msgId & 0xFF); + _client->write(buffer,4); + lastOutActivity = t; - } else { - payload = buffer+llen+3+tl; - callback(topic,payload,len-llen-3-tl); - } - } - } else if (type == MQTTPINGREQ) { - buffer[0] = MQTTPINGRESP; - buffer[1] = 0; - _client->write(buffer,2); - } else if (type == MQTTPINGRESP) { - pingOutstanding = false; - } - } - } - return true; - } - return false; + } else { + payload = buffer+llen+3+tl; + callback(topic,payload,len-llen-3-tl); + } + } + } else if (type == MQTTPINGREQ) { + buffer[0] = MQTTPINGRESP; + buffer[1] = 0; + _client->write(buffer,2); + } else if (type == MQTTPINGRESP) { + pingOutstanding = false; + } + } + } + return true; + } + return false; } -boolean PubSubClient::publish(const char* topic, const char* payload) { - return publish(topic,(const uint8_t*)payload,strlen(payload),false); +boolean PubSubClient::publish(const char* topic, const char* payload) +{ + return publish(topic,(const uint8_t*)payload,strlen(payload),false); } -boolean PubSubClient::publish(const char* topic, const char* payload, boolean retained) { - return publish(topic,(const uint8_t*)payload,strlen(payload),retained); +boolean PubSubClient::publish(const char* topic, const char* payload, boolean retained) +{ + return publish(topic,(const uint8_t*)payload,strlen(payload),retained); } -boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength) { - return publish(topic, payload, plength, false); +boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength) +{ + return publish(topic, payload, plength, false); } -boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) { - if (connected()) { - if (MQTT_MAX_PACKET_SIZE < 5 + 2+strlen(topic) + plength) { - // Too long - return false; - } - // Leave room in the buffer for header and variable length field - uint16_t length = 5; - length = writeString(topic,buffer,length); - uint16_t i; - for (i=0;i 0) { - digit |= 0x80; - } - buffer[pos++] = digit; - llen++; - } while(len>0); + header = MQTTPUBLISH; + if (retained) { + header |= 1; + } + buffer[pos++] = header; + len = plength + 2 + tlen; + do { + digit = len % 128; + len = len / 128; + if (len > 0) { + digit |= 0x80; + } + buffer[pos++] = digit; + llen++; + } while(len>0); - pos = writeString(topic,buffer,pos); + pos = writeString(topic,buffer,pos); - rc += _client->write(buffer,pos); + rc += _client->write(buffer,pos); - for (i=0;iwrite((char)pgm_read_byte_near(payload + i)); - } + for (i=0; iwrite((char)pgm_read_byte_near(payload + i)); + } - lastOutActivity = millis(); + lastOutActivity = millis(); - return rc == tlen + 4 + plength; + return rc == tlen + 4 + plength; } -boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) { - uint8_t lenBuf[4]; - uint8_t llen = 0; - uint8_t digit; - uint8_t pos = 0; - uint16_t rc; - uint16_t len = length; - do { - digit = len % 128; - len = len / 128; - if (len > 0) { - digit |= 0x80; - } - lenBuf[pos++] = digit; - llen++; - } while(len>0); +boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) +{ + uint8_t lenBuf[4]; + uint8_t llen = 0; + uint8_t digit; + uint8_t pos = 0; + uint16_t rc; + uint16_t len = length; + do { + digit = len % 128; + len = len / 128; + if (len > 0) { + digit |= 0x80; + } + lenBuf[pos++] = digit; + llen++; + } while(len>0); - buf[4-llen] = header; - for (int i=0;i 0) && result) { - bytesToWrite = (bytesRemaining > MQTT_MAX_TRANSFER_SIZE)?MQTT_MAX_TRANSFER_SIZE:bytesRemaining; - rc = _client->write(writeBuf,bytesToWrite); - result = (rc == bytesToWrite); - bytesRemaining -= rc; - writeBuf += rc; - } - return result; + uint8_t* writeBuf = buf+(4-llen); + uint16_t bytesRemaining = length+1+llen; //Match the length type + uint8_t bytesToWrite; + boolean result = true; + while((bytesRemaining > 0) && result) { + bytesToWrite = (bytesRemaining > MQTT_MAX_TRANSFER_SIZE)?MQTT_MAX_TRANSFER_SIZE:bytesRemaining; + rc = _client->write(writeBuf,bytesToWrite); + result = (rc == bytesToWrite); + bytesRemaining -= rc; + writeBuf += rc; + } + return result; #else - rc = _client->write(buf+(4-llen),length+1+llen); - lastOutActivity = millis(); - return (rc == 1+llen+length); + rc = _client->write(buf+(4-llen),length+1+llen); + lastOutActivity = millis(); + return (rc == 1+llen+length); #endif } -boolean PubSubClient::subscribe(const char* topic) { - return subscribe(topic, 0); +boolean PubSubClient::subscribe(const char* topic) +{ + return subscribe(topic, 0); } -boolean PubSubClient::subscribe(const char* topic, uint8_t qos) { - // original: if (qos < 0 || qos > 1) { (qos is uint8_t, hence qos < 0 impossible, tekka) +boolean PubSubClient::subscribe(const char* topic, uint8_t qos) +{ + // original: if (qos < 0 || qos > 1) { (qos is uint8_t, hence qos < 0 impossible, tekka) if (qos > 1) { - return false; - } - if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { - // Too long - return false; - } - if (connected()) { - // Leave room in the buffer for header and variable length field - uint16_t length = 5; - nextMsgId++; - if (nextMsgId == 0) { - nextMsgId = 1; - } - buffer[length++] = (nextMsgId >> 8); - buffer[length++] = (nextMsgId & 0xFF); - length = writeString((char*)topic, buffer,length); - buffer[length++] = qos; - return write(MQTTSUBSCRIBE|MQTTQOS1,buffer,length-5); - } - return false; + return false; + } + if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { + // Too long + return false; + } + if (connected()) { + // Leave room in the buffer for header and variable length field + uint16_t length = 5; + nextMsgId++; + if (nextMsgId == 0) { + nextMsgId = 1; + } + buffer[length++] = (nextMsgId >> 8); + buffer[length++] = (nextMsgId & 0xFF); + length = writeString((char*)topic, buffer,length); + buffer[length++] = qos; + return write(MQTTSUBSCRIBE|MQTTQOS1,buffer,length-5); + } + return false; } -boolean PubSubClient::unsubscribe(const char* topic) { - if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { - // Too long - return false; - } - if (connected()) { - uint16_t length = 5; - nextMsgId++; - if (nextMsgId == 0) { - nextMsgId = 1; - } - buffer[length++] = (nextMsgId >> 8); - buffer[length++] = (nextMsgId & 0xFF); - length = writeString(topic, buffer,length); - return write(MQTTUNSUBSCRIBE|MQTTQOS1,buffer,length-5); - } - return false; +boolean PubSubClient::unsubscribe(const char* topic) +{ + if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { + // Too long + return false; + } + if (connected()) { + uint16_t length = 5; + nextMsgId++; + if (nextMsgId == 0) { + nextMsgId = 1; + } + buffer[length++] = (nextMsgId >> 8); + buffer[length++] = (nextMsgId & 0xFF); + length = writeString(topic, buffer,length); + return write(MQTTUNSUBSCRIBE|MQTTQOS1,buffer,length-5); + } + return false; } -void PubSubClient::disconnect() { - buffer[0] = MQTTDISCONNECT; - buffer[1] = 0; - _client->write(buffer,2); - _state = MQTT_DISCONNECTED; - _client->stop(); - lastInActivity = lastOutActivity = millis(); +void PubSubClient::disconnect() +{ + buffer[0] = MQTTDISCONNECT; + buffer[1] = 0; + _client->write(buffer,2); + _state = MQTT_DISCONNECTED; + _client->stop(); + lastInActivity = lastOutActivity = millis(); } -uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t pos) { - const char* idp = string; - uint16_t i = 0; - pos += 2; - while (*idp) { - buf[pos++] = *idp++; - i++; - } - buf[pos-i-2] = (i >> 8); - buf[pos-i-1] = (i & 0xFF); - return pos; +uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t pos) +{ + const char* idp = string; + uint16_t i = 0; + pos += 2; + while (*idp) { + buf[pos++] = *idp++; + i++; + } + buf[pos-i-2] = (i >> 8); + buf[pos-i-1] = (i & 0xFF); + return pos; } -boolean PubSubClient::connected() { - boolean rc; - if (_client == NULL ) { - rc = false; - } else { - rc = (int)_client->connected(); - if (!rc) { - if (this->_state == MQTT_CONNECTED) { - this->_state = MQTT_CONNECTION_LOST; - _client->flush(); - _client->stop(); - } - } - } - return rc; +boolean PubSubClient::connected() +{ + boolean rc; + if (_client == NULL ) { + rc = false; + } else { + rc = (int)_client->connected(); + if (!rc) { + if (this->_state == MQTT_CONNECTED) { + this->_state = MQTT_CONNECTION_LOST; + _client->flush(); + _client->stop(); + } + } + } + return rc; } -PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port) { - IPAddress addr(ip[0],ip[1],ip[2],ip[3]); - return setServer(addr,port); +PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port) +{ + IPAddress addr(ip[0],ip[1],ip[2],ip[3]); + return setServer(addr,port); } -PubSubClient& PubSubClient::setServer(IPAddress ip, uint16_t port) { - this->ip = ip; - this->port = port; - this->domain = NULL; - return *this; +PubSubClient& PubSubClient::setServer(IPAddress ip, uint16_t port) +{ + this->ip = ip; + this->port = port; + this->domain = NULL; + return *this; } -PubSubClient& PubSubClient::setServer(const char * domain, uint16_t port) { - this->domain = domain; - this->port = port; - return *this; +PubSubClient& PubSubClient::setServer(const char * domain, uint16_t port) +{ + this->domain = domain; + this->port = port; + return *this; } -PubSubClient& PubSubClient::setCallback(MQTT_CALLBACK_SIGNATURE) { - this->callback = callback; - return *this; +PubSubClient& PubSubClient::setCallback(MQTT_CALLBACK_SIGNATURE) +{ + this->callback = callback; + return *this; } -PubSubClient& PubSubClient::setClient(Client& client){ - this->_client = &client; - return *this; +PubSubClient& PubSubClient::setClient(Client& client) +{ + this->_client = &client; + return *this; } -PubSubClient& PubSubClient::setStream(Stream& stream){ - this->stream = &stream; - return *this; +PubSubClient& PubSubClient::setStream(Stream& stream) +{ + this->stream = &stream; + return *this; } -int PubSubClient::state() { - return this->_state; +int PubSubClient::state() +{ + return this->_state; } diff --git a/drivers/PubSubClient/PubSubClient.h b/drivers/PubSubClient/PubSubClient.h index 90ad8ae..a1cf90b 100644 --- a/drivers/PubSubClient/PubSubClient.h +++ b/drivers/PubSubClient/PubSubClient.h @@ -81,64 +81,72 @@ #endif /** PubSubClient class */ -class PubSubClient { +class PubSubClient +{ private: - Client* _client; - uint8_t buffer[MQTT_MAX_PACKET_SIZE]; - uint16_t nextMsgId; - unsigned long lastOutActivity; - unsigned long lastInActivity; - bool pingOutstanding; - MQTT_CALLBACK_SIGNATURE; - uint16_t readPacket(uint8_t*); - boolean readByte(uint8_t * result); - boolean readByte(uint8_t * result, uint16_t * index); - boolean write(uint8_t header, uint8_t* buf, uint16_t length); - uint16_t writeString(const char* string, uint8_t* buf, uint16_t pos); - IPAddress ip; - const char* domain; - uint16_t port; - Stream* stream; - int _state; + Client* _client; + uint8_t buffer[MQTT_MAX_PACKET_SIZE]; + uint16_t nextMsgId; + unsigned long lastOutActivity; + unsigned long lastInActivity; + bool pingOutstanding; + MQTT_CALLBACK_SIGNATURE; + uint16_t readPacket(uint8_t*); + boolean readByte(uint8_t * result); + boolean readByte(uint8_t * result, uint16_t * index); + boolean write(uint8_t header, uint8_t* buf, uint16_t length); + uint16_t writeString(const char* string, uint8_t* buf, uint16_t pos); + IPAddress ip; + const char* domain; + uint16_t port; + Stream* stream; + int _state; public: - PubSubClient(); //!< PubSubClient - PubSubClient(Client& client); //!< PubSubClient - PubSubClient(IPAddress, uint16_t, Client& client); //!< PubSubClient - PubSubClient(IPAddress, uint16_t, Client& client, Stream&); //!< PubSubClient - PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient - PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); //!< PubSubClient - PubSubClient(uint8_t *, uint16_t, Client& client); //!< PubSubClient - PubSubClient(uint8_t *, uint16_t, Client& client, Stream&); //!< PubSubClient - PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient - PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); //!< PubSubClient - PubSubClient(const char*, uint16_t, Client& client); //!< PubSubClient - PubSubClient(const char*, uint16_t, Client& client, Stream&); //!< PubSubClient - PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient - PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); //!< PubSubClient + PubSubClient(); //!< PubSubClient + PubSubClient(Client& client); //!< PubSubClient + PubSubClient(IPAddress, uint16_t, Client& client); //!< PubSubClient + PubSubClient(IPAddress, uint16_t, Client& client, Stream&); //!< PubSubClient + PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient + PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, + Stream&); //!< PubSubClient + PubSubClient(uint8_t *, uint16_t, Client& client); //!< PubSubClient + PubSubClient(uint8_t *, uint16_t, Client& client, Stream&); //!< PubSubClient + PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient + PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, + Stream&); //!< PubSubClient + PubSubClient(const char*, uint16_t, Client& client); //!< PubSubClient + PubSubClient(const char*, uint16_t, Client& client, Stream&); //!< PubSubClient + PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient + PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, + Stream&); //!< PubSubClient - PubSubClient& setServer(IPAddress ip, uint16_t port); //!< setServer - PubSubClient& setServer(uint8_t * ip, uint16_t port); //!< setServer - PubSubClient& setServer(const char * domain, uint16_t port); //!< setServer - PubSubClient& setCallback(MQTT_CALLBACK_SIGNATURE); //!< setCallback - PubSubClient& setClient(Client& client); //!< setClient - PubSubClient& setStream(Stream& stream); //!< setStream + PubSubClient& setServer(IPAddress ip, uint16_t port); //!< setServer + PubSubClient& setServer(uint8_t * ip, uint16_t port); //!< setServer + PubSubClient& setServer(const char * domain, uint16_t port); //!< setServer + PubSubClient& setCallback(MQTT_CALLBACK_SIGNATURE); //!< setCallback + PubSubClient& setClient(Client& client); //!< setClient + PubSubClient& setStream(Stream& stream); //!< setStream - boolean connect(const char* id); //!< connect - boolean connect(const char* id, const char* user, const char* pass); //!< connect - boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); //!< connect - boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); //!< connect - void disconnect(); //!< disconnect - boolean publish(const char* topic, const char* payload); //!< publish - boolean publish(const char* topic, const char* payload, boolean retained); //!< publish - boolean publish(const char* topic, const uint8_t * payload, unsigned int plength); //!< publish - boolean publish(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained); //!< publish - boolean publish_P(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained); //!< publish_P - boolean subscribe(const char* topic); //!< subscribe - boolean subscribe(const char* topic, uint8_t qos); //!< subscribe - boolean unsubscribe(const char* topic); //!< unsubscribe - boolean loop(); //!< loop - boolean connected(); //!< connected - int state(); //!< state + boolean connect(const char* id); //!< connect + boolean connect(const char* id, const char* user, const char* pass); //!< connect + boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain, + const char* willMessage); //!< connect + boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, + uint8_t willQos, boolean willRetain, const char* willMessage); //!< connect + void disconnect(); //!< disconnect + boolean publish(const char* topic, const char* payload); //!< publish + boolean publish(const char* topic, const char* payload, boolean retained); //!< publish + boolean publish(const char* topic, const uint8_t * payload, unsigned int plength); //!< publish + boolean publish(const char* topic, const uint8_t * payload, unsigned int plength, + boolean retained); //!< publish + boolean publish_P(const char* topic, const uint8_t * payload, unsigned int plength, + boolean retained); //!< publish_P + boolean subscribe(const char* topic); //!< subscribe + boolean subscribe(const char* topic, uint8_t qos); //!< subscribe + boolean unsubscribe(const char* topic); //!< unsubscribe + boolean loop(); //!< loop + boolean connected(); //!< connected + int state(); //!< state }; diff --git a/drivers/RF24/RF24.cpp b/drivers/RF24/RF24.cpp index 34d1193..4544847 100644 --- a/drivers/RF24/RF24.cpp +++ b/drivers/RF24/RF24.cpp @@ -36,405 +36,410 @@ uint8_t spi_txbuff[32+1] ; //SPI transmit buffer (payload max 32 bytes + 1 byte LOCAL void RF24_csn(const bool level) { - hwDigitalWrite(MY_RF24_CS_PIN, level); + hwDigitalWrite(MY_RF24_CS_PIN, level); } LOCAL void RF24_ce(const bool level) { - hwDigitalWrite(MY_RF24_CE_PIN, level); + hwDigitalWrite(MY_RF24_CE_PIN, level); } -LOCAL uint8_t RF24_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_t len, const bool aReadMode) +LOCAL uint8_t RF24_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_t len, + const bool aReadMode) { - uint8_t status; - uint8_t* current = buf; + 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)); + _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); + 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 + 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++ = 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 - } + *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++); - } - } + 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); + RF24_csn(HIGH); #if !defined(MY_SOFTSPI) - _SPI.endTransaction(); + _SPI.endTransaction(); #endif - // timing - delayMicroseconds(10); - return status; + // timing + delayMicroseconds(10); + return status; } LOCAL uint8_t RF24_spiByteTransfer(const uint8_t cmd) { - return RF24_spiMultiByteTransfer(cmd, NULL, 0, false); + return RF24_spiMultiByteTransfer(cmd, NULL, 0, false); } 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; + 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(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); + 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(RF24_FLUSH_RX); + RF24_DEBUG(PSTR("RF24:flushRX\n")); + RF24_spiByteTransfer(RF24_FLUSH_RX); } LOCAL void RF24_flushTX(void) { - RF24_DEBUG(PSTR("RF24:flushTX\n")); - RF24_spiByteTransfer(RF24_FLUSH_TX); + RF24_DEBUG(PSTR("RF24:flushTX\n")); + RF24_spiByteTransfer(RF24_FLUSH_TX); } LOCAL uint8_t RF24_getStatus(void) { - return RF24_spiByteTransfer(RF24_NOP); + return RF24_spiByteTransfer(RF24_NOP); } LOCAL uint8_t RF24_getFIFOStatus(void) { - return RF24_readByteRegister(RF24_FIFO_STATUS); + return RF24_readByteRegister(RF24_FIFO_STATUS); } LOCAL void RF24_setChannel(const uint8_t channel) { - RF24_writeByteRegister(RF24_RF_CH,channel); + RF24_writeByteRegister(RF24_RF_CH,channel); } LOCAL void RF24_setRetries(const uint8_t retransmitDelay, const uint8_t retransmitCount) { - RF24_writeByteRegister(RF24_SETUP_RETR, retransmitDelay << RF24_ARD | retransmitCount << RF24_ARC); + RF24_writeByteRegister(RF24_SETUP_RETR, retransmitDelay << RF24_ARD | retransmitCount << RF24_ARC); } LOCAL void RF24_setAddressWidth(const uint8_t width) { - RF24_writeByteRegister(RF24_SETUP_AW, width - 2); + RF24_writeByteRegister(RF24_SETUP_AW, width - 2); } LOCAL void RF24_setRFSetup(const uint8_t RFsetup) { - RF24_writeByteRegister(RF24_RF_SETUP, RFsetup); + RF24_writeByteRegister(RF24_RF_SETUP, RFsetup); } LOCAL void RF24_setFeature(const uint8_t feature) { - RF24_writeByteRegister(RF24_FEATURE, feature); + RF24_writeByteRegister(RF24_FEATURE, feature); } LOCAL void RF24_setPipe(const uint8_t pipe) { - RF24_writeByteRegister(RF24_EN_RXADDR, pipe); + RF24_writeByteRegister(RF24_EN_RXADDR, pipe); } LOCAL void RF24_setAutoACK(const uint8_t pipe) { - RF24_writeByteRegister(RF24_EN_AA, pipe); + RF24_writeByteRegister(RF24_EN_AA, pipe); } LOCAL void RF24_setDynamicPayload(const uint8_t pipe) { - RF24_writeByteRegister(RF24_DYNPD, pipe); + RF24_writeByteRegister(RF24_DYNPD, pipe); } LOCAL void RF24_setRFConfiguration(const uint8_t configuration) { - RF24_writeByteRegister(RF24_NRF_CONFIG, configuration); + RF24_writeByteRegister(RF24_NRF_CONFIG, configuration); } LOCAL void RF24_setPipeAddress(const uint8_t pipe, uint8_t* address, const uint8_t width) { - RF24_writeMultiByteRegister(pipe, address, width); + RF24_writeMultiByteRegister(pipe, address, width); } LOCAL void RF24_setPipeLSB(const uint8_t pipe, const uint8_t LSB) { - RF24_writeByteRegister(pipe, LSB); + RF24_writeByteRegister(pipe, LSB); } LOCAL uint8_t RF24_getObserveTX(void) { - return RF24_readByteRegister(RF24_OBSERVE_TX); + return RF24_readByteRegister(RF24_OBSERVE_TX); } LOCAL void RF24_setStatus(const uint8_t status) { - RF24_writeByteRegister(RF24_STATUS, status); + RF24_writeByteRegister(RF24_STATUS, status); } LOCAL void RF24_enableFeatures(void) { - RF24_RAW_writeByteRegister(RF24_ACTIVATE, 0x73); + RF24_RAW_writeByteRegister(RF24_ACTIVATE, 0x73); } 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); + 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: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); + 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:STP LIS\n")); // stop listening - RF24_ce(LOW); - // timing - delayMicroseconds(130); - RF24_setRFConfiguration(MY_RF24_CONFIGURATION | _BV(RF24_PWR_UP) ); - // timing - delayMicroseconds(100); + 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:PD\n")); // power down + RF24_ce(LOW); + RF24_setRFConfiguration(MY_RF24_CONFIGURATION); + RF24_DEBUG(PSTR("RF24:PD\n")); // power down } 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)); + 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(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; + 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)) ); + return (!(RF24_getFIFOStatus() & _BV(0)) ); } 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; + 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(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)); - } + 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; + 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(RF24_RF_SETUP) == MY_RF24_RF_SETUP) & (RF24_readByteRegister(RF24_RF_CH) == MY_RF24_CHANNEL); + // 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) { - 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 (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(); + 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. + // 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. + // 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); + noInterrupts(); + attachInterrupt(digitalPinToInterrupt(MY_RF24_IRQ_PIN), RF24_irqHandler, FALLING); #endif - } else { - // clear RX interrupt - RF24_setStatus(_BV(RF24_RX_DR)); - } + } else { + // clear RX interrupt + RF24_setStatus(_BV(RF24_RX_DR)); + } } LOCAL void RF24_registerReceiveCallback(RF24_receiveCallbackType cb) { - MY_CRITICAL_SECTION { - RF24_receiveCallback = cb; - } + MY_CRITICAL_SECTION { + RF24_receiveCallback = cb; + } } #endif LOCAL bool RF24_initialize(void) { - // prevent warning - (void)RF24_getObserveTX; + // prevent warning + (void)RF24_getObserveTX; - // Initialize pins - hwPinMode(MY_RF24_CE_PIN,OUTPUT); - hwPinMode(MY_RF24_CS_PIN,OUTPUT); + // 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); + hwPinMode(MY_RF24_IRQ_PIN,INPUT); #endif - // Initialize SPI - _SPI.begin(); - RF24_ce(LOW); - RF24_csn(HIGH); + // 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); + // 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; + // 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 ae98d94..6d228a9 100644 --- a/drivers/RF24/RF24.h +++ b/drivers/RF24/RF24.h @@ -27,65 +27,66 @@ // SPI settings #if !defined(MY_RF24_SPI_MAX_SPEED) - // default 2Mhz - safe for nRF24L01+ clones - #define MY_RF24_SPI_MAX_SPEED 2000000 +// default 2Mhz - safe for nRF24L01+ clones +#define MY_RF24_SPI_MAX_SPEED 2000000 #endif #define MY_RF24_SPI_DATA_ORDER MSBFIRST #define MY_RF24_SPI_DATA_MODE SPI_MODE0 #if defined (ARDUINO) && !defined (__arm__) && !defined (_SPI) - #include - #if defined(MY_SOFTSPI) - SoftSPI _SPI; - #else - #define _SPI SPI - #endif +#include +#if defined(MY_SOFTSPI) +SoftSPI +_SPI; #else - #include - #include - #include - - #define _BV(x) (1<<(x)) - - #if defined(__arm__) - #include - #else - extern HardwareSPI SPI; - #endif - - #if !defined(_SPI) - #define _SPI SPI - #endif +#define _SPI SPI +#endif +#else +#include +#include +#include + +#define _BV(x) (1<<(x)) + +#if defined(__arm__) +#include +#else +extern HardwareSPI SPI; +#endif + +#if !defined(_SPI) +#define _SPI SPI +#endif #endif // verify RF24 IRQ defs #if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - #if !defined(MY_RF24_IRQ_PIN) - #error Message buffering feature requires MY_RF24_IRQ_PIN to be defined! - #endif - // SoftSPI does not support usingInterrupt() - #ifdef MY_SOFTSPI - #error RF24 IRQ usage cannot be used with Soft SPI - #endif - // ESP8266 does not support usingInterrupt() - #ifdef ARDUINO_ARCH_ESP8266 - #error RF24 IRQ usage cannot be used with ESP8266 - #endif - #ifndef SPI_HAS_TRANSACTION - #error RF24 IRQ usage requires transactional SPI support - #endif +#if !defined(MY_RF24_IRQ_PIN) +#error Message buffering feature requires MY_RF24_IRQ_PIN to be defined! +#endif +// SoftSPI does not support usingInterrupt() +#ifdef MY_SOFTSPI +#error RF24 IRQ usage cannot be used with Soft SPI +#endif +// ESP8266 does not support usingInterrupt() +#ifdef ARDUINO_ARCH_ESP8266 +#error RF24 IRQ usage cannot be used with ESP8266 +#endif +#ifndef SPI_HAS_TRANSACTION +#error RF24 IRQ usage requires transactional SPI support +#endif #else - #ifdef MY_RX_MESSAGE_BUFFER_SIZE - #error Receive message buffering requires RF24 IRQ usage - #endif +#ifdef MY_RX_MESSAGE_BUFFER_SIZE +#error Receive message buffering requires RF24 IRQ usage +#endif #endif // RF24 settings #if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - #define MY_RF24_CONFIGURATION (uint8_t) ((RF24_CRC_16 << 2) | (1 << RF24_MASK_TX_DS) | (1 << RF24_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) +#define MY_RF24_CONFIGURATION (uint8_t) (RF24_CRC_16 << 2) #endif #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 @@ -94,11 +95,11 @@ #define RF24_BROADCAST_PIPE (1) #define RF24_NODE_PIPE (0) -// debug +// debug #if defined(MY_DEBUG_VERBOSE_RF24) - #define RF24_DEBUG(x,...) debug(x, ##__VA_ARGS__) +#define RF24_DEBUG(x,...) debug(x, ##__VA_ARGS__) #else - #define RF24_DEBUG(x,...) +#define RF24_DEBUG(x,...) #endif // PA levels @@ -113,8 +114,8 @@ #define RF24_250KBPS (2) // CRC -#define RF24_CRC_DISABLED (0) -#define RF24_CRC_8 (2) +#define RF24_CRC_DISABLED (0) +#define RF24_CRC_8 (2) #define RF24_CRC_16 (3) // ARD, auto retry delay @@ -232,9 +233,10 @@ // functions -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 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); @@ -250,11 +252,11 @@ LOCAL uint8_t RF24_getFIFOStatus(void); LOCAL void RF24_openWritingPipe(uint8_t recipient); LOCAL void RF24_startListening(void); LOCAL void RF24_stopListening(void); -LOCAL void RF24_powerDown(void); +LOCAL void RF24_powerDown(void); 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 uint8_t RF24_readMessage(void* buf); LOCAL void RF24_setNodeAddress(const uint8_t address); LOCAL uint8_t RF24_getNodeID(void); LOCAL bool RF24_sanityCheck(void); @@ -275,14 +277,14 @@ LOCAL void RF24_setStatus(const uint8_t status); LOCAL void RF24_enableFeatures(void); #if defined(MY_RX_MESSAGE_BUFFER_FEATURE) - typedef void (*RF24_receiveCallbackType)(void); - /** - * Register a callback, which will be called (from interrupt context) for every message received. - * @note When a callback is registered, it _must_ retrieve the message from the nRF24 - * by calling RF24_readMessage(). Otherwise the interrupt will not get deasserted - * and message reception will stop. - */ - LOCAL void RF24_registerReceiveCallback(RF24_receiveCallbackType cb); +typedef void (*RF24_receiveCallbackType)(void); +/** + * Register a callback, which will be called (from interrupt context) for every message received. + * @note When a callback is registered, it _must_ retrieve the message from the nRF24 + * by calling RF24_readMessage(). Otherwise the interrupt will not get deasserted + * and message reception will stop. + */ +LOCAL void RF24_registerReceiveCallback(RF24_receiveCallbackType cb); #endif #endif // __RF24_H__ \ No newline at end of file diff --git a/drivers/RFM69/RFM69.cpp b/drivers/RFM69/RFM69.cpp index f967c09..bd3f3aa 100644 --- a/drivers/RFM69/RFM69.cpp +++ b/drivers/RFM69/RFM69.cpp @@ -39,171 +39,175 @@ volatile uint8_t RFM69::SENDERID; volatile uint8_t RFM69::TARGETID; // should match _address volatile uint8_t RFM69::PAYLOADLEN; volatile uint8_t RFM69::ACK_REQUESTED; -volatile uint8_t RFM69::ACK_RECEIVED; // should be polled immediately after sending a packet with ACK request -volatile int16_t RFM69::RSSI; // most accurate RSSI during reception (closest to the reception) +volatile uint8_t +RFM69::ACK_RECEIVED; // should be polled immediately after sending a packet with ACK request +volatile int16_t +RFM69::RSSI; // most accurate RSSI during reception (closest to the reception) RFM69* RFM69::selfPointer; bool RFM69::initialize(uint8_t freqBand, uint8_t nodeID, uint8_t networkID) { - const uint8_t CONFIG[][2] = - { - /* 0x01 */ { REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF | RF_OPMODE_STANDBY }, - /* 0x02 */ { REG_DATAMODUL, RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_00 }, // no shaping - /* 0x03 */ { REG_BITRATEMSB, RF_BITRATEMSB_55555}, // default: 4.8 KBPS - /* 0x04 */ { REG_BITRATELSB, RF_BITRATELSB_55555}, - /* 0x05 */ { REG_FDEVMSB, RF_FDEVMSB_50000}, // default: 5KHz, (FDEV + BitRate / 2 <= 500KHz) - /* 0x06 */ { REG_FDEVLSB, RF_FDEVLSB_50000}, + const uint8_t CONFIG[][2] = { + /* 0x01 */ { REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF | RF_OPMODE_STANDBY }, + /* 0x02 */ { REG_DATAMODUL, RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_00 }, // no shaping + /* 0x03 */ { REG_BITRATEMSB, RF_BITRATEMSB_55555}, // default: 4.8 KBPS + /* 0x04 */ { REG_BITRATELSB, RF_BITRATELSB_55555}, + /* 0x05 */ { REG_FDEVMSB, RF_FDEVMSB_50000}, // default: 5KHz, (FDEV + BitRate / 2 <= 500KHz) + /* 0x06 */ { REG_FDEVLSB, RF_FDEVLSB_50000}, - /* 0x07 */ { REG_FRFMSB, (uint8_t) (freqBand==RF69_315MHZ ? RF_FRFMSB_315 : (freqBand==RF69_433MHZ ? RF_FRFMSB_433 : (freqBand==RF69_868MHZ ? RF_FRFMSB_868 : RF_FRFMSB_915))) }, - /* 0x08 */ { REG_FRFMID, (uint8_t) (freqBand==RF69_315MHZ ? RF_FRFMID_315 : (freqBand==RF69_433MHZ ? RF_FRFMID_433 : (freqBand==RF69_868MHZ ? RF_FRFMID_868 : RF_FRFMID_915))) }, - /* 0x09 */ { REG_FRFLSB, (uint8_t) (freqBand==RF69_315MHZ ? RF_FRFLSB_315 : (freqBand==RF69_433MHZ ? RF_FRFLSB_433 : (freqBand==RF69_868MHZ ? RF_FRFLSB_868 : RF_FRFLSB_915))) }, + /* 0x07 */ { REG_FRFMSB, (uint8_t) (freqBand==RF69_315MHZ ? RF_FRFMSB_315 : (freqBand==RF69_433MHZ ? RF_FRFMSB_433 : (freqBand==RF69_868MHZ ? RF_FRFMSB_868 : RF_FRFMSB_915))) }, + /* 0x08 */ { REG_FRFMID, (uint8_t) (freqBand==RF69_315MHZ ? RF_FRFMID_315 : (freqBand==RF69_433MHZ ? RF_FRFMID_433 : (freqBand==RF69_868MHZ ? RF_FRFMID_868 : RF_FRFMID_915))) }, + /* 0x09 */ { REG_FRFLSB, (uint8_t) (freqBand==RF69_315MHZ ? RF_FRFLSB_315 : (freqBand==RF69_433MHZ ? RF_FRFLSB_433 : (freqBand==RF69_868MHZ ? RF_FRFLSB_868 : RF_FRFLSB_915))) }, - // looks like PA1 and PA2 are not implemented on RFM69W, hence the max output power is 13dBm - // +17dBm and +20dBm are possible on RFM69HW - // +13dBm formula: Pout = -18 + OutputPower (with PA0 or PA1**) - // +17dBm formula: Pout = -14 + OutputPower (with PA1 and PA2)** - // +20dBm formula: Pout = -11 + OutputPower (with PA1 and PA2)** and high power PA settings (section 3.3.7 in datasheet) - ///* 0x11 */ { REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | RF_PALEVEL_OUTPUTPOWER_11111}, - ///* 0x13 */ { REG_OCP, RF_OCP_ON | RF_OCP_TRIM_95 }, // over current protection (default is 95mA) + // looks like PA1 and PA2 are not implemented on RFM69W, hence the max output power is 13dBm + // +17dBm and +20dBm are possible on RFM69HW + // +13dBm formula: Pout = -18 + OutputPower (with PA0 or PA1**) + // +17dBm formula: Pout = -14 + OutputPower (with PA1 and PA2)** + // +20dBm formula: Pout = -11 + OutputPower (with PA1 and PA2)** and high power PA settings (section 3.3.7 in datasheet) + ///* 0x11 */ { REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | RF_PALEVEL_OUTPUTPOWER_11111}, + ///* 0x13 */ { REG_OCP, RF_OCP_ON | RF_OCP_TRIM_95 }, // over current protection (default is 95mA) - // RXBW defaults are { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_5} (RxBw: 10.4KHz) - /* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_16 | RF_RXBW_EXP_2 }, // (BitRate < 2 * RxBw) - //for BR-19200: /* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_3 }, - /* 0x25 */ { REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01 }, // DIO0 is the only IRQ we're using - /* 0x26 */ { REG_DIOMAPPING2, RF_DIOMAPPING2_CLKOUT_OFF }, // DIO5 ClkOut disable for power saving - /* 0x28 */ { REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN }, // writing to this bit ensures that the FIFO & status flags are reset - /* 0x29 */ { REG_RSSITHRESH, 220 }, // must be set to dBm = (-Sensitivity / 2), default is 0xE4 = 228 so -114dBm - ///* 0x2D */ { REG_PREAMBLELSB, RF_PREAMBLESIZE_LSB_VALUE } // default 3 preamble bytes 0xAAAAAA - /* 0x2E */ { REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_2 | RF_SYNC_TOL_0 }, - /* 0x2F */ { REG_SYNCVALUE1, 0x2D }, // attempt to make this compatible with sync1 byte of RFM12B lib - /* 0x30 */ { REG_SYNCVALUE2, networkID }, // NETWORK ID - /* 0x37 */ { REG_PACKETCONFIG1, RF_PACKET1_FORMAT_VARIABLE | RF_PACKET1_DCFREE_OFF | RF_PACKET1_CRC_ON | RF_PACKET1_CRCAUTOCLEAR_ON | RF_PACKET1_ADRSFILTERING_OFF }, - /* 0x38 */ { REG_PAYLOADLENGTH, 66 }, // in variable length mode: the max frame size, not used in TX - ///* 0x39 */ { REG_NODEADRS, nodeID }, // turned off because we're not using address filtering - /* 0x3C */ { REG_FIFOTHRESH, RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY | RF_FIFOTHRESH_VALUE }, // TX on FIFO not empty - /* 0x3D */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_2BITS | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, // RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent) - //for BR-19200: /* 0x3D */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_NONE | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, // RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent) - /* 0x6F */ { REG_TESTDAGC, RF_DAGC_IMPROVED_LOWBETA0 }, // run DAGC continuously in RX mode for Fading Margin Improvement, recommended default for AfcLowBetaOn=0 - {255, 0} - }; + // RXBW defaults are { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_5} (RxBw: 10.4KHz) + /* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_16 | RF_RXBW_EXP_2 }, // (BitRate < 2 * RxBw) + //for BR-19200: /* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_3 }, + /* 0x25 */ { REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01 }, // DIO0 is the only IRQ we're using + /* 0x26 */ { REG_DIOMAPPING2, RF_DIOMAPPING2_CLKOUT_OFF }, // DIO5 ClkOut disable for power saving + /* 0x28 */ { REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN }, // writing to this bit ensures that the FIFO & status flags are reset + /* 0x29 */ { REG_RSSITHRESH, 220 }, // must be set to dBm = (-Sensitivity / 2), default is 0xE4 = 228 so -114dBm + ///* 0x2D */ { REG_PREAMBLELSB, RF_PREAMBLESIZE_LSB_VALUE } // default 3 preamble bytes 0xAAAAAA + /* 0x2E */ { REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_2 | RF_SYNC_TOL_0 }, + /* 0x2F */ { REG_SYNCVALUE1, 0x2D }, // attempt to make this compatible with sync1 byte of RFM12B lib + /* 0x30 */ { REG_SYNCVALUE2, networkID }, // NETWORK ID + /* 0x37 */ { REG_PACKETCONFIG1, RF_PACKET1_FORMAT_VARIABLE | RF_PACKET1_DCFREE_OFF | RF_PACKET1_CRC_ON | RF_PACKET1_CRCAUTOCLEAR_ON | RF_PACKET1_ADRSFILTERING_OFF }, + /* 0x38 */ { REG_PAYLOADLENGTH, 66 }, // in variable length mode: the max frame size, not used in TX + ///* 0x39 */ { REG_NODEADRS, nodeID }, // turned off because we're not using address filtering + /* 0x3C */ { REG_FIFOTHRESH, RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY | RF_FIFOTHRESH_VALUE }, // TX on FIFO not empty + /* 0x3D */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_2BITS | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, // RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent) + //for BR-19200: /* 0x3D */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_NONE | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, // RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent) + /* 0x6F */ { REG_TESTDAGC, RF_DAGC_IMPROVED_LOWBETA0 }, // run DAGC continuously in RX mode for Fading Margin Improvement, recommended default for AfcLowBetaOn=0 + {255, 0} + }; - hwDigitalWrite(_slaveSelectPin, HIGH); - hwPinMode(_slaveSelectPin, OUTPUT); - SPI.begin(); - unsigned long start = millis(); - uint8_t timeout = 50; - do { - writeReg(REG_SYNCVALUE1, 0xAA); - yield(); - } while (readReg(REG_SYNCVALUE1) != 0xaa && millis()-start < timeout); - start = millis(); - do { - writeReg(REG_SYNCVALUE1, 0x55); - yield(); - } while (readReg(REG_SYNCVALUE1) != 0x55 && millis()-start < timeout); + hwDigitalWrite(_slaveSelectPin, HIGH); + hwPinMode(_slaveSelectPin, OUTPUT); + SPI.begin(); + unsigned long start = millis(); + uint8_t timeout = 50; + do { + writeReg(REG_SYNCVALUE1, 0xAA); + yield(); + } while (readReg(REG_SYNCVALUE1) != 0xaa && millis()-start < timeout); + start = millis(); + do { + writeReg(REG_SYNCVALUE1, 0x55); + yield(); + } while (readReg(REG_SYNCVALUE1) != 0x55 && millis()-start < timeout); - for (uint8_t i = 0; CONFIG[i][0] != 255; i++) { - writeReg(CONFIG[i][0], CONFIG[i][1]); - } + for (uint8_t i = 0; CONFIG[i][0] != 255; i++) { + writeReg(CONFIG[i][0], CONFIG[i][1]); + } - // Encryption is persistent between resets and can trip you up during debugging. - // Disable it during initialization so we always start from a known state. - encrypt(0); + // Encryption is persistent between resets and can trip you up during debugging. + // Disable it during initialization so we always start from a known state. + encrypt(0); - setHighPower(_isRFM69HW); // called regardless if it's a RFM69W or RFM69HW - setMode(RF69_MODE_STANDBY); - start = millis(); - while (((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) && millis()-start < timeout) { - yield(); - } // wait for ModeReady - if (millis()-start >= timeout) { - return false; - } - attachInterrupt(_interruptNum, RFM69::isr0, RISING); + setHighPower(_isRFM69HW); // called regardless if it's a RFM69W or RFM69HW + setMode(RF69_MODE_STANDBY); + start = millis(); + while (((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) && millis()-start < timeout) { + yield(); + } // wait for ModeReady + if (millis()-start >= timeout) { + return false; + } + attachInterrupt(_interruptNum, RFM69::isr0, RISING); - selfPointer = this; - _address = nodeID; - return true; + selfPointer = this; + _address = nodeID; + return true; } // return the frequency (in Hz) uint32_t RFM69::getFrequency() { - return RF69_FSTEP * (((uint32_t) readReg(REG_FRFMSB) << 16) + ((uint16_t) readReg(REG_FRFMID) << 8) + readReg(REG_FRFLSB)); + return RF69_FSTEP * (((uint32_t) readReg(REG_FRFMSB) << 16) + ((uint16_t) readReg( + REG_FRFMID) << 8) + readReg(REG_FRFLSB)); } // set the frequency (in Hz) void RFM69::setFrequency(uint32_t freqHz) { - uint8_t oldMode = _mode; - if (oldMode == RF69_MODE_TX) { - setMode(RF69_MODE_RX); - } - freqHz /= RF69_FSTEP; // divide down by FSTEP to get FRF - writeReg(REG_FRFMSB, freqHz >> 16); - writeReg(REG_FRFMID, freqHz >> 8); - writeReg(REG_FRFLSB, freqHz); - if (oldMode == RF69_MODE_RX) { - setMode(RF69_MODE_SYNTH); - } - setMode(oldMode); + uint8_t oldMode = _mode; + if (oldMode == RF69_MODE_TX) { + setMode(RF69_MODE_RX); + } + freqHz /= RF69_FSTEP; // divide down by FSTEP to get FRF + writeReg(REG_FRFMSB, freqHz >> 16); + writeReg(REG_FRFMID, freqHz >> 8); + writeReg(REG_FRFLSB, freqHz); + if (oldMode == RF69_MODE_RX) { + setMode(RF69_MODE_SYNTH); + } + setMode(oldMode); } void RFM69::setMode(uint8_t newMode) { - if (newMode == _mode) { - return; - } + if (newMode == _mode) { + return; + } - switch (newMode) { - case RF69_MODE_TX: - writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_TRANSMITTER); - if (_isRFM69HW) { - setHighPowerRegs(true); - } - break; - case RF69_MODE_RX: - writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_RECEIVER); - if (_isRFM69HW) { - setHighPowerRegs(false); - } - break; - case RF69_MODE_SYNTH: - writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_SYNTHESIZER); - break; - case RF69_MODE_STANDBY: - writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_STANDBY); - break; - case RF69_MODE_SLEEP: - writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_SLEEP); - break; - default: - return; - } + switch (newMode) { + case RF69_MODE_TX: + writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_TRANSMITTER); + if (_isRFM69HW) { + setHighPowerRegs(true); + } + break; + case RF69_MODE_RX: + writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_RECEIVER); + if (_isRFM69HW) { + setHighPowerRegs(false); + } + break; + case RF69_MODE_SYNTH: + writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_SYNTHESIZER); + break; + case RF69_MODE_STANDBY: + writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_STANDBY); + break; + case RF69_MODE_SLEEP: + writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_SLEEP); + break; + default: + return; + } - // we are using packet mode, so this check is not really needed - // but waiting for mode ready is necessary when going from sleep because the FIFO may not be immediately available from previous mode - while (_mode == RF69_MODE_SLEEP && (readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // wait for ModeReady + // we are using packet mode, so this check is not really needed + // but waiting for mode ready is necessary when going from sleep because the FIFO may not be immediately available from previous mode + while (_mode == RF69_MODE_SLEEP && + (readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // wait for ModeReady - _mode = newMode; + _mode = newMode; } //put transceiver in sleep mode to save battery - to wake or resume receiving just call receiveDone() -void RFM69::sleep() { - setMode(RF69_MODE_SLEEP); +void RFM69::sleep() +{ + setMode(RF69_MODE_SLEEP); } //set this node's address void RFM69::setAddress(uint8_t addr) { - _address = addr; - writeReg(REG_NODEADRS, _address); + _address = addr; + writeReg(REG_NODEADRS, _address); } //set this node's network id void RFM69::setNetwork(uint8_t networkID) { - writeReg(REG_SYNCVALUE2, networkID); + writeReg(REG_SYNCVALUE2, networkID); } // set *transmit/TX* output power: 0=min, 31=max @@ -215,31 +219,32 @@ void RFM69::setNetwork(uint8_t networkID) // - for RFM69HW the range is from 0-31 [5dBm to 20dBm] (PA1 & PA2 on PA_BOOST pin & high Power PA settings - see section 3.3.7 in datasheet, p22) void RFM69::setPowerLevel(uint8_t powerLevel) { - _powerLevel = (powerLevel > 31 ? 31 : powerLevel); - if (_isRFM69HW) { - _powerLevel /= 2; - } - writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0xE0) | _powerLevel); + _powerLevel = (powerLevel > 31 ? 31 : powerLevel); + if (_isRFM69HW) { + _powerLevel /= 2; + } + writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0xE0) | _powerLevel); } bool RFM69::canSend() { - if (_mode == RF69_MODE_RX && PAYLOADLEN == 0 && readRSSI() < CSMA_LIMIT) // if signal stronger than -100dBm is detected assume channel activity - { - setMode(RF69_MODE_STANDBY); - return true; - } - return false; + if (_mode == RF69_MODE_RX && PAYLOADLEN == 0 && + readRSSI() < CSMA_LIMIT) { // if signal stronger than -100dBm is detected assume channel activity + setMode(RF69_MODE_STANDBY); + return true; + } + return false; } void RFM69::send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK) { - writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART); // avoid RX deadlocks - uint32_t now = millis(); - while (!canSend() && millis() - now < RF69_CSMA_LIMIT_MS) { - receiveDone(); - } - sendFrame(toAddress, buffer, bufferSize, requestACK, false); + writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | + RF_PACKET2_RXRESTART); // avoid RX deadlocks + uint32_t now = millis(); + while (!canSend() && millis() - now < RF69_CSMA_LIMIT_MS) { + receiveDone(); + } + sendFrame(toAddress, buffer, bufferSize, requestACK, false); } // to increase the chance of getting a packet across, call this function instead of send @@ -248,287 +253,304 @@ void RFM69::send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool // The reason for the semi-automaton is that the lib is interrupt driven and // requires user action to read the received data and decide what to do with it // replies usually take only 5..8ms at 50kbps@915MHz -bool RFM69::sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize, uint8_t retries, uint8_t retryWaitTime) { - uint32_t sentTime; - for (uint8_t i = 0; i <= retries; i++) - { - send(toAddress, buffer, bufferSize, true); - sentTime = millis(); - while (millis() - sentTime < retryWaitTime) - { - if (ACKReceived(toAddress)) - { - //Serial.print(" ~ms:"); Serial.print(millis() - sentTime); - return true; - } - } - //Serial.print(" RETRY#"); Serial.println(i + 1); - } - return false; +bool RFM69::sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize, + uint8_t retries, uint8_t retryWaitTime) +{ + uint32_t sentTime; + for (uint8_t i = 0; i <= retries; i++) { + send(toAddress, buffer, bufferSize, true); + sentTime = millis(); + while (millis() - sentTime < retryWaitTime) { + if (ACKReceived(toAddress)) { + //Serial.print(" ~ms:"); Serial.print(millis() - sentTime); + return true; + } + } + //Serial.print(" RETRY#"); Serial.println(i + 1); + } + return false; } // should be polled immediately after sending a packet with ACK request -bool RFM69::ACKReceived(uint8_t fromNodeID) { - if (receiveDone()) { - return (SENDERID == fromNodeID || fromNodeID == RF69_BROADCAST_ADDR) && ACK_RECEIVED; - } - return false; +bool RFM69::ACKReceived(uint8_t fromNodeID) +{ + if (receiveDone()) { + return (SENDERID == fromNodeID || fromNodeID == RF69_BROADCAST_ADDR) && ACK_RECEIVED; + } + return false; } // check whether an ACK was requested in the last received packet (non-broadcasted packet) -bool RFM69::ACKRequested() { - return ACK_REQUESTED && (TARGETID != RF69_BROADCAST_ADDR); +bool RFM69::ACKRequested() +{ + return ACK_REQUESTED && (TARGETID != RF69_BROADCAST_ADDR); } // should be called immediately after reception in case sender wants ACK -void RFM69::sendACK(const void* buffer, uint8_t bufferSize) { - ACK_REQUESTED = 0; // TWS added to make sure we don't end up in a timing race and infinite loop sending Acks - uint8_t sender = SENDERID; - int16_t _RSSI = RSSI; // save payload received RSSI value - writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART); // avoid RX deadlocks - uint32_t now = millis(); - while (!canSend() && millis() - now < RF69_CSMA_LIMIT_MS) { - receiveDone(); - yield(); - } - SENDERID = sender; // TWS: Restore SenderID after it gets wiped out by receiveDone() - sendFrame(sender, buffer, bufferSize, false, true); - RSSI = _RSSI; // restore payload RSSI +void RFM69::sendACK(const void* buffer, uint8_t bufferSize) +{ + ACK_REQUESTED = + 0; // TWS added to make sure we don't end up in a timing race and infinite loop sending Acks + uint8_t sender = SENDERID; + int16_t _RSSI = RSSI; // save payload received RSSI value + writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | + RF_PACKET2_RXRESTART); // avoid RX deadlocks + uint32_t now = millis(); + while (!canSend() && millis() - now < RF69_CSMA_LIMIT_MS) { + receiveDone(); + yield(); + } + SENDERID = sender; // TWS: Restore SenderID after it gets wiped out by receiveDone() + sendFrame(sender, buffer, bufferSize, false, true); + RSSI = _RSSI; // restore payload RSSI } -void RFM69::interruptHook(uint8_t CTLbyte) { +void RFM69::interruptHook(uint8_t CTLbyte) +{ (void)CTLbyte; }; // 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 - while ((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) {} // wait for ModeReady - writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_00); // DIO0 is "Packet Sent" - if (bufferSize > RF69_MAX_DATA_LEN) { - bufferSize = RF69_MAX_DATA_LEN; - } + setMode(RF69_MODE_STANDBY); // turn off receiver to prevent reception while filling fifo + while ((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) {} // wait for ModeReady + writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_00); // DIO0 is "Packet Sent" + if (bufferSize > RF69_MAX_DATA_LEN) { + bufferSize = RF69_MAX_DATA_LEN; + } - // control byte - uint8_t CTLbyte = 0x00; - if (sendACK) { - CTLbyte = RFM69_CTL_SENDACK; - } - else if (requestACK) { - CTLbyte = RFM69_CTL_REQACK; - } + // control byte + uint8_t CTLbyte = 0x00; + if (sendACK) { + CTLbyte = RFM69_CTL_SENDACK; + } else if (requestACK) { + CTLbyte = RFM69_CTL_REQACK; + } - // write to FIFO - select(); - SPI.transfer(REG_FIFO | 0x80); - SPI.transfer(bufferSize + 3); - SPI.transfer(toAddress); - SPI.transfer(_address); - SPI.transfer(CTLbyte); + // write to FIFO + select(); + SPI.transfer(REG_FIFO | 0x80); + SPI.transfer(bufferSize + 3); + SPI.transfer(toAddress); + SPI.transfer(_address); + SPI.transfer(CTLbyte); - for (uint8_t i = 0; i < bufferSize; i++) { - SPI.transfer(((uint8_t*) buffer)[i]); - } - unselect(); + for (uint8_t i = 0; i < bufferSize; i++) { + SPI.transfer(((uint8_t*) buffer)[i]); + } + unselect(); - // no need to wait for transmit mode to be ready since its handled by the radio - setMode(RF69_MODE_TX); - uint32_t txStart = millis(); - 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 - setMode(RF69_MODE_STANDBY); + // no need to wait for transmit mode to be ready since its handled by the radio + setMode(RF69_MODE_TX); + uint32_t txStart = millis(); + 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 + setMode(RF69_MODE_STANDBY); } // internal function - interrupt gets called when a packet is received -void RFM69::interruptHandler() { - //hwPinMode(4, OUTPUT); - //hwDigitalWrite(4, 1); - if (_mode == RF69_MODE_RX && (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY)) - { - //RSSI = readRSSI(); - setMode(RF69_MODE_STANDBY); - select(); - SPI.transfer(REG_FIFO & 0x7F); - PAYLOADLEN = SPI.transfer(0); - PAYLOADLEN = PAYLOADLEN > 66 ? 66 : PAYLOADLEN; // precaution - TARGETID = SPI.transfer(0); - if(!(_promiscuousMode || TARGETID == _address || TARGETID == RF69_BROADCAST_ADDR) // match this node's address, or broadcast address or anything in promiscuous mode - || PAYLOADLEN < 3) // address situation could receive packets that are malformed and don't fit this libraries extra fields - { - PAYLOADLEN = 0; - unselect(); - receiveBegin(); - //hwDigitalWrite(4, 0); - return; - } +void RFM69::interruptHandler() +{ + //hwPinMode(4, OUTPUT); + //hwDigitalWrite(4, 1); + if (_mode == RF69_MODE_RX && (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY)) { + //RSSI = readRSSI(); + setMode(RF69_MODE_STANDBY); + select(); + SPI.transfer(REG_FIFO & 0x7F); + PAYLOADLEN = SPI.transfer(0); + PAYLOADLEN = PAYLOADLEN > 66 ? 66 : PAYLOADLEN; // precaution + TARGETID = SPI.transfer(0); + if(!(_promiscuousMode || TARGETID == _address || + TARGETID == RF69_BROADCAST_ADDR) // match this node's address, or broadcast address or anything in promiscuous mode + || PAYLOADLEN < + 3) { // address situation could receive packets that are malformed and don't fit this libraries extra fields + PAYLOADLEN = 0; + unselect(); + receiveBegin(); + //hwDigitalWrite(4, 0); + return; + } - DATALEN = PAYLOADLEN - 3; - SENDERID = SPI.transfer(0); - uint8_t CTLbyte = SPI.transfer(0); + DATALEN = PAYLOADLEN - 3; + SENDERID = SPI.transfer(0); + uint8_t CTLbyte = SPI.transfer(0); - ACK_RECEIVED = CTLbyte & RFM69_CTL_SENDACK; // extract ACK-received flag - ACK_REQUESTED = CTLbyte & RFM69_CTL_REQACK; // extract ACK-requested flag + ACK_RECEIVED = CTLbyte & RFM69_CTL_SENDACK; // extract ACK-received 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++) - { - DATA[i] = SPI.transfer(0); - } - if (DATALEN < RF69_MAX_DATA_LEN) { - DATA[DATALEN] = 0; // add null at end of string - } - unselect(); - setMode(RF69_MODE_RX); - } - RSSI = readRSSI(); - //hwDigitalWrite(4, 0); + for (uint8_t i = 0; i < DATALEN; i++) { + DATA[i] = SPI.transfer(0); + } + if (DATALEN < RF69_MAX_DATA_LEN) { + DATA[DATALEN] = 0; // add null at end of string + } + unselect(); + setMode(RF69_MODE_RX); + } + RSSI = readRSSI(); + //hwDigitalWrite(4, 0); } // internal function -void RFM69::isr0() { selfPointer->interruptHandler(); } +void RFM69::isr0() +{ + selfPointer->interruptHandler(); +} // internal function -void RFM69::receiveBegin() { - DATALEN = 0; - SENDERID = 0; - TARGETID = 0; - PAYLOADLEN = 0; - ACK_REQUESTED = 0; - ACK_RECEIVED = 0; - RSSI = 0; - if (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY) { - 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 - setMode(RF69_MODE_RX); +void RFM69::receiveBegin() +{ + DATALEN = 0; + SENDERID = 0; + TARGETID = 0; + PAYLOADLEN = 0; + ACK_REQUESTED = 0; + ACK_RECEIVED = 0; + RSSI = 0; + if (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY) { + 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 + setMode(RF69_MODE_RX); } // checks if a packet was received and/or puts transceiver in receive (ie RX or listen) mode -bool RFM69::receiveDone() { -//ATOMIC_BLOCK(ATOMIC_FORCEON) -//{ - noInterrupts(); // re-enabled in unselect() via setMode() or via receiveBegin() - if (_mode == RF69_MODE_RX && PAYLOADLEN > 0) - { - setMode(RF69_MODE_STANDBY); // enables interrupts - return true; - } - else if (_mode == RF69_MODE_RX) // already in RX no payload yet - { - interrupts(); // explicitly re-enable interrupts - return false; - } - receiveBegin(); - return false; -//} +bool RFM69::receiveDone() +{ + //ATOMIC_BLOCK(ATOMIC_FORCEON) + //{ + noInterrupts(); // re-enabled in unselect() via setMode() or via receiveBegin() + if (_mode == RF69_MODE_RX && PAYLOADLEN > 0) { + setMode(RF69_MODE_STANDBY); // enables interrupts + return true; + } else if (_mode == RF69_MODE_RX) { // already in RX no payload yet + interrupts(); // explicitly re-enable interrupts + return false; + } + receiveBegin(); + return false; + //} } // To enable encryption: radio.encrypt("ABCDEFGHIJKLMNOP"); // To disable encryption: radio.encrypt(null) or radio.encrypt(0) // KEY HAS TO BE 16 bytes !!! -void RFM69::encrypt(const char* key) { - setMode(RF69_MODE_STANDBY); - if (key != 0) - { - select(); - SPI.transfer(REG_AESKEY1 | 0x80); - for (uint8_t i = 0; i < 16; i++) { - SPI.transfer(key[i]); - } - unselect(); - } - writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFE) | (key ? 1 : 0)); +void RFM69::encrypt(const char* key) +{ + setMode(RF69_MODE_STANDBY); + if (key != 0) { + select(); + SPI.transfer(REG_AESKEY1 | 0x80); + for (uint8_t i = 0; i < 16; i++) { + SPI.transfer(key[i]); + } + unselect(); + } + writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFE) | (key ? 1 : 0)); } // get the received signal strength indicator (RSSI) -int16_t RFM69::readRSSI(bool forceTrigger) { - int16_t rssi = 0; - if (forceTrigger) - { - // RSSI trigger not needed if DAGC is in continuous mode - writeReg(REG_RSSICONFIG, RF_RSSI_START); - while ((readReg(REG_RSSICONFIG) & RF_RSSI_DONE) == 0x00) {} // wait for RSSI_Ready - } - rssi = -readReg(REG_RSSIVALUE); - rssi >>= 1; - return rssi; +int16_t RFM69::readRSSI(bool forceTrigger) +{ + int16_t rssi = 0; + if (forceTrigger) { + // RSSI trigger not needed if DAGC is in continuous mode + writeReg(REG_RSSICONFIG, RF_RSSI_START); + while ((readReg(REG_RSSICONFIG) & RF_RSSI_DONE) == 0x00) {} // wait for RSSI_Ready + } + rssi = -readReg(REG_RSSIVALUE); + rssi >>= 1; + return rssi; } uint8_t RFM69::readReg(uint8_t addr) { - select(); - SPI.transfer(addr & 0x7F); - uint8_t regval = SPI.transfer(0); - unselect(); - return regval; + select(); + SPI.transfer(addr & 0x7F); + uint8_t regval = SPI.transfer(0); + unselect(); + return regval; } void RFM69::writeReg(uint8_t addr, uint8_t value) { - select(); - SPI.transfer(addr | 0x80); - SPI.transfer(value); - unselect(); + select(); + SPI.transfer(addr | 0x80); + SPI.transfer(value); + unselect(); } // select the RFM69 transceiver (save SPI settings, set CS low) -void RFM69::select() { - noInterrupts(); +void RFM69::select() +{ + noInterrupts(); #if defined (SPCR) && defined (SPSR) - // save current SPI settings - _SPCR = SPCR; - _SPSR = SPSR; + // save current SPI settings + _SPCR = SPCR; + _SPSR = SPSR; #endif - // set RFM69 SPI settings - SPI.setDataMode(SPI_MODE0); - SPI.setBitOrder(MSBFIRST); - SPI.setClockDivider(SPI_CLOCK_DIV4); // decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present - hwDigitalWrite(_slaveSelectPin, LOW); + // set RFM69 SPI settings + SPI.setDataMode(SPI_MODE0); + SPI.setBitOrder(MSBFIRST); + SPI.setClockDivider( + SPI_CLOCK_DIV4); // decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present + hwDigitalWrite(_slaveSelectPin, LOW); } // unselect the RFM69 transceiver (set CS high, restore SPI settings) -void RFM69::unselect() { - hwDigitalWrite(_slaveSelectPin, HIGH); - // restore SPI settings to what they were before talking to RFM69 +void RFM69::unselect() +{ + hwDigitalWrite(_slaveSelectPin, HIGH); + // restore SPI settings to what they were before talking to RFM69 #if defined (SPCR) && defined (SPSR) - SPCR = _SPCR; - SPSR = _SPSR; + SPCR = _SPCR; + SPSR = _SPSR; #endif - interrupts(); + interrupts(); } // true = disable filtering to capture all frames on network // false = enable node/broadcast filtering to capture only frames sent to this/broadcast address -void RFM69::promiscuous(bool onOff) { - _promiscuousMode = onOff; - //writeReg(REG_PACKETCONFIG1, (readReg(REG_PACKETCONFIG1) & 0xF9) | (onOff ? RF_PACKET1_ADRSFILTERING_OFF : RF_PACKET1_ADRSFILTERING_NODEBROADCAST)); +void RFM69::promiscuous(bool onOff) +{ + _promiscuousMode = onOff; + //writeReg(REG_PACKETCONFIG1, (readReg(REG_PACKETCONFIG1) & 0xF9) | (onOff ? RF_PACKET1_ADRSFILTERING_OFF : RF_PACKET1_ADRSFILTERING_NODEBROADCAST)); } // for RFM69HW only: you must call setHighPower(true) after initialize() or else transmission won't work -void RFM69::setHighPower(bool onOff) { - _isRFM69HW = onOff; - writeReg(REG_OCP, _isRFM69HW ? RF_OCP_OFF : RF_OCP_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 - } - else { - writeReg(REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | _powerLevel); // enable P0 only - } +void RFM69::setHighPower(bool onOff) +{ + _isRFM69HW = onOff; + writeReg(REG_OCP, _isRFM69HW ? RF_OCP_OFF : RF_OCP_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 + } else { + writeReg(REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | + _powerLevel); // enable P0 only + } } // internal function -void RFM69::setHighPowerRegs(bool onOff) { - writeReg(REG_TESTPA1, onOff ? 0x5D : 0x55); - writeReg(REG_TESTPA2, onOff ? 0x7C : 0x70); +void RFM69::setHighPowerRegs(bool onOff) +{ + writeReg(REG_TESTPA1, onOff ? 0x5D : 0x55); + writeReg(REG_TESTPA2, onOff ? 0x7C : 0x70); } // set the slave select (CS) pin -void RFM69::setCS(uint8_t newSPISlaveSelect) { - _slaveSelectPin = newSPISlaveSelect; - hwDigitalWrite(_slaveSelectPin, HIGH); - hwPinMode(_slaveSelectPin, OUTPUT); +void RFM69::setCS(uint8_t newSPISlaveSelect) +{ + _slaveSelectPin = newSPISlaveSelect; + hwDigitalWrite(_slaveSelectPin, HIGH); + hwPinMode(_slaveSelectPin, OUTPUT); } //for debugging @@ -537,294 +559,295 @@ void RFM69::setCS(uint8_t newSPISlaveSelect) { // SERIAL PRINT // replace Serial.print("string") with SerialPrint("string") #define SerialPrint(x) SerialPrint_P(PSTR(x)) -void SerialWrite ( uint8_t c ) { - Serial.write ( c ); +void SerialWrite ( uint8_t c ) +{ + Serial.write ( c ); } -void SerialPrint_P(PGM_P str, void (*f)(uint8_t) = SerialWrite ) { - for (uint8_t c; (c = pgm_read_byte(str)); str++) { - (*f)(c); - } +void SerialPrint_P(PGM_P str, void (*f)(uint8_t) = SerialWrite ) +{ + for (uint8_t c; (c = pgm_read_byte(str)); str++) { + (*f)(c); + } } #endif void RFM69::readAllRegs() { - uint8_t regVal; + uint8_t regVal; #if REGISTER_DETAIL - int capVal; + int capVal; - //... State Variables for intelligent decoding - uint8_t modeFSK = 0; - int bitRate = 0; - int freqDev = 0; - long freqCenter = 0; + //... State Variables for intelligent decoding + uint8_t modeFSK = 0; + int bitRate = 0; + int freqDev = 0; + long freqCenter = 0; #endif - Serial.println("Address - HEX - BIN"); - for (uint8_t regAddr = 1; regAddr <= 0x4F; regAddr++) - { - select(); - SPI.transfer(regAddr & 0x7F); // send address + r/w bit - regVal = SPI.transfer(0); - unselect(); + Serial.println("Address - HEX - BIN"); + for (uint8_t regAddr = 1; regAddr <= 0x4F; regAddr++) { + select(); + SPI.transfer(regAddr & 0x7F); // send address + r/w bit + regVal = SPI.transfer(0); + unselect(); - Serial.print(regAddr, HEX); - Serial.print(" - "); - Serial.print(regVal,HEX); - Serial.print(" - "); - Serial.println(regVal,BIN); + Serial.print(regAddr, HEX); + Serial.print(" - "); + Serial.print(regVal,HEX); + Serial.print(" - "); + Serial.println(regVal,BIN); #if REGISTER_DETAIL - switch ( regAddr ) - { - case 0x1 : { - SerialPrint ( "Controls the automatic Sequencer ( see section 4.2 )\nSequencerOff : " ); - if ( 0x80 & regVal ) { - SerialPrint ( "1 -> Mode is forced by the user\n" ); - } else { - SerialPrint ( "0 -> Operating mode as selected with Mode bits in RegOpMode is automatically reached with the Sequencer\n" ); - } + switch ( regAddr ) { + case 0x1 : { + SerialPrint ( "Controls the automatic Sequencer ( see section 4.2 )\nSequencerOff : " ); + if ( 0x80 & regVal ) { + SerialPrint ( "1 -> Mode is forced by the user\n" ); + } else { + 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 : " ); - if ( 0x40 & regVal ) { - SerialPrint ( "1 -> On\n" ); - } else { - SerialPrint ( "0 -> Off ( see section 4.3)\n" ); - } + SerialPrint( "\nEnables Listen mode, should be enabled whilst in Standby mode:\nListenOn : " ); + if ( 0x40 & regVal ) { + SerialPrint ( "1 -> On\n" ); + } else { + 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" ); - if ( 0x20 & regVal ) { - SerialPrint ( "ERROR - ListenAbort should NEVER return 1 this is a write only register\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 ) { + SerialPrint ( "ERROR - ListenAbort should NEVER return 1 this is a write only register\n" ); + } - SerialPrint("\nTransceiver's operating modes:\nMode : "); - capVal = (regVal >> 2) & 0x7; - if ( capVal == 0b000 ) { - SerialPrint ( "000 -> Sleep mode (SLEEP)\n" ); - } else if ( capVal = 0b001 ) { - SerialPrint ( "001 -> Standby mode (STDBY)\n" ); - } else if ( capVal = 0b010 ) { - SerialPrint ( "010 -> Frequency Synthesizer mode (FS)\n" ); - } else if ( capVal = 0b011 ) { - SerialPrint ( "011 -> Transmitter mode (TX)\n" ); - } else if ( capVal = 0b100 ) { - SerialPrint ( "100 -> Receiver Mode (RX)\n" ); - } else { - Serial.print( capVal, BIN ); - SerialPrint ( " -> RESERVED\n" ); - } - SerialPrint ( "\n" ); - break; - } + SerialPrint("\nTransceiver's operating modes:\nMode : "); + capVal = (regVal >> 2) & 0x7; + if ( capVal == 0b000 ) { + SerialPrint ( "000 -> Sleep mode (SLEEP)\n" ); + } else if ( capVal = 0b001 ) { + SerialPrint ( "001 -> Standby mode (STDBY)\n" ); + } else if ( capVal = 0b010 ) { + SerialPrint ( "010 -> Frequency Synthesizer mode (FS)\n" ); + } else if ( capVal = 0b011 ) { + SerialPrint ( "011 -> Transmitter mode (TX)\n" ); + } else if ( capVal = 0b100 ) { + SerialPrint ( "100 -> Receiver Mode (RX)\n" ); + } else { + Serial.print( capVal, BIN ); + SerialPrint ( " -> RESERVED\n" ); + } + SerialPrint ( "\n" ); + break; + } - case 0x2 : { + case 0x2 : { - SerialPrint("Data Processing mode:\nDataMode : "); - capVal = (regVal >> 5) & 0x3; - if ( capVal == 0b00 ) { - SerialPrint ( "00 -> Packet mode\n" ); - } else if ( capVal == 0b01 ) { - SerialPrint ( "01 -> reserved\n" ); - } else if ( capVal == 0b10 ) { - SerialPrint ( "10 -> Continuous mode with bit synchronizer\n" ); - } else if ( capVal == 0b11 ) { - SerialPrint ( "11 -> Continuous mode without bit synchronizer\n" ); - } + SerialPrint("Data Processing mode:\nDataMode : "); + capVal = (regVal >> 5) & 0x3; + if ( capVal == 0b00 ) { + SerialPrint ( "00 -> Packet mode\n" ); + } else if ( capVal == 0b01 ) { + SerialPrint ( "01 -> reserved\n" ); + } else if ( capVal == 0b10 ) { + SerialPrint ( "10 -> Continuous mode with bit synchronizer\n" ); + } else if ( capVal == 0b11 ) { + SerialPrint ( "11 -> Continuous mode without bit synchronizer\n" ); + } - SerialPrint("\nModulation scheme:\nModulation Type : "); - capVal = (regVal >> 3) & 0x3; - if ( capVal == 0b00 ) { - SerialPrint ( "00 -> FSK\n" ); - modeFSK = 1; - } else if ( capVal == 0b01 ) { - SerialPrint ( "01 -> OOK\n" ); - } else if ( capVal == 0b10 ) { - SerialPrint ( "10 -> reserved\n" ); - } else if ( capVal == 0b11 ) { - SerialPrint ( "11 -> reserved\n" ); - } + SerialPrint("\nModulation scheme:\nModulation Type : "); + capVal = (regVal >> 3) & 0x3; + if ( capVal == 0b00 ) { + SerialPrint ( "00 -> FSK\n" ); + modeFSK = 1; + } else if ( capVal == 0b01 ) { + SerialPrint ( "01 -> OOK\n" ); + } else if ( capVal == 0b10 ) { + SerialPrint ( "10 -> reserved\n" ); + } else if ( capVal == 0b11 ) { + SerialPrint ( "11 -> reserved\n" ); + } - SerialPrint("\nData shaping: "); - if ( modeFSK ) { - SerialPrint( "in FSK:\n" ); - } else { - SerialPrint( "in OOK:\n" ); - } - SerialPrint ("ModulationShaping : "); - capVal = regVal & 0x3; - if ( modeFSK ) { - if ( capVal == 0b00 ) { - SerialPrint ( "00 -> no shaping\n" ); - } else if ( capVal == 0b01 ) { - SerialPrint ( "01 -> Gaussian filter, BT = 1.0\n" ); - } else if ( capVal == 0b10 ) { - SerialPrint ( "10 -> Gaussian filter, BT = 0.5\n" ); - } else if ( capVal == 0b11 ) { - SerialPrint ( "11 -> Gaussian filter, BT = 0.3\n" ); - } - } else { - if ( capVal == 0b00 ) { - SerialPrint ( "00 -> no shaping\n" ); - } else if ( capVal == 0b01 ) { - SerialPrint ( "01 -> filtering with f(cutoff) = BR\n" ); - } else if ( capVal == 0b10 ) { - SerialPrint ( "10 -> filtering with f(cutoff) = 2*BR\n" ); - } else if ( capVal == 0b11 ) { - SerialPrint ( "ERROR - 11 is reserved\n" ); - } - } + SerialPrint("\nData shaping: "); + if ( modeFSK ) { + SerialPrint( "in FSK:\n" ); + } else { + SerialPrint( "in OOK:\n" ); + } + SerialPrint ("ModulationShaping : "); + capVal = regVal & 0x3; + if ( modeFSK ) { + if ( capVal == 0b00 ) { + SerialPrint ( "00 -> no shaping\n" ); + } else if ( capVal == 0b01 ) { + SerialPrint ( "01 -> Gaussian filter, BT = 1.0\n" ); + } else if ( capVal == 0b10 ) { + SerialPrint ( "10 -> Gaussian filter, BT = 0.5\n" ); + } else if ( capVal == 0b11 ) { + SerialPrint ( "11 -> Gaussian filter, BT = 0.3\n" ); + } + } else { + if ( capVal == 0b00 ) { + SerialPrint ( "00 -> no shaping\n" ); + } else if ( capVal == 0b01 ) { + SerialPrint ( "01 -> filtering with f(cutoff) = BR\n" ); + } else if ( capVal == 0b10 ) { + SerialPrint ( "10 -> filtering with f(cutoff) = 2*BR\n" ); + } else if ( capVal == 0b11 ) { + SerialPrint ( "ERROR - 11 is reserved\n" ); + } + } - SerialPrint ( "\n" ); - break; - } + SerialPrint ( "\n" ); + break; + } - case 0x3 : { - bitRate = (regVal << 8); - break; - } + case 0x3 : { + bitRate = (regVal << 8); + break; + } - case 0x4 : { - bitRate |= regVal; - SerialPrint ( "Bit Rate (Chip Rate when Manchester encoding is enabled)\nBitRate : "); - unsigned long val = 32UL * 1000UL * 1000UL / bitRate; - Serial.println( val ); - SerialPrint( "\n" ); - break; - } + case 0x4 : { + bitRate |= regVal; + SerialPrint ( "Bit Rate (Chip Rate when Manchester encoding is enabled)\nBitRate : "); + unsigned long val = 32UL * 1000UL * 1000UL / bitRate; + Serial.println( val ); + SerialPrint( "\n" ); + break; + } - case 0x5 : { - freqDev = ( (regVal & 0x3f) << 8 ); - break; - } + case 0x5 : { + freqDev = ( (regVal & 0x3f) << 8 ); + break; + } - case 0x6 : { - freqDev |= regVal; - SerialPrint( "Frequency deviation\nFdev : " ); - unsigned long val = 61UL * freqDev; - Serial.println( val ); - SerialPrint ( "\n" ); - break; - } + case 0x6 : { + freqDev |= regVal; + SerialPrint( "Frequency deviation\nFdev : " ); + unsigned long val = 61UL * freqDev; + Serial.println( val ); + SerialPrint ( "\n" ); + break; + } - case 0x7 : { - unsigned long tempVal = regVal; - freqCenter = ( tempVal << 16 ); - break; - } + case 0x7 : { + unsigned long tempVal = regVal; + freqCenter = ( tempVal << 16 ); + break; + } - case 0x8 : { - unsigned long tempVal = regVal; - freqCenter = freqCenter | ( tempVal << 8 ); - break; - } + case 0x8 : { + unsigned long tempVal = regVal; + freqCenter = freqCenter | ( tempVal << 8 ); + break; + } - case 0x9 : { - freqCenter = freqCenter | regVal; - SerialPrint ( "RF Carrier frequency\nFRF : " ); - unsigned long val = 61UL * freqCenter; - Serial.println( val ); - SerialPrint( "\n" ); - break; - } + case 0x9 : { + freqCenter = freqCenter | regVal; + SerialPrint ( "RF Carrier frequency\nFRF : " ); + unsigned long val = 61UL * freqCenter; + Serial.println( val ); + SerialPrint( "\n" ); + break; + } - case 0xa : { - SerialPrint ( "RC calibration control & status\nRcCalDone : " ); - if ( 0x40 & regVal ) { - SerialPrint ( "1 -> RC calibration is over\n" ); - } else { - SerialPrint ( "0 -> RC calibration is in progress\n" ); - } + case 0xa : { + SerialPrint ( "RC calibration control & status\nRcCalDone : " ); + if ( 0x40 & regVal ) { + SerialPrint ( "1 -> RC calibration is over\n" ); + } else { + SerialPrint ( "0 -> RC calibration is in progress\n" ); + } - SerialPrint ( "\n" ); - break; - } + SerialPrint ( "\n" ); + break; + } - case 0xb : { - SerialPrint ( "Improved AFC routine for signals with modulation index lower than 2. Refer to section 3.4.16 for details\nAfcLowBetaOn : " ); - if ( 0x20 & regVal ) { - SerialPrint ( "1 -> Improved AFC routine\n" ); - } else { - SerialPrint ( "0 -> Standard AFC routine\n" ); - } - SerialPrint ( "\n" ); - break; - } + case 0xb : { + SerialPrint ( "Improved AFC routine for signals with modulation index lower than 2. Refer to section 3.4.16 for details\nAfcLowBetaOn : " ); + if ( 0x20 & regVal ) { + SerialPrint ( "1 -> Improved AFC routine\n" ); + } else { + SerialPrint ( "0 -> Standard AFC routine\n" ); + } + SerialPrint ( "\n" ); + break; + } - case 0xc : { - SerialPrint ( "Reserved\n\n" ); - break; - } + case 0xc : { + SerialPrint ( "Reserved\n\n" ); + break; + } - case 0xd : { - byte val; - SerialPrint ( "Resolution of Listen mode Idle time (calibrated RC osc):\nListenResolIdle : " ); - val = regVal >> 6; - if ( val == 0b00 ) { - SerialPrint ( "00 -> reserved\n" ); - } else if ( val == 0b01 ) { - SerialPrint ( "01 -> 64 us\n" ); - } else if ( val == 0b10 ) { - SerialPrint ( "10 -> 4.1 ms\n" ); - } else if ( val == 0b11 ) { - SerialPrint ( "11 -> 262 ms\n" ); - } + case 0xd : { + byte val; + SerialPrint ( "Resolution of Listen mode Idle time (calibrated RC osc):\nListenResolIdle : " ); + val = regVal >> 6; + if ( val == 0b00 ) { + SerialPrint ( "00 -> reserved\n" ); + } else if ( val == 0b01 ) { + SerialPrint ( "01 -> 64 us\n" ); + } else if ( val == 0b10 ) { + SerialPrint ( "10 -> 4.1 ms\n" ); + } else if ( val == 0b11 ) { + SerialPrint ( "11 -> 262 ms\n" ); + } - SerialPrint ( "\nResolution of Listen mode Rx time (calibrated RC osc):\nListenResolRx : " ); - val = (regVal >> 4) & 0x3; - if ( val == 0b00 ) { - SerialPrint ( "00 -> reserved\n" ); - } else if ( val == 0b01 ) { - SerialPrint ( "01 -> 64 us\n" ); - } else if ( val == 0b10 ) { - SerialPrint ( "10 -> 4.1 ms\n" ); - } else if ( val == 0b11 ) { - SerialPrint ( "11 -> 262 ms\n" ); - } + SerialPrint ( "\nResolution of Listen mode Rx time (calibrated RC osc):\nListenResolRx : " ); + val = (regVal >> 4) & 0x3; + if ( val == 0b00 ) { + SerialPrint ( "00 -> reserved\n" ); + } else if ( val == 0b01 ) { + SerialPrint ( "01 -> 64 us\n" ); + } else if ( val == 0b10 ) { + SerialPrint ( "10 -> 4.1 ms\n" ); + } else if ( val == 0b11 ) { + SerialPrint ( "11 -> 262 ms\n" ); + } - SerialPrint ( "\nCriteria for packet acceptance in Listen mode:\nListenCriteria : " ); - if ( 0x8 & regVal ) { - SerialPrint ( "1 -> signal strength is above RssiThreshold and SyncAddress matched\n" ); - } else { - SerialPrint ( "0 -> signal strength is above RssiThreshold\n" ); - } + SerialPrint ( "\nCriteria for packet acceptance in Listen mode:\nListenCriteria : " ); + if ( 0x8 & regVal ) { + SerialPrint ( "1 -> signal strength is above RssiThreshold and SyncAddress matched\n" ); + } else { + SerialPrint ( "0 -> signal strength is above RssiThreshold\n" ); + } - SerialPrint ( "\nAction taken after acceptance of a packet in Listen mode:\nListenEnd : " ); - val = (regVal >> 1 ) & 0x3; - if ( val == 0b00 ) { - SerialPrint ( "00 -> chip stays in Rx mode. Listen mode stops and must be disabled (see section 4.3)\n" ); - } else if ( val == 0b01 ) { - SerialPrint ( "01 -> chip stays in Rx mode until PayloadReady or Timeout interrupt occurs. It then goes to the mode defined by Mode. Listen mode stops and must be disabled (see section 4.3)\n" ); - } else if ( val == 0b10 ) { - SerialPrint ( "10 -> chip stays in Rx mode until PayloadReady or Timeout occurs. Listen mode then resumes in Idle state. FIFO content is lost at next Rx wakeup.\n" ); - } else if ( val == 0b11 ) { - SerialPrint ( "11 -> Reserved\n" ); - } + SerialPrint ( "\nAction taken after acceptance of a packet in Listen mode:\nListenEnd : " ); + val = (regVal >> 1 ) & 0x3; + if ( val == 0b00 ) { + SerialPrint ( "00 -> chip stays in Rx mode. Listen mode stops and must be disabled (see section 4.3)\n" ); + } else if ( val == 0b01 ) { + SerialPrint ( "01 -> chip stays in Rx mode until PayloadReady or Timeout interrupt occurs. It then goes to the mode defined by Mode. Listen mode stops and must be disabled (see section 4.3)\n" ); + } else if ( val == 0b10 ) { + SerialPrint ( "10 -> chip stays in Rx mode until PayloadReady or Timeout occurs. Listen mode then resumes in Idle state. FIFO content is lost at next Rx wakeup.\n" ); + } else if ( val == 0b11 ) { + SerialPrint ( "11 -> Reserved\n" ); + } - SerialPrint ( "\n" ); - break; - } + SerialPrint ( "\n" ); + break; + } - default : { - } - } + default : { + } + } #endif - } - unselect(); + } + unselect(); } uint8_t RFM69::readTemperature(uint8_t calFactor) // returns centigrade { - setMode(RF69_MODE_STANDBY); - writeReg(REG_TEMP1, RF_TEMP1_MEAS_START); - while ((readReg(REG_TEMP1) & RF_TEMP1_MEAS_RUNNING)) {} - return ~readReg(REG_TEMP2) + COURSE_TEMP_COEF + calFactor; // 'complement' corrects the slope, rising temp = rising val + setMode(RF69_MODE_STANDBY); + writeReg(REG_TEMP1, RF_TEMP1_MEAS_START); + while ((readReg(REG_TEMP1) & RF_TEMP1_MEAS_RUNNING)) {} + 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 void RFM69::rcCalibration() { - writeReg(REG_OSC1, RF_OSC1_RCCAL_START); - while ((readReg(REG_OSC1) & RF_OSC1_RCCAL_DONE) == 0x00) {} + writeReg(REG_OSC1, RF_OSC1_RCCAL_START); + while ((readReg(REG_OSC1) & RF_OSC1_RCCAL_DONE) == 0x00) {} } diff --git a/drivers/RFM69/RFM69.h b/drivers/RFM69/RFM69.h index d8eb7aa..682319b 100644 --- a/drivers/RFM69/RFM69.h +++ b/drivers/RFM69/RFM69.h @@ -6,23 +6,23 @@ // ********************************************************************************** // License // ********************************************************************************** -// This program is free software; you can redistribute it -// and/or modify it under the terms of the GNU General -// Public License as published by the Free Software -// Foundation; either version 3 of the License, or -// (at your option) any later version. -// -// This program 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 General Public -// License for more details. -// -// You should have received a copy of the GNU General +// This program is free software; you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 General Public +// License for more details. +// +// You should have received a copy of the GNU General // Public License along with this program. // If not, see . -// -// Licence can be viewed at +// +// Licence can be viewed at // http://www.gnu.org/licenses/gpl-3.0.txt // // Please maintain this license information along with authorship @@ -37,20 +37,20 @@ // INT0 on AVRs should be connected to RFM69's DIO0 (ex on ATmega328 it's D2, on ATmega644/1284 it's D2) #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__) - #define RF69_IRQ_PIN 2 - #define RF69_IRQ_NUM 0 +#define RF69_IRQ_PIN 2 +#define RF69_IRQ_NUM 0 #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) - #define RF69_IRQ_PIN 2 - #define RF69_IRQ_NUM 2 +#define RF69_IRQ_PIN 2 +#define RF69_IRQ_NUM 2 #elif defined(__AVR_ATmega32U4__) - #define RF69_IRQ_PIN 3 - #define RF69_IRQ_NUM 0 +#define RF69_IRQ_PIN 3 +#define RF69_IRQ_NUM 0 #elif defined(__arm__)//Use pin 10 or any pin you want - #define RF69_IRQ_PIN 10 - #define RF69_IRQ_NUM 10 -#else - #define RF69_IRQ_PIN 2 - #define RF69_IRQ_NUM 0 +#define RF69_IRQ_PIN 10 +#define RF69_IRQ_NUM 10 +#else +#define RF69_IRQ_PIN 2 +#define RF69_IRQ_NUM 0 #endif @@ -79,79 +79,96 @@ #define RFM69_CTL_REQACK 0x40 /** RFM69 class */ -class RFM69 { - public: - static volatile uint8_t DATA[RF69_MAX_DATA_LEN]; //!< recv/xmit buf, including hdr & crc bytes - static volatile uint8_t DATALEN; //!< DATALEN - static volatile uint8_t SENDERID; //!< SENDERID - static volatile uint8_t TARGETID; //!< should match _address - static volatile uint8_t PAYLOADLEN; //!< PAYLOADLEN - static volatile uint8_t ACK_REQUESTED; //!< ACK_REQUESTED - static volatile uint8_t ACK_RECEIVED; //!< Should be polled immediately after sending a packet with ACK requestwith ACK request - static volatile int16_t RSSI; //!< most accurate RSSI during reception (closest to the reception) - static volatile uint8_t _mode; //!< should be protected? +class RFM69 +{ +public: + static volatile uint8_t DATA[RF69_MAX_DATA_LEN]; //!< recv/xmit buf, including hdr & crc bytes + static volatile uint8_t DATALEN; //!< DATALEN + static volatile uint8_t SENDERID; //!< SENDERID + static volatile uint8_t TARGETID; //!< should match _address + static volatile uint8_t PAYLOADLEN; //!< PAYLOADLEN + static volatile uint8_t ACK_REQUESTED; //!< ACK_REQUESTED + static volatile uint8_t + ACK_RECEIVED; //!< Should be polled immediately after sending a packet with ACK requestwith ACK request + static volatile int16_t RSSI; //!< most accurate RSSI during reception (closest to the reception) + static volatile uint8_t _mode; //!< should be protected? - RFM69(uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false, uint8_t interruptNum=RF69_IRQ_NUM) { //!< Constructor - _slaveSelectPin = slaveSelectPin; - _interruptPin = interruptPin; - _interruptNum = interruptNum; - _mode = RF69_MODE_STANDBY; - _promiscuousMode = false; - _powerLevel = 31; - _isRFM69HW = isRFM69HW; - } + /** + * @brief Constructor + * + * @param slaveSelectPin ChipSelect pin. + * @param interruptPin Interrupt pin. + * @param isRFM69HW Set to @c true to indicate RFM69HW variant. + * @param interruptNum Interrupt number. + */ + RFM69(uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false, + uint8_t interruptNum=RF69_IRQ_NUM) + { + _slaveSelectPin = slaveSelectPin; + _interruptPin = interruptPin; + _interruptNum = interruptNum; + _mode = RF69_MODE_STANDBY; + _promiscuousMode = false; + _powerLevel = 31; + _isRFM69HW = isRFM69HW; + } - bool initialize(uint8_t freqBand, uint8_t ID, uint8_t networkID=1); //!< initialize - void setAddress(uint8_t addr); //!< setAddress - void setNetwork(uint8_t networkID); //!< setNetwork - bool canSend(); //!< canSend - virtual void send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK=false); //!< send - virtual bool sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize, uint8_t retries=2, uint8_t retryWaitTime=40); //!< sendWithRetry (40ms roundtrip req for 61byte packets) - virtual bool receiveDone(); //!< receiveDone - bool ACKReceived(uint8_t fromNodeID); //!< ACKReceived - bool ACKRequested(); //!< ACKRequested - virtual void sendACK(const void* buffer = "", uint8_t bufferSize=0); //!< sendACK - uint32_t getFrequency(); //!< getFrequency - void setFrequency(uint32_t freqHz); //!< setFrequency - void encrypt(const char* key); //!< encrypt - void setCS(uint8_t newSPISlaveSelect); //!< setCS - int16_t readRSSI(bool forceTrigger=false); //!< readRSSI - void promiscuous(bool onOff=true); //!< promiscuous - virtual void setHighPower(bool onOFF=true); //!< setHighPower (have to call it after initialize for RFM69HW) - virtual void setPowerLevel(uint8_t level); //!< setPowerLevel (reduce/increase transmit power level) - void sleep(); //!< sleep - uint8_t readTemperature(uint8_t calFactor=0); //!< readTemperature (get CMOS temperature (8bit)) - void rcCalibration(); //!< rcCalibration (calibrate the internal RC oscillator for use in wide temperature variations - see datasheet section [4.3.5. RC Timer Accuracy]) + bool initialize(uint8_t freqBand, uint8_t ID, uint8_t networkID=1); //!< initialize + void setAddress(uint8_t addr); //!< setAddress + void setNetwork(uint8_t networkID); //!< setNetwork + bool canSend(); //!< canSend + virtual void send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, + bool requestACK=false); //!< send + virtual bool sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize, + uint8_t retries=2, uint8_t retryWaitTime= + 40); //!< sendWithRetry (40ms roundtrip req for 61byte packets) + virtual bool receiveDone(); //!< receiveDone + bool ACKReceived(uint8_t fromNodeID); //!< ACKReceived + bool ACKRequested(); //!< ACKRequested + virtual void sendACK(const void* buffer = "", uint8_t bufferSize=0); //!< sendACK + uint32_t getFrequency(); //!< getFrequency + void setFrequency(uint32_t freqHz); //!< setFrequency + void encrypt(const char* key); //!< encrypt + void setCS(uint8_t newSPISlaveSelect); //!< setCS + int16_t readRSSI(bool forceTrigger=false); //!< readRSSI + void promiscuous(bool onOff=true); //!< promiscuous + virtual void setHighPower(bool onOFF= + true); //!< setHighPower (have to call it after initialize for RFM69HW) + virtual void setPowerLevel(uint8_t level); //!< setPowerLevel (reduce/increase transmit power level) + void sleep(); //!< sleep + uint8_t readTemperature(uint8_t calFactor=0); //!< readTemperature (get CMOS temperature (8bit)) + void rcCalibration(); //!< rcCalibration (calibrate the internal RC oscillator for use in wide temperature variations - see datasheet section [4.3.5. RC Timer Accuracy]) - // allow hacking registers by making these public - uint8_t readReg(uint8_t addr); //!< readReg - void writeReg(uint8_t addr, uint8_t val); //!< writeReg - void readAllRegs(); //!< readAllRegs + // allow hacking registers by making these public + uint8_t readReg(uint8_t addr); //!< readReg + void writeReg(uint8_t addr, uint8_t val); //!< writeReg + void readAllRegs(); //!< readAllRegs - protected: - static void isr0(); //!< isr0 - void virtual interruptHandler(); //!< interruptHandler - virtual void interruptHook(uint8_t CTLbyte); //!< interruptHook - virtual void sendFrame(uint8_t toAddress, const void* buffer, uint8_t size, bool requestACK=false, bool sendACK=false); //!< sendFrame +protected: + static void isr0(); //!< isr0 + void virtual interruptHandler(); //!< interruptHandler + virtual void interruptHook(uint8_t CTLbyte); //!< interruptHook + virtual void sendFrame(uint8_t toAddress, const void* buffer, uint8_t size, bool requestACK=false, + bool sendACK=false); //!< sendFrame - static RFM69* selfPointer; //!< selfPointer - uint8_t _slaveSelectPin; //!< _slaveSelectPin - uint8_t _interruptPin; //!< _interruptPin - uint8_t _interruptNum; //!< _interruptNum - uint8_t _address; //!< _address - bool _promiscuousMode; //!< _promiscuousMode - uint8_t _powerLevel; //!< _powerLevel - bool _isRFM69HW; //!< _isRFM69HW + static RFM69* selfPointer; //!< selfPointer + uint8_t _slaveSelectPin; //!< _slaveSelectPin + uint8_t _interruptPin; //!< _interruptPin + uint8_t _interruptNum; //!< _interruptNum + uint8_t _address; //!< _address + bool _promiscuousMode; //!< _promiscuousMode + uint8_t _powerLevel; //!< _powerLevel + bool _isRFM69HW; //!< _isRFM69HW #if defined (SPCR) && defined (SPSR) - uint8_t _SPCR; //!< _SPCR - uint8_t _SPSR; //!< _SPSR + uint8_t _SPCR; //!< _SPCR + uint8_t _SPSR; //!< _SPSR #endif - virtual void receiveBegin(); //!< receiveBegin - virtual void setMode(uint8_t mode); //!< setMode - virtual void setHighPowerRegs(bool onOff); //!< setHighPowerRegs - virtual void select(); //!< select - virtual void unselect(); //!< unselect + virtual void receiveBegin(); //!< receiveBegin + virtual void setMode(uint8_t mode); //!< setMode + virtual void setHighPowerRegs(bool onOff); //!< setHighPowerRegs + virtual void select(); //!< select + virtual void unselect(); //!< unselect }; #endif diff --git a/drivers/RFM69/RFM69registers.h b/drivers/RFM69/RFM69registers.h index 2d815ec..cb38359 100644 --- a/drivers/RFM69/RFM69registers.h +++ b/drivers/RFM69/RFM69registers.h @@ -6,25 +6,25 @@ // ********************************************************************************** // License // ********************************************************************************** -// This program is free software; you can redistribute it -// and/or modify it under the terms of the GNU General -// Public License as published by the Free Software -// Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program 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 General Public -// License for more details. -// -// You should have received a copy of the GNU General -// Public License along with this program; if not, write -// to the Free Software Foundation, Inc., +// This program is free software; you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program 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 General Public +// License for more details. +// +// You should have received a copy of the GNU General +// Public License along with this program; if not, write +// to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// Licence can be viewed at -// http://www.fsf.org/licenses/gpl.txt +// +// Licence can be viewed at +// http://www.fsf.org/licenses/gpl.txt // // Please maintain this license information along with authorship // and copyright notices in any redistribution of this code diff --git a/drivers/RFM95/RFM95.cpp b/drivers/RFM95/RFM95.cpp index 37bcf51..1ce4773 100644 --- a/drivers/RFM95/RFM95.cpp +++ b/drivers/RFM95/RFM95.cpp @@ -26,19 +26,24 @@ #if defined(LINUX_ARCH_RASPBERRYPI) uint8_t spi_rxbuff[32 + 1]; //SPI receive buffer (payload max 32 bytes, MYS protocol limitation) -uint8_t spi_txbuff[32 + 1]; //SPI transmit buffer (payload max 32 bytes + 1 byte for the command, MYS protocol limitation) +uint8_t spi_txbuff[32 + + 1]; //SPI transmit buffer (payload max 32 bytes + 1 byte for the command, MYS protocol limitation) #endif -LOCAL void RFM95_csn(const bool level) { +LOCAL void RFM95_csn(const bool level) +{ hwDigitalWrite(MY_RFM95_SPI_CS, level); } -LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_t len, const bool aReadMode) { +LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_t len, + const bool aReadMode) +{ uint8_t status; uint8_t* current = buf; - #if !defined(MY_SOFTSPI) - _SPI.beginTransaction(SPISettings(MY_RFM95_SPI_MAX_SPEED, MY_RFM95_SPI_DATA_ORDER, MY_RFM95_SPI_DATA_MODE)); - #endif +#if !defined(MY_SOFTSPI) + _SPI.beginTransaction(SPISettings(MY_RFM95_SPI_MAX_SPEED, MY_RFM95_SPI_DATA_ORDER, + MY_RFM95_SPI_DATA_MODE)); +#endif RFM95_csn(LOW); #if defined(LINUX_ARCH_RASPBERRYPI) uint8_t * prx = spi_rxbuff; @@ -49,8 +54,7 @@ LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_ while (len--) { if (aReadMode) { *ptx++ = RF24_NOP; - } - else { + } else { *ptx++ = *current++; } } @@ -58,16 +62,14 @@ LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_ if (aReadMode) { if (size == 2) { status = *++prx; // result is 2nd byte of receive buffer - } - else { + } else { 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++; } } - } - else { + } else { status = *prx; // status is 1st byte of receive buffer } #else @@ -78,24 +80,27 @@ LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_ if (buf != NULL) { *current++ = status; } + } else { + status = _SPI.transfer(*current++); } - else status = _SPI.transfer(*current++); } #endif RFM95_csn(HIGH); - #if !defined(MY_SOFTSPI) - _SPI.endTransaction(); - #endif +#if !defined(MY_SOFTSPI) + _SPI.endTransaction(); +#endif return status; } // low level register access -LOCAL uint8_t RFM95_RAW_readByteRegister(const uint8_t address) { +LOCAL uint8_t RFM95_RAW_readByteRegister(const uint8_t address) +{ return RFM95_spiMultiByteTransfer(address, NULL, 1, true); } // low level register access -LOCAL uint8_t RFM95_RAW_writeByteRegister(const uint8_t address, uint8_t value) { +LOCAL uint8_t RFM95_RAW_writeByteRegister(const uint8_t address, uint8_t value) +{ return RFM95_spiMultiByteTransfer(address, &value, 1, false); } @@ -109,24 +114,25 @@ LOCAL uint8_t RFM95_RAW_writeByteRegister(const uint8_t address, uint8_t value) // check RegPktRssiValue (0x1A) vs. RegRssiValue (0x1B) -LOCAL bool RFM95_initialise(const float frequency) { +LOCAL bool RFM95_initialise(const float frequency) +{ RFM95_DEBUG(PSTR("RFM95:INIT\n")); // reset radio module if rst pin defined - #if defined(MY_RFM95_RST_PIN) - hwPinMode(MY_RFM95_RST_PIN, OUTPUT); - hwDigitalWrite(MY_RFM95_RST_PIN, HIGH); - // 100uS - delayMicroseconds(100); - hwDigitalWrite(MY_RFM95_RST_PIN, LOW); - // wait until chip ready - delay(5); - #endif +#if defined(MY_RFM95_RST_PIN) + hwPinMode(MY_RFM95_RST_PIN, OUTPUT); + hwDigitalWrite(MY_RFM95_RST_PIN, HIGH); + // 100uS + delayMicroseconds(100); + hwDigitalWrite(MY_RFM95_RST_PIN, LOW); + // wait until chip ready + delay(5); +#endif // set variables RFM95.address = RFM95_BROADCAST_ADDRESS; RFM95.rxBufferValid = false; RFM95.txSequenceNumber = 0; // initialise TX sequence counter - RFM95.powerLevel = 0; + RFM95.powerLevel = 0; RFM95.ATCenabled = false; RFM95.ATCtargetRSSI = RFM95_TARGET_RSSI + RFM95_RSSI_OFFSET; @@ -158,23 +164,24 @@ LOCAL bool RFM95_initialise(const float frequency) { // IRQ hwPinMode(MY_RFM95_IRQ_PIN, INPUT); - #if defined (SPI_HAS_TRANSACTION) && !defined (ESP8266) - _SPI.usingInterrupt(digitalPinToInterrupt(MY_RFM95_IRQ_PIN)); - #endif +#if defined (SPI_HAS_TRANSACTION) && !defined (ESP8266) + _SPI.usingInterrupt(digitalPinToInterrupt(MY_RFM95_IRQ_PIN)); +#endif attachInterrupt(digitalPinToInterrupt(MY_RFM95_IRQ_PIN), RFM95_interruptHandler, RISING); return true; } // RxDone, TxDone, CADDone is mapped to DI0 -LOCAL void RFM95_interruptHandler(void) { +LOCAL void RFM95_interruptHandler(void) +{ // Read the interrupt register - const uint8_t irqFlags = RFM95_readReg(RFM95_REG_12_IRQ_FLAGS); - if (RFM95.radioMode == RFM95_RADIO_MODE_RX && (irqFlags & (RFM95_RX_TIMEOUT | RFM95_PAYLOAD_CRC_ERROR)) ) { + const uint8_t irqFlags = RFM95_readReg(RFM95_REG_12_IRQ_FLAGS); + if (RFM95.radioMode == RFM95_RADIO_MODE_RX && + (irqFlags & (RFM95_RX_TIMEOUT | RFM95_PAYLOAD_CRC_ERROR)) ) { // CRC error or timeout // RXcontinuous mode: radio stays in RX mode, clearing IRQ needed - } - else if (RFM95.radioMode == RFM95_RADIO_MODE_RX && (irqFlags & RFM95_RX_DONE)) { + } else if (RFM95.radioMode == RFM95_RADIO_MODE_RX && (irqFlags & RFM95_RX_DONE)) { // set radio to STDBY (we are in RXcontinuous mode) (void)RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY); // Have received a packet @@ -188,44 +195,46 @@ LOCAL void RFM95_interruptHandler(void) { RFM95.currentPacket.SNR = static_cast(RFM95_readReg(RFM95_REG_19_PKT_SNR_VALUE)); RFM95.currentPacket.payloadLen = bufLen - RFM95_HEADER_LEN; // Message for us - if ((RFM95.currentPacket.header.version >= RFM95_MIN_PACKET_HEADER_VERSION) && - (RFM95_PROMISCUOUS || RFM95.currentPacket.header.recipient == RFM95.address || RFM95.currentPacket.header.recipient == RFM95_BROADCAST_ADDRESS)) { + if ((RFM95.currentPacket.header.version >= RFM95_MIN_PACKET_HEADER_VERSION) && + (RFM95_PROMISCUOUS || RFM95.currentPacket.header.recipient == RFM95.address || + RFM95.currentPacket.header.recipient == RFM95_BROADCAST_ADDRESS)) { RFM95.rxBufferValid = true; } } - - } - else if (RFM95.radioMode == RFM95_RADIO_MODE_TX && (irqFlags & RFM95_TX_DONE) ) { + + } else if (RFM95.radioMode == RFM95_RADIO_MODE_TX && (irqFlags & RFM95_TX_DONE) ) { (void)RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY); - } - else if (RFM95.radioMode == RFM95_RADIO_MODE_CAD && (irqFlags & RFM95_CAD_DONE) ) { + } else if (RFM95.radioMode == RFM95_RADIO_MODE_CAD && (irqFlags & RFM95_CAD_DONE) ) { RFM95.cad = irqFlags & RFM95_CAD_DETECTED; (void)RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY); - } + } // Clear all IRQ flags RFM95_writeReg(RFM95_REG_12_IRQ_FLAGS, 0xFF); } -LOCAL bool RFM95_available(void) { +LOCAL bool RFM95_available(void) +{ if (RFM95.radioMode == RFM95_RADIO_MODE_TX) { return false; } (void)RFM95_setRadioMode(RFM95_RADIO_MODE_RX); - return RFM95.rxBufferValid; + return RFM95.rxBufferValid; } -LOCAL void RFM95_clearRxBuffer(void) { +LOCAL void RFM95_clearRxBuffer(void) +{ noInterrupts(); RFM95.rxBufferValid = false; interrupts(); } -LOCAL uint8_t RFM95_recv(uint8_t* buf) { +LOCAL uint8_t RFM95_recv(uint8_t* buf) +{ if (!RFM95_available()) { return false; } - + // atomic noInterrupts(); const uint8_t payloadLen = RFM95.currentPacket.payloadLen; @@ -234,10 +243,10 @@ LOCAL uint8_t RFM95_recv(uint8_t* buf) { const uint8_t controlFlags = RFM95.currentPacket.header.controlFlags; const rfm95_RSSI_t RSSI = RFM95.currentPacket.RSSI; // of incoming packet const rfm95_SNR_t SNR = RFM95.currentPacket.SNR; - if (buf != NULL) { + if (buf != NULL) { memcpy((void*)buf, (void*)RFM95.currentPacket.payload, payloadLen); RFM95.rxBufferValid = false; - } + } interrupts(); // ACK handling @@ -249,29 +258,32 @@ LOCAL uint8_t RFM95_recv(uint8_t* buf) { return payloadLen; } -LOCAL bool RFM95_send(rfm95_packet_t &packet) { +LOCAL bool RFM95_send(rfm95_packet_t &packet) +{ const uint8_t finalLen = packet.payloadLen + RFM95_HEADER_LEN; // Make sure we dont interrupt an outgoing message RFM95_waitPacketSent(); (void)RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY); - + // Check channel activity if (!RFM95_waitCAD()) { - return false; + return false; } - packet.header.sequenceNumber = RFM95.txSequenceNumber++; - // Position at the beginning of the TX FIFO + packet.header.sequenceNumber = RFM95.txSequenceNumber++; + // Position at the beginning of the TX FIFO RFM95_writeReg(RFM95_REG_0D_FIFO_ADDR_PTR, RFM95_TX_FIFO_ADDR); - // write packet + // write packet RFM95_burstWriteReg(RFM95_REG_00_FIFO, packet.data, finalLen); - // total payload length + // total payload length RFM95_writeReg(RFM95_REG_22_PAYLOAD_LENGTH, finalLen); // send message, if sent, irq fires and radio returns to standby (void)RFM95_setRadioMode(RFM95_RADIO_MODE_TX); return true; } -LOCAL bool RFM95_sendFrame(const uint8_t recipient, uint8_t* data, const uint8_t len, const rfm95_flag_t flags) { +LOCAL bool RFM95_sendFrame(const uint8_t recipient, uint8_t* data, const uint8_t len, + const rfm95_flag_t flags) +{ rfm95_packet_t packet; packet.header.version = RFM95_PACKET_HEADER_VERSION; packet.header.sender = RFM95.address; @@ -283,14 +295,16 @@ LOCAL bool RFM95_sendFrame(const uint8_t recipient, uint8_t* data, const uint8_t return RFM95_send(packet); } -LOCAL void RFM95_setFrequency(const float centre) { - const uint32_t freq = (centre * 1000000.0) / RFM95_FSTEP; +LOCAL void RFM95_setFrequency(const float centre) +{ + const uint32_t freq = (centre * 1000000.0) / RFM95_FSTEP; RFM95_writeReg(RFM95_REG_06_FRF_MSB, (freq >> 16) & 0xff); RFM95_writeReg(RFM95_REG_07_FRF_MID, (freq >> 8) & 0xff); RFM95_writeReg(RFM95_REG_08_FRF_LSB, freq & 0xff); } -LOCAL bool RFM95_setTxPower(uint8_t powerLevel) { +LOCAL bool RFM95_setTxPower(uint8_t powerLevel) +{ // RFM95/96/97/98 does not have RFO pins connected to anything. Only PA_BOOST powerLevel = max((uint8_t)RFM95_MIN_POWER_LEVEL_DBM, powerLevel); powerLevel = min((uint8_t)RFM95_MAX_POWER_LEVEL_DBM, powerLevel); @@ -304,8 +318,7 @@ LOCAL bool RFM95_setTxPower(uint8_t powerLevel) { // My measurements show 20dBm is correct RFM95_writeReg(RFM95_REG_4D_PA_DAC, RFM95_PA_DAC_ENABLE); val = powerLevel - 8; - } - else { + } else { RFM95_writeReg(RFM95_REG_4D_PA_DAC, RFM95_PA_DAC_DISABLE); val = powerLevel - 5; } @@ -318,27 +331,32 @@ LOCAL bool RFM95_setTxPower(uint8_t powerLevel) { } // Sets registers from a canned modem configuration structure -LOCAL void RFM95_setModemRegisters(const rfm95_modemConfig_t config) { +LOCAL void RFM95_setModemRegisters(const rfm95_modemConfig_t config) +{ RFM95_writeReg(RFM95_REG_1D_MODEM_CONFIG1, config.reg_1d); RFM95_writeReg(RFM95_REG_1E_MODEM_CONFIG2, config.reg_1e); RFM95_writeReg(RFM95_REG_26_MODEM_CONFIG3, config.reg_26); } -LOCAL void RFM95_setPreambleLength(const uint16_t preambleLength) { +LOCAL void RFM95_setPreambleLength(const uint16_t preambleLength) +{ RFM95_writeReg(RFM95_REG_20_PREAMBLE_MSB, preambleLength >> 8); RFM95_writeReg(RFM95_REG_21_PREAMBLE_LSB, preambleLength & 0xff); } -LOCAL void RFM95_setAddress(const uint8_t addr) { +LOCAL void RFM95_setAddress(const uint8_t addr) +{ RFM95.address = addr; } -LOCAL uint8_t RFM95_getAddress(void) { +LOCAL uint8_t RFM95_getAddress(void) +{ return RFM95.address; } -LOCAL bool RFM95_isChannelActive(void) { +LOCAL bool RFM95_isChannelActive(void) +{ (void)RFM95_setRadioMode(RFM95_RADIO_MODE_CAD); while (RFM95.radioMode == RFM95_RADIO_MODE_CAD) { doYield(); @@ -347,7 +365,8 @@ LOCAL bool RFM95_isChannelActive(void) { return RFM95.cad; } -LOCAL bool RFM95_setRadioMode(const rfm95_radioMode_t newRadioMode) { +LOCAL bool RFM95_setRadioMode(const rfm95_radioMode_t newRadioMode) +{ if (RFM95.radioMode == newRadioMode) { return false; } @@ -355,35 +374,35 @@ LOCAL bool RFM95_setRadioMode(const rfm95_radioMode_t newRadioMode) { if (newRadioMode == RFM95_RADIO_MODE_STDBY) { regMode = RFM95_MODE_STDBY; - } - else if (newRadioMode == RFM95_RADIO_MODE_SLEEP) { + } else if (newRadioMode == RFM95_RADIO_MODE_SLEEP) { regMode = RFM95_MODE_SLEEP; - } - else if (newRadioMode == RFM95_RADIO_MODE_CAD) { + } else if (newRadioMode == RFM95_RADIO_MODE_CAD) { regMode = RFM95_MODE_CAD; RFM95_writeReg(RFM95_REG_40_DIO_MAPPING1, 0x80); // Interrupt on CadDone, DIO0 - } - else if (newRadioMode == RFM95_RADIO_MODE_RX) { + } else if (newRadioMode == RFM95_RADIO_MODE_RX) { regMode = RFM95_MODE_RXCONTINUOUS; RFM95_writeReg(RFM95_REG_40_DIO_MAPPING1, 0x00); // Interrupt on RxDone, DIO0 - } - else if (newRadioMode == RFM95_RADIO_MODE_TX) { + } else if (newRadioMode == RFM95_RADIO_MODE_TX) { regMode = RFM95_MODE_TX; RFM95_writeReg(RFM95_REG_40_DIO_MAPPING1, 0x40); // Interrupt on TxDone, DIO0 + } else { + return false; } - else return false; RFM95_writeReg(RFM95_REG_01_OP_MODE, regMode); RFM95.radioMode = newRadioMode; return true; } -LOCAL bool RFM95_sleep(void) { +LOCAL bool RFM95_sleep(void) +{ return RFM95_setRadioMode(RFM95_RADIO_MODE_SLEEP); } // should be called immediately after reception in case sender wants ACK -LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t sequenceNumber, const rfm95_RSSI_t RSSI, const rfm95_RSSI_t SNR) { +LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t sequenceNumber, + const rfm95_RSSI_t RSSI, const rfm95_RSSI_t SNR) +{ RFM95_DEBUG(PSTR("RFM95:SAC:SEND ACK to=%d,RSSI=%d\n"),recipient,RSSI); rfm95_ack_t ACK; ACK.sequenceNumber = sequenceNumber; @@ -395,25 +414,26 @@ LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t s (void)RFM95_sendFrame(recipient, (uint8_t*)&ACK, sizeof(rfm95_ack_t), flags); } -LOCAL bool RFM95_executeATC(const rfm95_RSSI_t currentRSSI, const rfm95_RSSI_t targetRSSI) { +LOCAL bool RFM95_executeATC(const rfm95_RSSI_t currentRSSI, const rfm95_RSSI_t targetRSSI) +{ // allow +-5% if (currentRSSI < (targetRSSI*1.05) && RFM95.powerLevel < RFM95_MAX_POWER_LEVEL_DBM) { // increase transmitter power RFM95.powerLevel++; - } - else if (currentRSSI > (targetRSSI*0.95) && RFM95.powerLevel > RFM95_MIN_POWER_LEVEL_DBM) { + } else if (currentRSSI > (targetRSSI*0.95) && RFM95.powerLevel > RFM95_MIN_POWER_LEVEL_DBM) { // decrease transmitter power RFM95.powerLevel--; - } - else { + } else { // nothing to adjust return false; } - RFM95_DEBUG(PSTR("RFM95:ATC:ADJ TXL,cR=%d,tR=%d,TXL=%d\n"), currentRSSI - RFM95_RSSI_OFFSET, targetRSSI - RFM95_RSSI_OFFSET, RFM95.powerLevel); + RFM95_DEBUG(PSTR("RFM95:ATC:ADJ TXL,cR=%d,tR=%d,TXL=%d\n"), currentRSSI - RFM95_RSSI_OFFSET, + targetRSSI - RFM95_RSSI_OFFSET, RFM95.powerLevel); return RFM95_setTxPower(RFM95.powerLevel);; } -LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer, const uint8_t bufferSize, const uint8_t retries, const uint32_t retryWaitTime) +LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer, + const uint8_t bufferSize, const uint8_t retries, const uint32_t retryWaitTime) { for (uint8_t retry = 0; retry < retries; retry++) { RFM95_DEBUG(PSTR("RFM95:SWR:SEND TO=%d,RETRY=%d\n"), recipient, retry); @@ -431,10 +451,12 @@ LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer, cons const uint8_t sender = RFM95.currentPacket.header.sender; const rfm95_sequenceNumber_t ACKsequenceNumber = RFM95.currentPacket.ACK.sequenceNumber; const rfm95_flag_t flag = RFM95.currentPacket.header.controlFlags; - if (sender == recipient && RFM95_getACKReceived(flag) && (ACKsequenceNumber == RFM95.txSequenceNumber - 1)) { - RFM95_DEBUG(PSTR("RFM95:SWR:ACK FROM=%d,SEQ=%d,RSSI=%d,SNR=%d\n"),sender,ACKsequenceNumber, RFM95.currentPacket.ACK.RSSI-RFM95_RSSI_OFFSET, (int8_t)RFM95.currentPacket.ACK.SNR / 4); + if (sender == recipient && RFM95_getACKReceived(flag) && + (ACKsequenceNumber == RFM95.txSequenceNumber - 1)) { + RFM95_DEBUG(PSTR("RFM95:SWR:ACK FROM=%d,SEQ=%d,RSSI=%d,SNR=%d\n"),sender,ACKsequenceNumber, + RFM95.currentPacket.ACK.RSSI-RFM95_RSSI_OFFSET, (int8_t)RFM95.currentPacket.ACK.SNR / 4); RFM95_clearRxBuffer(); - + // ATC if (RFM95.ATCenabled && RFM95_getACKRSSIReport(flag)) { (void)RFM95_executeATC(RFM95.currentPacket.ACK.RSSI, RFM95.ATCtargetRSSI); @@ -455,7 +477,8 @@ LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer, cons // Wait until no channel activity detected or timeout -LOCAL bool RFM95_waitCAD(void) { +LOCAL bool RFM95_waitCAD(void) +{ const uint32_t enterMS = hwMillis(); while (RFM95_isChannelActive()) { if (hwMillis() - enterMS > RFM95_CAD_TIMEOUT_MS) { @@ -467,23 +490,27 @@ LOCAL bool RFM95_waitCAD(void) { } // Wait for any previous transmission to finish -LOCAL bool RFM95_waitPacketSent(void) { +LOCAL bool RFM95_waitPacketSent(void) +{ while (RFM95.radioMode == RFM95_RADIO_MODE_TX) { doYield(); } return true; } -LOCAL int16_t RFM95_getRSSI(void) { +LOCAL int16_t RFM95_getRSSI(void) +{ return (int16_t)(RFM95.currentPacket.RSSI - RFM95_RSSI_OFFSET); } -LOCAL void RFM95_ATCmode(const bool OnOff, const int16_t targetRSSI) { +LOCAL void RFM95_ATCmode(const bool OnOff, const int16_t targetRSSI) +{ RFM95.ATCenabled = OnOff; RFM95.ATCtargetRSSI = (uint8_t)(targetRSSI + RFM95_RSSI_OFFSET); } -LOCAL bool RFM95_sanityCheck(void) { +LOCAL bool RFM95_sanityCheck(void) +{ // not implemented yet return true; } diff --git a/drivers/RFM95/RFM95.h b/drivers/RFM95/RFM95.h index 963fcf7..0a35f29 100644 --- a/drivers/RFM95/RFM95.h +++ b/drivers/RFM95/RFM95.h @@ -23,73 +23,73 @@ * Changelog: * - ACK with sequenceNumber * - ATC control - * + * * Definitions for HopeRF LoRa radios: * http://www.hoperf.com/upload/rf/RFM95_96_97_98W.pdf * http://www.hoperf.cn/upload/rfchip/RF96_97_98.pdf * */ - /** - * @file RFM95.h - * - * @defgroup RFM95grp RFM95 - * @ingroup internals - * @{ - * - * RFM95 driver-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE - * - [!] Exclamation mark is prepended in case of error - * - * This section is WIP! - * - * |E| SYS | SUB | Message | Comment - * |-|-------|----------|-----------------------------------|--------------------------------------------------------------------- - * | | RFM95 | INIT | | Initialise RFM95 radio - * | | RFM95 | RCV | SEND ACK | ACK request received, sending ACK back - * | | RFM95 | PTC | LEVEL=%d | Set TX power level - * | | RFM95 | SAC | SEND ACK TO=%d,RSSI=%d | Send ACK to node (TO), RSSI of received message (RSSI) - * | | RFM95 | ATC | ADJ TXL,cR=%d,tR=%d,TXL=%d | Adjust TX level, current RSSI (cR), target RSSI (tR), TX level (TXL) - * | | RFM95 | SWR | SEND TO=%d,RETRY=%d | Send message to (TO), NACK retry counter (RETRY) - * | | RFM95 | SWR | ACK FROM=%d,SEQ=%d,RSSI=%d,SNR=%d | ACK received from node (FROM), seq ID (SEQ), (RSSI), (SNR) - * |!| RFM95 | SWR | NACK | No ACK received +/** +* @file RFM95.h +* +* @defgroup RFM95grp RFM95 +* @ingroup internals +* @{ +* +* RFM95 driver-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE +* - [!] Exclamation mark is prepended in case of error +* +* This section is WIP! +* +* |E| SYS | SUB | Message | Comment +* |-|-------|----------|-----------------------------------|--------------------------------------------------------------------- +* | | RFM95 | INIT | | Initialise RFM95 radio +* | | RFM95 | RCV | SEND ACK | ACK request received, sending ACK back +* | | RFM95 | PTC | LEVEL=%d | Set TX power level +* | | RFM95 | SAC | SEND ACK TO=%d,RSSI=%d | Send ACK to node (TO), RSSI of received message (RSSI) +* | | RFM95 | ATC | ADJ TXL,cR=%d,tR=%d,TXL=%d | Adjust TX level, current RSSI (cR), target RSSI (tR), TX level (TXL) +* | | RFM95 | SWR | SEND TO=%d,RETRY=%d | Send message to (TO), NACK retry counter (RETRY) +* | | RFM95 | SWR | ACK FROM=%d,SEQ=%d,RSSI=%d,SNR=%d | ACK received from node (FROM), seq ID (SEQ), (RSSI), (SNR) +* |!| RFM95 | SWR | NACK | No ACK received - * - * - * RFM95 modem configuration - * - * BW = Bandwidth in kHz - * CR = Error correction code - * SF = Spreading factor, chips / symbol - * - * | CONFIG | REG_1D | REG_1E | REG_26 | BW | CR | SF | Comment - * |------------------|--------|--------|--------|-------|-----|------|----------------------------- - * | BW125CR45SF128 | 0x72 | 0x74 | 0x04 | 125 | 4/5 | 128 | Default, medium range - * | BW500CR45SF128 | 0x92 | 0x74 | 0x04 | 500 | 4/5 | 128 | Fast, short range - * | BW31_25CR48SF512 | 0x48 | 0x94 | 0x04 | 31.25 | 4/8 | 512 | Slow, long range - * | BW125CR48SF4096 | 0x78 | 0xC4 | 0x0C | 125 | 4/8 | 4096 | Slow, long range - * - * @brief API declaration for RFM95 - * - */ +* +* +* RFM95 modem configuration +* +* BW = Bandwidth in kHz +* CR = Error correction code +* SF = Spreading factor, chips / symbol +* +* | CONFIG | REG_1D | REG_1E | REG_26 | BW | CR | SF | Comment +* |------------------|--------|--------|--------|-------|-----|------|----------------------------- +* | BW125CR45SF128 | 0x72 | 0x74 | 0x04 | 125 | 4/5 | 128 | Default, medium range +* | BW500CR45SF128 | 0x92 | 0x74 | 0x04 | 500 | 4/5 | 128 | Fast, short range +* | BW31_25CR48SF512 | 0x48 | 0x94 | 0x04 | 31.25 | 4/8 | 512 | Slow, long range +* | BW125CR48SF4096 | 0x78 | 0xC4 | 0x0C | 125 | 4/8 | 4096 | Slow, long range +* +* @brief API declaration for RFM95 +* +*/ #ifndef _RFM95_h #define _RFM95_h #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__) - #define RFM95_IRQ_PIN (2) - #define RFM95_RST_PIN (9) +#define RFM95_IRQ_PIN (2) +#define RFM95_RST_PIN (9) #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) - #define RFM95_IRQ_PIN (2) - #define RFM95_RST_PIN (9) +#define RFM95_IRQ_PIN (2) +#define RFM95_RST_PIN (9) #elif defined(__AVR_ATmega32U4__) - #define RFM95_IRQ_PIN (3) - #define RFM95_RST_PIN (9) +#define RFM95_IRQ_PIN (3) +#define RFM95_RST_PIN (9) #elif defined(__arm__) - #define RFM95_IRQ_PIN (10) - #define RFM95_RST_PIN (27) -#else - #define RFM95_IRQ_PIN (2) //!< RFM95_IRQ_PIN - #define RFM95_RST_PIN (9) //!< RFM95_IRQ_PIN +#define RFM95_IRQ_PIN (10) +#define RFM95_RST_PIN (27) +#else +#define RFM95_IRQ_PIN (2) //!< RFM95_IRQ_PIN +#define RFM95_RST_PIN (9) //!< RFM95_IRQ_PIN #endif // SPI settings @@ -97,36 +97,37 @@ #if !defined(MY_RFM95_SPI_MAX_SPEED) - #define MY_RFM95_SPI_MAX_SPEED 4000000 //!< SPI speed +#define MY_RFM95_SPI_MAX_SPEED 4000000 //!< SPI speed #endif #define MY_RFM95_SPI_DATA_ORDER MSBFIRST //!< SPI data order #define MY_RFM95_SPI_DATA_MODE SPI_MODE0 //!< SPI mode #if defined (ARDUINO) && !defined (__arm__) && !defined (_SPI) - #include - #if defined(MY_SOFTSPI) - SoftSPI _SPI; - #else - #define _SPI SPI - #endif +#include +#if defined(MY_SOFTSPI) +SoftSPI +_SPI; #else - #if defined(__arm__) - #include - #else - extern HardwareSPI SPI; //!< SPI - #endif - - #if !defined(_SPI) - #define _SPI SPI //!< SPI - #endif +#define _SPI SPI +#endif +#else +#if defined(__arm__) +#include +#else +extern HardwareSPI SPI; //!< SPI #endif -// debug +#if !defined(_SPI) +#define _SPI SPI //!< SPI +#endif +#endif + +// debug #if defined(MY_DEBUG_VERBOSE_RFM95) - #define RFM95_DEBUG(x,...) debug(x, ##__VA_ARGS__) //!< Debug print +#define RFM95_DEBUG(x,...) debug(x, ##__VA_ARGS__) //!< Debug print #else - #define RFM95_DEBUG(x,...) //!< Debug null +#define RFM95_DEBUG(x,...) //!< Debug null #endif #define RFM95_FIFO_SIZE (0xFFu) //!< Max number of bytes the LORA Rx/Tx FIFO can hold @@ -247,7 +248,7 @@ typedef struct { uint8_t payloadLen; //!< Length of payload (excluding header) rfm95_RSSI_t RSSI; //!< RSSI of current packet, RSSI = value - 137 rfm95_SNR_t SNR; //!< SNR of current packet -} __attribute__((packed)) rfm95_packet_t; +} __attribute__((packed)) rfm95_packet_t; /** @@ -316,7 +317,8 @@ LOCAL bool RFM95_send(rfm95_packet_t &packet); * @param flags * @return True if frame sent */ -LOCAL bool RFM95_sendFrame(const uint8_t recipient, uint8_t* data, const uint8_t len, const rfm95_flag_t flags); +LOCAL bool RFM95_sendFrame(const uint8_t recipient, uint8_t* data, const uint8_t len, + const rfm95_flag_t flags); /** * @brief RFM95_setPreambleLength * @param preambleLength @@ -350,7 +352,8 @@ LOCAL bool RFM95_isChannelActive(void); * @param RSSI (rfm95_RSSI_t) * @param SNR (rfm95_RSSI_t) */ -LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t sequenceNumber, const rfm95_RSSI_t RSSI, const rfm95_RSSI_t SNR); +LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t sequenceNumber, + const rfm95_RSSI_t RSSI, const rfm95_RSSI_t SNR); /** * @brief RFM95_sendWithRetry * @param recipient @@ -360,7 +363,9 @@ LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t s * @param retryWaitTime * @return True if packet successfully sent */ -LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer, const uint8_t bufferSize, const uint8_t retries = RFM95_RETRIES, const uint32_t retryWaitTime = RFM95_RETRY_TIMEOUT_MS); +LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer, + const uint8_t bufferSize, const uint8_t retries = RFM95_RETRIES, + const uint32_t retryWaitTime = RFM95_RETRY_TIMEOUT_MS); /** * @brief RFM95_waitCAD * @return True if no channel activity detected @@ -476,7 +481,7 @@ volatile rfm95_internal_t RFM95; //!< internal variables #define RFM95_MODE_RXSINGLE 0x06 //!< MODE_RXSINGLE #define RFM95_MODE_CAD 0x07 //!< MODE_CAD -// RFM95_REG_09_PA_CONFIG 0x09 +// RFM95_REG_09_PA_CONFIG 0x09 #define RFM95_OUTPUT_POWER 0x0F //!< OUTPUT_POWER #define RFM95_MAX_POWER 0x70 //!< MAX_POWER #define RFM95_PA_SELECT 0x80 //!< PA_SELECT diff --git a/drivers/RPi/SPI.cpp b/drivers/RPi/SPI.cpp index 9ec5857..1b8684e 100644 --- a/drivers/RPi/SPI.cpp +++ b/drivers/RPi/SPI.cpp @@ -31,11 +31,13 @@ SPIClass SPI = SPIClass(); uint8_t SPIClass::initialized = 0; -uint8_t SPIClass::is_initialized() { +uint8_t SPIClass::is_initialized() +{ return initialized; } -void SPIClass::begin() { +void SPIClass::begin() +{ if (!initialized) { if (!bcm2835_spi_begin()) { logError("You need root privilege to use SPI.\n"); @@ -46,7 +48,8 @@ void SPIClass::begin() { initialized++; // reference count } -void SPIClass::end() { +void SPIClass::end() +{ if (initialized) { initialized--; } @@ -57,47 +60,53 @@ void SPIClass::end() { } } -void SPIClass::setBitOrder(uint8_t bit_order) { +void SPIClass::setBitOrder(uint8_t bit_order) +{ bcm2835_spi_setBitOrder(bit_order); } -void SPIClass::setDataMode(uint8_t data_mode) { +void SPIClass::setDataMode(uint8_t data_mode) +{ bcm2835_spi_setDataMode(data_mode); } -void SPIClass::setClockDivider(uint16_t divider) { +void SPIClass::setClockDivider(uint16_t divider) +{ bcm2835_spi_setClockDivider(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; - } - else if (csn_pin == RPI_GPIO_P1_24) { + } else if (csn_pin == RPI_GPIO_P1_24) { csn_pin = BCM2835_SPI_CS0; - } - else { + } else { csn_pin = BCM2835_SPI_CS0; } bcm2835_spi_chipSelect(csn_pin); delayMicroseconds(5); } -void SPIClass::beginTransaction(SPISettings settings) { +void SPIClass::beginTransaction(SPISettings settings) +{ pthread_mutex_lock(&spiMutex); setBitOrder(settings.border); setDataMode(settings.dmode); setClockDivider(settings.cdiv); } -void SPIClass::endTransaction() { +void SPIClass::endTransaction() +{ pthread_mutex_unlock(&spiMutex); } -void SPIClass::usingInterrupt(uint8_t interruptNumber) { +void SPIClass::usingInterrupt(uint8_t interruptNumber) +{ (void)interruptNumber; } -void SPIClass::notUsingInterrupt(uint8_t interruptNumber) { +void SPIClass::notUsingInterrupt(uint8_t interruptNumber) +{ (void)interruptNumber; } diff --git a/drivers/RPi/SPI.h b/drivers/RPi/SPI.h index d83a540..7aba9c3 100644 --- a/drivers/RPi/SPI.h +++ b/drivers/RPi/SPI.h @@ -45,7 +45,8 @@ /** * SPISettings class */ -class SPISettings { +class SPISettings +{ public: /** @@ -53,7 +54,8 @@ public: * * Default clock speed is 8Mhz. */ - SPISettings() { + SPISettings() + { init(BCM2835_SPI_CLOCK_DIVIDER_32, BCM2835_SPI_BIT_ORDER_MSBFIRST, BCM2835_SPI_MODE0); } /** @@ -63,31 +65,32 @@ public: * @param bitOrder SPI bit order. * @param dataMode SPI data mode. */ - SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { + SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) + { uint16_t divider; switch (clock) { - case 500000: - divider = BCM2835_SPI_CLOCK_DIVIDER_512; - break; - case 1000000: - divider = BCM2835_SPI_CLOCK_DIVIDER_256; - break; - case 2000000: - divider = BCM2835_SPI_CLOCK_DIVIDER_128; - break; - case 4000000: - divider = BCM2835_SPI_CLOCK_DIVIDER_64; - break; - case 8000000: - divider = BCM2835_SPI_CLOCK_DIVIDER_32; - break; - case 16000000: - divider = BCM2835_SPI_CLOCK_DIVIDER_16; - break; - default: - // 8Mhz - divider = BCM2835_SPI_CLOCK_DIVIDER_32; + case 500000: + divider = BCM2835_SPI_CLOCK_DIVIDER_512; + break; + case 1000000: + divider = BCM2835_SPI_CLOCK_DIVIDER_256; + break; + case 2000000: + divider = BCM2835_SPI_CLOCK_DIVIDER_128; + break; + case 4000000: + divider = BCM2835_SPI_CLOCK_DIVIDER_64; + break; + case 8000000: + divider = BCM2835_SPI_CLOCK_DIVIDER_32; + break; + case 16000000: + divider = BCM2835_SPI_CLOCK_DIVIDER_16; + break; + default: + // 8Mhz + divider = BCM2835_SPI_CLOCK_DIVIDER_32; } init(divider, bitOrder, dataMode); @@ -105,7 +108,8 @@ private: * @param bitOrder SPI bit order. * @param dataMode SPI data mode. */ - void init(uint16_t divider, uint8_t bitOrder, uint8_t dataMode) { + void init(uint16_t divider, uint8_t bitOrder, uint8_t dataMode) + { cdiv = divider; border = bitOrder; dmode = dataMode; @@ -117,7 +121,8 @@ private: /** * SPIClass class */ -class SPIClass { +class SPIClass +{ private: static uint8_t initialized; //!< @brief SPI initialized flag. @@ -150,7 +155,7 @@ public: * @param buf Buffer to read from and write to. * @param len Buffer length. */ - inline static void transfern(char* buf, uint32_t len); + inline static void transfern(char* buf, uint32_t len); /** * @brief Start SPI operations. */ @@ -207,15 +212,18 @@ public: static void notUsingInterrupt(uint8_t interruptNumber); }; -uint8_t SPIClass::transfer(uint8_t data) { +uint8_t SPIClass::transfer(uint8_t data) +{ return bcm2835_spi_transfer(data); } -void SPIClass::transfernb(char* tbuf, char* rbuf, uint32_t len) { +void SPIClass::transfernb(char* tbuf, char* rbuf, uint32_t len) +{ bcm2835_spi_transfernb( tbuf, rbuf, len); } -void SPIClass::transfern(char* buf, uint32_t len) { +void SPIClass::transfern(char* buf, uint32_t len) +{ transfernb(buf, buf, len); } diff --git a/drivers/RPi/Wire.cpp b/drivers/RPi/Wire.cpp index 69ac5a3..eeb487f 100644 --- a/drivers/RPi/Wire.cpp +++ b/drivers/RPi/Wire.cpp @@ -150,7 +150,7 @@ size_t TwoWire::write(uint8_t data) // put byte in tx buffer txBuffer[txBufferIndex] = data; ++txBufferIndex; - // update amount in buffer + // update amount in buffer txBufferLength = txBufferIndex; return 1; diff --git a/drivers/RPi/Wire.h b/drivers/RPi/Wire.h index a82625b..57c799b 100644 --- a/drivers/RPi/Wire.h +++ b/drivers/RPi/Wire.h @@ -31,7 +31,8 @@ #define BUFFER_LENGTH 32 -class TwoWire : public Stream { +class TwoWire : public Stream +{ private: static uint8_t rxBuffer[]; @@ -67,10 +68,22 @@ public: int peek(); void flush(); - inline size_t write(unsigned long n) { return write((uint8_t)n); } - inline size_t write(long n) { return write((uint8_t)n); } - inline size_t write(unsigned int n) { return write((uint8_t)n); } - inline size_t write(int n) { return write((uint8_t)n); } + inline size_t write(unsigned long n) + { + return write((uint8_t)n); + } + inline size_t write(long n) + { + return write((uint8_t)n); + } + inline size_t write(unsigned int n) + { + return write((uint8_t)n); + } + inline size_t write(int n) + { + return write((uint8_t)n); + } using Print::write; }; diff --git a/drivers/RPi/bcm2835.c b/drivers/RPi/bcm2835.c index 26aa8d6..2753826 100644 --- a/drivers/RPi/bcm2835.c +++ b/drivers/RPi/bcm2835.c @@ -44,7 +44,7 @@ uint32_t *bcm2835_peripherals_base = (uint32_t *)BCM2835_PERI_BASE; uint32_t bcm2835_peripherals_size = BCM2835_PERI_SIZE; -/* Virtual memory address of the mapped peripherals block +/* Virtual memory address of the mapped peripherals block */ uint32_t *bcm2835_peripherals = (uint32_t *)MAP_FAILED; @@ -77,36 +77,35 @@ static int i2c_byte_wait_us = 0; /* Function to return the pointers to the hardware register bases */ uint32_t* bcm2835_regbase(uint8_t regbase) { - switch (regbase) - { + switch (regbase) { case BCM2835_REGBASE_ST: - return (uint32_t *)bcm2835_st; + return (uint32_t *)bcm2835_st; case BCM2835_REGBASE_GPIO: - return (uint32_t *)bcm2835_gpio; + return (uint32_t *)bcm2835_gpio; case BCM2835_REGBASE_PWM: - return (uint32_t *)bcm2835_pwm; + return (uint32_t *)bcm2835_pwm; case BCM2835_REGBASE_CLK: - return (uint32_t *)bcm2835_clk; + return (uint32_t *)bcm2835_clk; case BCM2835_REGBASE_PADS: - return (uint32_t *)bcm2835_pads; + return (uint32_t *)bcm2835_pads; case BCM2835_REGBASE_SPI0: - return (uint32_t *)bcm2835_spi0; + return (uint32_t *)bcm2835_spi0; case BCM2835_REGBASE_BSC0: - return (uint32_t *)bcm2835_bsc0; + return (uint32_t *)bcm2835_bsc0; case BCM2835_REGBASE_BSC1: - return (uint32_t *)bcm2835_st; - } - return (uint32_t *)MAP_FAILED; + return (uint32_t *)bcm2835_st; + } + return (uint32_t *)MAP_FAILED; } void bcm2835_set_debug(uint8_t d) { - debug = d; + debug = d; } -unsigned int bcm2835_version(void) +unsigned int bcm2835_version(void) { - return BCM2835_VERSION; + return BCM2835_VERSION; } /* Read with memory barriers from peripheral @@ -114,19 +113,16 @@ unsigned int bcm2835_version(void) */ uint32_t bcm2835_peri_read(volatile uint32_t* paddr) { - uint32_t ret; - if (debug) - { - printf("bcm2835_peri_read paddr %08X\n", (unsigned) paddr); - return 0; - } - else - { - __sync_synchronize(); - ret = *paddr; - __sync_synchronize(); - return ret; - } + uint32_t ret; + if (debug) { + printf("bcm2835_peri_read paddr %08X\n", (unsigned) paddr); + return 0; + } else { + __sync_synchronize(); + ret = *paddr; + __sync_synchronize(); + return ret; + } } /* read from peripheral without the read barrier @@ -137,15 +133,12 @@ uint32_t bcm2835_peri_read(volatile uint32_t* paddr) */ uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr) { - if (debug) - { - printf("bcm2835_peri_read_nb paddr %08X\n", (unsigned) paddr); - return 0; - } - else - { - return *paddr; - } + if (debug) { + printf("bcm2835_peri_read_nb paddr %08X\n", (unsigned) paddr); + return 0; + } else { + return *paddr; + } } /* Write with memory barriers to peripheral @@ -153,30 +146,24 @@ uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr) void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value) { - if (debug) - { - printf("bcm2835_peri_write paddr %08X, value %08X\n", (unsigned) paddr, value); - } - else - { - __sync_synchronize(); - *paddr = value; - __sync_synchronize(); - } + if (debug) { + printf("bcm2835_peri_write paddr %08X, value %08X\n", (unsigned) paddr, value); + } else { + __sync_synchronize(); + *paddr = value; + __sync_synchronize(); + } } /* write to peripheral without the write barrier */ void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value) { - if (debug) - { - printf("bcm2835_peri_write_nb paddr %08X, value %08X\n", - (unsigned) paddr, value); - } - else - { - *paddr = value; - } + if (debug) { + printf("bcm2835_peri_write_nb paddr %08X, value %08X\n", + (unsigned) paddr, value); + } else { + *paddr = value; + } } /* Set/clear only the bits in value covered by the mask @@ -184,9 +171,9 @@ void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value) */ void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask) { - uint32_t v = bcm2835_peri_read(paddr); - v = (v & ~mask) | (value & mask); - bcm2835_peri_write(paddr, v); + uint32_t v = bcm2835_peri_read(paddr); + v = (v & ~mask) | (value & mask); + bcm2835_peri_write(paddr, v); } /* @@ -213,51 +200,51 @@ void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t ma */ void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode) { - /* Function selects are 10 pins per 32 bit word, 3 bits per pin */ - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFSEL0/4 + (pin/10); - uint8_t shift = (pin % 10) * 3; - uint32_t mask = BCM2835_GPIO_FSEL_MASK << shift; - uint32_t value = mode << shift; - bcm2835_peri_set_bits(paddr, value, mask); + /* Function selects are 10 pins per 32 bit word, 3 bits per pin */ + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFSEL0/4 + (pin/10); + uint8_t shift = (pin % 10) * 3; + uint32_t mask = BCM2835_GPIO_FSEL_MASK << shift; + uint32_t value = mode << shift; + bcm2835_peri_set_bits(paddr, value, mask); } /* Set output pin */ void bcm2835_gpio_set(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPSET0/4 + pin/32; - uint8_t shift = pin % 32; - bcm2835_peri_write(paddr, 1 << shift); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPSET0/4 + pin/32; + uint8_t shift = pin % 32; + bcm2835_peri_write(paddr, 1 << shift); } /* Clear output pin */ void bcm2835_gpio_clr(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPCLR0/4 + pin/32; - uint8_t shift = pin % 32; - bcm2835_peri_write(paddr, 1 << shift); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPCLR0/4 + pin/32; + uint8_t shift = pin % 32; + bcm2835_peri_write(paddr, 1 << shift); } /* Set all output pins in the mask */ void bcm2835_gpio_set_multi(uint32_t mask) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPSET0/4; - bcm2835_peri_write(paddr, mask); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPSET0/4; + bcm2835_peri_write(paddr, mask); } /* Clear all output pins in the mask */ void bcm2835_gpio_clr_multi(uint32_t mask) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPCLR0/4; - bcm2835_peri_write(paddr, mask); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPCLR0/4; + bcm2835_peri_write(paddr, mask); } /* Read input pin */ uint8_t bcm2835_gpio_lev(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEV0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = bcm2835_peri_read(paddr); - return (value & (1 << shift)) ? HIGH : LOW; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEV0/4 + pin/32; + uint8_t shift = pin % 32; + uint32_t value = bcm2835_peri_read(paddr); + return (value & (1 << shift)) ? HIGH : LOW; } /* See if an event detection bit is set @@ -265,135 +252,135 @@ uint8_t bcm2835_gpio_lev(uint8_t pin) */ uint8_t bcm2835_gpio_eds(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = bcm2835_peri_read(paddr); - return (value & (1 << shift)) ? HIGH : LOW; + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4 + pin/32; + uint8_t shift = pin % 32; + uint32_t value = bcm2835_peri_read(paddr); + return (value & (1 << shift)) ? HIGH : LOW; } uint32_t bcm2835_gpio_eds_multi(uint32_t mask) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4; - uint32_t value = bcm2835_peri_read(paddr); - return (value & mask); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4; + uint32_t value = bcm2835_peri_read(paddr); + return (value & mask); } /* Write a 1 to clear the bit in EDS */ void bcm2835_gpio_set_eds(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_write(paddr, value); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4 + pin/32; + uint8_t shift = pin % 32; + uint32_t value = 1 << shift; + bcm2835_peri_write(paddr, value); } void bcm2835_gpio_set_eds_multi(uint32_t mask) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4; - bcm2835_peri_write(paddr, mask); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4; + bcm2835_peri_write(paddr, mask); } /* Rising edge detect enable */ void bcm2835_gpio_ren(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPREN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPREN0/4 + pin/32; + uint8_t shift = pin % 32; + uint32_t value = 1 << shift; + bcm2835_peri_set_bits(paddr, value, value); } void bcm2835_gpio_clr_ren(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPREN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPREN0/4 + pin/32; + uint8_t shift = pin % 32; + uint32_t value = 1 << shift; + bcm2835_peri_set_bits(paddr, 0, value); } /* Falling edge detect enable */ void bcm2835_gpio_fen(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFEN0/4 + pin/32; + uint8_t shift = pin % 32; + uint32_t value = 1 << shift; + bcm2835_peri_set_bits(paddr, value, value); } void bcm2835_gpio_clr_fen(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPFEN0/4 + pin/32; + uint8_t shift = pin % 32; + uint32_t value = 1 << shift; + bcm2835_peri_set_bits(paddr, 0, value); } /* High detect enable */ void bcm2835_gpio_hen(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPHEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPHEN0/4 + pin/32; + uint8_t shift = pin % 32; + uint32_t value = 1 << shift; + bcm2835_peri_set_bits(paddr, value, value); } void bcm2835_gpio_clr_hen(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPHEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPHEN0/4 + pin/32; + uint8_t shift = pin % 32; + uint32_t value = 1 << shift; + bcm2835_peri_set_bits(paddr, 0, value); } /* Low detect enable */ void bcm2835_gpio_len(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEN0/4 + pin/32; + uint8_t shift = pin % 32; + uint32_t value = 1 << shift; + bcm2835_peri_set_bits(paddr, value, value); } void bcm2835_gpio_clr_len(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPLEN0/4 + pin/32; + uint8_t shift = pin % 32; + uint32_t value = 1 << shift; + bcm2835_peri_set_bits(paddr, 0, value); } /* Async rising edge detect enable */ void bcm2835_gpio_aren(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAREN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAREN0/4 + pin/32; + uint8_t shift = pin % 32; + uint32_t value = 1 << shift; + bcm2835_peri_set_bits(paddr, value, value); } void bcm2835_gpio_clr_aren(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAREN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAREN0/4 + pin/32; + uint8_t shift = pin % 32; + uint32_t value = 1 << shift; + bcm2835_peri_set_bits(paddr, 0, value); } /* Async falling edge detect enable */ void bcm2835_gpio_afen(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAFEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, value, value); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAFEN0/4 + pin/32; + uint8_t shift = pin % 32; + uint32_t value = 1 << shift; + bcm2835_peri_set_bits(paddr, value, value); } void bcm2835_gpio_clr_afen(uint8_t pin) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAFEN0/4 + pin/32; - uint8_t shift = pin % 32; - uint32_t value = 1 << shift; - bcm2835_peri_set_bits(paddr, 0, value); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPAFEN0/4 + pin/32; + uint8_t shift = pin % 32; + uint32_t value = 1 << shift; + bcm2835_peri_set_bits(paddr, 0, value); } /* Set pullup/down */ void bcm2835_gpio_pud(uint8_t pud) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUD/4; - bcm2835_peri_write(paddr, pud); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUD/4; + bcm2835_peri_write(paddr, pud); } /* Pullup/down clock @@ -401,20 +388,20 @@ void bcm2835_gpio_pud(uint8_t pud) */ void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on) { - volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUDCLK0/4 + pin/32; - uint8_t shift = pin % 32; - bcm2835_peri_write(paddr, (on ? 1 : 0) << shift); + volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUDCLK0/4 + pin/32; + uint8_t shift = pin % 32; + bcm2835_peri_write(paddr, (on ? 1 : 0) << shift); } /* Read GPIO pad behaviour for groups of GPIOs */ uint32_t bcm2835_gpio_pad(uint8_t group) { - if (bcm2835_pads == MAP_FAILED) { - return 0; - } - - volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group; - return bcm2835_peri_read(paddr); + if (bcm2835_pads == MAP_FAILED) { + return 0; + } + + volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group; + return bcm2835_peri_read(paddr); } /* Set GPIO pad behaviour for groups of GPIOs @@ -423,12 +410,12 @@ uint32_t bcm2835_gpio_pad(uint8_t group) */ void bcm2835_gpio_set_pad(uint8_t group, uint32_t control) { - if (bcm2835_pads == MAP_FAILED) { - return; - } + if (bcm2835_pads == MAP_FAILED) { + return; + } - volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group; - bcm2835_peri_write(paddr, control | BCM2835_PAD_PASSWRD); + volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group; + bcm2835_peri_write(paddr, control | BCM2835_PAD_PASSWRD); } /* Some convenient arduino-like functions @@ -436,39 +423,37 @@ void bcm2835_gpio_set_pad(uint8_t group, uint32_t control) */ void bcm2835_delay(unsigned int millis) { - struct timespec sleeper; - - sleeper.tv_sec = (time_t)(millis / 1000); - sleeper.tv_nsec = (long)(millis % 1000) * 1000000; - nanosleep(&sleeper, NULL); + struct timespec sleeper; + + sleeper.tv_sec = (time_t)(millis / 1000); + sleeper.tv_nsec = (long)(millis % 1000) * 1000000; + nanosleep(&sleeper, NULL); } /* microseconds */ void bcm2835_delayMicroseconds(uint64_t micros) { - struct timespec t1; - uint64_t start; - - if (debug) - { - /* Cant access sytem timers in debug mode */ - printf("bcm2835_delayMicroseconds %lld\n", micros); - return; - } + struct timespec t1; + uint64_t start; - /* Calling nanosleep() takes at least 100-200 us, so use it for - // long waits and use a busy wait on the System Timer for the rest. - */ - start = bcm2835_st_read(); - - if (micros > 450) - { - t1.tv_sec = 0; - t1.tv_nsec = 1000 * (long)(micros - 200); - nanosleep(&t1, NULL); - } - - bcm2835_st_delay(start, micros); + if (debug) { + /* Cant access sytem timers in debug mode */ + printf("bcm2835_delayMicroseconds %lld\n", micros); + return; + } + + /* Calling nanosleep() takes at least 100-200 us, so use it for + // long waits and use a busy wait on the System Timer for the rest. + */ + start = bcm2835_st_read(); + + if (micros > 450) { + t1.tv_sec = 0; + t1.tv_nsec = 1000 * (long)(micros - 200); + nanosleep(&t1, NULL); + } + + bcm2835_st_delay(start, micros); } /* @@ -478,26 +463,28 @@ void bcm2835_delayMicroseconds(uint64_t micros) /* Set the state of an output */ void bcm2835_gpio_write(uint8_t pin, uint8_t on) { - if (on) - bcm2835_gpio_set(pin); - else - bcm2835_gpio_clr(pin); + if (on) { + bcm2835_gpio_set(pin); + } else { + bcm2835_gpio_clr(pin); + } } /* Set the state of a all 32 outputs in the mask to on or off */ void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on) { - if (on) - bcm2835_gpio_set_multi(mask); - else - bcm2835_gpio_clr_multi(mask); + if (on) { + bcm2835_gpio_set_multi(mask); + } else { + bcm2835_gpio_clr_multi(mask); + } } /* Set the state of a all 32 outputs in the mask to the values in value */ void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask) { - bcm2835_gpio_set_multi(value & mask); - bcm2835_gpio_clr_multi((~value) & mask); + bcm2835_gpio_set_multi(value & mask); + bcm2835_gpio_clr_multi((~value) & mask); } /* Set the pullup/down resistor for a pin @@ -520,51 +507,52 @@ void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask) */ void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud) { - bcm2835_gpio_pud(pud); - delayMicroseconds(10); - bcm2835_gpio_pudclk(pin, 1); - delayMicroseconds(10); - bcm2835_gpio_pud(BCM2835_GPIO_PUD_OFF); - bcm2835_gpio_pudclk(pin, 0); + bcm2835_gpio_pud(pud); + delayMicroseconds(10); + bcm2835_gpio_pudclk(pin, 1); + delayMicroseconds(10); + bcm2835_gpio_pud(BCM2835_GPIO_PUD_OFF); + bcm2835_gpio_pudclk(pin, 0); } int bcm2835_spi_begin(void) { - volatile uint32_t* paddr; + volatile uint32_t* paddr; - if (bcm2835_spi0 == MAP_FAILED) - return 0; /* bcm2835_init() failed, or not root */ - - /* Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them */ - bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); /* CE1 */ - bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_ALT0); /* CE0 */ - bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_ALT0); /* MISO */ - bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_ALT0); /* MOSI */ - bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_ALT0); /* CLK */ - - /* Set the SPI CS register to the some sensible defaults */ - paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - bcm2835_peri_write(paddr, 0); /* All 0s */ - - /* Clear TX and RX fifos */ - bcm2835_peri_write_nb(paddr, BCM2835_SPI0_CS_CLEAR); + if (bcm2835_spi0 == MAP_FAILED) { + return 0; /* bcm2835_init() failed, or not root */ + } - return 1; // OK + /* Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them */ + bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); /* CE1 */ + bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_ALT0); /* CE0 */ + bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_ALT0); /* MISO */ + bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_ALT0); /* MOSI */ + bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_ALT0); /* CLK */ + + /* Set the SPI CS register to the some sensible defaults */ + paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; + bcm2835_peri_write(paddr, 0); /* All 0s */ + + /* Clear TX and RX fifos */ + bcm2835_peri_write_nb(paddr, BCM2835_SPI0_CS_CLEAR); + + return 1; // OK } void bcm2835_spi_end(void) -{ - /* Set all the SPI0 pins back to input */ - bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_INPT); /* CE1 */ - bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_INPT); /* CE0 */ - bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_INPT); /* MISO */ - bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_INPT); /* MOSI */ - bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_INPT); /* CLK */ +{ + /* Set all the SPI0 pins back to input */ + bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_INPT); /* CE1 */ + bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_INPT); /* CE0 */ + bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_INPT); /* MISO */ + bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_INPT); /* MOSI */ + bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_INPT); /* CLK */ } void bcm2835_spi_setBitOrder(uint8_t __attribute__((unused)) order) { - /* BCM2835_SPI_BIT_ORDER_MSBFIRST is the only one supported by SPI0 */ + /* BCM2835_SPI_BIT_ORDER_MSBFIRST is the only one supported by SPI0 */ } /* defaults to 0, which means a divider of 65536. @@ -574,138 +562,136 @@ void bcm2835_spi_setBitOrder(uint8_t __attribute__((unused)) order) */ void bcm2835_spi_setClockDivider(uint16_t divider) { - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CLK/4; - bcm2835_peri_write(paddr, divider); + volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CLK/4; + bcm2835_peri_write(paddr, divider); } void bcm2835_spi_setDataMode(uint8_t mode) { - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - /* Mask in the CPO and CPHA bits of CS */ - bcm2835_peri_set_bits(paddr, mode << 2, BCM2835_SPI0_CS_CPOL | BCM2835_SPI0_CS_CPHA); + volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; + /* Mask in the CPO and CPHA bits of CS */ + bcm2835_peri_set_bits(paddr, mode << 2, BCM2835_SPI0_CS_CPOL | BCM2835_SPI0_CS_CPHA); } /* Writes (and reads) a single byte to SPI */ uint8_t bcm2835_spi_transfer(uint8_t value) { - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; - uint32_t ret; + volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; + volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; + uint32_t ret; - /* This is Polled transfer as per section 10.6.1 - // BUG ALERT: what happens if we get interupted in this section, and someone else - // accesses a different peripheral? - // Clear TX and RX fifos - */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); + /* This is Polled transfer as per section 10.6.1 + // BUG ALERT: what happens if we get interupted in this section, and someone else + // accesses a different peripheral? + // Clear TX and RX fifos + */ + bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); - /* Set TA = 1 */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); + /* Set TA = 1 */ + bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - /* Maybe wait for TXD */ - while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) - ; + /* Maybe wait for TXD */ + while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) + ; - /* Write to FIFO, no barrier */ - bcm2835_peri_write_nb(fifo, value); + /* Write to FIFO, no barrier */ + bcm2835_peri_write_nb(fifo, value); - /* Wait for DONE to be set */ - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) - ; + /* Wait for DONE to be set */ + while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) + ; - /* Read any byte that was sent back by the slave while we sere sending to it */ - ret = bcm2835_peri_read_nb(fifo); + /* Read any byte that was sent back by the slave while we sere sending to it */ + ret = bcm2835_peri_read_nb(fifo); - /* Set TA = 0, and also set the barrier */ - bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); + /* Set TA = 0, and also set the barrier */ + bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); - return ret; + return ret; } /* Writes (and reads) an number of bytes to SPI */ void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len) { - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; - uint32_t TXCnt=0; - uint32_t RXCnt=0; + volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; + volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; + uint32_t TXCnt=0; + uint32_t RXCnt=0; - /* This is Polled transfer as per section 10.6.1 - // BUG ALERT: what happens if we get interupted in this section, and someone else - // accesses a different peripheral? - */ + /* This is Polled transfer as per section 10.6.1 + // BUG ALERT: what happens if we get interupted in this section, and someone else + // accesses a different peripheral? + */ - /* Clear TX and RX fifos */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); + /* Clear TX and RX fifos */ + bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); - /* Set TA = 1 */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); + /* Set TA = 1 */ + bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - /* Use the FIFO's to reduce the interbyte times */ - while((TXCnt < len)||(RXCnt < len)) - { - /* TX fifo not full, so add some more bytes */ - while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD))&&(TXCnt < len )) - { - bcm2835_peri_write_nb(fifo, tbuf[TXCnt]); - TXCnt++; - } - /* Rx fifo not empty, so get the next received bytes */ - while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD))&&( RXCnt < len )) - { - rbuf[RXCnt] = bcm2835_peri_read_nb(fifo); - RXCnt++; - } - } - /* Wait for DONE to be set */ - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) - ; + /* Use the FIFO's to reduce the interbyte times */ + while((TXCnt < len)||(RXCnt < len)) { + /* TX fifo not full, so add some more bytes */ + while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD))&&(TXCnt < len )) { + bcm2835_peri_write_nb(fifo, tbuf[TXCnt]); + TXCnt++; + } + /* Rx fifo not empty, so get the next received bytes */ + while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD))&&( RXCnt < len )) { + rbuf[RXCnt] = bcm2835_peri_read_nb(fifo); + RXCnt++; + } + } + /* Wait for DONE to be set */ + while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) + ; - /* Set TA = 0, and also set the barrier */ - bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); + /* Set TA = 0, and also set the barrier */ + bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); } /* Writes an number of bytes to SPI */ void bcm2835_spi_writenb(char* tbuf, uint32_t len) { - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; - uint32_t i; + volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; + volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; + uint32_t i; - /* This is Polled transfer as per section 10.6.1 - // BUG ALERT: what happens if we get interupted in this section, and someone else - // accesses a different peripheral? - // Answer: an ISR is required to issue the required memory barriers. - */ + /* This is Polled transfer as per section 10.6.1 + // BUG ALERT: what happens if we get interupted in this section, and someone else + // accesses a different peripheral? + // Answer: an ISR is required to issue the required memory barriers. + */ - /* Clear TX and RX fifos */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); + /* Clear TX and RX fifos */ + bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); - /* Set TA = 1 */ - bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); + /* Set TA = 1 */ + bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); - for (i = 0; i < len; i++) - { - /* Maybe wait for TXD */ - while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) - ; - - /* Write to FIFO, no barrier */ - bcm2835_peri_write_nb(fifo, tbuf[i]); - - /* Read from FIFO to prevent stalling */ - while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) - (void) bcm2835_peri_read_nb(fifo); - } - - /* Wait for DONE to be set */ - while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) { - while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) - (void) bcm2835_peri_read_nb(fifo); - }; + for (i = 0; i < len; i++) { + /* Maybe wait for TXD */ + while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) + ; - /* Set TA = 0, and also set the barrier */ - bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); + /* Write to FIFO, no barrier */ + bcm2835_peri_write_nb(fifo, tbuf[i]); + + /* Read from FIFO to prevent stalling */ + while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) { + (void) bcm2835_peri_read_nb(fifo); + } + } + + /* Wait for DONE to be set */ + while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) { + while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) { + (void) bcm2835_peri_read_nb(fifo); + } + }; + + /* Set TA = 0, and also set the barrier */ + bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); } /* Writes (and reads) an number of bytes to SPI @@ -713,77 +699,78 @@ void bcm2835_spi_writenb(char* tbuf, uint32_t len) */ void bcm2835_spi_transfern(char* buf, uint32_t len) { - bcm2835_spi_transfernb(buf, buf, len); + bcm2835_spi_transfernb(buf, buf, len); } void bcm2835_spi_chipSelect(uint8_t cs) { - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - /* Mask in the CS bits of CS */ - bcm2835_peri_set_bits(paddr, cs, BCM2835_SPI0_CS_CS); + volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; + /* Mask in the CS bits of CS */ + bcm2835_peri_set_bits(paddr, cs, BCM2835_SPI0_CS_CS); } void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active) { - volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; - uint8_t shift = 21 + cs; - /* Mask in the appropriate CSPOLn bit */ - bcm2835_peri_set_bits(paddr, active << shift, 1 << shift); + volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; + uint8_t shift = 21 + cs; + /* Mask in the appropriate CSPOLn bit */ + bcm2835_peri_set_bits(paddr, active << shift, 1 << shift); } int bcm2835_i2c_begin(void) { - uint16_t cdiv; + uint16_t cdiv; - if ( bcm2835_bsc0 == MAP_FAILED - || bcm2835_bsc1 == MAP_FAILED) - return 0; /* bcm2835_init() failed, or not root */ + if ( bcm2835_bsc0 == MAP_FAILED + || bcm2835_bsc1 == MAP_FAILED) { + return 0; /* bcm2835_init() failed, or not root */ + } #ifdef I2C_V1 - volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4; - /* Set the I2C/BSC0 pins to the Alt 0 function to enable I2C access on them */ - bcm2835_gpio_fsel(RPI_GPIO_P1_03, BCM2835_GPIO_FSEL_ALT0); /* SDA */ - bcm2835_gpio_fsel(RPI_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); /* SCL */ + volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4; + /* Set the I2C/BSC0 pins to the Alt 0 function to enable I2C access on them */ + bcm2835_gpio_fsel(RPI_GPIO_P1_03, BCM2835_GPIO_FSEL_ALT0); /* SDA */ + bcm2835_gpio_fsel(RPI_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); /* SCL */ #else - volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4; - /* Set the I2C/BSC1 pins to the Alt 0 function to enable I2C access on them */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_ALT0); /* SDA */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); /* SCL */ -#endif + volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4; + /* Set the I2C/BSC1 pins to the Alt 0 function to enable I2C access on them */ + bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_ALT0); /* SDA */ + bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); /* SCL */ +#endif - /* Read the clock divider register */ - cdiv = bcm2835_peri_read(paddr); - /* Calculate time for transmitting one byte - // 1000000 = micros seconds in a second - // 9 = Clocks per byte : 8 bits + ACK - */ - i2c_byte_wait_us = ((float)cdiv / BCM2835_CORE_CLK_HZ) * 1000000 * 9; + /* Read the clock divider register */ + cdiv = bcm2835_peri_read(paddr); + /* Calculate time for transmitting one byte + // 1000000 = micros seconds in a second + // 9 = Clocks per byte : 8 bits + ACK + */ + i2c_byte_wait_us = ((float)cdiv / BCM2835_CORE_CLK_HZ) * 1000000 * 9; - return 1; + return 1; } void bcm2835_i2c_end(void) { #ifdef I2C_V1 - /* Set all the I2C/BSC0 pins back to input */ - bcm2835_gpio_fsel(RPI_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); /* SDA */ - bcm2835_gpio_fsel(RPI_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); /* SCL */ + /* Set all the I2C/BSC0 pins back to input */ + bcm2835_gpio_fsel(RPI_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); /* SDA */ + bcm2835_gpio_fsel(RPI_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); /* SCL */ #else - /* Set all the I2C/BSC1 pins back to input */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); /* SDA */ - bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); /* SCL */ + /* Set all the I2C/BSC1 pins back to input */ + bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); /* SDA */ + bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); /* SCL */ #endif } void bcm2835_i2c_setSlaveAddress(uint8_t addr) { - /* Set I2C Device Address */ + /* Set I2C Device Address */ #ifdef I2C_V1 - volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_A/4; -#else - volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_A/4; + volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_A/4; +#else + volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_A/4; #endif - bcm2835_peri_write(paddr, addr); + bcm2835_peri_write(paddr, addr); } /* defaults to 0x5dc, should result in a 166.666 kHz I2C clock frequency. @@ -793,16 +780,16 @@ void bcm2835_i2c_setSlaveAddress(uint8_t addr) void bcm2835_i2c_setClockDivider(uint16_t divider) { #ifdef I2C_V1 - volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4; + volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4; #else - volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4; -#endif - bcm2835_peri_write(paddr, divider); - /* Calculate time for transmitting one byte - // 1000000 = micros seconds in a second - // 9 = Clocks per byte : 8 bits + ACK - */ - i2c_byte_wait_us = ((float)divider / BCM2835_CORE_CLK_HZ) * 1000000 * 9; + volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4; +#endif + bcm2835_peri_write(paddr, divider); + /* Calculate time for transmitting one byte + // 1000000 = micros seconds in a second + // 9 = Clocks per byte : 8 bits + ACK + */ + i2c_byte_wait_us = ((float)divider / BCM2835_CORE_CLK_HZ) * 1000000 * 9; } /* set I2C clock divider by means of a baudrate number */ @@ -818,468 +805,449 @@ void bcm2835_i2c_set_baudrate(uint32_t baudrate) uint8_t bcm2835_i2c_write(const char * buf, uint32_t len) { #ifdef I2C_V1 - volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; + volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; + volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; + volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; + volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; #else - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; -#endif + volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; + volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; + volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; + volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; +#endif - uint32_t remaining = len; - uint32_t i = 0; - uint8_t reason = BCM2835_I2C_REASON_OK; + uint32_t remaining = len; + uint32_t i = 0; + uint8_t reason = BCM2835_I2C_REASON_OK; - /* Clear FIFO */ - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); - /* Clear Status */ - bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - /* Set Data Length */ - bcm2835_peri_write(dlen, len); - /* pre populate FIFO with max buffer */ - while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) - { - bcm2835_peri_write_nb(fifo, buf[i]); - i++; - remaining--; - } - - /* Enable device and start transfer */ - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); - - /* Transfer is over when BCM2835_BSC_S_DONE */ - while(!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE )) - { - while ( remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_TXD )) - { - /* Write to FIFO */ - bcm2835_peri_write(fifo, buf[i]); - i++; - remaining--; - } - } + /* Clear FIFO */ + bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); + /* Clear Status */ + bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); + /* Set Data Length */ + bcm2835_peri_write(dlen, len); + /* pre populate FIFO with max buffer */ + while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) { + bcm2835_peri_write_nb(fifo, buf[i]); + i++; + remaining--; + } - /* Received a NACK */ - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) - { - reason = BCM2835_I2C_REASON_ERROR_NACK; - } + /* Enable device and start transfer */ + bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); - /* Received Clock Stretch Timeout */ - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) - { - reason = BCM2835_I2C_REASON_ERROR_CLKT; - } + /* Transfer is over when BCM2835_BSC_S_DONE */ + while(!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE )) { + while ( remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_TXD )) { + /* Write to FIFO */ + bcm2835_peri_write(fifo, buf[i]); + i++; + remaining--; + } + } - /* Not all data is sent */ - else if (remaining) - { - reason = BCM2835_I2C_REASON_ERROR_DATA; - } + /* Received a NACK */ + if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { + reason = BCM2835_I2C_REASON_ERROR_NACK; + } - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); + /* Received Clock Stretch Timeout */ + else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) { + reason = BCM2835_I2C_REASON_ERROR_CLKT; + } - return reason; + /* Not all data is sent */ + else if (remaining) { + reason = BCM2835_I2C_REASON_ERROR_DATA; + } + + bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); + + return reason; } /* Read an number of bytes from I2C */ uint8_t bcm2835_i2c_read(char* buf, uint32_t len) { #ifdef I2C_V1 - volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; + volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; + volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; + volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; + volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; #else - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; -#endif + volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; + volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; + volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; + volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; +#endif - uint32_t remaining = len; - uint32_t i = 0; - uint8_t reason = BCM2835_I2C_REASON_OK; + uint32_t remaining = len; + uint32_t i = 0; + uint8_t reason = BCM2835_I2C_REASON_OK; - /* Clear FIFO */ - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); - /* Clear Status */ - bcm2835_peri_write_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - /* Set Data Length */ - bcm2835_peri_write_nb(dlen, len); - /* Start read */ - bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ); - - /* wait for transfer to complete */ - while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) - { - /* we must empty the FIFO as it is populated and not use any delay */ - while (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD) - { - /* Read from FIFO, no barrier */ - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; - } - } - - /* transfer has finished - grab any remaining stuff in FIFO */ - while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD)) - { - /* Read from FIFO, no barrier */ - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; - } - - /* Received a NACK */ - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) - { - reason = BCM2835_I2C_REASON_ERROR_NACK; - } + /* Clear FIFO */ + bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); + /* Clear Status */ + bcm2835_peri_write_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); + /* Set Data Length */ + bcm2835_peri_write_nb(dlen, len); + /* Start read */ + bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ); - /* Received Clock Stretch Timeout */ - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) - { - reason = BCM2835_I2C_REASON_ERROR_CLKT; - } + /* wait for transfer to complete */ + while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) { + /* we must empty the FIFO as it is populated and not use any delay */ + while (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD) { + /* Read from FIFO, no barrier */ + buf[i] = bcm2835_peri_read_nb(fifo); + i++; + remaining--; + } + } - /* Not all data is received */ - else if (remaining) - { - reason = BCM2835_I2C_REASON_ERROR_DATA; - } + /* transfer has finished - grab any remaining stuff in FIFO */ + while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD)) { + /* Read from FIFO, no barrier */ + buf[i] = bcm2835_peri_read_nb(fifo); + i++; + remaining--; + } - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); + /* Received a NACK */ + if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { + reason = BCM2835_I2C_REASON_ERROR_NACK; + } - return reason; + /* Received Clock Stretch Timeout */ + else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) { + reason = BCM2835_I2C_REASON_ERROR_CLKT; + } + + /* Not all data is received */ + else if (remaining) { + reason = BCM2835_I2C_REASON_ERROR_DATA; + } + + bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); + + return reason; } /* Read an number of bytes from I2C sending a repeated start after writing // the required register. Only works if your device supports this mode */ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len) -{ +{ #ifdef I2C_V1 - volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; + volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; + volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; + volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; + volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; #else - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; -#endif + volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; + volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; + volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; + volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; +#endif uint32_t remaining = len; - uint32_t i = 0; - uint8_t reason = BCM2835_I2C_REASON_OK; - - /* Clear FIFO */ - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); - /* Clear Status */ - bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - /* Set Data Length */ - bcm2835_peri_write(dlen, 1); - /* Enable device and start transfer */ - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN); - bcm2835_peri_write(fifo, regaddr[0]); - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); - - /* poll for transfer has started */ - while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) - { - /* Linux may cause us to miss entire transfer stage */ - if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE) - break; - } - - /* Send a repeated start with read bit set in address */ - bcm2835_peri_write(dlen, len); - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ ); - - /* Wait for write to complete and first byte back. */ - bcm2835_delayMicroseconds(i2c_byte_wait_us * 3); - - /* wait for transfer to complete */ - while (!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE)) - { - /* we must empty the FIFO as it is populated and not use any delay */ - while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) - { - /* Read from FIFO */ - buf[i] = bcm2835_peri_read(fifo); - i++; - remaining--; - } - } - - /* transfer has finished - grab any remaining stuff in FIFO */ - while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) - { - /* Read from FIFO */ - buf[i] = bcm2835_peri_read(fifo); - i++; - remaining--; - } - - /* Received a NACK */ - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) - { + uint32_t i = 0; + uint8_t reason = BCM2835_I2C_REASON_OK; + + /* Clear FIFO */ + bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); + /* Clear Status */ + bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); + /* Set Data Length */ + bcm2835_peri_write(dlen, 1); + /* Enable device and start transfer */ + bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN); + bcm2835_peri_write(fifo, regaddr[0]); + bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); + + /* poll for transfer has started */ + while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) { + /* Linux may cause us to miss entire transfer stage */ + if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE) { + break; + } + } + + /* Send a repeated start with read bit set in address */ + bcm2835_peri_write(dlen, len); + bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ ); + + /* Wait for write to complete and first byte back. */ + bcm2835_delayMicroseconds(i2c_byte_wait_us * 3); + + /* wait for transfer to complete */ + while (!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE)) { + /* we must empty the FIFO as it is populated and not use any delay */ + while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) { + /* Read from FIFO */ + buf[i] = bcm2835_peri_read(fifo); + i++; + remaining--; + } + } + + /* transfer has finished - grab any remaining stuff in FIFO */ + while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) { + /* Read from FIFO */ + buf[i] = bcm2835_peri_read(fifo); + i++; + remaining--; + } + + /* Received a NACK */ + if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { reason = BCM2835_I2C_REASON_ERROR_NACK; - } + } - /* Received Clock Stretch Timeout */ - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) - { - reason = BCM2835_I2C_REASON_ERROR_CLKT; - } + /* Received Clock Stretch Timeout */ + else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) { + reason = BCM2835_I2C_REASON_ERROR_CLKT; + } - /* Not all data is sent */ - else if (remaining) - { - reason = BCM2835_I2C_REASON_ERROR_DATA; - } + /* Not all data is sent */ + else if (remaining) { + reason = BCM2835_I2C_REASON_ERROR_DATA; + } - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); + bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); - return reason; + return reason; } -/* Sending an arbitrary number of bytes before issuing a repeated start +/* Sending an arbitrary number of bytes before issuing a repeated start // (with no prior stop) and reading a response. Some devices require this behavior. */ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint32_t buf_len) -{ +{ #ifdef I2C_V1 - volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; + volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; + volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; + volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; + volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; #else - volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; - volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; - volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; - volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; -#endif + volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; + volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; + volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; + volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; +#endif - uint32_t remaining = cmds_len; - uint32_t i = 0; - uint8_t reason = BCM2835_I2C_REASON_OK; - - /* Clear FIFO */ - bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); + uint32_t remaining = cmds_len; + uint32_t i = 0; + uint8_t reason = BCM2835_I2C_REASON_OK; - /* Clear Status */ - bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); + /* Clear FIFO */ + bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); - /* Set Data Length */ - bcm2835_peri_write(dlen, cmds_len); - - /* pre populate FIFO with max buffer */ - while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) - { - bcm2835_peri_write_nb(fifo, cmds[i]); - i++; - remaining--; - } + /* Clear Status */ + bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); - /* Enable device and start transfer */ - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); - - /* poll for transfer has started (way to do repeated start, from BCM2835 datasheet) */ - while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) - { - /* Linux may cause us to miss entire transfer stage */ - if(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE) - break; - } - - remaining = buf_len; - i = 0; + /* Set Data Length */ + bcm2835_peri_write(dlen, cmds_len); - /* Send a repeated start with read bit set in address */ - bcm2835_peri_write(dlen, buf_len); - bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ ); - - /* Wait for write to complete and first byte back. */ - bcm2835_delayMicroseconds(i2c_byte_wait_us * (cmds_len + 1)); - - /* wait for transfer to complete */ - while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) - { - /* we must empty the FIFO as it is populated and not use any delay */ - while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) - { - /* Read from FIFO, no barrier */ - buf[i] = bcm2835_peri_read_nb(fifo); - i++; - remaining--; - } - } - - /* transfer has finished - grab any remaining stuff in FIFO */ - while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) - { - /* Read from FIFO */ - buf[i] = bcm2835_peri_read(fifo); - i++; - remaining--; - } - - /* Received a NACK */ - if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) - { - reason = BCM2835_I2C_REASON_ERROR_NACK; - } + /* pre populate FIFO with max buffer */ + while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) { + bcm2835_peri_write_nb(fifo, cmds[i]); + i++; + remaining--; + } - /* Received Clock Stretch Timeout */ - else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) - { - reason = BCM2835_I2C_REASON_ERROR_CLKT; - } + /* Enable device and start transfer */ + bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); - /* Not all data is sent */ - else if (remaining) - { - reason = BCM2835_I2C_REASON_ERROR_DATA; - } + /* poll for transfer has started (way to do repeated start, from BCM2835 datasheet) */ + while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) { + /* Linux may cause us to miss entire transfer stage */ + if(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE) { + break; + } + } - bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); + remaining = buf_len; + i = 0; - return reason; + /* Send a repeated start with read bit set in address */ + bcm2835_peri_write(dlen, buf_len); + bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ ); + + /* Wait for write to complete and first byte back. */ + bcm2835_delayMicroseconds(i2c_byte_wait_us * (cmds_len + 1)); + + /* wait for transfer to complete */ + while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) { + /* we must empty the FIFO as it is populated and not use any delay */ + while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) { + /* Read from FIFO, no barrier */ + buf[i] = bcm2835_peri_read_nb(fifo); + i++; + remaining--; + } + } + + /* transfer has finished - grab any remaining stuff in FIFO */ + while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) { + /* Read from FIFO */ + buf[i] = bcm2835_peri_read(fifo); + i++; + remaining--; + } + + /* Received a NACK */ + if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { + reason = BCM2835_I2C_REASON_ERROR_NACK; + } + + /* Received Clock Stretch Timeout */ + else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) { + reason = BCM2835_I2C_REASON_ERROR_CLKT; + } + + /* Not all data is sent */ + else if (remaining) { + reason = BCM2835_I2C_REASON_ERROR_DATA; + } + + bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); + + return reason; } /* Read the System Timer Counter (64-bits) */ uint64_t bcm2835_st_read(void) { - volatile uint32_t* paddr; - uint32_t hi, lo; - uint64_t st; - paddr = bcm2835_st + BCM2835_ST_CHI/4; - hi = bcm2835_peri_read(paddr); + volatile uint32_t* paddr; + uint32_t hi, lo; + uint64_t st; + paddr = bcm2835_st + BCM2835_ST_CHI/4; + hi = bcm2835_peri_read(paddr); - paddr = bcm2835_st + BCM2835_ST_CLO/4; - lo = bcm2835_peri_read(paddr); - - paddr = bcm2835_st + BCM2835_ST_CHI/4; - st = bcm2835_peri_read(paddr); - - /* Test for overflow */ - if (st == hi) - { - st <<= 32; - st += lo; - } - else - { - st <<= 32; - paddr = bcm2835_st + BCM2835_ST_CLO/4; - st += bcm2835_peri_read(paddr); - } - return st; + paddr = bcm2835_st + BCM2835_ST_CLO/4; + lo = bcm2835_peri_read(paddr); + + paddr = bcm2835_st + BCM2835_ST_CHI/4; + st = bcm2835_peri_read(paddr); + + /* Test for overflow */ + if (st == hi) { + st <<= 32; + st += lo; + } else { + st <<= 32; + paddr = bcm2835_st + BCM2835_ST_CLO/4; + st += bcm2835_peri_read(paddr); + } + return st; } /* Delays for the specified number of microseconds with offset */ void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros) { - uint64_t compare = offset_micros + micros; + uint64_t compare = offset_micros + micros; - while(bcm2835_st_read() < compare) - ; + while(bcm2835_st_read() < compare) + ; } /* PWM */ void bcm2835_pwm_set_clock(uint32_t divisor) { - if ( bcm2835_clk == MAP_FAILED - || bcm2835_pwm == MAP_FAILED) - return; /* bcm2835_init() failed or not root */ - - /* From Gerts code */ - divisor &= 0xfff; - /* Stop PWM clock */ - bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x01); - bcm2835_delay(110); /* Prevents clock going slow */ - /* Wait for the clock to be not busy */ - while ((bcm2835_peri_read(bcm2835_clk + BCM2835_PWMCLK_CNTL) & 0x80) != 0) - bcm2835_delay(1); - /* set the clock divider and enable PWM clock */ - bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_DIV, BCM2835_PWM_PASSWRD | (divisor << 12)); - bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x11); /* Source=osc and enable */ + if ( bcm2835_clk == MAP_FAILED + || bcm2835_pwm == MAP_FAILED) { + return; /* bcm2835_init() failed or not root */ + } + + /* From Gerts code */ + divisor &= 0xfff; + /* Stop PWM clock */ + bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x01); + bcm2835_delay(110); /* Prevents clock going slow */ + /* Wait for the clock to be not busy */ + while ((bcm2835_peri_read(bcm2835_clk + BCM2835_PWMCLK_CNTL) & 0x80) != 0) { + bcm2835_delay(1); + } + /* set the clock divider and enable PWM clock */ + bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_DIV, BCM2835_PWM_PASSWRD | (divisor << 12)); + bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, + BCM2835_PWM_PASSWRD | 0x11); /* Source=osc and enable */ } void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled) { - if ( bcm2835_clk == MAP_FAILED - || bcm2835_pwm == MAP_FAILED) - return; /* bcm2835_init() failed or not root */ + if ( bcm2835_clk == MAP_FAILED + || bcm2835_pwm == MAP_FAILED) { + return; /* bcm2835_init() failed or not root */ + } - uint32_t control = bcm2835_peri_read(bcm2835_pwm + BCM2835_PWM_CONTROL); + uint32_t control = bcm2835_peri_read(bcm2835_pwm + BCM2835_PWM_CONTROL); - if (channel == 0) - { - if (markspace) - control |= BCM2835_PWM0_MS_MODE; - else - control &= ~BCM2835_PWM0_MS_MODE; - if (enabled) - control |= BCM2835_PWM0_ENABLE; - else - control &= ~BCM2835_PWM0_ENABLE; - } - else if (channel == 1) - { - if (markspace) - control |= BCM2835_PWM1_MS_MODE; - else - control &= ~BCM2835_PWM1_MS_MODE; - if (enabled) - control |= BCM2835_PWM1_ENABLE; - else - control &= ~BCM2835_PWM1_ENABLE; - } + if (channel == 0) { + if (markspace) { + control |= BCM2835_PWM0_MS_MODE; + } else { + control &= ~BCM2835_PWM0_MS_MODE; + } + if (enabled) { + control |= BCM2835_PWM0_ENABLE; + } else { + control &= ~BCM2835_PWM0_ENABLE; + } + } else if (channel == 1) { + if (markspace) { + control |= BCM2835_PWM1_MS_MODE; + } else { + control &= ~BCM2835_PWM1_MS_MODE; + } + if (enabled) { + control |= BCM2835_PWM1_ENABLE; + } else { + control &= ~BCM2835_PWM1_ENABLE; + } + } - /* If you use the barrier here, wierd things happen, and the commands dont work */ - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, control); - /* bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, BCM2835_PWM0_ENABLE | BCM2835_PWM1_ENABLE | BCM2835_PWM0_MS_MODE | BCM2835_PWM1_MS_MODE); */ + /* If you use the barrier here, wierd things happen, and the commands dont work */ + bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, control); + /* bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, BCM2835_PWM0_ENABLE | BCM2835_PWM1_ENABLE | BCM2835_PWM0_MS_MODE | BCM2835_PWM1_MS_MODE); */ } void bcm2835_pwm_set_range(uint8_t channel, uint32_t range) { - if ( bcm2835_clk == MAP_FAILED - || bcm2835_pwm == MAP_FAILED) - return; /* bcm2835_init() failed or not root */ + if ( bcm2835_clk == MAP_FAILED + || bcm2835_pwm == MAP_FAILED) { + return; /* bcm2835_init() failed or not root */ + } - if (channel == 0) - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_RANGE, range); - else if (channel == 1) - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_RANGE, range); + if (channel == 0) { + bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_RANGE, range); + } else if (channel == 1) { + bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_RANGE, range); + } } void bcm2835_pwm_set_data(uint8_t channel, uint32_t data) { - if ( bcm2835_clk == MAP_FAILED - || bcm2835_pwm == MAP_FAILED) - return; /* bcm2835_init() failed or not root */ + if ( bcm2835_clk == MAP_FAILED + || bcm2835_pwm == MAP_FAILED) { + return; /* bcm2835_init() failed or not root */ + } - if (channel == 0) - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_DATA, data); - else if (channel == 1) - bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_DATA, data); + if (channel == 0) { + bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_DATA, data); + } else if (channel == 1) { + bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_DATA, data); + } } /* Allocate page-aligned memory. */ void *malloc_aligned(size_t size) { - void *mem; - errno = posix_memalign(&mem, BCM2835_PAGE_SIZE, size); - return (errno ? NULL : mem); + void *mem; + errno = posix_memalign(&mem, BCM2835_PAGE_SIZE, size); + return (errno ? NULL : mem); } /* Map 'size' bytes starting at 'off' in file 'fd' to memory. @@ -1288,217 +1256,224 @@ void *malloc_aligned(size_t size) */ static void *mapmem(const char *msg, size_t size, int fd, off_t off) { - void *map = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, off); - if (map == MAP_FAILED) - logError("bcm2835_init: %s mmap failed: %s\n", msg, strerror(errno)); - return map; + void *map = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, off); + if (map == MAP_FAILED) { + logError("bcm2835_init: %s mmap failed: %s\n", msg, strerror(errno)); + } + return map; } static void unmapmem(void **pmem, size_t size) { - if (*pmem == MAP_FAILED) return; - munmap(*pmem, size); - *pmem = MAP_FAILED; + if (*pmem == MAP_FAILED) { + return; + } + munmap(*pmem, size); + *pmem = MAP_FAILED; } /* Initialise this library. */ int bcm2835_init(void) { - int memfd; - int ok; - FILE *fp; + int memfd; + int ok; + FILE *fp; - if (debug) - { - bcm2835_peripherals = (uint32_t*)BCM2835_PERI_BASE; + if (debug) { + bcm2835_peripherals = (uint32_t*)BCM2835_PERI_BASE; - bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4; - bcm2835_clk = bcm2835_peripherals + BCM2835_CLOCK_BASE/4; - bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE/4; - bcm2835_pwm = bcm2835_peripherals + BCM2835_GPIO_PWM/4; - bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE/4; - bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE/4; - bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE/4; - bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4; - return 1; /* Success */ - } - - /* Figure out the base and size of the peripheral address block - // using the device-tree. Required for RPi2, optional for RPi 1 - */ - if ((fp = fopen(BMC2835_RPI2_DT_FILENAME , "rb"))) - { - unsigned char buf[4]; - fseek(fp, BMC2835_RPI2_DT_PERI_BASE_ADDRESS_OFFSET, SEEK_SET); - if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf)) - bcm2835_peripherals_base = (uint32_t *)(buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0); - fseek(fp, BMC2835_RPI2_DT_PERI_SIZE_OFFSET, SEEK_SET); - if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf)) - bcm2835_peripherals_size = (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0); - fclose(fp); - } - /* else we are prob on RPi 1 with BCM2835, and use the hardwired defaults */ - - /* Now get ready to map the peripherals block - * If we are not root, try for the new /dev/gpiomem interface and accept - * the fact that we can only access GPIO - * else try for the /dev/mem interface and get access to everything - */ - memfd = -1; - ok = 0; - if (geteuid() == 0) - { - /* Open the master /dev/mem device */ - if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) - { - logError("bcm2835_init: Unable to open /dev/mem: %s\n", - strerror(errno)) ; - goto exit; + bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4; + bcm2835_clk = bcm2835_peripherals + BCM2835_CLOCK_BASE/4; + bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE/4; + bcm2835_pwm = bcm2835_peripherals + BCM2835_GPIO_PWM/4; + bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE/4; + bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE/4; + bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE/4; + bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4; + return 1; /* Success */ } - - /* Base of the peripherals block is mapped to VM */ - bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, (uint32_t)bcm2835_peripherals_base); - if (bcm2835_peripherals == MAP_FAILED) goto exit; - - /* Now compute the base addresses of various peripherals, - // which are at fixed offsets within the mapped peripherals block - // Caution: bcm2835_peripherals is uint32_t*, so divide offsets by 4 - */ - bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE/4; - bcm2835_pwm = bcm2835_peripherals + BCM2835_GPIO_PWM/4; - bcm2835_clk = bcm2835_peripherals + BCM2835_CLOCK_BASE/4; - bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4; - bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE/4; - bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE/4; /* I2C */ - bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE/4; /* I2C */ - bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4; - - ok = 1; - } - else - { - /* Not root, try /dev/gpiomem */ - /* Open the master /dev/mem device */ - if ((memfd = open("/dev/gpiomem", O_RDWR | O_SYNC) ) < 0) - { - logError("bcm2835_init: Unable to open /dev/gpiomem: %s\n", - strerror(errno)) ; - goto exit; + + /* Figure out the base and size of the peripheral address block + // using the device-tree. Required for RPi2, optional for RPi 1 + */ + if ((fp = fopen(BMC2835_RPI2_DT_FILENAME , "rb"))) { + unsigned char buf[4]; + fseek(fp, BMC2835_RPI2_DT_PERI_BASE_ADDRESS_OFFSET, SEEK_SET); + if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf)) { + bcm2835_peripherals_base = (uint32_t *)(buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0); + } + fseek(fp, BMC2835_RPI2_DT_PERI_SIZE_OFFSET, SEEK_SET); + if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf)) { + bcm2835_peripherals_size = (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0); + } + fclose(fp); + } + /* else we are prob on RPi 1 with BCM2835, and use the hardwired defaults */ + + /* Now get ready to map the peripherals block + * If we are not root, try for the new /dev/gpiomem interface and accept + * the fact that we can only access GPIO + * else try for the /dev/mem interface and get access to everything + */ + memfd = -1; + ok = 0; + if (geteuid() == 0) { + /* Open the master /dev/mem device */ + if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) { + logError("bcm2835_init: Unable to open /dev/mem: %s\n", + strerror(errno)) ; + goto exit; + } + + /* Base of the peripherals block is mapped to VM */ + bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, + (uint32_t)bcm2835_peripherals_base); + if (bcm2835_peripherals == MAP_FAILED) { + goto exit; + } + + /* Now compute the base addresses of various peripherals, + // which are at fixed offsets within the mapped peripherals block + // Caution: bcm2835_peripherals is uint32_t*, so divide offsets by 4 + */ + bcm2835_gpio = bcm2835_peripherals + BCM2835_GPIO_BASE/4; + bcm2835_pwm = bcm2835_peripherals + BCM2835_GPIO_PWM/4; + bcm2835_clk = bcm2835_peripherals + BCM2835_CLOCK_BASE/4; + bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4; + bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE/4; + bcm2835_bsc0 = bcm2835_peripherals + BCM2835_BSC0_BASE/4; /* I2C */ + bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE/4; /* I2C */ + bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4; + + ok = 1; + } else { + /* Not root, try /dev/gpiomem */ + /* Open the master /dev/mem device */ + if ((memfd = open("/dev/gpiomem", O_RDWR | O_SYNC) ) < 0) { + logError("bcm2835_init: Unable to open /dev/gpiomem: %s\n", + strerror(errno)) ; + goto exit; + } + + /* Base of the peripherals block is mapped to VM */ + bcm2835_peripherals_base = 0; + bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, + (uint32_t)bcm2835_peripherals_base); + if (bcm2835_peripherals == MAP_FAILED) { + goto exit; + } + bcm2835_gpio = bcm2835_peripherals; + ok = 1; } - - /* Base of the peripherals block is mapped to VM */ - bcm2835_peripherals_base = 0; - bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, (uint32_t)bcm2835_peripherals_base); - if (bcm2835_peripherals == MAP_FAILED) goto exit; - bcm2835_gpio = bcm2835_peripherals; - ok = 1; - } exit: - if (memfd >= 0) - close(memfd); + if (memfd >= 0) { + close(memfd); + } - if (!ok) - bcm2835_close(); + if (!ok) { + bcm2835_close(); + } - return ok; + return ok; } /* Close this library and deallocate everything */ int bcm2835_close(void) { - if (debug) return 1; /* Success */ + if (debug) { + return 1; /* Success */ + } - unmapmem((void**) &bcm2835_peripherals, bcm2835_peripherals_size); - bcm2835_peripherals = MAP_FAILED; - bcm2835_gpio = MAP_FAILED; - bcm2835_pwm = MAP_FAILED; - bcm2835_clk = MAP_FAILED; - bcm2835_pads = MAP_FAILED; - bcm2835_spi0 = MAP_FAILED; - bcm2835_bsc0 = MAP_FAILED; - bcm2835_bsc1 = MAP_FAILED; - bcm2835_st = MAP_FAILED; - return 1; /* Success */ -} + unmapmem((void**) &bcm2835_peripherals, bcm2835_peripherals_size); + bcm2835_peripherals = MAP_FAILED; + bcm2835_gpio = MAP_FAILED; + bcm2835_pwm = MAP_FAILED; + bcm2835_clk = MAP_FAILED; + bcm2835_pads = MAP_FAILED; + bcm2835_spi0 = MAP_FAILED; + bcm2835_bsc0 = MAP_FAILED; + bcm2835_bsc1 = MAP_FAILED; + bcm2835_st = MAP_FAILED; + return 1; /* Success */ +} #ifdef BCM2835_TEST -/* this is a simple test program that prints out what it will do rather than +/* this is a simple test program that prints out what it will do rather than // actually doing it */ int main(int argc, char **argv) { - /* Be non-destructive */ - bcm2835_set_debug(1); + /* Be non-destructive */ + bcm2835_set_debug(1); - if (!bcm2835_init()) - return 1; - - /* Configure some GPIO pins fo some testing - // Set RPI pin P1-11 to be an output - */ - bcm2835_gpio_fsel(RPI_GPIO_P1_11, BCM2835_GPIO_FSEL_OUTP); - /* Set RPI pin P1-15 to be an input */ - bcm2835_gpio_fsel(RPI_GPIO_P1_15, BCM2835_GPIO_FSEL_INPT); - /* with a pullup */ - bcm2835_gpio_set_pud(RPI_GPIO_P1_15, BCM2835_GPIO_PUD_UP); - /* And a low detect enable */ - bcm2835_gpio_len(RPI_GPIO_P1_15); - /* and input hysteresis disabled on GPIOs 0 to 27 */ - bcm2835_gpio_set_pad(BCM2835_PAD_GROUP_GPIO_0_27, BCM2835_PAD_SLEW_RATE_UNLIMITED|BCM2835_PAD_DRIVE_8mA); - -#if 1 - /* Blink */ - while (1) - { - /* Turn it on */ - bcm2835_gpio_write(RPI_GPIO_P1_11, HIGH); - - /* wait a bit */ - bcm2835_delay(500); - - /* turn it off */ - bcm2835_gpio_write(RPI_GPIO_P1_11, LOW); - - /* wait a bit */ - bcm2835_delay(500); - } -#endif - -#if 0 - /* Read input */ - while (1) - { - /* Read some data */ - uint8_t value = bcm2835_gpio_lev(RPI_GPIO_P1_15); - printf("read from pin 15: %d\n", value); - - /* wait a bit */ - bcm2835_delay(500); - } -#endif - -#if 0 - /* Look for a low event detection - // eds will be set whenever pin 15 goes low - */ - while (1) - { - if (bcm2835_gpio_eds(RPI_GPIO_P1_15)) - { - /* Now clear the eds flag by setting it to 1 */ - bcm2835_gpio_set_eds(RPI_GPIO_P1_15); - printf("low event detect for pin 15\n"); + if (!bcm2835_init()) { + return 1; } - /* wait a bit */ - bcm2835_delay(500); - } + /* Configure some GPIO pins fo some testing + // Set RPI pin P1-11 to be an output + */ + bcm2835_gpio_fsel(RPI_GPIO_P1_11, BCM2835_GPIO_FSEL_OUTP); + /* Set RPI pin P1-15 to be an input */ + bcm2835_gpio_fsel(RPI_GPIO_P1_15, BCM2835_GPIO_FSEL_INPT); + /* with a pullup */ + bcm2835_gpio_set_pud(RPI_GPIO_P1_15, BCM2835_GPIO_PUD_UP); + /* And a low detect enable */ + bcm2835_gpio_len(RPI_GPIO_P1_15); + /* and input hysteresis disabled on GPIOs 0 to 27 */ + bcm2835_gpio_set_pad(BCM2835_PAD_GROUP_GPIO_0_27, + BCM2835_PAD_SLEW_RATE_UNLIMITED|BCM2835_PAD_DRIVE_8mA); + +#if 1 + /* Blink */ + while (1) { + /* Turn it on */ + bcm2835_gpio_write(RPI_GPIO_P1_11, HIGH); + + /* wait a bit */ + bcm2835_delay(500); + + /* turn it off */ + bcm2835_gpio_write(RPI_GPIO_P1_11, LOW); + + /* wait a bit */ + bcm2835_delay(500); + } #endif - if (!bcm2835_close()) - return 1; +#if 0 + /* Read input */ + while (1) { + /* Read some data */ + uint8_t value = bcm2835_gpio_lev(RPI_GPIO_P1_15); + printf("read from pin 15: %d\n", value); - return 0; + /* wait a bit */ + bcm2835_delay(500); + } +#endif + +#if 0 + /* Look for a low event detection + // eds will be set whenever pin 15 goes low + */ + while (1) { + if (bcm2835_gpio_eds(RPI_GPIO_P1_15)) { + /* Now clear the eds flag by setting it to 1 */ + bcm2835_gpio_set_eds(RPI_GPIO_P1_15); + printf("low event detect for pin 15\n"); + } + + /* wait a bit */ + bcm2835_delay(500); + } +#endif + + if (!bcm2835_close()) { + return 1; + } + + return 0; } #endif diff --git a/drivers/RPi/bcm2835.h b/drivers/RPi/bcm2835.h index 26acee2..4dc0816 100644 --- a/drivers/RPi/bcm2835.h +++ b/drivers/RPi/bcm2835.h @@ -1,7 +1,7 @@ /* bcm2835.h - + C and C++ support for Broadcom BCM 2835 as used in Raspberry Pi - + Author: Mike McCauley Copyright (C) 2011-2013 Mike McCauley $Id: bcm2835.h,v 1.20 2015/03/31 04:55:41 mikem Exp mikem $ @@ -9,46 +9,46 @@ /*! \defgroup BCM2835grp C library for Broadcom BCM 2835 as used in Raspberry Pi \ingroup internals - - This is a C library for Raspberry Pi (RPi). It provides access to + + This is a C library for Raspberry Pi (RPi). It provides access to GPIO and other IO functions on the Broadcom BCM 2835 chip, allowing access to the GPIO pins on the 26 pin IDE plug on the RPi board so you can control and interface with various external devices. - + It provides functions for reading digital inputs and setting digital outputs, using SPI and I2C, and for accessing the system timers. Pin event detection is supported by polling (interrupts are not supported). - - It is C++ compatible, and installs as a header file and non-shared library on - any Linux-based distro (but clearly is no use except on Raspberry Pi or another board with + + It is C++ compatible, and installs as a header file and non-shared library on + any Linux-based distro (but clearly is no use except on Raspberry Pi or another board with BCM 2835). - - The version of the package that this documentation refers to can be downloaded + + The version of the package that this documentation refers to can be downloaded from http://www.airspayce.com/mikem/bcm2835/bcm2835-1.50.tar.gz You can find the latest version at http://www.airspayce.com/mikem/bcm2835 - + Several example programs are provided. - - Based on data in http://elinux.org/RPi_Low-level_peripherals and + + Based on data in http://elinux.org/RPi_Low-level_peripherals and http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf and http://www.scribd.com/doc/101830961/GPIO-Pads-Control2 - + You can also find online help and discussion at http://groups.google.com/group/bcm2835 - Please use that group for all questions and discussions on this topic. + Please use that group for all questions and discussions on this topic. Do not contact the author directly, unless it is to discuss commercial licensing. Before asking a question or reporting a bug, please read http://www.catb.org/esr/faqs/smart-questions.html - + Tested on debian6-19-04-2012, 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian and Occidentalisv01, 2016-02-09 Raspbian Jessie. - CAUTION: it has been observed that when detect enables such as bcm2835_gpio_len() + CAUTION: it has been observed that when detect enables such as bcm2835_gpio_len() are used and the pin is pulled LOW it can cause temporary hangs on 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian and Occidentalisv01. Reason for this is not yet determined, but we suspect that an interrupt handler is hitting a hard loop on those OSs. - If you must use bcm2835_gpio_len() and friends, make sure you disable the pins with - bcm2835_gpio_clr_len() and friends after use. - + If you must use bcm2835_gpio_len() and friends, make sure you disable the pins with + bcm2835_gpio_clr_len() and friends after use. + \par Running as root Prior to the release of Raspbian Jessie in Feb 2016, access to any @@ -68,10 +68,10 @@ other non-gpio operations may fail silently or crash. \par Installation - + This library consists of a single non-shared library and header file, which will be installed in the usual places by make install - + \code # download the latest version of the library, say bcm2835-1.xx.tar.gz, then: tar zxvf bcm2835-1.xx.tar.gz @@ -81,22 +81,22 @@ sudo make check sudo make install \endcode - + \par Physical Addresses - - The functions bcm2835_peri_read(), bcm2835_peri_write() and bcm2835_peri_set_bits() + + The functions bcm2835_peri_read(), bcm2835_peri_write() and bcm2835_peri_set_bits() are low level peripheral register access functions. They are designed to use physical addresses as described in section 1.2.3 ARM physical addresses - of the BCM2835 ARM Peripherals manual. + of the BCM2835 ARM Peripherals manual. Physical addresses range from 0x20000000 to 0x20FFFFFF for peripherals. The bus addresses for peripherals are set up to map onto the peripheral bus address range starting at 0x7E000000. Thus a peripheral advertised in the manual at bus address 0x7Ennnnnn is available at physical address 0x20nnnnnn. - - On RPI 2, the peripheral addresses are different and the bcm2835 library gets them + + On RPI 2, the peripheral addresses are different and the bcm2835 library gets them from reading /proc/device-tree/soc/ranges. This is only availble with recent versions of the kernel on RPI 2. - - After initialisation, the base address of the various peripheral + + After initialisation, the base address of the various peripheral registers are available with the following externals: bcm2835_gpio @@ -114,8 +114,8 @@ You should also ensure you are using the latest version of Linux. The library has been tested on RPI2 with 2015-02-16-raspbian-wheezy and ArchLinuxARM-rpi-2 as of 2015-03-29. - When device tree suport is enabled, the file /proc/device-tree/soc/ranges will appear in the file system, - and the bcm2835 module relies on its presence to correctly run on RPI2 (it is optional for RPI1). + When device tree suport is enabled, the file /proc/device-tree/soc/ranges will appear in the file system, + and the bcm2835 module relies on its presence to correctly run on RPI2 (it is optional for RPI1). Without device tree support enabled and the presence of this file, it will not work on RPI2. To enable device tree support: @@ -125,59 +125,59 @@ under Advanced Options - enable Device Tree Reboot. \endcode - + \par Pin Numbering - - The GPIO pin numbering as used by RPi is different to and inconsistent with the underlying + + The GPIO pin numbering as used by RPi is different to and inconsistent with the underlying BCM 2835 chip pin numbering. http://elinux.org/RPi_BCM2835_GPIOs - + RPi has a 26 pin IDE header that provides access to some of the GPIO pins on the BCM 2835, - as well as power and ground pins. Not all GPIO pins on the BCM 2835 are available on the + as well as power and ground pins. Not all GPIO pins on the BCM 2835 are available on the IDE header. - + RPi Version 2 also has a P5 connector with 4 GPIO pins, 5V, 3.3V and Gnd. - - The functions in this library are designed to be passed the BCM 2835 GPIO pin number and _not_ + + The functions in this library are designed to be passed the BCM 2835 GPIO pin number and _not_ the RPi pin number. There are symbolic definitions for each of the available pins that you should use for convenience. See \ref RPiGPIOPin. - + \par SPI Pins - - The bcm2835_spi_* functions allow you to control the BCM 2835 SPI0 interface, + + The bcm2835_spi_* functions allow you to control the BCM 2835 SPI0 interface, allowing you to send and received data by SPI (Serial Peripheral Interface). For more information about SPI, see http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus - - When bcm2835_spi_begin() is called it changes the bahaviour of the SPI interface pins from their - default GPIO behaviour in order to support SPI. While SPI is in use, you will not be able + + When bcm2835_spi_begin() is called it changes the bahaviour of the SPI interface pins from their + default GPIO behaviour in order to support SPI. While SPI is in use, you will not be able to control the state of the SPI pins through the usual bcm2835_spi_gpio_write(). When bcm2835_spi_end() is called, the SPI pins will all revert to inputs, and can then be configured and controled with the usual bcm2835_gpio_* calls. - + The Raspberry Pi GPIO pins used for SPI are: - + - P1-19 (MOSI) - - P1-21 (MISO) - - P1-23 (CLK) - - P1-24 (CE0) + - P1-21 (MISO) + - P1-23 (CLK) + - P1-24 (CE0) - P1-26 (CE1) - + \par I2C Pins - + The bcm2835_i2c_* functions allow you to control the BCM 2835 BSC interface, allowing you to send and received data by I2C ("eye-squared cee"; generically referred to as "two-wire interface") . For more information about I?C, see http://en.wikipedia.org/wiki/I%C2%B2C - + The Raspberry Pi V2 GPIO pins used for I2C are: - + - P1-03 (SDA) - P1-05 (SLC) - + \par PWM - - The BCM2835 supports hardware PWM on a limited subset of GPIO pins. This bcm2835 library provides + + The BCM2835 supports hardware PWM on a limited subset of GPIO pins. This bcm2835 library provides functions for configuring and controlling PWM output on these pins. - - The BCM2835 contains 2 independent PWM channels (0 and 1), each of which be connnected to a limited subset of + + The BCM2835 contains 2 independent PWM channels (0 and 1), each of which be connnected to a limited subset of GPIO pins. The following GPIO pins may be connected to the following PWM channels (from section 9.5): \code GPIO PIN RPi pin PWM Channel ALT FUN @@ -195,27 +195,27 @@ Note carefully that current versions of the Raspberry Pi only expose one of these pins (GPIO 18 = RPi Pin 1-12) on the IO headers, and therefore this is the only IO pin on the RPi that can be used for PWM. Further it must be set to ALT FUN 5 to get PWM output. - - Both PWM channels are driven by the same PWM clock, whose clock dvider can be varied using + + Both PWM channels are driven by the same PWM clock, whose clock dvider can be varied using bcm2835_pwm_set_clock(). Each channel can be separately enabled with bcm2835_pwm_set_mode(). The average output of the PWM channel is determined by the ratio of DATA/RANGE for that channel. Use bcm2835_pwm_set_range() to set the range and bcm2835_pwm_set_data() to set the data in that ratio - - Each PWM channel can run in either Balanced or Mark-Space mode. In Balanced mode, the hardware + + Each PWM channel can run in either Balanced or Mark-Space mode. In Balanced mode, the hardware sends a combination of clock pulses that results in an overall DATA pulses per RANGE pulses. - In Mark-Space mode, the hardware sets the output HIGH for DATA clock pulses wide, followed by - LOW for RANGE-DATA clock pulses. - - The PWM clock can be set to control the PWM pulse widths. The PWM clock is derived from + In Mark-Space mode, the hardware sets the output HIGH for DATA clock pulses wide, followed by + LOW for RANGE-DATA clock pulses. + + The PWM clock can be set to control the PWM pulse widths. The PWM clock is derived from a 19.2MHz clock. You can set any divider, but some common ones are provided by the BCM2835_PWM_CLOCK_DIVIDER_* values of \ref bcm2835PWMClockDivider. - - For example, say you wanted to drive a DC motor with PWM at about 1kHz, - and control the speed in 1/1024 increments from - 0/1024 (stopped) through to 1024/1024 (full on). In that case you might set the + + For example, say you wanted to drive a DC motor with PWM at about 1kHz, + and control the speed in 1/1024 increments from + 0/1024 (stopped) through to 1024/1024 (full on). In that case you might set the clock divider to be 16, and the RANGE to 1024. The pulse repetition frequency will be 1.2MHz/1024 = 1171.875Hz. - + \par SPI In order for bcm2835 library SPI to work, you may need to disable the SPI kernel module using: @@ -228,18 +228,18 @@ \endcode \par Real Time performance constraints - - The bcm2835 is a library for user programs (i.e. they run in 'userland'). + + The bcm2835 is a library for user programs (i.e. they run in 'userland'). Such programs are not part of the kernel and are usually - subject to paging and swapping by the kernel while it does other things besides running your program. - This means that you should not expect to get real-time performance or - real-time timing constraints from such programs. In particular, there is no guarantee that the - bcm2835_delay() and bcm2835_delayMicroseconds() will return after exactly the time requested. + subject to paging and swapping by the kernel while it does other things besides running your program. + This means that you should not expect to get real-time performance or + real-time timing constraints from such programs. In particular, there is no guarantee that the + bcm2835_delay() and bcm2835_delayMicroseconds() will return after exactly the time requested. In fact, depending on other activity on the host, IO etc, you might get significantly longer delay times than the one you asked for. So please dont expect to get exactly the time delay you request. - + Arjan reports that you can prevent swapping on Linux with the following code fragment: - + \code struct sched_param sp; memset(&sp, 0, sizeof(sp)); @@ -247,34 +247,34 @@ sched_setscheduler(0, SCHED_FIFO, &sp); mlockall(MCL_CURRENT | MCL_FUTURE); \endcode - + \par Bindings to other languages - + mikem has made Perl bindings available at CPAN: http://search.cpan.org/~mikem/Device-BCM2835-1.9/lib/Device/BCM2835.pm Matthew Baker has kindly made Python bindings available at: https: github.com/mubeta06/py-libbcm2835 - Gary Marks has created a Serial Peripheral Interface (SPI) command-line utility - for Raspberry Pi, based on the bcm2835 library. The - utility, spincl, is licensed under Open Source GNU GPLv3 by iP Solutions (http://ipsolutionscorp.com), as a + Gary Marks has created a Serial Peripheral Interface (SPI) command-line utility + for Raspberry Pi, based on the bcm2835 library. The + utility, spincl, is licensed under Open Source GNU GPLv3 by iP Solutions (http://ipsolutionscorp.com), as a free download with source included: http://ipsolutionscorp.com/raspberry-pi-spi-utility/ - + \par Open Source Licensing GPL V2 - + This is the appropriate option if you want to share the source code of your application with everyone you distribute it to, and you also want to give them the right to share who uses it. If you wish to use this software under Open Source Licensing, you must contribute all your source code to the open source community in accordance with the GPL Version 2 when your application is distributed. See http://www.gnu.org/copyleft/gpl.html and COPYING - + \par Acknowledgements - + Some of this code has been inspired by Dom and Gert. The I2C code has been inspired by Alan Barr. - + \par Revision History - + \version 1.0 Initial release \version 1.1 Minor bug fixes @@ -289,18 +289,18 @@ \version 1.6 Document testing on 2012-07-15-wheezy-raspbian and Occidentalisv01 Functions bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen() - bcm2835_gpio_len(), bcm2835_gpio_aren() and bcm2835_gpio_afen() now + bcm2835_gpio_len(), bcm2835_gpio_aren() and bcm2835_gpio_afen() now changes only the pin specified. Other pins that were already previously enabled stay enabled. Added bcm2835_gpio_clr_ren(), bcm2835_gpio_clr_fen(), bcm2835_gpio_clr_hen() - bcm2835_gpio_clr_len(), bcm2835_gpio_clr_aren(), bcm2835_gpio_clr_afen() + bcm2835_gpio_clr_len(), bcm2835_gpio_clr_aren(), bcm2835_gpio_clr_afen() to clear the enable for individual pins, suggested by Andreas Sundstrom. \version 1.7 Added bcm2835_spi_transfernb to support different buffers for read and write. \version 1.8 Improvements to read barrier, as suggested by maddin. - \version 1.9 Improvements contributed by mikew: + \version 1.9 Improvements contributed by mikew: I noticed that it was mallocing memory for the mmaps on /dev/mem. It's not necessary to do that, you can just mmap the file directly, so I've removed the mallocs (and frees). @@ -315,7 +315,7 @@ Also added a define for the passwrd value that Gert says is needed to change pad control settings. - \version 1.10 Changed the names of the delay functions to bcm2835_delay() + \version 1.10 Changed the names of the delay functions to bcm2835_delay() and bcm2835_delayMicroseconds() to prevent collisions with wiringPi. Macros to map delay()-> bcm2835_delay() and Macros to map delayMicroseconds()-> bcm2835_delayMicroseconds(), which @@ -323,14 +323,14 @@ \version 1.11 Fixed incorrect link to download file - \version 1.12 New GPIO pin definitions for RPi version 2 (which has a different GPIO mapping) + \version 1.12 New GPIO pin definitions for RPi version 2 (which has a different GPIO mapping) \version 1.13 New GPIO pin definitions for RPi version 2 plug P5 Hardware base pointers are now available (after initialisation) externally as bcm2835_gpio bcm2835_pwm bcm2835_clk bcm2835_pads bcm2835_spi0. \version 1.14 Now compiles even if CLOCK_MONOTONIC_RAW is not available, uses CLOCK_MONOTONIC instead. - Fixed errors in documentation of SPI divider frequencies based on 250MHz clock. + Fixed errors in documentation of SPI divider frequencies based on 250MHz clock. Reported by Ben Simpson. \version 1.15 Added bcm2835_close() to end of examples as suggested by Mark Wolfe. @@ -340,30 +340,30 @@ \version 1.17 Added bcm2835_gpio_write_mask. Requested by Sebastian Loncar. - \version 1.18 Added bcm2835_i2c_* functions. Changes to bcm2835_delayMicroseconds: - now uses the RPi system timer counter, instead of clock_gettime, for improved accuracy. + \version 1.18 Added bcm2835_i2c_* functions. Changes to bcm2835_delayMicroseconds: + now uses the RPi system timer counter, instead of clock_gettime, for improved accuracy. No need to link with -lrt now. Contributed by Arjan van Vught. - \version 1.19 Removed inlines added by previous patch since they don't seem to work everywhere. + \version 1.19 Removed inlines added by previous patch since they don't seem to work everywhere. Reported by olly. \version 1.20 Patch from Mark Dootson to close /dev/mem after access to the peripherals has been granted. - \version 1.21 delayMicroseconds is now not susceptible to 32 bit timer overruns. + \version 1.21 delayMicroseconds is now not susceptible to 32 bit timer overruns. Patch courtesy Jeremy Mortis. - \version 1.22 Fixed incorrect definition of BCM2835_GPFEN0 which broke the ability to set + \version 1.22 Fixed incorrect definition of BCM2835_GPFEN0 which broke the ability to set falling edge events. Reported by Mark Dootson. - \version 1.23 Added bcm2835_i2c_set_baudrate and bcm2835_i2c_read_register_rs. + \version 1.23 Added bcm2835_i2c_set_baudrate and bcm2835_i2c_read_register_rs. Improvements to bcm2835_i2c_read and bcm2835_i2c_write functions to fix ocasional reads not completing. Patched by Mark Dootson. \version 1.24 Mark Dootson p[atched a problem with his previously submitted code - under high load from other processes. + under high load from other processes. \version 1.25 Updated author and distribution location details to airspayce.com - \version 1.26 Added missing unmapmem for pads in bcm2835_close to prevent a memory leak. + \version 1.26 Added missing unmapmem for pads in bcm2835_close to prevent a memory leak. Reported by Hartmut Henkel. \version 1.27 bcm2835_gpio_set_pad() no longer needs BCM2835_PAD_PASSWRD: it is @@ -380,13 +380,13 @@ \version 1.31 Fix a GCC warning about dummy variable, patched by Alan Watson. Thanks. - \version 1.32 Added option I2C_V1 definition to compile for version 1 RPi. + \version 1.32 Added option I2C_V1 definition to compile for version 1 RPi. By default I2C code is generated for the V2 RPi which has SDA1 and SCL1 connected. Contributed by Malcolm Wiles based on work by Arvi Govindaraj. \version 1.33 Added command line utilities i2c and gpio to examples. Contributed by Shahrooz Shahparnia. - \version 1.34 Added bcm2835_i2c_write_read_rs() which writes an arbitrary number of bytes, + \version 1.34 Added bcm2835_i2c_write_read_rs() which writes an arbitrary number of bytes, sends a repeat start, and reads from the device. Contributed by Eduardo Steinhorst. \version 1.35 Fix build errors when compiled under Qt. Also performance improvements with SPI transfers. Contributed b Udo Klaas. @@ -401,7 +401,7 @@ \version 1.38 Added bcm2835_regbase for the benefit of C# wrappers, patch by Frank Hommers
- \version 1.39 Beta version of RPi2 compatibility. Not tested here on RPi2 hardware. + \version 1.39 Beta version of RPi2 compatibility. Not tested here on RPi2 hardware. Testers please confirm correct operation on RPi2.
Unneccessary 'volatile' qualifiers removed from all variables and signatures.
Removed unsupportable PWM dividers, based on a report from Christophe Cecillon.
@@ -413,21 +413,21 @@ Reported by tlhackque.
Fixed a problem where calling bcm2835_delayMicroseconds loops forever when debug is set. Reported by tlhackque.
Reinstated use of volatile in 2 functions where there was a danger of lost reads or writes. Reported by tlhackque.
- + \version 1.41 Added BCM2835_VERSION macro and new function bcm2835_version(); Requested by tlhackque.
Improvements to peripheral memory barriers as suggested by tlhackque.
Reinstated some necessary volatile declarations as requested by tlhackque.
\version 1.42 Further improvements to memory barriers with the patient assistance and patches of tlhackque.
- \version 1.43 Fixed problems with compiling barriers on RPI 2 with Arch Linux and gcc 4.9.2. + \version 1.43 Fixed problems with compiling barriers on RPI 2 with Arch Linux and gcc 4.9.2. Reported and patched by Lars Christensen.
Testing on RPI 2, with ArchLinuxARM-rpi-2-latest and 2015-02-16-raspbian-wheezy.
\version 1.44 Added documention about the need for device tree to be enabled on RPI2.
Improvements to detection of availablity of DMB instruction based on value of __ARM_ARCH macro.
- \version 1.45 Fixed an error in the pad group offsets that would prevent bcm2835_gpio_set_pad() + \version 1.45 Fixed an error in the pad group offsets that would prevent bcm2835_gpio_set_pad() and bcm2835_gpio_pad() working correctly with non-0 pad groups. Reported by Guido. \version 1.46 2015-09-18 @@ -445,8 +445,8 @@ \version 1.50 2016-02-28 Added support for running as non-root, permitting access to GPIO only. Functions - bcm2835_spi_begin() and bcm2835_i2c_begin() will now return 0 if not running as root - (which prevents access to the SPI and I2C peripherals, amongst others). + bcm2835_spi_begin() and bcm2835_i2c_begin() will now return 0 if not running as root + (which prevents access to the SPI and I2C peripherals, amongst others). Testing on Raspbian Jessie. \author Mike McCauley (mikem@airspayce.com) DO NOT CONTACT THE AUTHOR DIRECTLY: USE THE LISTS @@ -577,16 +577,15 @@ extern volatile uint32_t *bcm2835_bsc1; /*! \brief bcm2835RegisterBase Register bases for bcm2835_regbase() */ -typedef enum -{ - BCM2835_REGBASE_ST = 1, /*!< Base of the ST (System Timer) registers. */ - BCM2835_REGBASE_GPIO = 2, /*!< Base of the GPIO registers. */ - BCM2835_REGBASE_PWM = 3, /*!< Base of the PWM registers. */ - BCM2835_REGBASE_CLK = 4, /*!< Base of the CLK registers. */ - BCM2835_REGBASE_PADS = 5, /*!< Base of the PADS registers. */ - BCM2835_REGBASE_SPI0 = 6, /*!< Base of the SPI0 registers. */ - BCM2835_REGBASE_BSC0 = 7, /*!< Base of the BSC0 registers. */ - BCM2835_REGBASE_BSC1 = 8 /*!< Base of the BSC1 registers. */ +typedef enum { + BCM2835_REGBASE_ST = 1, /*!< Base of the ST (System Timer) registers. */ + BCM2835_REGBASE_GPIO = 2, /*!< Base of the GPIO registers. */ + BCM2835_REGBASE_PWM = 3, /*!< Base of the PWM registers. */ + BCM2835_REGBASE_CLK = 4, /*!< Base of the CLK registers. */ + BCM2835_REGBASE_PADS = 5, /*!< Base of the PADS registers. */ + BCM2835_REGBASE_SPI0 = 6, /*!< Base of the SPI0 registers. */ + BCM2835_REGBASE_BSC0 = 7, /*!< Base of the BSC0 registers. */ + BCM2835_REGBASE_BSC1 = 8 /*!< Base of the BSC1 registers. */ } bcm2835RegisterBase; /*! Size of memory page on RPi */ @@ -599,8 +598,8 @@ typedef enum The BCM2835 has 54 GPIO pins. BCM2835 data sheet, Page 90 onwards. */ -/*! GPIO register offsets from BCM2835_GPIO_BASE. - Offsets into the GPIO Peripheral block in bytes per 6.1 Register View +/*! GPIO register offsets from BCM2835_GPIO_BASE. + Offsets into the GPIO Peripheral block in bytes per 6.1 Register View */ #define BCM2835_GPFSEL0 0x0000 /*!< GPIO Function Select 0 */ #define BCM2835_GPFSEL1 0x0004 /*!< GPIO Function Select 1 */ @@ -635,27 +634,25 @@ typedef enum /*! \brief bcm2835PortFunction Port function select modes for bcm2835_gpio_fsel() */ -typedef enum -{ - BCM2835_GPIO_FSEL_INPT = 0x00, /*!< Input 0b000 */ - BCM2835_GPIO_FSEL_OUTP = 0x01, /*!< Output 0b001 */ - BCM2835_GPIO_FSEL_ALT0 = 0x04, /*!< Alternate function 0 0b100 */ - BCM2835_GPIO_FSEL_ALT1 = 0x05, /*!< Alternate function 1 0b101 */ - BCM2835_GPIO_FSEL_ALT2 = 0x06, /*!< Alternate function 2 0b110, */ - BCM2835_GPIO_FSEL_ALT3 = 0x07, /*!< Alternate function 3 0b111 */ - BCM2835_GPIO_FSEL_ALT4 = 0x03, /*!< Alternate function 4 0b011 */ - BCM2835_GPIO_FSEL_ALT5 = 0x02, /*!< Alternate function 5 0b010 */ - BCM2835_GPIO_FSEL_MASK = 0x07 /*!< Function select bits mask 0b111 */ +typedef enum { + BCM2835_GPIO_FSEL_INPT = 0x00, /*!< Input 0b000 */ + BCM2835_GPIO_FSEL_OUTP = 0x01, /*!< Output 0b001 */ + BCM2835_GPIO_FSEL_ALT0 = 0x04, /*!< Alternate function 0 0b100 */ + BCM2835_GPIO_FSEL_ALT1 = 0x05, /*!< Alternate function 1 0b101 */ + BCM2835_GPIO_FSEL_ALT2 = 0x06, /*!< Alternate function 2 0b110, */ + BCM2835_GPIO_FSEL_ALT3 = 0x07, /*!< Alternate function 3 0b111 */ + BCM2835_GPIO_FSEL_ALT4 = 0x03, /*!< Alternate function 4 0b011 */ + BCM2835_GPIO_FSEL_ALT5 = 0x02, /*!< Alternate function 5 0b010 */ + BCM2835_GPIO_FSEL_MASK = 0x07 /*!< Function select bits mask 0b111 */ } bcm2835FunctionSelect; /*! \brief bcm2835PUDControl Pullup/Pulldown defines for bcm2835_gpio_pud() */ -typedef enum -{ - BCM2835_GPIO_PUD_OFF = 0x00, /*!< Off ? disable pull-up/down 0b00 */ - BCM2835_GPIO_PUD_DOWN = 0x01, /*!< Enable Pull Down control 0b01 */ - BCM2835_GPIO_PUD_UP = 0x02 /*!< Enable Pull Up control 0b10 */ +typedef enum { + BCM2835_GPIO_PUD_OFF = 0x00, /*!< Off ? disable pull-up/down 0b00 */ + BCM2835_GPIO_PUD_DOWN = 0x01, /*!< Enable Pull Down control 0b01 */ + BCM2835_GPIO_PUD_UP = 0x02 /*!< Enable Pull Up control 0b10 */ } bcm2835PUDControl; /*! Pad control register offsets from BCM2835_GPIO_PADS */ @@ -679,15 +676,14 @@ typedef enum /*! \brief bcm2835PadGroup Pad group specification for bcm2835_gpio_pad() */ -typedef enum -{ - BCM2835_PAD_GROUP_GPIO_0_27 = 0, /*!< Pad group for GPIO pads 0 to 27 */ - BCM2835_PAD_GROUP_GPIO_28_45 = 1, /*!< Pad group for GPIO pads 28 to 45 */ - BCM2835_PAD_GROUP_GPIO_46_53 = 2 /*!< Pad group for GPIO pads 46 to 53 */ +typedef enum { + BCM2835_PAD_GROUP_GPIO_0_27 = 0, /*!< Pad group for GPIO pads 0 to 27 */ + BCM2835_PAD_GROUP_GPIO_28_45 = 1, /*!< Pad group for GPIO pads 28 to 45 */ + BCM2835_PAD_GROUP_GPIO_46_53 = 2 /*!< Pad group for GPIO pads 46 to 53 */ } bcm2835PadGroup; /*! \brief GPIO Pin Numbers - + Here we define Raspberry Pin GPIO pins on P1 in terms of the underlying BCM GPIO pin numbers. These can be passed as a pin number to any function requiring a pin. Not all pins on the RPi 26 bin IDE plug are connected to GPIO pins @@ -700,91 +696,90 @@ typedef enum If you are using the RPi Compute Module, just use the GPIO number: there is no need to use one of these symbolic names */ -typedef enum -{ - RPI_GPIO_P1_03 = 0, /*!< Version 1, Pin P1-03 */ - RPI_GPIO_P1_05 = 1, /*!< Version 1, Pin P1-05 */ - RPI_GPIO_P1_07 = 4, /*!< Version 1, Pin P1-07 */ - RPI_GPIO_P1_08 = 14, /*!< Version 1, Pin P1-08, defaults to alt function 0 UART0_TXD */ - RPI_GPIO_P1_10 = 15, /*!< Version 1, Pin P1-10, defaults to alt function 0 UART0_RXD */ - RPI_GPIO_P1_11 = 17, /*!< Version 1, Pin P1-11 */ - RPI_GPIO_P1_12 = 18, /*!< Version 1, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */ - RPI_GPIO_P1_13 = 21, /*!< Version 1, Pin P1-13 */ - RPI_GPIO_P1_15 = 22, /*!< Version 1, Pin P1-15 */ - RPI_GPIO_P1_16 = 23, /*!< Version 1, Pin P1-16 */ - RPI_GPIO_P1_18 = 24, /*!< Version 1, Pin P1-18 */ - RPI_GPIO_P1_19 = 10, /*!< Version 1, Pin P1-19, MOSI when SPI0 in use */ - RPI_GPIO_P1_21 = 9, /*!< Version 1, Pin P1-21, MISO when SPI0 in use */ - RPI_GPIO_P1_22 = 25, /*!< Version 1, Pin P1-22 */ - RPI_GPIO_P1_23 = 11, /*!< Version 1, Pin P1-23, CLK when SPI0 in use */ - RPI_GPIO_P1_24 = 8, /*!< Version 1, Pin P1-24, CE0 when SPI0 in use */ - RPI_GPIO_P1_26 = 7, /*!< Version 1, Pin P1-26, CE1 when SPI0 in use */ +typedef enum { + RPI_GPIO_P1_03 = 0, /*!< Version 1, Pin P1-03 */ + RPI_GPIO_P1_05 = 1, /*!< Version 1, Pin P1-05 */ + RPI_GPIO_P1_07 = 4, /*!< Version 1, Pin P1-07 */ + RPI_GPIO_P1_08 = 14, /*!< Version 1, Pin P1-08, defaults to alt function 0 UART0_TXD */ + RPI_GPIO_P1_10 = 15, /*!< Version 1, Pin P1-10, defaults to alt function 0 UART0_RXD */ + RPI_GPIO_P1_11 = 17, /*!< Version 1, Pin P1-11 */ + RPI_GPIO_P1_12 = 18, /*!< Version 1, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */ + RPI_GPIO_P1_13 = 21, /*!< Version 1, Pin P1-13 */ + RPI_GPIO_P1_15 = 22, /*!< Version 1, Pin P1-15 */ + RPI_GPIO_P1_16 = 23, /*!< Version 1, Pin P1-16 */ + RPI_GPIO_P1_18 = 24, /*!< Version 1, Pin P1-18 */ + RPI_GPIO_P1_19 = 10, /*!< Version 1, Pin P1-19, MOSI when SPI0 in use */ + RPI_GPIO_P1_21 = 9, /*!< Version 1, Pin P1-21, MISO when SPI0 in use */ + RPI_GPIO_P1_22 = 25, /*!< Version 1, Pin P1-22 */ + RPI_GPIO_P1_23 = 11, /*!< Version 1, Pin P1-23, CLK when SPI0 in use */ + RPI_GPIO_P1_24 = 8, /*!< Version 1, Pin P1-24, CE0 when SPI0 in use */ + RPI_GPIO_P1_26 = 7, /*!< Version 1, Pin P1-26, CE1 when SPI0 in use */ - /* RPi Version 2 */ - RPI_V2_GPIO_P1_03 = 2, /*!< Version 2, Pin P1-03 */ - RPI_V2_GPIO_P1_05 = 3, /*!< Version 2, Pin P1-05 */ - RPI_V2_GPIO_P1_07 = 4, /*!< Version 2, Pin P1-07 */ - RPI_V2_GPIO_P1_08 = 14, /*!< Version 2, Pin P1-08, defaults to alt function 0 UART0_TXD */ - RPI_V2_GPIO_P1_10 = 15, /*!< Version 2, Pin P1-10, defaults to alt function 0 UART0_RXD */ - RPI_V2_GPIO_P1_11 = 17, /*!< Version 2, Pin P1-11 */ - RPI_V2_GPIO_P1_12 = 18, /*!< Version 2, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */ - RPI_V2_GPIO_P1_13 = 27, /*!< Version 2, Pin P1-13 */ - RPI_V2_GPIO_P1_15 = 22, /*!< Version 2, Pin P1-15 */ - RPI_V2_GPIO_P1_16 = 23, /*!< Version 2, Pin P1-16 */ - RPI_V2_GPIO_P1_18 = 24, /*!< Version 2, Pin P1-18 */ - RPI_V2_GPIO_P1_19 = 10, /*!< Version 2, Pin P1-19, MOSI when SPI0 in use */ - RPI_V2_GPIO_P1_21 = 9, /*!< Version 2, Pin P1-21, MISO when SPI0 in use */ - RPI_V2_GPIO_P1_22 = 25, /*!< Version 2, Pin P1-22 */ - RPI_V2_GPIO_P1_23 = 11, /*!< Version 2, Pin P1-23, CLK when SPI0 in use */ - RPI_V2_GPIO_P1_24 = 8, /*!< Version 2, Pin P1-24, CE0 when SPI0 in use */ - RPI_V2_GPIO_P1_26 = 7, /*!< Version 2, Pin P1-26, CE1 when SPI0 in use */ - RPI_V2_GPIO_P1_29 = 5, /*!< Version 2, Pin P1-29 */ - RPI_V2_GPIO_P1_31 = 6, /*!< Version 2, Pin P1-31 */ - RPI_V2_GPIO_P1_32 = 12, /*!< Version 2, Pin P1-32 */ - RPI_V2_GPIO_P1_33 = 13, /*!< Version 2, Pin P1-33 */ - RPI_V2_GPIO_P1_35 = 19, /*!< Version 2, Pin P1-35 */ - RPI_V2_GPIO_P1_36 = 16, /*!< Version 2, Pin P1-36 */ - RPI_V2_GPIO_P1_37 = 26, /*!< Version 2, Pin P1-37 */ - RPI_V2_GPIO_P1_38 = 20, /*!< Version 2, Pin P1-38 */ - RPI_V2_GPIO_P1_40 = 21, /*!< Version 2, Pin P1-40 */ + /* RPi Version 2 */ + RPI_V2_GPIO_P1_03 = 2, /*!< Version 2, Pin P1-03 */ + RPI_V2_GPIO_P1_05 = 3, /*!< Version 2, Pin P1-05 */ + RPI_V2_GPIO_P1_07 = 4, /*!< Version 2, Pin P1-07 */ + RPI_V2_GPIO_P1_08 = 14, /*!< Version 2, Pin P1-08, defaults to alt function 0 UART0_TXD */ + RPI_V2_GPIO_P1_10 = 15, /*!< Version 2, Pin P1-10, defaults to alt function 0 UART0_RXD */ + RPI_V2_GPIO_P1_11 = 17, /*!< Version 2, Pin P1-11 */ + RPI_V2_GPIO_P1_12 = 18, /*!< Version 2, Pin P1-12, can be PWM channel 0 in ALT FUN 5 */ + RPI_V2_GPIO_P1_13 = 27, /*!< Version 2, Pin P1-13 */ + RPI_V2_GPIO_P1_15 = 22, /*!< Version 2, Pin P1-15 */ + RPI_V2_GPIO_P1_16 = 23, /*!< Version 2, Pin P1-16 */ + RPI_V2_GPIO_P1_18 = 24, /*!< Version 2, Pin P1-18 */ + RPI_V2_GPIO_P1_19 = 10, /*!< Version 2, Pin P1-19, MOSI when SPI0 in use */ + RPI_V2_GPIO_P1_21 = 9, /*!< Version 2, Pin P1-21, MISO when SPI0 in use */ + RPI_V2_GPIO_P1_22 = 25, /*!< Version 2, Pin P1-22 */ + RPI_V2_GPIO_P1_23 = 11, /*!< Version 2, Pin P1-23, CLK when SPI0 in use */ + RPI_V2_GPIO_P1_24 = 8, /*!< Version 2, Pin P1-24, CE0 when SPI0 in use */ + RPI_V2_GPIO_P1_26 = 7, /*!< Version 2, Pin P1-26, CE1 when SPI0 in use */ + RPI_V2_GPIO_P1_29 = 5, /*!< Version 2, Pin P1-29 */ + RPI_V2_GPIO_P1_31 = 6, /*!< Version 2, Pin P1-31 */ + RPI_V2_GPIO_P1_32 = 12, /*!< Version 2, Pin P1-32 */ + RPI_V2_GPIO_P1_33 = 13, /*!< Version 2, Pin P1-33 */ + RPI_V2_GPIO_P1_35 = 19, /*!< Version 2, Pin P1-35 */ + RPI_V2_GPIO_P1_36 = 16, /*!< Version 2, Pin P1-36 */ + RPI_V2_GPIO_P1_37 = 26, /*!< Version 2, Pin P1-37 */ + RPI_V2_GPIO_P1_38 = 20, /*!< Version 2, Pin P1-38 */ + RPI_V2_GPIO_P1_40 = 21, /*!< Version 2, Pin P1-40 */ - /* RPi Version 2, new plug P5 */ - RPI_V2_GPIO_P5_03 = 28, /*!< Version 2, Pin P5-03 */ - RPI_V2_GPIO_P5_04 = 29, /*!< Version 2, Pin P5-04 */ - RPI_V2_GPIO_P5_05 = 30, /*!< Version 2, Pin P5-05 */ - RPI_V2_GPIO_P5_06 = 31, /*!< Version 2, Pin P5-06 */ + /* RPi Version 2, new plug P5 */ + RPI_V2_GPIO_P5_03 = 28, /*!< Version 2, Pin P5-03 */ + RPI_V2_GPIO_P5_04 = 29, /*!< Version 2, Pin P5-04 */ + RPI_V2_GPIO_P5_05 = 30, /*!< Version 2, Pin P5-05 */ + RPI_V2_GPIO_P5_06 = 31, /*!< Version 2, Pin P5-06 */ - /* RPi B+ J8 header, also RPi 2 40 pin GPIO header */ - RPI_BPLUS_GPIO_J8_03 = 2, /*!< B+, Pin J8-03 */ - RPI_BPLUS_GPIO_J8_05 = 3, /*!< B+, Pin J8-05 */ - RPI_BPLUS_GPIO_J8_07 = 4, /*!< B+, Pin J8-07 */ - RPI_BPLUS_GPIO_J8_08 = 14, /*!< B+, Pin J8-08, defaults to alt function 0 UART0_TXD */ - RPI_BPLUS_GPIO_J8_10 = 15, /*!< B+, Pin J8-10, defaults to alt function 0 UART0_RXD */ - RPI_BPLUS_GPIO_J8_11 = 17, /*!< B+, Pin J8-11 */ - RPI_BPLUS_GPIO_J8_12 = 18, /*!< B+, Pin J8-12, can be PWM channel 0 in ALT FUN 5 */ - RPI_BPLUS_GPIO_J8_13 = 27, /*!< B+, Pin J8-13 */ - RPI_BPLUS_GPIO_J8_15 = 22, /*!< B+, Pin J8-15 */ - RPI_BPLUS_GPIO_J8_16 = 23, /*!< B+, Pin J8-16 */ - RPI_BPLUS_GPIO_J8_18 = 24, /*!< B+, Pin J8-18 */ - RPI_BPLUS_GPIO_J8_19 = 10, /*!< B+, Pin J8-19, MOSI when SPI0 in use */ - RPI_BPLUS_GPIO_J8_21 = 9, /*!< B+, Pin J8-21, MISO when SPI0 in use */ - RPI_BPLUS_GPIO_J8_22 = 25, /*!< B+, Pin J8-22 */ - RPI_BPLUS_GPIO_J8_23 = 11, /*!< B+, Pin J8-23, CLK when SPI0 in use */ - RPI_BPLUS_GPIO_J8_24 = 8, /*!< B+, Pin J8-24, CE0 when SPI0 in use */ - RPI_BPLUS_GPIO_J8_26 = 7, /*!< B+, Pin J8-26, CE1 when SPI0 in use */ - RPI_BPLUS_GPIO_J8_29 = 5, /*!< B+, Pin J8-29, */ - RPI_BPLUS_GPIO_J8_31 = 6, /*!< B+, Pin J8-31, */ - RPI_BPLUS_GPIO_J8_32 = 12, /*!< B+, Pin J8-32, */ - RPI_BPLUS_GPIO_J8_33 = 13, /*!< B+, Pin J8-33, */ - RPI_BPLUS_GPIO_J8_35 = 19, /*!< B+, Pin J8-35, */ - RPI_BPLUS_GPIO_J8_36 = 16, /*!< B+, Pin J8-36, */ - RPI_BPLUS_GPIO_J8_37 = 26, /*!< B+, Pin J8-37, */ - RPI_BPLUS_GPIO_J8_38 = 20, /*!< B+, Pin J8-38, */ - RPI_BPLUS_GPIO_J8_40 = 21 /*!< B+, Pin J8-40, */ + /* RPi B+ J8 header, also RPi 2 40 pin GPIO header */ + RPI_BPLUS_GPIO_J8_03 = 2, /*!< B+, Pin J8-03 */ + RPI_BPLUS_GPIO_J8_05 = 3, /*!< B+, Pin J8-05 */ + RPI_BPLUS_GPIO_J8_07 = 4, /*!< B+, Pin J8-07 */ + RPI_BPLUS_GPIO_J8_08 = 14, /*!< B+, Pin J8-08, defaults to alt function 0 UART0_TXD */ + RPI_BPLUS_GPIO_J8_10 = 15, /*!< B+, Pin J8-10, defaults to alt function 0 UART0_RXD */ + RPI_BPLUS_GPIO_J8_11 = 17, /*!< B+, Pin J8-11 */ + RPI_BPLUS_GPIO_J8_12 = 18, /*!< B+, Pin J8-12, can be PWM channel 0 in ALT FUN 5 */ + RPI_BPLUS_GPIO_J8_13 = 27, /*!< B+, Pin J8-13 */ + RPI_BPLUS_GPIO_J8_15 = 22, /*!< B+, Pin J8-15 */ + RPI_BPLUS_GPIO_J8_16 = 23, /*!< B+, Pin J8-16 */ + RPI_BPLUS_GPIO_J8_18 = 24, /*!< B+, Pin J8-18 */ + RPI_BPLUS_GPIO_J8_19 = 10, /*!< B+, Pin J8-19, MOSI when SPI0 in use */ + RPI_BPLUS_GPIO_J8_21 = 9, /*!< B+, Pin J8-21, MISO when SPI0 in use */ + RPI_BPLUS_GPIO_J8_22 = 25, /*!< B+, Pin J8-22 */ + RPI_BPLUS_GPIO_J8_23 = 11, /*!< B+, Pin J8-23, CLK when SPI0 in use */ + RPI_BPLUS_GPIO_J8_24 = 8, /*!< B+, Pin J8-24, CE0 when SPI0 in use */ + RPI_BPLUS_GPIO_J8_26 = 7, /*!< B+, Pin J8-26, CE1 when SPI0 in use */ + RPI_BPLUS_GPIO_J8_29 = 5, /*!< B+, Pin J8-29, */ + RPI_BPLUS_GPIO_J8_31 = 6, /*!< B+, Pin J8-31, */ + RPI_BPLUS_GPIO_J8_32 = 12, /*!< B+, Pin J8-32, */ + RPI_BPLUS_GPIO_J8_33 = 13, /*!< B+, Pin J8-33, */ + RPI_BPLUS_GPIO_J8_35 = 19, /*!< B+, Pin J8-35, */ + RPI_BPLUS_GPIO_J8_36 = 16, /*!< B+, Pin J8-36, */ + RPI_BPLUS_GPIO_J8_37 = 26, /*!< B+, Pin J8-37, */ + RPI_BPLUS_GPIO_J8_38 = 20, /*!< B+, Pin J8-38, */ + RPI_BPLUS_GPIO_J8_40 = 21 /*!< B+, Pin J8-40, */ } RPiGPIOPin; /* Defines for SPI - GPIO register offsets from BCM2835_SPI0_BASE. + GPIO register offsets from BCM2835_SPI0_BASE. Offsets into the SPI Peripheral block in bytes per 10.5 SPI Register Map */ #define BCM2835_SPI0_CS 0x0000 /*!< SPI Master Control and Status */ @@ -825,32 +820,29 @@ typedef enum /*! \brief bcm2835SPIBitOrder SPI Bit order Specifies the SPI data bit ordering for bcm2835_spi_setBitOrder() */ -typedef enum -{ - BCM2835_SPI_BIT_ORDER_LSBFIRST = 0, /*!< LSB First */ - BCM2835_SPI_BIT_ORDER_MSBFIRST = 1 /*!< MSB First */ -}bcm2835SPIBitOrder; +typedef enum { + BCM2835_SPI_BIT_ORDER_LSBFIRST = 0, /*!< LSB First */ + BCM2835_SPI_BIT_ORDER_MSBFIRST = 1 /*!< MSB First */ +} bcm2835SPIBitOrder; /*! \brief SPI Data mode Specify the SPI data mode to be passed to bcm2835_spi_setDataMode() */ -typedef enum -{ - BCM2835_SPI_MODE0 = 0, /*!< CPOL = 0, CPHA = 0 */ - BCM2835_SPI_MODE1 = 1, /*!< CPOL = 0, CPHA = 1 */ - BCM2835_SPI_MODE2 = 2, /*!< CPOL = 1, CPHA = 0 */ - BCM2835_SPI_MODE3 = 3 /*!< CPOL = 1, CPHA = 1 */ -}bcm2835SPIMode; +typedef enum { + BCM2835_SPI_MODE0 = 0, /*!< CPOL = 0, CPHA = 0 */ + BCM2835_SPI_MODE1 = 1, /*!< CPOL = 0, CPHA = 1 */ + BCM2835_SPI_MODE2 = 2, /*!< CPOL = 1, CPHA = 0 */ + BCM2835_SPI_MODE3 = 3 /*!< CPOL = 1, CPHA = 1 */ +} bcm2835SPIMode; /*! \brief bcm2835SPIChipSelect Specify the SPI chip select pin(s) */ -typedef enum -{ - BCM2835_SPI_CS0 = 0, /*!< Chip Select 0 */ - BCM2835_SPI_CS1 = 1, /*!< Chip Select 1 */ - BCM2835_SPI_CS2 = 2, /*!< Chip Select 2 (ie pins CS1 and CS2 are asserted) */ - BCM2835_SPI_CS_NONE = 3 /*!< No CS, control it yourself */ +typedef enum { + BCM2835_SPI_CS0 = 0, /*!< Chip Select 0 */ + BCM2835_SPI_CS1 = 1, /*!< Chip Select 1 */ + BCM2835_SPI_CS2 = 2, /*!< Chip Select 2 (ie pins CS1 and CS2 are asserted) */ + BCM2835_SPI_CS_NONE = 3 /*!< No CS, control it yourself */ } bcm2835SPIChipSelect; /*! \brief bcm2835SPIClockDivider @@ -860,25 +852,24 @@ typedef enum It is reported that (contrary to the documentation) any even divider may used. The frequencies shown for each divider have been confirmed by measurement. */ -typedef enum -{ - BCM2835_SPI_CLOCK_DIVIDER_65536 = 0, /*!< 65536 = 262.144us = 3.814697260kHz */ - BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768, /*!< 32768 = 131.072us = 7.629394531kHz */ - BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384, /*!< 16384 = 65.536us = 15.25878906kHz */ - BCM2835_SPI_CLOCK_DIVIDER_8192 = 8192, /*!< 8192 = 32.768us = 30/51757813kHz */ - BCM2835_SPI_CLOCK_DIVIDER_4096 = 4096, /*!< 4096 = 16.384us = 61.03515625kHz */ - BCM2835_SPI_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 8.192us = 122.0703125kHz */ - BCM2835_SPI_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 4.096us = 244.140625kHz */ - BCM2835_SPI_CLOCK_DIVIDER_512 = 512, /*!< 512 = 2.048us = 488.28125kHz */ - BCM2835_SPI_CLOCK_DIVIDER_256 = 256, /*!< 256 = 1.024us = 976.5625kHz */ - BCM2835_SPI_CLOCK_DIVIDER_128 = 128, /*!< 128 = 512ns = = 1.953125MHz */ - BCM2835_SPI_CLOCK_DIVIDER_64 = 64, /*!< 64 = 256ns = 3.90625MHz */ - BCM2835_SPI_CLOCK_DIVIDER_32 = 32, /*!< 32 = 128ns = 7.8125MHz */ - BCM2835_SPI_CLOCK_DIVIDER_16 = 16, /*!< 16 = 64ns = 15.625MHz */ - BCM2835_SPI_CLOCK_DIVIDER_8 = 8, /*!< 8 = 32ns = 31.25MHz */ - BCM2835_SPI_CLOCK_DIVIDER_4 = 4, /*!< 4 = 16ns = 62.5MHz */ - BCM2835_SPI_CLOCK_DIVIDER_2 = 2, /*!< 2 = 8ns = 125MHz, fastest you can get */ - BCM2835_SPI_CLOCK_DIVIDER_1 = 1 /*!< 1 = 262.144us = 3.814697260kHz, same as 0/65536 */ +typedef enum { + BCM2835_SPI_CLOCK_DIVIDER_65536 = 0, /*!< 65536 = 262.144us = 3.814697260kHz */ + BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768, /*!< 32768 = 131.072us = 7.629394531kHz */ + BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384, /*!< 16384 = 65.536us = 15.25878906kHz */ + BCM2835_SPI_CLOCK_DIVIDER_8192 = 8192, /*!< 8192 = 32.768us = 30/51757813kHz */ + BCM2835_SPI_CLOCK_DIVIDER_4096 = 4096, /*!< 4096 = 16.384us = 61.03515625kHz */ + BCM2835_SPI_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 8.192us = 122.0703125kHz */ + BCM2835_SPI_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 4.096us = 244.140625kHz */ + BCM2835_SPI_CLOCK_DIVIDER_512 = 512, /*!< 512 = 2.048us = 488.28125kHz */ + BCM2835_SPI_CLOCK_DIVIDER_256 = 256, /*!< 256 = 1.024us = 976.5625kHz */ + BCM2835_SPI_CLOCK_DIVIDER_128 = 128, /*!< 128 = 512ns = = 1.953125MHz */ + BCM2835_SPI_CLOCK_DIVIDER_64 = 64, /*!< 64 = 256ns = 3.90625MHz */ + BCM2835_SPI_CLOCK_DIVIDER_32 = 32, /*!< 32 = 128ns = 7.8125MHz */ + BCM2835_SPI_CLOCK_DIVIDER_16 = 16, /*!< 16 = 64ns = 15.625MHz */ + BCM2835_SPI_CLOCK_DIVIDER_8 = 8, /*!< 8 = 32ns = 31.25MHz */ + BCM2835_SPI_CLOCK_DIVIDER_4 = 4, /*!< 4 = 16ns = 62.5MHz */ + BCM2835_SPI_CLOCK_DIVIDER_2 = 2, /*!< 2 = 8ns = 125MHz, fastest you can get */ + BCM2835_SPI_CLOCK_DIVIDER_1 = 1 /*!< 1 = 262.144us = 3.814697260kHz, same as 0/65536 */ } bcm2835SPIClockDivider; /* Defines for I2C @@ -922,23 +913,21 @@ typedef enum Specifies the divider used to generate the I2C clock from the system clock. Clock divided is based on nominal base clock rate of 250MHz */ -typedef enum -{ - BCM2835_I2C_CLOCK_DIVIDER_2500 = 2500, /*!< 2500 = 10us = 100 kHz */ - BCM2835_I2C_CLOCK_DIVIDER_626 = 626, /*!< 622 = 2.504us = 399.3610 kHz */ - BCM2835_I2C_CLOCK_DIVIDER_150 = 150, /*!< 150 = 60ns = 1.666 MHz (default at reset) */ - BCM2835_I2C_CLOCK_DIVIDER_148 = 148 /*!< 148 = 59ns = 1.689 MHz */ +typedef enum { + BCM2835_I2C_CLOCK_DIVIDER_2500 = 2500, /*!< 2500 = 10us = 100 kHz */ + BCM2835_I2C_CLOCK_DIVIDER_626 = 626, /*!< 622 = 2.504us = 399.3610 kHz */ + BCM2835_I2C_CLOCK_DIVIDER_150 = 150, /*!< 150 = 60ns = 1.666 MHz (default at reset) */ + BCM2835_I2C_CLOCK_DIVIDER_148 = 148 /*!< 148 = 59ns = 1.689 MHz */ } bcm2835I2CClockDivider; /*! \brief bcm2835I2CReasonCodes Specifies the reason codes for the bcm2835_i2c_write and bcm2835_i2c_read functions. */ -typedef enum -{ - BCM2835_I2C_REASON_OK = 0x00, /*!< Success */ - BCM2835_I2C_REASON_ERROR_NACK = 0x01, /*!< Received a NACK */ - BCM2835_I2C_REASON_ERROR_CLKT = 0x02, /*!< Received Clock Stretch Timeout */ - BCM2835_I2C_REASON_ERROR_DATA = 0x04 /*!< Not all data is sent / received */ +typedef enum { + BCM2835_I2C_REASON_OK = 0x00, /*!< Success */ + BCM2835_I2C_REASON_ERROR_NACK = 0x01, /*!< Received a NACK */ + BCM2835_I2C_REASON_ERROR_CLKT = 0x02, /*!< Received Clock Stretch Timeout */ + BCM2835_I2C_REASON_ERROR_DATA = 0x04 /*!< Not all data is sent / received */ } bcm2835I2CReasonCodes; /* Defines for ST @@ -994,20 +983,19 @@ typedef enum Clock divided is based on nominal PWM base clock rate of 19.2MHz The frequencies shown for each divider have been confirmed by measurement */ -typedef enum -{ - BCM2835_PWM_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 9.375kHz */ - BCM2835_PWM_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 18.75kHz */ - BCM2835_PWM_CLOCK_DIVIDER_512 = 512, /*!< 512 = 37.5kHz */ - BCM2835_PWM_CLOCK_DIVIDER_256 = 256, /*!< 256 = 75kHz */ - BCM2835_PWM_CLOCK_DIVIDER_128 = 128, /*!< 128 = 150kHz */ - BCM2835_PWM_CLOCK_DIVIDER_64 = 64, /*!< 64 = 300kHz */ - BCM2835_PWM_CLOCK_DIVIDER_32 = 32, /*!< 32 = 600.0kHz */ - BCM2835_PWM_CLOCK_DIVIDER_16 = 16, /*!< 16 = 1.2MHz */ - BCM2835_PWM_CLOCK_DIVIDER_8 = 8, /*!< 8 = 2.4MHz */ - BCM2835_PWM_CLOCK_DIVIDER_4 = 4, /*!< 4 = 4.8MHz */ - BCM2835_PWM_CLOCK_DIVIDER_2 = 2, /*!< 2 = 9.6MHz, fastest you can get */ - BCM2835_PWM_CLOCK_DIVIDER_1 = 1 /*!< 1 = 4.6875kHz, same as divider 4096 */ +typedef enum { + BCM2835_PWM_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 9.375kHz */ + BCM2835_PWM_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 18.75kHz */ + BCM2835_PWM_CLOCK_DIVIDER_512 = 512, /*!< 512 = 37.5kHz */ + BCM2835_PWM_CLOCK_DIVIDER_256 = 256, /*!< 256 = 75kHz */ + BCM2835_PWM_CLOCK_DIVIDER_128 = 128, /*!< 128 = 150kHz */ + BCM2835_PWM_CLOCK_DIVIDER_64 = 64, /*!< 64 = 300kHz */ + BCM2835_PWM_CLOCK_DIVIDER_32 = 32, /*!< 32 = 600.0kHz */ + BCM2835_PWM_CLOCK_DIVIDER_16 = 16, /*!< 16 = 1.2MHz */ + BCM2835_PWM_CLOCK_DIVIDER_8 = 8, /*!< 8 = 2.4MHz */ + BCM2835_PWM_CLOCK_DIVIDER_4 = 4, /*!< 4 = 4.8MHz */ + BCM2835_PWM_CLOCK_DIVIDER_2 = 2, /*!< 2 = 9.6MHz, fastest you can get */ + BCM2835_PWM_CLOCK_DIVIDER_1 = 1 /*!< 1 = 4.6875kHz, same as divider 4096 */ } bcm2835PWMClockDivider; /*! @} */ @@ -1022,625 +1010,626 @@ typedef enum extern "C" { #endif - /*! \defgroup BCM2835initgrp Library initialisation and management - \ingroup BCM2835grp - These functions allow you to intialise and control the bcm2835 library - @{ - */ - - /*! Initialise the library by opening /dev/mem (if you are root) - or /dev/gpiomem (if you are not) - and getting pointers to the - internal memory for BCM 2835 device registers. You must call this (successfully) - before calling any other - functions in this library (except bcm2835_set_debug). - If bcm2835_init() fails by returning 0, - calling any other function may result in crashes or other failures. - If bcm2835_init() succeeds but you are not running as root, then only gpio operations - are permitted, and calling any other functions may result in crashes or other failures. . - Prints messages to stderr in case of errors. - \return 1 if successful else 0 - */ - extern int bcm2835_init(void); - - /*! Close the library, deallocating any allocated memory and closing /dev/mem - \return 1 if successful else 0 - */ - extern int bcm2835_close(void); - - /*! Sets the debug level of the library. - A value of 1 prevents mapping to /dev/mem, and makes the library print out - what it would do, rather than accessing the GPIO registers. - A value of 0, the default, causes normal operation. - Call this before calling bcm2835_init(); - \param[in] debug The new debug level. 1 means debug - */ - extern void bcm2835_set_debug(uint8_t debug); - - /*! Returns the version number of the library, same as BCM2835_VERSION - \return the current library version number - */ - extern unsigned int bcm2835_version(void); - - /*! @} */ - - /*! \defgroup BCM2835lowlevelgrp Low level register access - \ingroup BCM2835grp - These functions provide low level register access, and should not generally - need to be used - - @{ - */ - - /*! Gets the base of a register - \param[in] regbase You can use one of the common values BCM2835_REGBASE_* - in \ref bcm2835RegisterBase - \return the register base - \sa Physical Addresses - */ - extern uint32_t* bcm2835_regbase(uint8_t regbase); - - /*! Reads 32 bit value from a peripheral address WITH a memory barrier before and after each read. - This is safe, but slow. The MB before protects this read from any in-flight reads that didn't - use a MB. The MB after protects subsequent reads from another peripheral. - - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \return the value read from the 32 bit register - \sa Physical Addresses - */ - extern uint32_t bcm2835_peri_read(volatile uint32_t* paddr); - - /*! Reads 32 bit value from a peripheral address WITHOUT the read barriers - You should only use this when: - o your code has previously called bcm2835_peri_read() for a register - within the same peripheral, and no read or write to another peripheral has occurred since. - o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral. - - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \return the value read from the 32 bit register - \sa Physical Addresses - */ - extern uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr); - - - /*! Writes 32 bit value from a peripheral address WITH a memory barrier before and after each write - This is safe, but slow. The MB before ensures that any in-flight write to another peripheral - completes before this write is issued. The MB after ensures that subsequent reads and writes - to another peripheral will see the effect of this write. - - This is a tricky optimization; if you aren't sure, use the barrier version. - - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \param[in] value The 32 bit value to write - \sa Physical Addresses - */ - extern void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value); - - /*! Writes 32 bit value from a peripheral address without the write barrier - You should only use this when: - o your code has previously called bcm2835_peri_write() for a register - within the same peripheral, and no other peripheral access has occurred since. - o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral. - - This is a tricky optimization; if you aren't sure, use the barrier version. - - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \param[in] value The 32 bit value to write - \sa Physical Addresses - */ - extern void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value); - - /*! Alters a number of bits in a 32 peripheral regsiter. - It reads the current valu and then alters the bits defines as 1 in mask, - according to the bit value in value. - All other bits that are 0 in the mask are unaffected. - Use this to alter a subset of the bits in a register. - Memory barriers are used. Note that this is not atomic; an interrupt - routine can cause unexpected results. - \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - \param[in] value The 32 bit value to write, masked in by mask. - \param[in] mask Bitmask that defines the bits that will be altered in the register. - \sa Physical Addresses - */ - extern void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask); - /*! @} end of lowlevel */ - - /*! \defgroup BCM2835gpiogrp GPIO register access - \ingroup BCM2835grp - These functions allow you to control the GPIO interface. You can set the - function of each GPIO pin, read the input state and set the output state. - @{ - */ - - /*! Sets the Function Select register for the given pin, which configures - the pin as Input, Output or one of the 6 alternate functions. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \param[in] mode Mode to set the pin to, one of BCM2835_GPIO_FSEL_* from \ref bcm2835FunctionSelect - */ - extern void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode); - - /*! Sets the specified pin output to - HIGH. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \sa bcm2835_gpio_write() - */ - extern void bcm2835_gpio_set(uint8_t pin); - - /*! Sets the specified pin output to - LOW. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \sa bcm2835_gpio_write() - */ - extern void bcm2835_gpio_clr(uint8_t pin); - - /*! Sets any of the first 32 GPIO output pins specified in the mask to - HIGH. - \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \sa bcm2835_gpio_write_multi() - */ - extern void bcm2835_gpio_set_multi(uint32_t mask); - - /*! Sets any of the first 32 GPIO output pins specified in the mask to - LOW. - \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \sa bcm2835_gpio_write_multi() - */ - extern void bcm2835_gpio_clr_multi(uint32_t mask); - - /*! Reads the current level on the specified - pin and returns either HIGH or LOW. Works whether or not the pin - is an input or an output. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \return the current level either HIGH or LOW - */ - extern uint8_t bcm2835_gpio_lev(uint8_t pin); - - /*! Event Detect Status. - Tests whether the specified pin has detected a level or edge - as requested by bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen(), - bcm2835_gpio_len(), bcm2835_gpio_aren(), bcm2835_gpio_afen(). - Clear the flag for a given pin by calling bcm2835_gpio_set_eds(pin); - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \return HIGH if the event detect status for the given pin is true. - */ - extern uint8_t bcm2835_gpio_eds(uint8_t pin); - - /*! Same as bcm2835_gpio_eds() but checks if any of the pins specified in - the mask have detected a level or edge. - \param[in] mask Mask of pins to check. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \return Mask of pins HIGH if the event detect status for the given pin is true. - */ - extern uint32_t bcm2835_gpio_eds_multi(uint32_t mask); - - /*! Sets the Event Detect Status register for a given pin to 1, - which has the effect of clearing the flag. Use this afer seeing - an Event Detect Status on the pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_set_eds(uint8_t pin); - - /*! Same as bcm2835_gpio_set_eds() but clears the flag for any pin which - is set in the mask. - \param[in] mask Mask of pins to clear. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - */ - extern void bcm2835_gpio_set_eds_multi(uint32_t mask); - - /*! Enable Rising Edge Detect Enable for the specified pin. - When a rising edge is detected, sets the appropriate pin in Event Detect Status. - The GPRENn registers use - synchronous edge detection. This means the input signal is sampled using the - system clock and then it is looking for a ?011? pattern on the sampled signal. This - has the effect of suppressing glitches. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_ren(uint8_t pin); - - /*! Disable Rising Edge Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_ren(uint8_t pin); - - /*! Enable Falling Edge Detect Enable for the specified pin. - When a falling edge is detected, sets the appropriate pin in Event Detect Status. - The GPRENn registers use - synchronous edge detection. This means the input signal is sampled using the - system clock and then it is looking for a ?100? pattern on the sampled signal. This - has the effect of suppressing glitches. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_fen(uint8_t pin); - - /*! Disable Falling Edge Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_fen(uint8_t pin); - - /*! Enable High Detect Enable for the specified pin. - When a HIGH level is detected on the pin, sets the appropriate pin in Event Detect Status. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_hen(uint8_t pin); - - /*! Disable High Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_hen(uint8_t pin); - - /*! Enable Low Detect Enable for the specified pin. - When a LOW level is detected on the pin, sets the appropriate pin in Event Detect Status. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_len(uint8_t pin); - - /*! Disable Low Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_len(uint8_t pin); - - /*! Enable Asynchronous Rising Edge Detect Enable for the specified pin. - When a rising edge is detected, sets the appropriate pin in Event Detect Status. - Asynchronous means the incoming signal is not sampled by the system clock. As such - rising edges of very short duration can be detected. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_aren(uint8_t pin); - - /*! Disable Asynchronous Rising Edge Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_aren(uint8_t pin); - - /*! Enable Asynchronous Falling Edge Detect Enable for the specified pin. - When a falling edge is detected, sets the appropriate pin in Event Detect Status. - Asynchronous means the incoming signal is not sampled by the system clock. As such - falling edges of very short duration can be detected. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_afen(uint8_t pin); - - /*! Disable Asynchronous Falling Edge Detect Enable for the specified pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - */ - extern void bcm2835_gpio_clr_afen(uint8_t pin); - - /*! Sets the Pull-up/down register for the given pin. This is - used with bcm2835_gpio_pudclk() to set the Pull-up/down resistor for the given pin. - However, it is usually more convenient to use bcm2835_gpio_set_pud(). - \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl - \sa bcm2835_gpio_set_pud() - */ - extern void bcm2835_gpio_pud(uint8_t pud); - - /*! Clocks the Pull-up/down value set earlier by bcm2835_gpio_pud() into the pin. - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \param[in] on HIGH to clock the value from bcm2835_gpio_pud() into the pin. - LOW to remove the clock. - \sa bcm2835_gpio_set_pud() - */ - extern void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on); - - /*! Reads and returns the Pad Control for the given GPIO group. - \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* - \return Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup - */ - extern uint32_t bcm2835_gpio_pad(uint8_t group); - - /*! Sets the Pad Control for the given GPIO group. - \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* - \param[in] control Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup. Note - that it is not necessary to include BCM2835_PAD_PASSWRD in the mask as this - is automatically included. - */ - extern void bcm2835_gpio_set_pad(uint8_t group, uint32_t control); - - /*! Delays for the specified number of milliseconds. - Uses nanosleep(), and therefore does not use CPU until the time is up. - However, you are at the mercy of nanosleep(). From the manual for nanosleep(): - If the interval specified in req is not an exact multiple of the granularity - underlying clock (see time(7)), then the interval will be - rounded up to the next multiple. Furthermore, after the sleep completes, - there may still be a delay before the CPU becomes free to once - again execute the calling thread. - \param[in] millis Delay in milliseconds - */ - extern void bcm2835_delay (unsigned int millis); - - /*! Delays for the specified number of microseconds. - Uses a combination of nanosleep() and a busy wait loop on the BCM2835 system timers, - However, you are at the mercy of nanosleep(). From the manual for nanosleep(): - If the interval specified in req is not an exact multiple of the granularity - underlying clock (see time(7)), then the interval will be - rounded up to the next multiple. Furthermore, after the sleep completes, - there may still be a delay before the CPU becomes free to once - again execute the calling thread. - For times less than about 450 microseconds, uses a busy wait on the System Timer. - It is reported that a delay of 0 microseconds on RaspberryPi will in fact - result in a delay of about 80 microseconds. Your mileage may vary. - \param[in] micros Delay in microseconds - */ - extern void bcm2835_delayMicroseconds (uint64_t micros); - - /*! Sets the output state of the specified pin - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \param[in] on HIGH sets the output to HIGH and LOW to LOW. - */ - extern void bcm2835_gpio_write(uint8_t pin, uint8_t on); - - /*! Sets any of the first 32 GPIO output pins specified in the mask to the state given by on - \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \param[in] on HIGH sets the output to HIGH and LOW to LOW. - */ - extern void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on); - - /*! Sets the first 32 GPIO output pins specified in the mask to the value given by value - \param[in] value values required for each bit masked in by mask, eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - */ - extern void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask); - - /*! Sets the Pull-up/down mode for the specified pin. This is more convenient than - clocking the mode in with bcm2835_gpio_pud() and bcm2835_gpio_pudclk(). - \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl - */ - extern void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud); - - /*! @} */ - - /*! \defgroup BCM2835spigrp SPI access - \ingroup BCM2835grp - These functions let you use SPI0 (Serial Peripheral Interface) to - interface with an external SPI device. - @{ - */ - - /*! Start SPI operations. - Forces RPi SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) - to alternate function ALT0, which enables those pins for SPI interface. - You should call bcm2835_spi_end() when all SPI funcitons are complete to return the pins to - their default functions. - \sa bcm2835_spi_end() - \return 1 if successful, 0 otherwise (perhaps because you are not running as root) - */ - extern int bcm2835_spi_begin(void); - - /*! End SPI operations. - SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) - are returned to their default INPUT behaviour. - */ - extern void bcm2835_spi_end(void); - - /*! Sets the SPI bit order - NOTE: has no effect. Not supported by SPI0. - Defaults to - \param[in] order The desired bit order, one of BCM2835_SPI_BIT_ORDER_*, - see \ref bcm2835SPIBitOrder - */ - extern void bcm2835_spi_setBitOrder(uint8_t order); - - /*! Sets the SPI clock divider and therefore the - SPI clock speed. - \param[in] divider The desired SPI clock divider, one of BCM2835_SPI_CLOCK_DIVIDER_*, - see \ref bcm2835SPIClockDivider - */ - extern void bcm2835_spi_setClockDivider(uint16_t divider); - - /*! Sets the SPI data mode - Sets the clock polariy and phase - \param[in] mode The desired data mode, one of BCM2835_SPI_MODE*, - see \ref bcm2835SPIMode - */ - extern void bcm2835_spi_setDataMode(uint8_t mode); - - /*! Sets the chip select pin(s) - When an bcm2835_spi_transfer() is made, the selected pin(s) will be asserted during the - transfer. - \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave. - One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect - */ - extern void bcm2835_spi_chipSelect(uint8_t cs); - - /*! Sets the chip select pin polarity for a given pin - When an bcm2835_spi_transfer() occurs, the currently selected chip select pin(s) - will be asserted to the - value given by active. When transfers are not happening, the chip select pin(s) - return to the complement (inactive) value. - \param[in] cs The chip select pin to affect - \param[in] active Whether the chip select pin is to be active HIGH - */ - extern void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active); - - /*! Transfers one byte to and from the currently selected SPI slave. - Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - during the transfer. - Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO. - Returns the read data byte from the slave. - Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual - \param[in] value The 8 bit data byte to write to MOSI - \return The 8 bit byte simultaneously read from MISO - \sa bcm2835_spi_transfern() - */ - extern uint8_t bcm2835_spi_transfer(uint8_t value); - - /*! Transfers any number of bytes to and from the currently selected SPI slave. - Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - during the transfer. - Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO. - The data read read from the slave is placed into rbuf. rbuf must be at least len bytes long - Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual - \param[in] tbuf Buffer of bytes to send. - \param[out] rbuf Received bytes will by put in this buffer - \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send/received - \sa bcm2835_spi_transfer() - */ - extern void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len); - - /*! Transfers any number of bytes to and from the currently selected SPI slave - using bcm2835_spi_transfernb. - The returned data from the slave replaces the transmitted data in the buffer. - \param[in,out] buf Buffer of bytes to send. Received bytes will replace the contents - \param[in] len Number of bytes int eh buffer, and the number of bytes to send/received - \sa bcm2835_spi_transfer() - */ - extern void bcm2835_spi_transfern(char* buf, uint32_t len); - - /*! Transfers any number of bytes to the currently selected SPI slave. - Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - during the transfer. - \param[in] buf Buffer of bytes to send. - \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send - */ - extern void bcm2835_spi_writenb(char* buf, uint32_t len); - - /*! @} */ - - /*! \defgroup BCM2835i2cgrp I2C access - \ingroup BCM2835grp - These functions let you use I2C (The Broadcom Serial Control bus with the Philips - I2C bus/interface version 2.1 January 2000.) to interface with an external I2C device. - @{ - */ - - /*! Start I2C operations. - Forces RPi I2C pins P1-03 (SDA) and P1-05 (SCL) - to alternate function ALT0, which enables those pins for I2C interface. - You should call bcm2835_i2c_end() when all I2C functions are complete to return the pins to - their default functions - \return 1 if successful, 0 otherwise (perhaps because you are not running as root) - \sa bcm2835_i2c_end() - */ - extern int bcm2835_i2c_begin(void); - - /*! End I2C operations. - I2C pins P1-03 (SDA) and P1-05 (SCL) - are returned to their default INPUT behaviour. - */ - extern void bcm2835_i2c_end(void); - - /*! Sets the I2C slave address. - \param[in] addr The I2C slave address. - */ - extern void bcm2835_i2c_setSlaveAddress(uint8_t addr); - - /*! Sets the I2C clock divider and therefore the I2C clock speed. - \param[in] divider The desired I2C clock divider, one of BCM2835_I2C_CLOCK_DIVIDER_*, - see \ref bcm2835I2CClockDivider - */ - extern void bcm2835_i2c_setClockDivider(uint16_t divider); - - /*! Sets the I2C clock divider by converting the baudrate parameter to - the equivalent I2C clock divider. ( see \sa bcm2835_i2c_setClockDivider) - For the I2C standard 100khz you would set baudrate to 100000 - The use of baudrate corresponds to its use in the I2C kernel device - driver. (Of course, bcm2835 has nothing to do with the kernel driver) - */ - extern void bcm2835_i2c_set_baudrate(uint32_t baudrate); - - /*! Transfers any number of bytes to the currently selected I2C slave. - (as previously set by \sa bcm2835_i2c_setSlaveAddress) - \param[in] buf Buffer of bytes to send. - \param[in] len Number of bytes in the buf buffer, and the number of bytes to send. - \return reason see \ref bcm2835I2CReasonCodes - */ - extern uint8_t bcm2835_i2c_write(const char * buf, uint32_t len); - - /*! Transfers any number of bytes from the currently selected I2C slave. - (as previously set by \sa bcm2835_i2c_setSlaveAddress) - \param[in] buf Buffer of bytes to receive. - \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. - \return reason see \ref bcm2835I2CReasonCodes - */ - extern uint8_t bcm2835_i2c_read(char* buf, uint32_t len); - - /*! Allows reading from I2C slaves that require a repeated start (without any prior stop) - to read after the required slave register has been set. For example, the popular - MPL3115A2 pressure and temperature sensor. Note that your device must support or - require this mode. If your device does not require this mode then the standard - combined: - \sa bcm2835_i2c_write - \sa bcm2835_i2c_read - are a better choice. - Will read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress - \param[in] regaddr Buffer containing the slave register you wish to read from. - \param[in] buf Buffer of bytes to receive. - \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. - \return reason see \ref bcm2835I2CReasonCodes - */ - extern uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len); - - /*! Allows sending an arbitrary number of bytes to I2C slaves before issuing a repeated - start (with no prior stop) and reading a response. - Necessary for devices that require such behavior, such as the MLX90620. - Will write to and read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress - \param[in] cmds Buffer containing the bytes to send before the repeated start condition. - \param[in] cmds_len Number of bytes to send from cmds buffer - \param[in] buf Buffer of bytes to receive. - \param[in] buf_len Number of bytes to receive in the buf buffer. - \return reason see \ref bcm2835I2CReasonCodes - */ - extern uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint32_t buf_len); - - /*! @} */ - - /*! \defgroup BCM2835stgrp System Timer access - \ingroup BCM2835grp - Allows access to and delays using the System Timer Counter. - @{ - */ - - /*! Read the System Timer Counter register. - \return the value read from the System Timer Counter Lower 32 bits register - */ - extern uint64_t bcm2835_st_read(void); - - /*! Delays for the specified number of microseconds with offset. - \param[in] offset_micros Offset in microseconds - \param[in] micros Delay in microseconds - */ - extern void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros); - - /*! @} */ - - /*! \defgroup BCM2835pwmgrp Pulse Width Modulation - \ingroup BCM2835grp - Allows control of 2 independent PWM channels. A limited subset of GPIO pins - can be connected to one of these 2 channels, allowing PWM control of GPIO pins. - You have to set the desired pin into a particular Alt Fun to PWM output. See the PWM - documentation on the Main Page. - @{ - */ - - /*! Sets the PWM clock divisor, - to control the basic PWM pulse widths. - \param[in] divisor Divides the basic 19.2MHz PWM clock. You can use one of the common - values BCM2835_PWM_CLOCK_DIVIDER_* in \ref bcm2835PWMClockDivider - */ - extern void bcm2835_pwm_set_clock(uint32_t divisor); - - /*! Sets the mode of the given PWM channel, - allowing you to control the PWM mode and enable/disable that channel - \param[in] channel The PWM channel. 0 or 1. - \param[in] markspace Set true if you want Mark-Space mode. 0 for Balanced mode. - \param[in] enabled Set true to enable this channel and produce PWM pulses. - */ - extern void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled); - - /*! Sets the maximum range of the PWM output. - The data value can vary between 0 and this range to control PWM output - \param[in] channel The PWM channel. 0 or 1. - \param[in] range The maximum value permitted for DATA. - */ - extern void bcm2835_pwm_set_range(uint8_t channel, uint32_t range); - - /*! Sets the PWM pulse ratio to emit to DATA/RANGE, - where RANGE is set by bcm2835_pwm_set_range(). - \param[in] channel The PWM channel. 0 or 1. - \param[in] data Controls the PWM output ratio as a fraction of the range. - Can vary from 0 to RANGE. - */ - extern void bcm2835_pwm_set_data(uint8_t channel, uint32_t data); - - /*! @} */ +/*! \defgroup BCM2835initgrp Library initialisation and management + \ingroup BCM2835grp + These functions allow you to intialise and control the bcm2835 library + @{ +*/ + +/*! Initialise the library by opening /dev/mem (if you are root) + or /dev/gpiomem (if you are not) + and getting pointers to the + internal memory for BCM 2835 device registers. You must call this (successfully) + before calling any other + functions in this library (except bcm2835_set_debug). + If bcm2835_init() fails by returning 0, + calling any other function may result in crashes or other failures. + If bcm2835_init() succeeds but you are not running as root, then only gpio operations + are permitted, and calling any other functions may result in crashes or other failures. . + Prints messages to stderr in case of errors. + \return 1 if successful else 0 +*/ +extern int bcm2835_init(void); + +/*! Close the library, deallocating any allocated memory and closing /dev/mem + \return 1 if successful else 0 +*/ +extern int bcm2835_close(void); + +/*! Sets the debug level of the library. + A value of 1 prevents mapping to /dev/mem, and makes the library print out + what it would do, rather than accessing the GPIO registers. + A value of 0, the default, causes normal operation. + Call this before calling bcm2835_init(); + \param[in] debug The new debug level. 1 means debug +*/ +extern void bcm2835_set_debug(uint8_t debug); + +/*! Returns the version number of the library, same as BCM2835_VERSION + \return the current library version number +*/ +extern unsigned int bcm2835_version(void); + +/*! @} */ + +/*! \defgroup BCM2835lowlevelgrp Low level register access + \ingroup BCM2835grp + These functions provide low level register access, and should not generally + need to be used + + @{ +*/ + +/*! Gets the base of a register + \param[in] regbase You can use one of the common values BCM2835_REGBASE_* + in \ref bcm2835RegisterBase + \return the register base + \sa Physical Addresses +*/ +extern uint32_t* bcm2835_regbase(uint8_t regbase); + +/*! Reads 32 bit value from a peripheral address WITH a memory barrier before and after each read. + This is safe, but slow. The MB before protects this read from any in-flight reads that didn't + use a MB. The MB after protects subsequent reads from another peripheral. + + \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. + \return the value read from the 32 bit register + \sa Physical Addresses +*/ +extern uint32_t bcm2835_peri_read(volatile uint32_t* paddr); + +/*! Reads 32 bit value from a peripheral address WITHOUT the read barriers + You should only use this when: + o your code has previously called bcm2835_peri_read() for a register + within the same peripheral, and no read or write to another peripheral has occurred since. + o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral. + + \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. + \return the value read from the 32 bit register + \sa Physical Addresses +*/ +extern uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr); + + +/*! Writes 32 bit value from a peripheral address WITH a memory barrier before and after each write + This is safe, but slow. The MB before ensures that any in-flight write to another peripheral + completes before this write is issued. The MB after ensures that subsequent reads and writes + to another peripheral will see the effect of this write. + + This is a tricky optimization; if you aren't sure, use the barrier version. + + \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. + \param[in] value The 32 bit value to write + \sa Physical Addresses +*/ +extern void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value); + +/*! Writes 32 bit value from a peripheral address without the write barrier + You should only use this when: + o your code has previously called bcm2835_peri_write() for a register + within the same peripheral, and no other peripheral access has occurred since. + o your code has called bcm2835_memory_barrier() since the last access to ANOTHER peripheral. + + This is a tricky optimization; if you aren't sure, use the barrier version. + + \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. + \param[in] value The 32 bit value to write + \sa Physical Addresses +*/ +extern void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value); + +/*! Alters a number of bits in a 32 peripheral regsiter. + It reads the current valu and then alters the bits defines as 1 in mask, + according to the bit value in value. + All other bits that are 0 in the mask are unaffected. + Use this to alter a subset of the bits in a register. + Memory barriers are used. Note that this is not atomic; an interrupt + routine can cause unexpected results. + \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. + \param[in] value The 32 bit value to write, masked in by mask. + \param[in] mask Bitmask that defines the bits that will be altered in the register. + \sa Physical Addresses +*/ +extern void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask); +/*! @} end of lowlevel */ + +/*! \defgroup BCM2835gpiogrp GPIO register access + \ingroup BCM2835grp + These functions allow you to control the GPIO interface. You can set the + function of each GPIO pin, read the input state and set the output state. + @{ +*/ + +/*! Sets the Function Select register for the given pin, which configures + the pin as Input, Output or one of the 6 alternate functions. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \param[in] mode Mode to set the pin to, one of BCM2835_GPIO_FSEL_* from \ref bcm2835FunctionSelect +*/ +extern void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode); + +/*! Sets the specified pin output to + HIGH. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \sa bcm2835_gpio_write() +*/ +extern void bcm2835_gpio_set(uint8_t pin); + +/*! Sets the specified pin output to + LOW. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \sa bcm2835_gpio_write() +*/ +extern void bcm2835_gpio_clr(uint8_t pin); + +/*! Sets any of the first 32 GPIO output pins specified in the mask to + HIGH. + \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + \sa bcm2835_gpio_write_multi() +*/ +extern void bcm2835_gpio_set_multi(uint32_t mask); + +/*! Sets any of the first 32 GPIO output pins specified in the mask to + LOW. + \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + \sa bcm2835_gpio_write_multi() +*/ +extern void bcm2835_gpio_clr_multi(uint32_t mask); + +/*! Reads the current level on the specified + pin and returns either HIGH or LOW. Works whether or not the pin + is an input or an output. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \return the current level either HIGH or LOW +*/ +extern uint8_t bcm2835_gpio_lev(uint8_t pin); + +/*! Event Detect Status. + Tests whether the specified pin has detected a level or edge + as requested by bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen(), + bcm2835_gpio_len(), bcm2835_gpio_aren(), bcm2835_gpio_afen(). + Clear the flag for a given pin by calling bcm2835_gpio_set_eds(pin); + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \return HIGH if the event detect status for the given pin is true. +*/ +extern uint8_t bcm2835_gpio_eds(uint8_t pin); + +/*! Same as bcm2835_gpio_eds() but checks if any of the pins specified in + the mask have detected a level or edge. + \param[in] mask Mask of pins to check. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + \return Mask of pins HIGH if the event detect status for the given pin is true. +*/ +extern uint32_t bcm2835_gpio_eds_multi(uint32_t mask); + +/*! Sets the Event Detect Status register for a given pin to 1, + which has the effect of clearing the flag. Use this afer seeing + an Event Detect Status on the pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_set_eds(uint8_t pin); + +/*! Same as bcm2835_gpio_set_eds() but clears the flag for any pin which + is set in the mask. + \param[in] mask Mask of pins to clear. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) +*/ +extern void bcm2835_gpio_set_eds_multi(uint32_t mask); + +/*! Enable Rising Edge Detect Enable for the specified pin. + When a rising edge is detected, sets the appropriate pin in Event Detect Status. + The GPRENn registers use + synchronous edge detection. This means the input signal is sampled using the + system clock and then it is looking for a ?011? pattern on the sampled signal. This + has the effect of suppressing glitches. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_ren(uint8_t pin); + +/*! Disable Rising Edge Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_clr_ren(uint8_t pin); + +/*! Enable Falling Edge Detect Enable for the specified pin. + When a falling edge is detected, sets the appropriate pin in Event Detect Status. + The GPRENn registers use + synchronous edge detection. This means the input signal is sampled using the + system clock and then it is looking for a ?100? pattern on the sampled signal. This + has the effect of suppressing glitches. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_fen(uint8_t pin); + +/*! Disable Falling Edge Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_clr_fen(uint8_t pin); + +/*! Enable High Detect Enable for the specified pin. + When a HIGH level is detected on the pin, sets the appropriate pin in Event Detect Status. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_hen(uint8_t pin); + +/*! Disable High Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_clr_hen(uint8_t pin); + +/*! Enable Low Detect Enable for the specified pin. + When a LOW level is detected on the pin, sets the appropriate pin in Event Detect Status. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_len(uint8_t pin); + +/*! Disable Low Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_clr_len(uint8_t pin); + +/*! Enable Asynchronous Rising Edge Detect Enable for the specified pin. + When a rising edge is detected, sets the appropriate pin in Event Detect Status. + Asynchronous means the incoming signal is not sampled by the system clock. As such + rising edges of very short duration can be detected. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_aren(uint8_t pin); + +/*! Disable Asynchronous Rising Edge Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_clr_aren(uint8_t pin); + +/*! Enable Asynchronous Falling Edge Detect Enable for the specified pin. + When a falling edge is detected, sets the appropriate pin in Event Detect Status. + Asynchronous means the incoming signal is not sampled by the system clock. As such + falling edges of very short duration can be detected. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_afen(uint8_t pin); + +/*! Disable Asynchronous Falling Edge Detect Enable for the specified pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. +*/ +extern void bcm2835_gpio_clr_afen(uint8_t pin); + +/*! Sets the Pull-up/down register for the given pin. This is + used with bcm2835_gpio_pudclk() to set the Pull-up/down resistor for the given pin. + However, it is usually more convenient to use bcm2835_gpio_set_pud(). + \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl + \sa bcm2835_gpio_set_pud() +*/ +extern void bcm2835_gpio_pud(uint8_t pud); + +/*! Clocks the Pull-up/down value set earlier by bcm2835_gpio_pud() into the pin. + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \param[in] on HIGH to clock the value from bcm2835_gpio_pud() into the pin. + LOW to remove the clock. + \sa bcm2835_gpio_set_pud() +*/ +extern void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on); + +/*! Reads and returns the Pad Control for the given GPIO group. + \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* + \return Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup +*/ +extern uint32_t bcm2835_gpio_pad(uint8_t group); + +/*! Sets the Pad Control for the given GPIO group. + \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* + \param[in] control Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup. Note + that it is not necessary to include BCM2835_PAD_PASSWRD in the mask as this + is automatically included. +*/ +extern void bcm2835_gpio_set_pad(uint8_t group, uint32_t control); + +/*! Delays for the specified number of milliseconds. + Uses nanosleep(), and therefore does not use CPU until the time is up. + However, you are at the mercy of nanosleep(). From the manual for nanosleep(): + If the interval specified in req is not an exact multiple of the granularity + underlying clock (see time(7)), then the interval will be + rounded up to the next multiple. Furthermore, after the sleep completes, + there may still be a delay before the CPU becomes free to once + again execute the calling thread. + \param[in] millis Delay in milliseconds +*/ +extern void bcm2835_delay (unsigned int millis); + +/*! Delays for the specified number of microseconds. + Uses a combination of nanosleep() and a busy wait loop on the BCM2835 system timers, + However, you are at the mercy of nanosleep(). From the manual for nanosleep(): + If the interval specified in req is not an exact multiple of the granularity + underlying clock (see time(7)), then the interval will be + rounded up to the next multiple. Furthermore, after the sleep completes, + there may still be a delay before the CPU becomes free to once + again execute the calling thread. + For times less than about 450 microseconds, uses a busy wait on the System Timer. + It is reported that a delay of 0 microseconds on RaspberryPi will in fact + result in a delay of about 80 microseconds. Your mileage may vary. + \param[in] micros Delay in microseconds +*/ +extern void bcm2835_delayMicroseconds (uint64_t micros); + +/*! Sets the output state of the specified pin + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \param[in] on HIGH sets the output to HIGH and LOW to LOW. +*/ +extern void bcm2835_gpio_write(uint8_t pin, uint8_t on); + +/*! Sets any of the first 32 GPIO output pins specified in the mask to the state given by on + \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + \param[in] on HIGH sets the output to HIGH and LOW to LOW. +*/ +extern void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on); + +/*! Sets the first 32 GPIO output pins specified in the mask to the value given by value + \param[in] value values required for each bit masked in by mask, eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) + \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) +*/ +extern void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask); + +/*! Sets the Pull-up/down mode for the specified pin. This is more convenient than + clocking the mode in with bcm2835_gpio_pud() and bcm2835_gpio_pudclk(). + \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. + \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl +*/ +extern void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud); + +/*! @} */ + +/*! \defgroup BCM2835spigrp SPI access + \ingroup BCM2835grp + These functions let you use SPI0 (Serial Peripheral Interface) to + interface with an external SPI device. + @{ +*/ + +/*! Start SPI operations. + Forces RPi SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) + to alternate function ALT0, which enables those pins for SPI interface. + You should call bcm2835_spi_end() when all SPI funcitons are complete to return the pins to + their default functions. + \sa bcm2835_spi_end() + \return 1 if successful, 0 otherwise (perhaps because you are not running as root) +*/ +extern int bcm2835_spi_begin(void); + +/*! End SPI operations. + SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) + are returned to their default INPUT behaviour. +*/ +extern void bcm2835_spi_end(void); + +/*! Sets the SPI bit order + NOTE: has no effect. Not supported by SPI0. + Defaults to + \param[in] order The desired bit order, one of BCM2835_SPI_BIT_ORDER_*, + see \ref bcm2835SPIBitOrder +*/ +extern void bcm2835_spi_setBitOrder(uint8_t order); + +/*! Sets the SPI clock divider and therefore the + SPI clock speed. + \param[in] divider The desired SPI clock divider, one of BCM2835_SPI_CLOCK_DIVIDER_*, + see \ref bcm2835SPIClockDivider +*/ +extern void bcm2835_spi_setClockDivider(uint16_t divider); + +/*! Sets the SPI data mode + Sets the clock polariy and phase + \param[in] mode The desired data mode, one of BCM2835_SPI_MODE*, + see \ref bcm2835SPIMode +*/ +extern void bcm2835_spi_setDataMode(uint8_t mode); + +/*! Sets the chip select pin(s) + When an bcm2835_spi_transfer() is made, the selected pin(s) will be asserted during the + transfer. + \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave. + One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect +*/ +extern void bcm2835_spi_chipSelect(uint8_t cs); + +/*! Sets the chip select pin polarity for a given pin + When an bcm2835_spi_transfer() occurs, the currently selected chip select pin(s) + will be asserted to the + value given by active. When transfers are not happening, the chip select pin(s) + return to the complement (inactive) value. + \param[in] cs The chip select pin to affect + \param[in] active Whether the chip select pin is to be active HIGH +*/ +extern void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active); + +/*! Transfers one byte to and from the currently selected SPI slave. + Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) + during the transfer. + Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO. + Returns the read data byte from the slave. + Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual + \param[in] value The 8 bit data byte to write to MOSI + \return The 8 bit byte simultaneously read from MISO + \sa bcm2835_spi_transfern() +*/ +extern uint8_t bcm2835_spi_transfer(uint8_t value); + +/*! Transfers any number of bytes to and from the currently selected SPI slave. + Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) + during the transfer. + Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO. + The data read read from the slave is placed into rbuf. rbuf must be at least len bytes long + Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual + \param[in] tbuf Buffer of bytes to send. + \param[out] rbuf Received bytes will by put in this buffer + \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send/received + \sa bcm2835_spi_transfer() +*/ +extern void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len); + +/*! Transfers any number of bytes to and from the currently selected SPI slave + using bcm2835_spi_transfernb. + The returned data from the slave replaces the transmitted data in the buffer. + \param[in,out] buf Buffer of bytes to send. Received bytes will replace the contents + \param[in] len Number of bytes int eh buffer, and the number of bytes to send/received + \sa bcm2835_spi_transfer() +*/ +extern void bcm2835_spi_transfern(char* buf, uint32_t len); + +/*! Transfers any number of bytes to the currently selected SPI slave. + Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) + during the transfer. + \param[in] buf Buffer of bytes to send. + \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send +*/ +extern void bcm2835_spi_writenb(char* buf, uint32_t len); + +/*! @} */ + +/*! \defgroup BCM2835i2cgrp I2C access + \ingroup BCM2835grp + These functions let you use I2C (The Broadcom Serial Control bus with the Philips + I2C bus/interface version 2.1 January 2000.) to interface with an external I2C device. + @{ +*/ + +/*! Start I2C operations. + Forces RPi I2C pins P1-03 (SDA) and P1-05 (SCL) + to alternate function ALT0, which enables those pins for I2C interface. + You should call bcm2835_i2c_end() when all I2C functions are complete to return the pins to + their default functions + \return 1 if successful, 0 otherwise (perhaps because you are not running as root) + \sa bcm2835_i2c_end() +*/ +extern int bcm2835_i2c_begin(void); + +/*! End I2C operations. + I2C pins P1-03 (SDA) and P1-05 (SCL) + are returned to their default INPUT behaviour. +*/ +extern void bcm2835_i2c_end(void); + +/*! Sets the I2C slave address. + \param[in] addr The I2C slave address. +*/ +extern void bcm2835_i2c_setSlaveAddress(uint8_t addr); + +/*! Sets the I2C clock divider and therefore the I2C clock speed. + \param[in] divider The desired I2C clock divider, one of BCM2835_I2C_CLOCK_DIVIDER_*, + see \ref bcm2835I2CClockDivider +*/ +extern void bcm2835_i2c_setClockDivider(uint16_t divider); + +/*! Sets the I2C clock divider by converting the baudrate parameter to + the equivalent I2C clock divider. ( see \sa bcm2835_i2c_setClockDivider) + For the I2C standard 100khz you would set baudrate to 100000 + The use of baudrate corresponds to its use in the I2C kernel device + driver. (Of course, bcm2835 has nothing to do with the kernel driver) +*/ +extern void bcm2835_i2c_set_baudrate(uint32_t baudrate); + +/*! Transfers any number of bytes to the currently selected I2C slave. + (as previously set by \sa bcm2835_i2c_setSlaveAddress) + \param[in] buf Buffer of bytes to send. + \param[in] len Number of bytes in the buf buffer, and the number of bytes to send. + \return reason see \ref bcm2835I2CReasonCodes +*/ +extern uint8_t bcm2835_i2c_write(const char * buf, uint32_t len); + +/*! Transfers any number of bytes from the currently selected I2C slave. + (as previously set by \sa bcm2835_i2c_setSlaveAddress) + \param[in] buf Buffer of bytes to receive. + \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. + \return reason see \ref bcm2835I2CReasonCodes +*/ +extern uint8_t bcm2835_i2c_read(char* buf, uint32_t len); + +/*! Allows reading from I2C slaves that require a repeated start (without any prior stop) + to read after the required slave register has been set. For example, the popular + MPL3115A2 pressure and temperature sensor. Note that your device must support or + require this mode. If your device does not require this mode then the standard + combined: + \sa bcm2835_i2c_write + \sa bcm2835_i2c_read + are a better choice. + Will read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress + \param[in] regaddr Buffer containing the slave register you wish to read from. + \param[in] buf Buffer of bytes to receive. + \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. + \return reason see \ref bcm2835I2CReasonCodes +*/ +extern uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len); + +/*! Allows sending an arbitrary number of bytes to I2C slaves before issuing a repeated + start (with no prior stop) and reading a response. + Necessary for devices that require such behavior, such as the MLX90620. + Will write to and read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress + \param[in] cmds Buffer containing the bytes to send before the repeated start condition. + \param[in] cmds_len Number of bytes to send from cmds buffer + \param[in] buf Buffer of bytes to receive. + \param[in] buf_len Number of bytes to receive in the buf buffer. + \return reason see \ref bcm2835I2CReasonCodes +*/ +extern uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, + uint32_t buf_len); + +/*! @} */ + +/*! \defgroup BCM2835stgrp System Timer access + \ingroup BCM2835grp + Allows access to and delays using the System Timer Counter. + @{ +*/ + +/*! Read the System Timer Counter register. + \return the value read from the System Timer Counter Lower 32 bits register +*/ +extern uint64_t bcm2835_st_read(void); + +/*! Delays for the specified number of microseconds with offset. + \param[in] offset_micros Offset in microseconds + \param[in] micros Delay in microseconds +*/ +extern void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros); + +/*! @} */ + +/*! \defgroup BCM2835pwmgrp Pulse Width Modulation + \ingroup BCM2835grp + Allows control of 2 independent PWM channels. A limited subset of GPIO pins + can be connected to one of these 2 channels, allowing PWM control of GPIO pins. + You have to set the desired pin into a particular Alt Fun to PWM output. See the PWM + documentation on the Main Page. + @{ +*/ + +/*! Sets the PWM clock divisor, + to control the basic PWM pulse widths. + \param[in] divisor Divides the basic 19.2MHz PWM clock. You can use one of the common + values BCM2835_PWM_CLOCK_DIVIDER_* in \ref bcm2835PWMClockDivider +*/ +extern void bcm2835_pwm_set_clock(uint32_t divisor); + +/*! Sets the mode of the given PWM channel, + allowing you to control the PWM mode and enable/disable that channel + \param[in] channel The PWM channel. 0 or 1. + \param[in] markspace Set true if you want Mark-Space mode. 0 for Balanced mode. + \param[in] enabled Set true to enable this channel and produce PWM pulses. +*/ +extern void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled); + +/*! Sets the maximum range of the PWM output. + The data value can vary between 0 and this range to control PWM output + \param[in] channel The PWM channel. 0 or 1. + \param[in] range The maximum value permitted for DATA. +*/ +extern void bcm2835_pwm_set_range(uint8_t channel, uint32_t range); + +/*! Sets the PWM pulse ratio to emit to DATA/RANGE, + where RANGE is set by bcm2835_pwm_set_range(). + \param[in] channel The PWM channel. 0 or 1. + \param[in] data Controls the PWM output ratio as a fraction of the range. + Can vary from 0 to RANGE. +*/ +extern void bcm2835_pwm_set_data(uint8_t channel, uint32_t data); + +/*! @} */ #ifdef __cplusplus } #endif diff --git a/drivers/RPi/cpuinfo.c b/drivers/RPi/cpuinfo.c index 5fa48dc..8c16a0d 100644 --- a/drivers/RPi/cpuinfo.c +++ b/drivers/RPi/cpuinfo.c @@ -27,167 +27,232 @@ SOFTWARE. int get_rpi_info(rpi_info *info) { - FILE *fp; - char buffer[1024]; - char hardware[1024]; - char revision[1024]; - char *rev; - int found = 0; - int len; + FILE *fp; + char buffer[1024]; + char hardware[1024]; + char revision[1024]; + char *rev; + int found = 0; + int len; - if ((fp = fopen("/proc/cpuinfo", "r")) == NULL) - return -1; - while(!feof(fp)) { - fgets(buffer, sizeof(buffer), fp); - sscanf(buffer, "Hardware : %s", hardware); - if (strcmp(hardware, "BCM2708") == 0 || - strcmp(hardware, "BCM2709") == 0 || - strcmp(hardware, "BCM2835") == 0 || - strcmp(hardware, "BCM2836") == 0 || - strcmp(hardware, "BCM2837") == 0 ) { - found = 1; - } - sscanf(buffer, "Revision : %s", revision); - } - fclose(fp); + if ((fp = fopen("/proc/cpuinfo", "r")) == NULL) { + return -1; + } + while(!feof(fp)) { + fgets(buffer, sizeof(buffer), fp); + sscanf(buffer, "Hardware : %s", hardware); + if (strcmp(hardware, "BCM2708") == 0 || + strcmp(hardware, "BCM2709") == 0 || + strcmp(hardware, "BCM2835") == 0 || + strcmp(hardware, "BCM2836") == 0 || + strcmp(hardware, "BCM2837") == 0 ) { + found = 1; + } + sscanf(buffer, "Revision : %s", revision); + } + fclose(fp); - if (!found) - return -1; + if (!found) { + return -1; + } - if ((len = strlen(revision)) == 0) - return -1; + if ((len = strlen(revision)) == 0) { + return -1; + } - if (len >= 6 && strtol((char[]){revision[len-6],0}, NULL, 16) & 8) { - // new scheme - //info->rev = revision[len-1]-'0'; - strcpy(info->revision, revision); - switch (revision[len-2]) { - case '0': info->type = "Model A"; info->p1_revision = 2; break; - case '1': info->type = "Model B"; info->p1_revision = 2; break; - case '2': info->type = "Model A+"; info->p1_revision = 3; break; - case '3': info->type = "Model B+"; info->p1_revision = 3; break; - case '4': info->type = "Pi 2 Model B"; info->p1_revision = 3; break; - case '5': info->type = "Alpha"; info->p1_revision = 3; break; - case '6': info->type = "Compute"; info->p1_revision = 0; break; - case '8': info->type = "Pi 3 Model B"; info->p1_revision = 3; break; - case '9': info->type = "Zero"; info->p1_revision = 3; break; - default : info->type = "Unknown"; info->p1_revision = 3; break; - } - switch (revision[len-4]) { - case '0': info->processor = "BCM2835"; break; - case '1': info->processor = "BCM2836"; break; - case '2': info->processor = "BCM2837"; break; - default : info->processor = "Unknown"; break; - } - switch (revision[len-5]) { - case '0': info->manufacturer = "Sony"; break; - case '1': info->manufacturer = "Egoman"; break; - case '2': info->manufacturer = "Embest"; break; - case '4': info->manufacturer = "Embest"; break; - default : info->manufacturer = "Unknown"; break; - } - switch (strtol((char[]){revision[len-6],0}, NULL, 16) & 7) { - case 0: info->ram = "256M"; break; - case 1: info->ram = "512M"; break; - case 2: info->ram = "1024M"; break; - default: info->ram = "Unknown"; break; - } - } else { - // old scheme - info->ram = "Unknown"; - info->manufacturer = "Unknown"; - info->processor = "Unknown"; - info->type = "Unknown"; - strcpy(info->revision, revision); + if (len >= 6 && strtol((char[]) { + revision[len-6],0 + }, NULL, 16) & 8) { + // new scheme + //info->rev = revision[len-1]-'0'; + strcpy(info->revision, revision); + switch (revision[len-2]) { + case '0': + info->type = "Model A"; + info->p1_revision = 2; + break; + case '1': + info->type = "Model B"; + info->p1_revision = 2; + break; + case '2': + info->type = "Model A+"; + info->p1_revision = 3; + break; + case '3': + info->type = "Model B+"; + info->p1_revision = 3; + break; + case '4': + info->type = "Pi 2 Model B"; + info->p1_revision = 3; + break; + case '5': + info->type = "Alpha"; + info->p1_revision = 3; + break; + case '6': + info->type = "Compute"; + info->p1_revision = 0; + break; + case '8': + info->type = "Pi 3 Model B"; + info->p1_revision = 3; + break; + case '9': + info->type = "Zero"; + info->p1_revision = 3; + break; + default : + info->type = "Unknown"; + info->p1_revision = 3; + break; + } + switch (revision[len-4]) { + case '0': + info->processor = "BCM2835"; + break; + case '1': + info->processor = "BCM2836"; + break; + case '2': + info->processor = "BCM2837"; + break; + default : + info->processor = "Unknown"; + break; + } + switch (revision[len-5]) { + case '0': + info->manufacturer = "Sony"; + break; + case '1': + info->manufacturer = "Egoman"; + break; + case '2': + info->manufacturer = "Embest"; + break; + case '4': + info->manufacturer = "Embest"; + break; + default : + info->manufacturer = "Unknown"; + break; + } + switch (strtol((char[]) { + revision[len-6],0 + }, NULL, 16) & 7) { + case 0: + info->ram = "256M"; + break; + case 1: + info->ram = "512M"; + break; + case 2: + info->ram = "1024M"; + break; + default: + info->ram = "Unknown"; + break; + } + } + else { + // old scheme + info->ram = "Unknown"; + info->manufacturer = "Unknown"; + info->processor = "Unknown"; + info->type = "Unknown"; + strcpy(info->revision, revision); - // get last four characters (ignore preceeding 1000 for overvolt) - if (len > 4) - rev = (char *)&revision+len-4; - else - rev = revision; + // get last four characters (ignore preceeding 1000 for overvolt) + if (len > 4) { + rev = (char *)&revision+len-4; + } else { + rev = revision; + } - if ((strcmp(rev, "0002") == 0) || - (strcmp(rev, "0003") == 0)) { - info->type = "Model B"; - info->p1_revision = 1; - info->ram = "256M"; - info->processor = "BCM2835"; - } else if (strcmp(rev, "0004") == 0) { - info->type = "Model B"; - info->p1_revision = 2; - info->ram = "256M"; - info->manufacturer = "Sony"; - info->processor = "BCM2835"; - } else if (strcmp(rev, "0005") == 0) { - info->type = "Model B"; - info->p1_revision = 2; - info->ram = "256M"; - info->manufacturer = "Qisda"; - info->processor = "BCM2835"; - } else if (strcmp(rev, "0006") == 0) { - info->type = "Model B"; - info->p1_revision = 2; - info->ram = "256M"; - info->manufacturer = "Egoman"; - info->processor = "BCM2835"; - } else if (strcmp(rev, "0007") == 0) { - info->type = "Model A"; - info->p1_revision = 2; - info->ram = "256M"; - info->manufacturer = "Egoman"; - info->processor = "BCM2835"; - } else if (strcmp(rev, "0008") == 0) { - info->type = "Model A"; - info->p1_revision = 2; - info->ram = "256M"; - info->manufacturer = "Sony"; - info->processor = "BCM2835"; - } else if (strcmp(rev, "0009") == 0) { - info->type = "Model A"; - info->p1_revision = 2; - info->ram = "256M"; - info->manufacturer = "Qisda"; - info->processor = "BCM2835"; - } else if (strcmp(rev, "000d") == 0) { - info->type = "Model B"; - info->p1_revision = 2; - info->ram = "512M"; - info->manufacturer = "Egoman"; - info->processor = "BCM2835"; - } else if (strcmp(rev, "000e") == 0) { - info->type = "Model B"; - info->p1_revision = 2; - info->ram = "512M"; - info->manufacturer = "Sony"; - info->processor = "BCM2835"; - } else if (strcmp(rev, "000f") == 0) { - info->type = "Model B"; - info->p1_revision = 2; - info->ram = "512M"; - info->manufacturer = "Qisda"; - info->processor = "BCM2835"; - } else if ((strcmp(rev, "0011") == 0) || - (strcmp(rev, "0014") == 0)) { - info->type = "Compute Module"; - info->p1_revision = 0; - info->ram = "512M"; - info->processor = "BCM2835"; - } else if (strcmp(rev, "0012") == 0) { - info->type = "Model A+"; - info->p1_revision = 3; - info->ram = "256M"; - info->processor = "BCM2835"; - } else if ((strcmp(rev, "0010") == 0) || - (strcmp(rev, "0013") == 0)) { - info->type = "Model B+"; - info->p1_revision = 3; - info->ram = "512M"; - info->processor = "BCM2835"; - } else { // don't know - assume revision 3 p1 connector - info->p1_revision = 3; - } - } - return 0; + if ((strcmp(rev, "0002") == 0) || + (strcmp(rev, "0003") == 0)) { + info->type = "Model B"; + info->p1_revision = 1; + info->ram = "256M"; + info->processor = "BCM2835"; + } else if (strcmp(rev, "0004") == 0) { + info->type = "Model B"; + info->p1_revision = 2; + info->ram = "256M"; + info->manufacturer = "Sony"; + info->processor = "BCM2835"; + } else if (strcmp(rev, "0005") == 0) { + info->type = "Model B"; + info->p1_revision = 2; + info->ram = "256M"; + info->manufacturer = "Qisda"; + info->processor = "BCM2835"; + } else if (strcmp(rev, "0006") == 0) { + info->type = "Model B"; + info->p1_revision = 2; + info->ram = "256M"; + info->manufacturer = "Egoman"; + info->processor = "BCM2835"; + } else if (strcmp(rev, "0007") == 0) { + info->type = "Model A"; + info->p1_revision = 2; + info->ram = "256M"; + info->manufacturer = "Egoman"; + info->processor = "BCM2835"; + } else if (strcmp(rev, "0008") == 0) { + info->type = "Model A"; + info->p1_revision = 2; + info->ram = "256M"; + info->manufacturer = "Sony"; + info->processor = "BCM2835"; + } else if (strcmp(rev, "0009") == 0) { + info->type = "Model A"; + info->p1_revision = 2; + info->ram = "256M"; + info->manufacturer = "Qisda"; + info->processor = "BCM2835"; + } else if (strcmp(rev, "000d") == 0) { + info->type = "Model B"; + info->p1_revision = 2; + info->ram = "512M"; + info->manufacturer = "Egoman"; + info->processor = "BCM2835"; + } else if (strcmp(rev, "000e") == 0) { + info->type = "Model B"; + info->p1_revision = 2; + info->ram = "512M"; + info->manufacturer = "Sony"; + info->processor = "BCM2835"; + } else if (strcmp(rev, "000f") == 0) { + info->type = "Model B"; + info->p1_revision = 2; + info->ram = "512M"; + info->manufacturer = "Qisda"; + info->processor = "BCM2835"; + } else if ((strcmp(rev, "0011") == 0) || + (strcmp(rev, "0014") == 0)) { + info->type = "Compute Module"; + info->p1_revision = 0; + info->ram = "512M"; + info->processor = "BCM2835"; + } else if (strcmp(rev, "0012") == 0) { + info->type = "Model A+"; + info->p1_revision = 3; + info->ram = "256M"; + info->processor = "BCM2835"; + } else if ((strcmp(rev, "0010") == 0) || + (strcmp(rev, "0013") == 0)) { + info->type = "Model B+"; + info->p1_revision = 3; + info->ram = "512M"; + info->processor = "BCM2835"; + } else { // don't know - assume revision 3 p1 connector + info->p1_revision = 3; + } + } + return 0; } /* diff --git a/drivers/RPi/cpuinfo.h b/drivers/RPi/cpuinfo.h index b3c43fe..dc32f44 100644 --- a/drivers/RPi/cpuinfo.h +++ b/drivers/RPi/cpuinfo.h @@ -28,14 +28,13 @@ SOFTWARE. extern "C" { #endif -typedef struct -{ - int p1_revision; - char *ram; - char *manufacturer; - char *processor; - char *type; - char revision[1024]; +typedef struct { + int p1_revision; + char *ram; + char *manufacturer; + char *processor; + char *type; + char revision[1024]; } rpi_info; int get_rpi_info(rpi_info *info); diff --git a/drivers/RPi/piHiPri.c b/drivers/RPi/piHiPri.c index 63c0216..2300298 100644 --- a/drivers/RPi/piHiPri.c +++ b/drivers/RPi/piHiPri.c @@ -35,14 +35,15 @@ int piHiPri (const int pri) { - struct sched_param sched ; + struct sched_param sched ; - memset (&sched, 0, sizeof(sched)) ; + memset (&sched, 0, sizeof(sched)) ; - if (pri > sched_get_priority_max (SCHED_RR)) - sched.sched_priority = sched_get_priority_max (SCHED_RR) ; - else - sched.sched_priority = pri ; + if (pri > sched_get_priority_max (SCHED_RR)) { + sched.sched_priority = sched_get_priority_max (SCHED_RR) ; + } else { + sched.sched_priority = pri ; + } - return sched_setscheduler (0, SCHED_RR, &sched) ; + return sched_setscheduler (0, SCHED_RR, &sched) ; } diff --git a/drivers/RPi/rpi_util.cpp b/drivers/RPi/rpi_util.cpp index f3ea8fe..3981575 100644 --- a/drivers/RPi/rpi_util.cpp +++ b/drivers/RPi/rpi_util.cpp @@ -55,8 +55,7 @@ static pthread_t *threadIds[64] = {NULL}; // sysFds: // Map a file descriptor from the /sys/class/gpio/gpioX/value -static int sysFds[64] = -{ +static int sysFds[64] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -82,7 +81,7 @@ int get_gpio_number(uint8_t physPin, uint8_t *gpio) } if ((rpiinfo.p1_revision != 3 && physPin > 26) - || (rpiinfo.p1_revision == 3 && physPin > 40)) { + || (rpiinfo.p1_revision == 3 && physPin > 40)) { return -1; } @@ -95,7 +94,8 @@ int get_gpio_number(uint8_t physPin, uint8_t *gpio) return 0; } -void *interruptHandler(void *args) { +void *interruptHandler(void *args) +{ int fd, ret; struct pollfd polls; char c; @@ -126,7 +126,7 @@ void *interruptHandler(void *args) { // A one character read appars to be enough. // Followed by a seek to reset it. (void)read (fd, &c, 1) ; - lseek (fd, 0, SEEK_SET) ; + lseek (fd, 0, SEEK_SET) ; // Call user function. pthread_mutex_lock(&intMutex); if (interruptsEnabled) { @@ -142,7 +142,8 @@ void *interruptHandler(void *args) { return NULL; } -void rpi_util::pinMode(uint8_t physPin, uint8_t mode) { +void rpi_util::pinMode(uint8_t physPin, uint8_t mode) +{ uint8_t gpioPin; if (get_gpio_number(physPin, &gpioPin)) { @@ -158,7 +159,8 @@ void rpi_util::pinMode(uint8_t physPin, uint8_t mode) { } } -void rpi_util::digitalWrite(uint8_t physPin, uint8_t value) { +void rpi_util::digitalWrite(uint8_t physPin, uint8_t value) +{ uint8_t gpioPin; if (get_gpio_number(physPin, &gpioPin)) { @@ -178,7 +180,8 @@ void rpi_util::digitalWrite(uint8_t physPin, uint8_t value) { } } -uint8_t rpi_util::digitalRead(uint8_t physPin) { +uint8_t rpi_util::digitalRead(uint8_t physPin) +{ uint8_t gpioPin; if (get_gpio_number(physPin, &gpioPin)) { @@ -194,7 +197,8 @@ uint8_t rpi_util::digitalRead(uint8_t physPin) { } } -void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode) { +void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode) +{ FILE *fd; char fName[40]; char c; @@ -220,7 +224,7 @@ void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode) { logError("attachInterrupt: Unable to export pin %d for interrupt: %s\n", physPin, strerror(errno)); exit(1); } - fprintf(fd, "%d\n", gpioPin); + fprintf(fd, "%d\n", gpioPin); fclose(fd); // Wait a bit the system to create /sys/class/gpio/gpio @@ -228,7 +232,8 @@ void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode) { snprintf(fName, sizeof(fName), "/sys/class/gpio/gpio%d/direction", gpioPin) ; if ((fd = fopen (fName, "w")) == NULL) { - fprintf (stderr, "attachInterrupt: Unable to open GPIO direction interface for pin %d: %s\n", physPin, strerror(errno)); + fprintf (stderr, "attachInterrupt: Unable to open GPIO direction interface for pin %d: %s\n", + physPin, strerror(errno)); exit(1) ; } fprintf(fd, "in\n") ; @@ -236,18 +241,27 @@ void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode) { snprintf(fName, sizeof(fName), "/sys/class/gpio/gpio%d/edge", gpioPin) ; if ((fd = fopen(fName, "w")) == NULL) { - fprintf (stderr, "attachInterrupt: Unable to open GPIO edge interface for pin %d: %s\n", physPin, strerror(errno)); + fprintf (stderr, "attachInterrupt: Unable to open GPIO edge interface for pin %d: %s\n", physPin, + strerror(errno)); exit(1) ; } switch (mode) { - case CHANGE: fprintf(fd, "both\n"); break; - case FALLING: fprintf(fd, "falling\n"); break; - case RISING: fprintf(fd, "rising\n"); break; - case NONE: fprintf(fd, "none\n"); break; - default: - logError("attachInterrupt: Invalid mode\n"); - fclose(fd); - return; + case CHANGE: + fprintf(fd, "both\n"); + break; + case FALLING: + fprintf(fd, "falling\n"); + break; + case RISING: + fprintf(fd, "rising\n"); + break; + case NONE: + fprintf(fd, "none\n"); + break; + default: + logError("attachInterrupt: Invalid mode\n"); + fclose(fd); + return; } fclose(fd); @@ -275,7 +289,8 @@ void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode) { pthread_create(threadIds[gpioPin], NULL, interruptHandler, (void *)threadArgs); } -void rpi_util::detachInterrupt(uint8_t physPin) { +void rpi_util::detachInterrupt(uint8_t physPin) +{ uint8_t gpioPin; if (get_gpio_number(physPin, &gpioPin)) { @@ -301,22 +316,25 @@ void rpi_util::detachInterrupt(uint8_t physPin) { logError("Unable to unexport pin %d for interrupt\n", gpioPin); exit(1); } - fprintf(fp, "%d", gpioPin); + fprintf(fp, "%d", gpioPin); fclose(fp); } -uint8_t rpi_util::digitalPinToInterrupt(uint8_t physPin) { +uint8_t rpi_util::digitalPinToInterrupt(uint8_t physPin) +{ // No need to convert the pin to gpio, we do it in attachInterrupt(). return physPin; } -void rpi_util::interrupts() { +void rpi_util::interrupts() +{ pthread_mutex_lock(&intMutex); interruptsEnabled = true; pthread_mutex_unlock(&intMutex); } -void rpi_util::noInterrupts() { +void rpi_util::noInterrupts() +{ pthread_mutex_lock(&intMutex); interruptsEnabled = false; pthread_mutex_unlock(&intMutex); diff --git a/drivers/RPi/rpi_util.h b/drivers/RPi/rpi_util.h index 0a10981..9e115d2 100644 --- a/drivers/RPi/rpi_util.h +++ b/drivers/RPi/rpi_util.h @@ -29,7 +29,8 @@ const int pin_to_gpio_rev1[41] = {-1, -1, -1, 0, -1, 1, -1, 4, 14, -1, 15, 17, 1 const int pin_to_gpio_rev2[41] = {-1, -1, -1, 2, -1, 3, -1, 4, 14, -1, 15, 17, 18, 27, -1, 22, 23, -1, 24, 10, -1, 9, 25, 11, 8, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; const int pin_to_gpio_rev3[41] = {-1, -1, -1, 2, -1, 3, -1, 4, 14, -1, 15, 17, 18, 27, -1, 22, 23, -1, 24, 10, -1, 9, 25, 11, 8, -1, 7, -1, -1, 5, -1, 6, 12, 13, -1, 19, 16, 26, 20, -1, 21 }; -namespace rpi_util { +namespace rpi_util +{ typedef enum { LSBFIRST = BCM2835_SPI_BIT_ORDER_LSBFIRST, diff --git a/drivers/SPIFlash/SPIFlash.cpp b/drivers/SPIFlash/SPIFlash.cpp index 52bf06c..cd3d873 100644 --- a/drivers/SPIFlash/SPIFlash.cpp +++ b/drivers/SPIFlash/SPIFlash.cpp @@ -47,46 +47,50 @@ uint8_t SPIFlash::UNIQUEID[8]; /// get this from the datasheet of your flash chip /// Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf) /// Example for Winbond 4Mbit W25X40CL: 0xEF30 (page 14: http://www.winbond.com/NR/rdonlyres/6E25084C-0BFE-4B25-903D-AE10221A0929/0/W25X40CL.pdf) -SPIFlash::SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID) { - _slaveSelectPin = slaveSelectPin; - _jedecID = jedecID; +SPIFlash::SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID) +{ + _slaveSelectPin = slaveSelectPin; + _jedecID = jedecID; } /// Select the flash chip -void SPIFlash::select() { - //save current SPI settings +void SPIFlash::select() +{ + //save current SPI settings #ifndef SPI_HAS_TRANSACTION - noInterrupts(); + noInterrupts(); #endif #ifndef ESP8266 - _SPCR = SPCR; - _SPSR = SPSR; + _SPCR = SPCR; + _SPSR = SPSR; #endif #ifdef SPI_HAS_TRANSACTION - SPI.beginTransaction(_settings); + SPI.beginTransaction(_settings); #else - // set FLASH SPI settings - SPI.setDataMode(SPI_MODE0); - SPI.setBitOrder(MSBFIRST); - SPI.setClockDivider(SPI_CLOCK_DIV4); //decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present - SPI.begin(); + // set FLASH SPI settings + SPI.setDataMode(SPI_MODE0); + SPI.setBitOrder(MSBFIRST); + SPI.setClockDivider( + SPI_CLOCK_DIV4); //decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present + SPI.begin(); #endif - hwDigitalWrite(_slaveSelectPin, LOW); + hwDigitalWrite(_slaveSelectPin, LOW); } /// UNselect the flash chip -void SPIFlash::unselect() { - hwDigitalWrite(_slaveSelectPin, HIGH); - //restore SPI settings to what they were before talking to the FLASH chip +void SPIFlash::unselect() +{ + hwDigitalWrite(_slaveSelectPin, HIGH); + //restore SPI settings to what they were before talking to the FLASH chip #ifdef SPI_HAS_TRANSACTION - SPI.endTransaction(); + SPI.endTransaction(); #else - interrupts(); + interrupts(); #endif #ifndef ESP8266 - SPCR = _SPCR; - SPSR = _SPSR; + SPCR = _SPCR; + SPSR = _SPSR; #endif } @@ -94,39 +98,39 @@ void SPIFlash::unselect() { boolean SPIFlash::initialize() { #ifndef ESP8266 - _SPCR = SPCR; - _SPSR = SPSR; + _SPCR = SPCR; + _SPSR = SPSR; #endif - hwPinMode(_slaveSelectPin, OUTPUT); + hwPinMode(_slaveSelectPin, OUTPUT); #ifdef SPI_HAS_TRANSACTION - _settings = SPISettings(4000000, MSBFIRST, SPI_MODE0); + _settings = SPISettings(4000000, MSBFIRST, SPI_MODE0); #endif - unselect(); - wakeup(); + unselect(); + wakeup(); - if (_jedecID == 0 || readDeviceId() == _jedecID) { - command(SPIFLASH_STATUSWRITE, true); // Write Status Register - SPI.transfer(0); // Global Unprotect - unselect(); - return true; - } - return false; + if (_jedecID == 0 || readDeviceId() == _jedecID) { + command(SPIFLASH_STATUSWRITE, true); // Write Status Register + SPI.transfer(0); // Global Unprotect + unselect(); + return true; + } + return false; } /// Get the manufacturer and device ID bytes (as a short word) uint16_t SPIFlash::readDeviceId() { #if defined(__AVR_ATmega32U4__) // Arduino Leonardo, MoteinoLeo - command(SPIFLASH_IDREAD); // Read JEDEC ID + command(SPIFLASH_IDREAD); // Read JEDEC ID #else - select(); - SPI.transfer(SPIFLASH_IDREAD); + select(); + SPI.transfer(SPIFLASH_IDREAD); #endif - uint16_t jedecid = SPI.transfer(0) << 8; - jedecid |= SPI.transfer(0); - unselect(); - return jedecid; + uint16_t jedecid = SPI.transfer(0) << 8; + jedecid |= SPI.transfer(0); + unselect(); + return jedecid; } /// Get the 64 bit unique identifier, stores it in UNIQUEID[8]. Only needs to be called once, ie after initialize @@ -137,97 +141,100 @@ uint16_t SPIFlash::readDeviceId() /// flash.readUniqueId(); uint8_t* MAC = flash.readUniqueId(); for (uint8_t i=0;i<8;i++) { Serial.print(MAC[i], HEX); Serial.print(' '); } uint8_t* SPIFlash::readUniqueId() { - command(SPIFLASH_MACREAD); - SPI.transfer(0); - SPI.transfer(0); - SPI.transfer(0); - SPI.transfer(0); - for (uint8_t i=0;i<8;i++) { - UNIQUEID[i] = SPI.transfer(0); - } - unselect(); - return UNIQUEID; + command(SPIFLASH_MACREAD); + SPI.transfer(0); + SPI.transfer(0); + SPI.transfer(0); + SPI.transfer(0); + for (uint8_t i=0; i<8; i++) { + UNIQUEID[i] = SPI.transfer(0); + } + unselect(); + return UNIQUEID; } /// read 1 byte from flash memory -uint8_t SPIFlash::readByte(uint32_t addr) { - command(SPIFLASH_ARRAYREADLOWFREQ); - SPI.transfer(addr >> 16); - SPI.transfer(addr >> 8); - SPI.transfer(addr); - uint8_t result = SPI.transfer(0); - unselect(); - return result; +uint8_t SPIFlash::readByte(uint32_t addr) +{ + command(SPIFLASH_ARRAYREADLOWFREQ); + SPI.transfer(addr >> 16); + SPI.transfer(addr >> 8); + SPI.transfer(addr); + uint8_t result = SPI.transfer(0); + unselect(); + return result; } /// read unlimited # of bytes -void SPIFlash::readBytes(uint32_t addr, void* buf, uint16_t len) { - command(SPIFLASH_ARRAYREAD); - SPI.transfer(addr >> 16); - SPI.transfer(addr >> 8); - SPI.transfer(addr); - SPI.transfer(0); //"dont care" - for (uint16_t i = 0; i < len; ++i) { - ((uint8_t*) buf)[i] = SPI.transfer(0); - } - unselect(); +void SPIFlash::readBytes(uint32_t addr, void* buf, uint16_t len) +{ + command(SPIFLASH_ARRAYREAD); + SPI.transfer(addr >> 16); + SPI.transfer(addr >> 8); + SPI.transfer(addr); + SPI.transfer(0); //"dont care" + for (uint16_t i = 0; i < len; ++i) { + ((uint8_t*) buf)[i] = SPI.transfer(0); + } + unselect(); } /// Send a command to the flash chip, pass TRUE for isWrite when its a write command -void SPIFlash::command(uint8_t cmd, boolean isWrite){ +void SPIFlash::command(uint8_t cmd, boolean isWrite) +{ #if defined(__AVR_ATmega32U4__) // Arduino Leonardo, MoteinoLeo - DDRB |= B00000001; // Make sure the SS pin (PB0 - used by RFM12B on MoteinoLeo R1) is set as output HIGH! - PORTB |= B00000001; + DDRB |= B00000001; // Make sure the SS pin (PB0 - used by RFM12B on MoteinoLeo R1) is set as output HIGH! + PORTB |= B00000001; #endif - if (isWrite) - { - command(SPIFLASH_WRITEENABLE); // Write Enable - unselect(); - } - //wait for any write/erase to complete - // a time limit cannot really be added here without it being a very large safe limit - // that is because some chips can take several seconds to carry out a chip erase or other similar multi block or entire-chip operations - // a recommended alternative to such situations where chip can be or not be present is to add a 10k or similar weak pulldown on the - // open drain MISO input which can read noise/static and hence return a non 0 status byte, causing the while() to hang when a flash chip is not present - while(busy()); - select(); - SPI.transfer(cmd); + if (isWrite) { + command(SPIFLASH_WRITEENABLE); // Write Enable + unselect(); + } + //wait for any write/erase to complete + // a time limit cannot really be added here without it being a very large safe limit + // that is because some chips can take several seconds to carry out a chip erase or other similar multi block or entire-chip operations + // a recommended alternative to such situations where chip can be or not be present is to add a 10k or similar weak pulldown on the + // open drain MISO input which can read noise/static and hence return a non 0 status byte, causing the while() to hang when a flash chip is not present + while(busy()); + select(); + SPI.transfer(cmd); } /// check if the chip is busy erasing/writing boolean SPIFlash::busy() { - /* - select(); - SPI.transfer(SPIFLASH_STATUSREAD); - uint8_t status = SPI.transfer(0); - unselect(); - return status & 1; - */ - return readStatus() & 1; + /* + select(); + SPI.transfer(SPIFLASH_STATUSREAD); + uint8_t status = SPI.transfer(0); + unselect(); + return status & 1; + */ + return readStatus() & 1; } /// return the STATUS register uint8_t SPIFlash::readStatus() { - select(); - SPI.transfer(SPIFLASH_STATUSREAD); - uint8_t status = SPI.transfer(0); - unselect(); - return status; + select(); + SPI.transfer(SPIFLASH_STATUSREAD); + uint8_t status = SPI.transfer(0); + unselect(); + return status; } /// Write 1 byte to flash memory /// WARNING: you can only write to previously erased memory locations (see datasheet) /// use the block erase commands to first clear memory (write 0xFFs) -void SPIFlash::writeByte(uint32_t addr, uint8_t byt) { - command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program - SPI.transfer(addr >> 16); - SPI.transfer(addr >> 8); - SPI.transfer(addr); - SPI.transfer(byt); - unselect(); +void SPIFlash::writeByte(uint32_t addr, uint8_t byt) +{ + command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program + SPI.transfer(addr >> 16); + SPI.transfer(addr >> 8); + SPI.transfer(addr); + SPI.transfer(byt); + unselect(); } /// write multiple bytes to flash memory (up to 64K) @@ -235,74 +242,74 @@ void SPIFlash::writeByte(uint32_t addr, uint8_t byt) { /// use the block erase commands to first clear memory (write 0xFFs) /// This version handles both page alignment and data blocks larger than 256 bytes. /// See documentation of #MY_SPIFLASH_SST25TYPE define for more information -void SPIFlash::writeBytes(uint32_t addr, const void* buf, uint16_t len) { +void SPIFlash::writeBytes(uint32_t addr, const void* buf, uint16_t len) +{ #ifdef MY_SPIFLASH_SST25TYPE - //SST25 Type of Flash does not support Page Programming but AAI Word Programming - uint16_t i=0; - uint8_t oddAdr=0; - char s[5]; + //SST25 Type of Flash does not support Page Programming but AAI Word Programming + uint16_t i=0; + uint8_t oddAdr=0; + char s[5]; - command(SPIFLASH_AAIWORDPROGRAM, true); // Byte/Page Program - SPI.transfer(addr >> 16); - SPI.transfer(addr >> 8); - SPI.transfer(addr); + command(SPIFLASH_AAIWORDPROGRAM, true); // Byte/Page Program + SPI.transfer(addr >> 16); + SPI.transfer(addr >> 8); + SPI.transfer(addr); - if (addr%2){ - //start address is not even, i.e. first byte of word must be 0xff - SPI.transfer(0xff); - SPI.transfer(((uint8_t*) buf)[0]); - unselect(); - oddAdr=1; //following addresses must all be shifted one off - len--; - if (len > 0) { - command(SPIFLASH_AAIWORDPROGRAM); //If for loop will run issue Wordprogram command - } - } + if (addr%2) { + //start address is not even, i.e. first byte of word must be 0xff + SPI.transfer(0xff); + SPI.transfer(((uint8_t*) buf)[0]); + unselect(); + oddAdr=1; //following addresses must all be shifted one off + len--; + if (len > 0) { + command(SPIFLASH_AAIWORDPROGRAM); //If for loop will run issue Wordprogram command + } + } - for (i=0;i<(len/2);i++){ - //AAI command must be set before every new word - 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+1+oddAdr]); - unselect(); - } + for (i=0; i<(len/2); i++) { + //AAI command must be set before every new word + 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+1+oddAdr]); + unselect(); + } - 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) - 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(0xff); - unselect(); - } + 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) + 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(0xff); + unselect(); + } - command(SPIFLASH_WRITEDISABLE); //end AAI programming - unselect(); + command(SPIFLASH_WRITEDISABLE); //end AAI programming + unselect(); #else - uint16_t n; - uint16_t maxBytes = 256-(addr%256); // force the first set of bytes to stay within the first page - uint16_t offset = 0; - while (len>0) - { - n = (len<=maxBytes) ? len : maxBytes; - command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program - SPI.transfer(addr >> 16); - SPI.transfer(addr >> 8); - SPI.transfer(addr); + uint16_t n; + uint16_t maxBytes = 256-(addr%256); // force the first set of bytes to stay within the first page + uint16_t offset = 0; + while (len>0) { + n = (len<=maxBytes) ? len : maxBytes; + command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program + SPI.transfer(addr >> 16); + SPI.transfer(addr >> 8); + SPI.transfer(addr); - for (uint16_t i = 0; i < n; i++) { - SPI.transfer(((uint8_t*) buf)[offset + i]); - } - unselect(); + for (uint16_t i = 0; i < n; i++) { + SPI.transfer(((uint8_t*) buf)[offset + i]); + } + unselect(); - addr+=n; // adjust the addresses and remaining bytes by what we've just transferred. - offset +=n; - len -= n; - maxBytes = 256; // now we can do up to 256 bytes per loop - } + addr+=n; // adjust the addresses and remaining bytes by what we've just transferred. + offset +=n; + len -= n; + maxBytes = 256; // now we can do up to 256 bytes per loop + } #endif } @@ -312,40 +319,46 @@ void SPIFlash::writeBytes(uint32_t addr, const void* buf, uint16_t len) { /// other things and later check if the chip is done with busy() /// note that any command will first wait for chip to become available using busy() /// so no need to do that twice -void SPIFlash::chipErase() { - command(SPIFLASH_CHIPERASE, true); - unselect(); +void SPIFlash::chipErase() +{ + command(SPIFLASH_CHIPERASE, true); + unselect(); } /// erase a 4Kbyte block -void SPIFlash::blockErase4K(uint32_t addr) { - command(SPIFLASH_BLOCKERASE_4K, true); // Block Erase - SPI.transfer(addr >> 16); - SPI.transfer(addr >> 8); - SPI.transfer(addr); - unselect(); +void SPIFlash::blockErase4K(uint32_t addr) +{ + command(SPIFLASH_BLOCKERASE_4K, true); // Block Erase + SPI.transfer(addr >> 16); + SPI.transfer(addr >> 8); + SPI.transfer(addr); + unselect(); } /// erase a 32Kbyte block -void SPIFlash::blockErase32K(uint32_t addr) { - command(SPIFLASH_BLOCKERASE_32K, true); // Block Erase - SPI.transfer(addr >> 16); - SPI.transfer(addr >> 8); - SPI.transfer(addr); - unselect(); +void SPIFlash::blockErase32K(uint32_t addr) +{ + command(SPIFLASH_BLOCKERASE_32K, true); // Block Erase + SPI.transfer(addr >> 16); + SPI.transfer(addr >> 8); + SPI.transfer(addr); + unselect(); } -void SPIFlash::sleep() { - command(SPIFLASH_SLEEP); - unselect(); +void SPIFlash::sleep() +{ + command(SPIFLASH_SLEEP); + unselect(); } -void SPIFlash::wakeup() { - command(SPIFLASH_WAKE); - unselect(); +void SPIFlash::wakeup() +{ + command(SPIFLASH_WAKE); + unselect(); } /// cleanup -void SPIFlash::end() { - SPI.end(); +void SPIFlash::end() +{ + SPI.end(); } diff --git a/drivers/SPIFlash/SPIFlash.h b/drivers/SPIFlash/SPIFlash.h index e08b6d5..c3ac5f6 100644 --- a/drivers/SPIFlash/SPIFlash.h +++ b/drivers/SPIFlash/SPIFlash.h @@ -7,28 +7,28 @@ // > 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) // > 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. Added / changed comments to better suit doxygen // ********************************************************************************** // License // ********************************************************************************** -// This program is free software; you can redistribute it -// and/or modify it under the terms of the GNU General -// Public License as published by the Free Software -// Foundation; either version 3 of the License, or -// (at your option) any later version. -// -// This program 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 General Public -// License for more details. -// -// You should have received a copy of the GNU General +// This program is free software; you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 General Public +// License for more details. +// +// You should have received a copy of the GNU General // Public License along with this program. // If not, see . -// -// Licence can be viewed at +// +// Licence can be viewed at // http://www.gnu.org/licenses/gpl-3.0.txt // // Please maintain this license information along with authorship @@ -82,7 +82,7 @@ #define SPIFLASH_BLOCKERASE_32K 0x52 //!< erase one 32K block of flash memory #define SPIFLASH_BLOCKERASE_64K 0xD8 //!< erase one 64K block of flash memory #define SPIFLASH_CHIPERASE 0x60 //!< @brief chip erase (may take several seconds depending on size) - //!< Chip is erased but not actually waited for completion (instead need to check the status register BUSY bit) +//!< Chip is erased but not actually waited for completion (instead need to check the status register BUSY bit) #define SPIFLASH_STATUSREAD 0x05 //!< read status register #define SPIFLASH_STATUSWRITE 0x01 //!< write status register #define SPIFLASH_ARRAYREAD 0x0B //!< read array (fast, need to add 1 dummy byte after 3 address bytes) @@ -92,13 +92,13 @@ #define SPIFLASH_WAKE 0xAB //!< deep power wake up #define SPIFLASH_BYTEPAGEPROGRAM 0x02 //!< write (1 to 256bytes). Writing more than one Byte is not supported on all devices (e.g. SST25 Series) #define SPIFLASH_AAIWORDPROGRAM 0xAD //!< @brief Auto Address Increment Programming on Microchip SST Family Devices which do not support page program.
- //!< Use define #MY_SPIFLASH_SST25TYPE to use AAI prog instead of Bytepageprogram which does not work on SST Family Chips - //!< tested with SST25PF020B80 http://ww1.microchip.com/downloads/en/DeviceDoc/20005135B.pdf +//!< Use define #MY_SPIFLASH_SST25TYPE to use AAI prog instead of Bytepageprogram which does not work on SST Family Chips +//!< tested with SST25PF020B80 http://ww1.microchip.com/downloads/en/DeviceDoc/20005135B.pdf #define SPIFLASH_IDREAD 0x9F //!< @brief read JEDEC manufacturer and device ID (2 bytes, specific bytes for each manufacturer and device) - //!< Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf) - //!< Example for Winbond 4Mbit W25X40CL: 0xEF30 (page 14: http://www.winbond.com/NR/rdonlyres/6E25084C-0BFE-4B25-903D-AE10221A0929/0/W25X40CL.pdf) +//!< Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf) +//!< Example for Winbond 4Mbit W25X40CL: 0xEF30 (page 14: http://www.winbond.com/NR/rdonlyres/6E25084C-0BFE-4B25-903D-AE10221A0929/0/W25X40CL.pdf) #define SPIFLASH_MACREAD 0x4B //!< read unique ID number (MAC) - + /// /// @def MY_SPIFLASH_SST25TYPE /// @brief If set AAI Word Programming is used to support SST25 Family SPI Flash. @@ -107,41 +107,44 @@ /// If SPIFLASH_SST25TYPE is set and writeBytes is called, it will use opcode 0xAD #SPIFLASH_AAIWORDPROGRAM and care for Byte alignment.
/// Note: AAI Wordprogramming is independent of Pages, so pagebreaking is not an issue when using AAI Wordprogramming. /// - #ifdef DOXYGEN //needed to tell doxygen not to ignore the define which is actually made somewhere else - #define MY_SPIFLASH_SST25TYPE - #endif - +#ifdef DOXYGEN //needed to tell doxygen not to ignore the define which is actually made somewhere else +#define MY_SPIFLASH_SST25TYPE +#endif + /** SPIFlash class */ -class SPIFlash { +class SPIFlash +{ public: - static uint8_t UNIQUEID[8]; //!< Storage for unique identifier - SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID=0); //!< Constructor - boolean initialize(); //!< setup SPI, read device ID etc... - void command(uint8_t cmd, boolean isWrite=false); //!< Send a command to the flash chip, pass TRUE for isWrite when its a write command - uint8_t readStatus(); //!< return the STATUS register - uint8_t readByte(uint32_t addr); //!< read 1 byte from flash memory - void readBytes(uint32_t addr, void* buf, uint16_t len); //!< read unlimited # of bytes - void writeByte(uint32_t addr, uint8_t byt); //!< Write 1 byte to flash memory - void writeBytes(uint32_t addr, const void* buf, uint16_t len); //!< write multiple bytes to flash memory (up to 64K), if define SPIFLASH_SST25TYPE is set AAI Word Programming will be used - boolean busy(); //!< check if the chip is busy erasing/writing - void chipErase(); //!< erase entire flash memory array - void blockErase4K(uint32_t address); //!< erase a 4Kbyte block - void blockErase32K(uint32_t address); //!< erase a 32Kbyte block - uint16_t readDeviceId(); //!< Get the manufacturer and device ID bytes (as a short word) - uint8_t* readUniqueId(); //!< Get the 64 bit unique identifier, stores it in @ref UNIQUEID[8] - - void sleep(); //!< Put device to sleep - void wakeup(); //!< Wake device - void end(); //!< end + static uint8_t UNIQUEID[8]; //!< Storage for unique identifier + SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID=0); //!< Constructor + boolean initialize(); //!< setup SPI, read device ID etc... + void command(uint8_t cmd, boolean isWrite= + false); //!< Send a command to the flash chip, pass TRUE for isWrite when its a write command + uint8_t readStatus(); //!< return the STATUS register + uint8_t readByte(uint32_t addr); //!< read 1 byte from flash memory + void readBytes(uint32_t addr, void* buf, uint16_t len); //!< read unlimited # of bytes + void writeByte(uint32_t addr, uint8_t byt); //!< Write 1 byte to flash memory + void writeBytes(uint32_t addr, const void* buf, + uint16_t len); //!< write multiple bytes to flash memory (up to 64K), if define SPIFLASH_SST25TYPE is set AAI Word Programming will be used + boolean busy(); //!< check if the chip is busy erasing/writing + void chipErase(); //!< erase entire flash memory array + void blockErase4K(uint32_t address); //!< erase a 4Kbyte block + void blockErase32K(uint32_t address); //!< erase a 32Kbyte block + uint16_t readDeviceId(); //!< Get the manufacturer and device ID bytes (as a short word) + uint8_t* readUniqueId(); //!< Get the 64 bit unique identifier, stores it in @ref UNIQUEID[8] + + void sleep(); //!< Put device to sleep + void wakeup(); //!< Wake device + void end(); //!< end protected: - void select(); //!< select - void unselect(); //!< unselect - uint8_t _slaveSelectPin; //!< Slave select pin - uint16_t _jedecID; //!< JEDEC ID - uint8_t _SPCR; //!< SPCR - uint8_t _SPSR; //!< SPSR + void select(); //!< select + void unselect(); //!< unselect + uint8_t _slaveSelectPin; //!< Slave select pin + uint16_t _jedecID; //!< JEDEC ID + uint8_t _SPCR; //!< SPCR + uint8_t _SPSR; //!< SPSR #ifdef SPI_HAS_TRANSACTION - SPISettings _settings; + SPISettings _settings; #endif }; diff --git a/examples/AirQualitySensor/AirQualitySensor.ino b/examples/AirQualitySensor/AirQualitySensor.ino index 07827aa..bdf77d0 100644 --- a/examples/AirQualitySensor/AirQualitySensor.ino +++ b/examples/AirQualitySensor/AirQualitySensor.ino @@ -48,14 +48,14 @@ #define MQ_SENSOR_ANALOG_PIN (0) //define which analog input channel you are going to use #define RL_VALUE (5) //define the load resistance on the board, in kilo ohms #define RO_CLEAN_AIR_FACTOR (9.83) //RO_CLEAR_AIR_FACTOR=(Sensor resistance in clean air)/RO, - //which is derived from the chart in datasheet +//which is derived from the chart in datasheet /***********************Software Related Macros************************************/ #define CALIBARAION_SAMPLE_TIMES (50) //define how many samples you are going to take in the calibration phase #define CALIBRATION_SAMPLE_INTERVAL (500) //define the time interal(in milisecond) between each samples in the - //cablibration phase +//cablibration phase #define READ_SAMPLE_INTERVAL (50) //define how many samples you are going to take in normal operation #define READ_SAMPLE_TIMES (5) //define the time interal(in milisecond) between each samples in - //normal operation +//normal operation /**********************Application Related Macros**********************************/ #define GAS_LPG (0) #define GAS_CO (1) @@ -68,58 +68,60 @@ int val = 0; // variable to store the value coming from the sensor float valMQ =0.0; float lastMQ =0.0; float LPGCurve[3] = {2.3,0.21,-0.47}; //two points are taken from the curve. - //with these two points, a line is formed which is "approximately equivalent" - //to the original curve. - //data format:{ x, y, slope}; point1: (lg200, 0.21), point2: (lg10000, -0.59) +//with these two points, a line is formed which is "approximately equivalent" +//to the original curve. +//data format:{ x, y, slope}; point1: (lg200, 0.21), point2: (lg10000, -0.59) float COCurve[3] = {2.3,0.72,-0.34}; //two points are taken from the curve. - //with these two points, a line is formed which is "approximately equivalent" - //to the original curve. - //data format:{ x, y, slope}; point1: (lg200, 0.72), point2: (lg10000, 0.15) -float SmokeCurve[3] ={2.3,0.53,-0.44}; //two points are taken from the curve. - //with these two points, a line is formed which is "approximately equivalent" - //to the original curve. - //data format:{ x, y, slope}; point1: (lg200, 0.53), point2:(lg10000,-0.22) +//with these two points, a line is formed which is "approximately equivalent" +//to the original curve. +//data format:{ x, y, slope}; point1: (lg200, 0.72), point2: (lg10000, 0.15) +float SmokeCurve[3] = {2.3,0.53,-0.44}; //two points are taken from the curve. +//with these two points, a line is formed which is "approximately equivalent" +//to the original curve. +//data format:{ x, y, slope}; point1: (lg200, 0.53), point2:(lg10000,-0.22) MyMessage msg(CHILD_ID_MQ, V_LEVEL); void setup() { - Ro = MQCalibration(MQ_SENSOR_ANALOG_PIN); //Calibrating the sensor. Please make sure the sensor is in clean air + Ro = MQCalibration( + MQ_SENSOR_ANALOG_PIN); //Calibrating the sensor. Please make sure the sensor is in clean air } -void presentation() { - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Air Quality Sensor", "1.0"); +void presentation() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Air Quality Sensor", "1.0"); - // Register all sensors to gateway (they will be created as child devices) - present(CHILD_ID_MQ, S_AIR_QUALITY); + // Register all sensors to gateway (they will be created as child devices) + present(CHILD_ID_MQ, S_AIR_QUALITY); } void loop() { - uint16_t valMQ = MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_CO); - Serial.println(val); + uint16_t valMQ = MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_CO); + Serial.println(val); - Serial.print("LPG:"); - Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_LPG) ); - Serial.print( "ppm" ); - Serial.print(" "); - Serial.print("CO:"); - Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_CO) ); - Serial.print( "ppm" ); - Serial.print(" "); - Serial.print("SMOKE:"); - Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_SMOKE) ); - Serial.print( "ppm" ); - Serial.print("\n"); + Serial.print("LPG:"); + Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_LPG) ); + Serial.print( "ppm" ); + Serial.print(" "); + Serial.print("CO:"); + Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_CO) ); + Serial.print( "ppm" ); + Serial.print(" "); + Serial.print("SMOKE:"); + Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_SMOKE) ); + Serial.print( "ppm" ); + Serial.print("\n"); - if (valMQ != lastMQ) { - send(msg.set((int16_t)ceil(valMQ))); - lastMQ = ceil(valMQ); - } + if (valMQ != lastMQ) { + send(msg.set((int16_t)ceil(valMQ))); + lastMQ = ceil(valMQ); + } - sleep(SLEEP_TIME); //sleep for: sleepTime + sleep(SLEEP_TIME); //sleep for: sleepTime } /****************** MQResistanceCalculation **************************************** @@ -131,7 +133,7 @@ Remarks: The sensor and the load resistor forms a voltage divider. Given the vol ************************************************************************************/ float MQResistanceCalculation(int raw_adc) { - return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc)); + return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc)); } /***************************** MQCalibration **************************************** @@ -144,19 +146,19 @@ Remarks: This function assumes that the sensor is in clean air. It use ************************************************************************************/ float MQCalibration(int mq_pin) { - int i; - float val=0; + int i; + float val=0; - for (i=0;i pin 6 * * From: http://davidegironi.blogspot.fr/2014/01/co2-meter-using-ndir-infrared-mh-z14.html @@ -39,13 +39,13 @@ */ // Enable debug prints to serial monitor -#define MY_DEBUG +#define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 -#include +#include #define CHILD_ID_AIQ 0 #define AIQ_SENSOR_ANALOG_PIN 6 @@ -58,44 +58,48 @@ float lastAIQ =0.0; MyMessage msg(CHILD_ID_AIQ, V_LEVEL); MyMessage msg2(CHILD_ID_AIQ, V_UNIT_PREFIX); -void setup() +void setup() { - pinMode(AIQ_SENSOR_ANALOG_PIN, INPUT); + pinMode(AIQ_SENSOR_ANALOG_PIN, INPUT); } -void presentation() { - // Send the sketch version information to the gateway and Controller - sendSketchInfo("AIQ Sensor CO2 MH-Z14", "1.0"); +void presentation() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("AIQ Sensor CO2 MH-Z14", "1.0"); - // Register all sensors to gateway (they will be created as child devices) - present(CHILD_ID_AIQ, S_AIR_QUALITY); - send(msg2.set("ppm")); + // Register all sensors to gateway (they will be created as child devices) + present(CHILD_ID_AIQ, S_AIR_QUALITY); + send(msg2.set("ppm")); } -void loop() { +void loop() +{ - //unsigned long duration = pulseIn(AIQ_SENSOR_ANALOG_PIN, HIGH); - while(digitalRead(AIQ_SENSOR_ANALOG_PIN) == HIGH) {;} - //wait for the pin to go HIGH and measure HIGH time - unsigned long duration = pulseIn(AIQ_SENSOR_ANALOG_PIN, HIGH); - - //Serial.print(duration/1000); Serial.println(" ms "); - //from datasheet + //unsigned long duration = pulseIn(AIQ_SENSOR_ANALOG_PIN, HIGH); + while(digitalRead(AIQ_SENSOR_ANALOG_PIN) == HIGH) { + ; + } + //wait for the pin to go HIGH and measure HIGH time + unsigned long duration = pulseIn(AIQ_SENSOR_ANALOG_PIN, HIGH); + + //Serial.print(duration/1000); Serial.println(" ms "); + //from datasheet //CO2 ppm = 2000 * (Th - 2ms) / (Th + Tl - 4ms) // given Tl + Th = 1004 // Tl = 1004 - Th // = 2000 * (Th - 2ms) / (Th + 1004 - Th -4ms) // = 2000 * (Th - 2ms) / 1000 = 2 * (Th - 2ms) - long co2ppm = 2 * ((duration/1000) - 2); - //Serial.print(co2ppm); - if ((co2ppm != lastAIQ)&&(abs(co2ppm-lastAIQ)>=10)) { - send(msg.set((long)ceil(co2ppm))); - lastAIQ = ceil(co2ppm); - } - - //Serial.println(); - - // Power down the radio. Note that the radio will get powered back up - // on the next write() call. - sleep(SLEEP_TIME); //sleep for: sleepTime + long co2ppm = 2 * ((duration/1000) - 2); + //Serial.print(co2ppm); + if ((co2ppm != lastAIQ)&&(abs(co2ppm-lastAIQ)>=10)) { + send(msg.set((long)ceil(co2ppm))); + lastAIQ = ceil(co2ppm); + } + + //Serial.println(); + + // Power down the radio. Note that the radio will get powered back up + // on the next write() call. + sleep(SLEEP_TIME); //sleep for: sleepTime } diff --git a/examples/ClearEepromConfig/ClearEepromConfig.ino b/examples/ClearEepromConfig/ClearEepromConfig.ino index e885917..da7628d 100644 --- a/examples/ClearEepromConfig/ClearEepromConfig.ino +++ b/examples/ClearEepromConfig/ClearEepromConfig.ino @@ -21,24 +21,24 @@ * DESCRIPTION * * This sketch clears radioId, relayId and other routing information in EEPROM back to factory default - * + * */ // load core modules only #define MY_CORE_ONLY -#include +#include -void setup() -{ - Serial.begin(MY_BAUD_RATE); - Serial.println("Started clearing. Please wait..."); - for (int i=0;i 100 ? 100 : requestedLevel; - requestedLevel = requestedLevel < 0 ? 0 : requestedLevel; + // Clip incoming level to valid range of 0 to 100 + requestedLevel = requestedLevel > 100 ? 100 : requestedLevel; + requestedLevel = requestedLevel < 0 ? 0 : requestedLevel; - Serial.print( "Changing level to " ); - Serial.print( requestedLevel ); - Serial.print( ", from " ); - Serial.println( currentLevel ); + Serial.print( "Changing level to " ); + Serial.print( requestedLevel ); + Serial.print( ", from " ); + Serial.println( currentLevel ); - fadeToLevel( requestedLevel ); + fadeToLevel( requestedLevel ); - // Inform the gateway of the current DimmableLED's SwitchPower1 and LoadLevelStatus value... - send(lightMsg.set(currentLevel > 0)); + // Inform the gateway of the current DimmableLED's SwitchPower1 and LoadLevelStatus value... + send(lightMsg.set(currentLevel > 0)); - // hek comment: Is this really nessesary? - send( dimmerMsg.set(currentLevel) ); + // hek comment: Is this really nessesary? + send( dimmerMsg.set(currentLevel) ); - } + } } /*** * This method provides a graceful fade up/down effect */ -void fadeToLevel( int toLevel ) { +void fadeToLevel( int toLevel ) +{ - int delta = ( toLevel - currentLevel ) < 0 ? -1 : 1; + int delta = ( toLevel - currentLevel ) < 0 ? -1 : 1; - while ( currentLevel != toLevel ) { - currentLevel += delta; - analogWrite( LED_PIN, (int)(currentLevel / 100. * 255) ); - delay( FADE_DELAY ); - } + while ( currentLevel != toLevel ) { + currentLevel += delta; + analogWrite( LED_PIN, (int)(currentLevel / 100. * 255) ); + delay( FADE_DELAY ); + } } diff --git a/examples/DimmableLight/DimmableLight.ino b/examples/DimmableLight/DimmableLight.ino index 12bac2d..e4bb52e 100644 --- a/examples/DimmableLight/DimmableLight.ino +++ b/examples/DimmableLight/DimmableLight.ino @@ -57,28 +57,29 @@ MyMessage dimmerMsg(CHILD_ID_LIGHT, V_DIMMER); void setup() { - //Retreive our last light state from the eprom - int LightState=loadState(EPROM_LIGHT_STATE); - if (LightState<=1) { - LastLightState=LightState; - int DimValue=loadState(EPROM_DIMMER_LEVEL); - if ((DimValue>0)&&(DimValue<=100)) { - //There should be no Dim value of 0, this would mean LIGHT_OFF - LastDimValue=DimValue; - } - } + //Retreive our last light state from the eprom + int LightState=loadState(EPROM_LIGHT_STATE); + if (LightState<=1) { + LastLightState=LightState; + int DimValue=loadState(EPROM_DIMMER_LEVEL); + if ((DimValue>0)&&(DimValue<=100)) { + //There should be no Dim value of 0, this would mean LIGHT_OFF + LastDimValue=DimValue; + } + } - //Here you actualy switch on/off the light with the last known dim level - SetCurrentState2Hardware(); + //Here you actualy switch on/off the light with the last known dim level + SetCurrentState2Hardware(); - Serial.println( "Node ready to receive messages..." ); + Serial.println( "Node ready to receive messages..." ); } -void presentation() { - // Send the Sketch Version Information to the Gateway - sendSketchInfo(SN, SV); +void presentation() +{ + // Send the Sketch Version Information to the Gateway + sendSketchInfo(SN, SV); - present(CHILD_ID_LIGHT, S_DIMMER ); + present(CHILD_ID_LIGHT, S_DIMMER ); } void loop() @@ -87,74 +88,69 @@ void loop() void receive(const MyMessage &message) { - if (message.type == V_LIGHT) { - Serial.println( "V_LIGHT command received..." ); + if (message.type == V_LIGHT) { + Serial.println( "V_LIGHT command received..." ); - int lstate= atoi( message.data ); - if ((lstate<0)||(lstate>1)) { - Serial.println( "V_LIGHT data invalid (should be 0/1)" ); - return; - } - LastLightState=lstate; - saveState(EPROM_LIGHT_STATE, LastLightState); + int lstate= atoi( message.data ); + if ((lstate<0)||(lstate>1)) { + Serial.println( "V_LIGHT data invalid (should be 0/1)" ); + return; + } + LastLightState=lstate; + saveState(EPROM_LIGHT_STATE, LastLightState); - if ((LastLightState==LIGHT_ON)&&(LastDimValue==0)) { - //In the case that the Light State = On, but the dimmer value is zero, - //then something (probably the controller) did something wrong, - //for the Dim value to 100% - LastDimValue=100; - saveState(EPROM_DIMMER_LEVEL, LastDimValue); - } + if ((LastLightState==LIGHT_ON)&&(LastDimValue==0)) { + //In the case that the Light State = On, but the dimmer value is zero, + //then something (probably the controller) did something wrong, + //for the Dim value to 100% + LastDimValue=100; + saveState(EPROM_DIMMER_LEVEL, LastDimValue); + } - //When receiving a V_LIGHT command we switch the light between OFF and the last received dimmer value - //This means if you previously set the lights dimmer value to 50%, and turn the light ON - //it will do so at 50% - } - else if (message.type == V_DIMMER) { - Serial.println( "V_DIMMER command received..." ); - int dimvalue= atoi( message.data ); - if ((dimvalue<0)||(dimvalue>100)) { - Serial.println( "V_DIMMER data invalid (should be 0..100)" ); - return; - } - if (dimvalue==0) { - LastLightState=LIGHT_OFF; - } - else { - LastLightState=LIGHT_ON; - LastDimValue=dimvalue; - saveState(EPROM_DIMMER_LEVEL, LastDimValue); - } - } - else { - Serial.println( "Invalid command received..." ); - return; - } + //When receiving a V_LIGHT command we switch the light between OFF and the last received dimmer value + //This means if you previously set the lights dimmer value to 50%, and turn the light ON + //it will do so at 50% + } else if (message.type == V_DIMMER) { + Serial.println( "V_DIMMER command received..." ); + int dimvalue= atoi( message.data ); + if ((dimvalue<0)||(dimvalue>100)) { + Serial.println( "V_DIMMER data invalid (should be 0..100)" ); + return; + } + if (dimvalue==0) { + LastLightState=LIGHT_OFF; + } else { + LastLightState=LIGHT_ON; + LastDimValue=dimvalue; + saveState(EPROM_DIMMER_LEVEL, LastDimValue); + } + } else { + Serial.println( "Invalid command received..." ); + return; + } - //Here you set the actual light state/level - SetCurrentState2Hardware(); + //Here you set the actual light state/level + SetCurrentState2Hardware(); } void SetCurrentState2Hardware() { - if (LastLightState==LIGHT_OFF) { - Serial.println( "Light state: OFF" ); - } - else { - Serial.print( "Light state: ON, Level: " ); - Serial.println( LastDimValue ); - } + if (LastLightState==LIGHT_OFF) { + Serial.println( "Light state: OFF" ); + } else { + Serial.print( "Light state: ON, Level: " ); + Serial.println( LastDimValue ); + } - //Send current state to the controller - SendCurrentState2Controller(); + //Send current state to the controller + SendCurrentState2Controller(); } void SendCurrentState2Controller() { - if ((LastLightState==LIGHT_OFF)||(LastDimValue==0)) { - send(dimmerMsg.set((int16_t)0)); - } - else { - send(dimmerMsg.set(LastDimValue)); - } + if ((LastLightState==LIGHT_OFF)||(LastDimValue==0)) { + send(dimmerMsg.set((int16_t)0)); + } else { + send(dimmerMsg.set(LastDimValue)); + } } diff --git a/examples/DustSensor/DustSensor.ino b/examples/DustSensor/DustSensor.ino index e6ea3b2..35524e2 100644 --- a/examples/DustSensor/DustSensor.ino +++ b/examples/DustSensor/DustSensor.ino @@ -21,21 +21,21 @@ * REVISION HISTORY * Version 1.0 - epierre * Converted to 1.4 by Henrik Ekblad - * + * * DESCRIPTION * Arduino Dust Sensort * * connect the sensor as follows : - * + * * VCC >>> 5V * A >>> A0 * GND >>> GND * - * Based on: http://www.dfrobot.com/wiki/index.php/Sharp_GP2Y1010AU + * Based on: http://www.dfrobot.com/wiki/index.php/Sharp_GP2Y1010AU * Authors: Cyrille Médard de Chardon (serialC), Christophe Trefois (Trefex) - * + * * http://www.mysensors.org/build/dust - * + * */ // Enable debug prints @@ -45,7 +45,7 @@ #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 -#include +#include #define CHILD_ID_DUST 0 #define DUST_SENSOR_ANALOG_PIN 1 @@ -64,38 +64,40 @@ float dustDensity = 0; MyMessage dustMsg(CHILD_ID_DUST, V_LEVEL); -void presentation() { - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Dust Sensor", "1.1"); +void presentation() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Dust Sensor", "1.1"); - // Register all sensors to gateway (they will be created as child devices) - present(CHILD_ID_DUST, S_DUST); + // Register all sensors to gateway (they will be created as child devices) + present(CHILD_ID_DUST, S_DUST); } -void loop() { - uint16_t voMeasured = analogRead(DUST_SENSOR_ANALOG_PIN);// Get DUST value +void loop() +{ + uint16_t voMeasured = analogRead(DUST_SENSOR_ANALOG_PIN);// Get DUST value - // 0 - 5V mapped to 0 - 1023 integer values - // recover voltage - calcVoltage = voMeasured * (5.0 / 1024.0); + // 0 - 5V mapped to 0 - 1023 integer values + // recover voltage + calcVoltage = voMeasured * (5.0 / 1024.0); - // linear eqaution taken from http://www.howmuchsnow.com/arduino/airquality/ - // Chris Nafis (c) 2012 - dustDensity = (0.17 * calcVoltage - 0.1)*1000; - - Serial.print("Raw Signal Value (0-1023): "); - Serial.print(voMeasured); - - Serial.print(" - Voltage: "); - Serial.print(calcVoltage); - - Serial.print(" - Dust Density: "); - Serial.println(dustDensity); // unit: ug/m3 - - if (ceil(dustDensity) != lastDUST) { - send(dustMsg.set((int16_t)ceil(dustDensity))); - lastDUST = ceil(dustDensity); - } - - sleep(SLEEP_TIME); + // linear eqaution taken from http://www.howmuchsnow.com/arduino/airquality/ + // Chris Nafis (c) 2012 + dustDensity = (0.17 * calcVoltage - 0.1)*1000; + + Serial.print("Raw Signal Value (0-1023): "); + Serial.print(voMeasured); + + Serial.print(" - Voltage: "); + Serial.print(calcVoltage); + + Serial.print(" - Dust Density: "); + Serial.println(dustDensity); // unit: ug/m3 + + if (ceil(dustDensity) != lastDUST) { + send(dustMsg.set((int16_t)ceil(dustDensity))); + lastDUST = ceil(dustDensity); + } + + sleep(SLEEP_TIME); } diff --git a/examples/DustSensorDSM/DustSensorDSM.ino b/examples/DustSensorDSM/DustSensorDSM.ino index 6657110..5dcaf54 100644 --- a/examples/DustSensorDSM/DustSensorDSM.ino +++ b/examples/DustSensorDSM/DustSensorDSM.ino @@ -19,12 +19,12 @@ ******************************* * * DESCRIPTION - * + * * Dust Sensor for SamYoung DSM501 * connect the sensor as follows : * Pin 2 of dust sensor PM1 -> Digital 3 (PMW) - * Pin 3 of dust sensor -> +5V - * Pin 4 of dust sensor PM2.5 -> Digital 6 (PWM) + * Pin 3 of dust sensor -> +5V + * Pin 4 of dust sensor PM2.5 -> Digital 6 (PWM) * Pin 5 of dust sensor -> Ground * Datasheet: http://www.samyoungsnc.com/products/3-1%20Specification%20DSM501.pdf * Contributor: epierre @@ -37,7 +37,7 @@ #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 -#include +#include #define CHILD_ID_DUST_PM10 0 #define CHILD_ID_DUST_PM25 1 @@ -65,84 +65,85 @@ MyMessage msgPM10(CHILD_ID_DUST_PM10, V_UNIT_PREFIX); MyMessage dustMsgPM25(CHILD_ID_DUST_PM25, V_LEVEL); MyMessage msgPM25(CHILD_ID_DUST_PM25, V_UNIT_PREFIX); -void setup() +void setup() { - pinMode(DUST_SENSOR_DIGITAL_PIN_PM10,INPUT); - pinMode(DUST_SENSOR_DIGITAL_PIN_PM25,INPUT); + pinMode(DUST_SENSOR_DIGITAL_PIN_PM10,INPUT); + pinMode(DUST_SENSOR_DIGITAL_PIN_PM25,INPUT); } -void presentation() { - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Dust Sensor DSM501", "1.4"); +void presentation() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Dust Sensor DSM501", "1.4"); - // Register all sensors to gateway (they will be created as child devices) - present(CHILD_ID_DUST_PM10, S_DUST); - send(msgPM10.set("ppm")); - present(CHILD_ID_DUST_PM25, S_DUST); - send(msgPM25.set("ppm")); + // Register all sensors to gateway (they will be created as child devices) + present(CHILD_ID_DUST_PM10, S_DUST); + send(msgPM10.set("ppm")); + present(CHILD_ID_DUST_PM25, S_DUST); + send(msgPM25.set("ppm")); } -void loop() -{ +void loop() +{ - //get PM 2.5 density of particles over 2.5 μm. - concentrationPM25=(long)getPM(DUST_SENSOR_DIGITAL_PIN_PM25); - Serial.print("PM25: "); - Serial.println(concentrationPM25); - Serial.print("\n"); + //get PM 2.5 density of particles over 2.5 μm. + concentrationPM25=(long)getPM(DUST_SENSOR_DIGITAL_PIN_PM25); + Serial.print("PM25: "); + Serial.println(concentrationPM25); + Serial.print("\n"); + + if ((concentrationPM25 != lastDUSTPM25)&&(concentrationPM25>0)) { + send(dustMsgPM25.set((long)ceil(concentrationPM25))); + lastDUSTPM25 = ceil(concentrationPM25); + } + + //get PM 1.0 - density of particles over 1 μm. + concentrationPM10=getPM(DUST_SENSOR_DIGITAL_PIN_PM10); + Serial.print("PM10: "); + Serial.println(concentrationPM10); + Serial.print("\n"); + //ppmv=mg/m3 * (0.08205*Tmp)/Molecular_mass + //0.08205 = Universal gas constant in atm·m3/(kmol·K) + int temp=20; //external temperature, if you can replace this with a DHT11 or better + long ppmv=(concentrationPM10*0.0283168/100/1000) * (0.08205*temp)/0.01; + + if ((ceil(concentrationPM10) != lastDUSTPM10)&&((long)concentrationPM10>0)) { + send(dustMsgPM10.set((long)ppmv)); + lastDUSTPM10 = ceil(concentrationPM10); + } + + //sleep to save on radio + sleep(SLEEP_TIME); - if ((concentrationPM25 != lastDUSTPM25)&&(concentrationPM25>0)) { - send(dustMsgPM25.set((long)ceil(concentrationPM25))); - lastDUSTPM25 = ceil(concentrationPM25); - } - - //get PM 1.0 - density of particles over 1 μm. - concentrationPM10=getPM(DUST_SENSOR_DIGITAL_PIN_PM10); - Serial.print("PM10: "); - Serial.println(concentrationPM10); - Serial.print("\n"); - //ppmv=mg/m3 * (0.08205*Tmp)/Molecular_mass - //0.08205 = Universal gas constant in atm·m3/(kmol·K) - int temp=20; //external temperature, if you can replace this with a DHT11 or better - long ppmv=(concentrationPM10*0.0283168/100/1000) * (0.08205*temp)/0.01; - - if ((ceil(concentrationPM10) != lastDUSTPM10)&&((long)concentrationPM10>0)) { - send(dustMsgPM10.set((long)ppmv)); - lastDUSTPM10 = ceil(concentrationPM10); - } - - //sleep to save on radio - sleep(SLEEP_TIME); - } -long getPM(int DUST_SENSOR_DIGITAL_PIN) { +long getPM(int DUST_SENSOR_DIGITAL_PIN) +{ - starttime = millis(); + starttime = millis(); - while (1) { - - duration = pulseIn(DUST_SENSOR_DIGITAL_PIN, LOW); - lowpulseoccupancy += duration; - endtime = millis(); - - if ((endtime-starttime) > sampletime_ms) - { - ratio = (lowpulseoccupancy-endtime+starttime)/(sampletime_ms*10.0); // Integer percentage 0=>100 - long concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62; // using spec sheet curve - //Serial.print("lowpulseoccupancy:"); - //Serial.print(lowpulseoccupancy); - //Serial.print("\n"); - //Serial.print("ratio:"); - //Serial.print(ratio); - //Serial.print("\n"); - //Serial.print("DSM501A:"); - //Serial.println(concentration); - //Serial.print("\n"); - - lowpulseoccupancy = 0; - return(concentration); - } - } + while (1) { + + duration = pulseIn(DUST_SENSOR_DIGITAL_PIN, LOW); + lowpulseoccupancy += duration; + endtime = millis(); + + if ((endtime-starttime) > sampletime_ms) { + ratio = (lowpulseoccupancy-endtime+starttime)/(sampletime_ms*10.0); // Integer percentage 0=>100 + long concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62; // using spec sheet curve + //Serial.print("lowpulseoccupancy:"); + //Serial.print(lowpulseoccupancy); + //Serial.print("\n"); + //Serial.print("ratio:"); + //Serial.print(ratio); + //Serial.print("\n"); + //Serial.print("DSM501A:"); + //Serial.println(concentration); + //Serial.print("\n"); + + lowpulseoccupancy = 0; + return(concentration); + } + } } diff --git a/examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino b/examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino index 041f0b2..0ae30df 100644 --- a/examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino +++ b/examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino @@ -20,16 +20,16 @@ * * REVISION HISTORY * Version 1.0 - Henrik EKblad - * + * * DESCRIPTION - * This sketch provides an example how to implement a distance sensor using HC-SR04 + * This sketch provides an example how to implement a distance sensor using HC-SR04 * Use this sensor to measure KWH and Watt of your house meeter * You need to set the correct pulsefactor of your meeter (blinks per KWH). * The sensor starts by fetching current KWH value from gateway. * Reports both KWH and Watt back to gateway. * - * Unfortunately millis() won't increment when the Arduino is in - * sleepmode. So we cannot make this sensor sleep if we also want + * Unfortunately millis() won't increment when the Arduino is in + * sleepmode. So we cannot make this sensor sleep if we also want * to calculate/report watt-number. * http://www.mysensors.org/build/pulse_power */ @@ -41,7 +41,7 @@ #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 -#include +#include #define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR 1000 // Nummber of blinks per KWH of your meeter @@ -49,13 +49,14 @@ #define MAX_WATT 10000 // Max watt value to report. This filetrs outliers. #define CHILD_ID 1 // Id of the sensor child -unsigned long SEND_FREQUENCY = 20000; // Minimum time between send (in milliseconds). We don't wnat to spam the gateway. +unsigned long SEND_FREQUENCY = + 20000; // Minimum time between send (in milliseconds). We don't wnat to spam the gateway. double ppwh = ((double)PULSE_FACTOR)/1000; // Pulses per watt hour bool pcReceived = false; -volatile unsigned long pulseCount = 0; +volatile unsigned long pulseCount = 0; volatile unsigned long lastBlink = 0; volatile unsigned long watt = 0; -unsigned long oldPulseCount = 0; +unsigned long oldPulseCount = 0; unsigned long oldWatt = 0; double oldKwh; unsigned long lastSend; @@ -64,88 +65,90 @@ MyMessage kwhMsg(CHILD_ID,V_KWH); MyMessage pcMsg(CHILD_ID,V_VAR1); -void setup() -{ - // Fetch last known pulse count value from gw - request(CHILD_ID, V_VAR1); +void setup() +{ + // Fetch last known pulse count value from gw + request(CHILD_ID, V_VAR1); - // Use the internal pullup to be able to hook up this sketch directly to an energy meter with S0 output - // If no pullup is used, the reported usage will be too high because of the floating pin - pinMode(DIGITAL_INPUT_SENSOR,INPUT_PULLUP); + // Use the internal pullup to be able to hook up this sketch directly to an energy meter with S0 output + // If no pullup is used, the reported usage will be too high because of the floating pin + pinMode(DIGITAL_INPUT_SENSOR,INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), onPulse, RISING); - lastSend=millis(); + attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), onPulse, RISING); + lastSend=millis(); } -void presentation() { - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Energy Meter", "1.0"); +void presentation() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Energy Meter", "1.0"); - // Register this device as power sensor - present(CHILD_ID, S_POWER); + // Register this device as power sensor + present(CHILD_ID, S_POWER); } -void loop() -{ - unsigned long now = millis(); - // Only send values at a maximum frequency or woken up from sleep - bool sendTime = now - lastSend > SEND_FREQUENCY; - if (pcReceived && (SLEEP_MODE || sendTime)) { - // New watt value has been calculated - if (!SLEEP_MODE && watt != oldWatt) { - // Check that we dont get unresonable large watt value. - // could hapen when long wraps or false interrupt triggered - if (watt<((unsigned long)MAX_WATT)) { - send(wattMsg.set(watt)); // Send watt value to gw - } - Serial.print("Watt:"); - Serial.println(watt); - oldWatt = watt; - } - - // Pulse cout has changed - if (pulseCount != oldPulseCount) { - send(pcMsg.set(pulseCount)); // Send pulse count value to gw - double kwh = ((double)pulseCount/((double)PULSE_FACTOR)); - oldPulseCount = pulseCount; - if (kwh != oldKwh) { - send(kwhMsg.set(kwh, 4)); // Send kwh value to gw - oldKwh = kwh; - } - } - lastSend = now; - } else if (sendTime && !pcReceived) { - // No count received. Try requesting it again - request(CHILD_ID, V_VAR1); - lastSend=now; - } - - if (SLEEP_MODE) { - sleep(SEND_FREQUENCY); - } +void loop() +{ + unsigned long now = millis(); + // Only send values at a maximum frequency or woken up from sleep + bool sendTime = now - lastSend > SEND_FREQUENCY; + if (pcReceived && (SLEEP_MODE || sendTime)) { + // New watt value has been calculated + if (!SLEEP_MODE && watt != oldWatt) { + // Check that we dont get unresonable large watt value. + // could hapen when long wraps or false interrupt triggered + if (watt<((unsigned long)MAX_WATT)) { + send(wattMsg.set(watt)); // Send watt value to gw + } + Serial.print("Watt:"); + Serial.println(watt); + oldWatt = watt; + } + + // Pulse cout has changed + if (pulseCount != oldPulseCount) { + send(pcMsg.set(pulseCount)); // Send pulse count value to gw + double kwh = ((double)pulseCount/((double)PULSE_FACTOR)); + oldPulseCount = pulseCount; + if (kwh != oldKwh) { + send(kwhMsg.set(kwh, 4)); // Send kwh value to gw + oldKwh = kwh; + } + } + lastSend = now; + } else if (sendTime && !pcReceived) { + // No count received. Try requesting it again + request(CHILD_ID, V_VAR1); + lastSend=now; + } + + if (SLEEP_MODE) { + sleep(SEND_FREQUENCY); + } } -void receive(const MyMessage &message) { - if (message.type==V_VAR1) { - pulseCount = oldPulseCount = message.getLong(); - Serial.print("Received last pulse count from gw:"); - Serial.println(pulseCount); - pcReceived = true; - } +void receive(const MyMessage &message) +{ + if (message.type==V_VAR1) { + pulseCount = oldPulseCount = message.getLong(); + Serial.print("Received last pulse count from gw:"); + Serial.println(pulseCount); + pcReceived = true; + } } -void onPulse() -{ - if (!SLEEP_MODE) { - unsigned long newBlink = micros(); - unsigned long interval = newBlink-lastBlink; - if (interval<10000L) { // Sometimes we get interrupt on RISING - return; - } - watt = (3600000000.0 /interval) / ppwh; - lastBlink = newBlink; - } - pulseCount++; +void onPulse() +{ + if (!SLEEP_MODE) { + unsigned long newBlink = micros(); + unsigned long interval = newBlink-lastBlink; + if (interval<10000L) { // Sometimes we get interrupt on RISING + return; + } + watt = (3600000000.0 /interval) / ppwh; + lastBlink = newBlink; + } + pulseCount++; } diff --git a/examples/GatewayESP8266/GatewayESP8266.ino b/examples/GatewayESP8266/GatewayESP8266.ino index 4e7f38d..950bd31 100644 --- a/examples/GatewayESP8266/GatewayESP8266.ino +++ b/examples/GatewayESP8266/GatewayESP8266.ino @@ -126,21 +126,24 @@ #define MY_DEFAULT_TX_LED_PIN 16 // the PCB, on board LED #if defined(MY_USE_UDP) - #include +#include #endif #include #include -void setup() { +void setup() +{ } -void presentation() { - // Present locally attached sensors here +void presentation() +{ + // Present locally attached sensors here } -void loop() { - // Send locally attached sensors data here +void loop() +{ + // Send locally attached sensors data here } diff --git a/examples/GatewayESP8266MQTTClient/GatewayESP8266MQTTClient.ino b/examples/GatewayESP8266MQTTClient/GatewayESP8266MQTTClient.ino index 0b4933b..2f2aecd 100644 --- a/examples/GatewayESP8266MQTTClient/GatewayESP8266MQTTClient.ino +++ b/examples/GatewayESP8266MQTTClient/GatewayESP8266MQTTClient.ino @@ -104,7 +104,7 @@ // The MQTT broker port to to open #define MY_PORT 1883 - /* +/* // Enable inclusion mode #define MY_INCLUSION_MODE_FEATURE // Enable Inclusion mode button on gateway @@ -126,14 +126,17 @@ #include #include -void setup() { +void setup() +{ } -void presentation() { - // Present locally attached sensors here +void presentation() +{ + // Present locally attached sensors here } -void loop() { - // Send locally attech sensors data here +void loop() +{ + // Send locally attech sensors data here } diff --git a/examples/GatewayESP8266OTA/GatewayESP8266OTA.ino b/examples/GatewayESP8266OTA/GatewayESP8266OTA.ino index 353a5f2..5de0965 100644 --- a/examples/GatewayESP8266OTA/GatewayESP8266OTA.ino +++ b/examples/GatewayESP8266OTA/GatewayESP8266OTA.ino @@ -128,45 +128,54 @@ #define MY_DEFAULT_TX_LED_PIN 16 // the PCB, on board LED #if defined(MY_USE_UDP) - #include +#include #else - #include +#include #endif #include -void setup() { +void setup() +{ - ArduinoOTA.onStart([]() { - Serial.println("ArduinoOTA start"); - }); - ArduinoOTA.onEnd([]() { - Serial.println("\nArduinoOTA end"); - }); - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - Serial.printf("OTA Progress: %u%%\r", (progress / (total / 100))); - }); - ArduinoOTA.onError([](ota_error_t error) { - Serial.printf("Error[%u]: ", error); - if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); - else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); - else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); - else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); - else if (error == OTA_END_ERROR) Serial.println("End Failed"); - }); - ArduinoOTA.begin(); - Serial.println("Ready"); - Serial.print("IP address: "); - Serial.println(WiFi.localIP()); + ArduinoOTA.onStart([]() { + Serial.println("ArduinoOTA start"); + }); + ArduinoOTA.onEnd([]() { + Serial.println("\nArduinoOTA end"); + }); + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { + Serial.printf("OTA Progress: %u%%\r", (progress / (total / 100))); + }); + ArduinoOTA.onError([](ota_error_t error) { + Serial.printf("Error[%u]: ", error); + if (error == OTA_AUTH_ERROR) { + Serial.println("Auth Failed"); + } else if (error == OTA_BEGIN_ERROR) { + Serial.println("Begin Failed"); + } else if (error == OTA_CONNECT_ERROR) { + Serial.println("Connect Failed"); + } else if (error == OTA_RECEIVE_ERROR) { + Serial.println("Receive Failed"); + } else if (error == OTA_END_ERROR) { + Serial.println("End Failed"); + } + }); + ArduinoOTA.begin(); + Serial.println("Ready"); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); } -void presentation() { - // Present locally attached sensors here +void presentation() +{ + // Present locally attached sensors here } -void loop() { - // Send locally attech sensors data here - ArduinoOTA.handle(); +void loop() +{ + // Send locally attech sensors data here + ArduinoOTA.handle(); } diff --git a/examples/GatewaySerial/GatewaySerial.ino b/examples/GatewaySerial/GatewaySerial.ino index 747ba9f..7ddcdbf 100644 --- a/examples/GatewaySerial/GatewaySerial.ino +++ b/examples/GatewaySerial/GatewaySerial.ino @@ -1,40 +1,40 @@ - /** - * 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 any of the MY_DEFAULT_xx_LED_PINs - * - 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 - * - */ +/** +* 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 any of the MY_DEFAULT_xx_LED_PINs +* - 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 +* +*/ // Enable debug prints to serial monitor #define MY_DEBUG @@ -83,14 +83,17 @@ #include -void setup() { - // Setup locally attached sensors +void setup() +{ + // Setup locally attached sensors } -void presentation() { - // Present locally attached sensors +void presentation() +{ + // Present locally attached sensors } -void loop() { - // Send locally attached sensor data here +void loop() +{ + // Send locally attached sensor data here } diff --git a/examples/GatewaySerialRS485/GatewaySerialRS485.ino b/examples/GatewaySerialRS485/GatewaySerialRS485.ino index 2db67c9..1cca1b0 100644 --- a/examples/GatewaySerialRS485/GatewaySerialRS485.ino +++ b/examples/GatewaySerialRS485/GatewaySerialRS485.ino @@ -1,54 +1,54 @@ - /** - * 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 RS485 Gateway prints data received from sensors on the serial link. - * The gateway accepts input on seral which will be sent out on - * the RS485 link. - * - * 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): - * - 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 - * - * If your Arduino board has additional serial ports - * you can use to connect the RS485 module. - * Otherwise, the gateway uses AltSoftSerial to handle two serial - * links on one Arduino. Use the following pins for RS485 link - * - * Board Transmit Receive PWM Unusable - * ----- -------- ------- ------------ - * Teensy 3.0 & 3.1 21 20 22 - * Teensy 2.0 9 10 (none) - * Teensy++ 2.0 25 4 26, 27 - * Arduino Uno 9 8 10 - * Arduino Leonardo 5 13 (none) - * Arduino Mega 46 48 44, 45 - * Wiring-S 5 6 4 - * Sanguino 13 14 12 - * - */ +/** +* 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 RS485 Gateway prints data received from sensors on the serial link. +* The gateway accepts input on seral which will be sent out on +* the RS485 link. +* +* 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): +* - 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 +* +* If your Arduino board has additional serial ports +* you can use to connect the RS485 module. +* Otherwise, the gateway uses AltSoftSerial to handle two serial +* links on one Arduino. Use the following pins for RS485 link +* +* Board Transmit Receive PWM Unusable +* ----- -------- ------- ------------ +* Teensy 3.0 & 3.1 21 20 22 +* Teensy 2.0 9 10 (none) +* Teensy++ 2.0 25 4 26, 27 +* Arduino Uno 9 8 10 +* Arduino Leonardo 5 13 (none) +* Arduino Mega 46 48 44, 45 +* Wiring-S 5 6 4 +* Sanguino 13 14 12 +* +*/ // Enable debug prints to serial monitor #define MY_DEBUG @@ -88,14 +88,17 @@ #include -void setup() { - // Setup locally attached sensors +void setup() +{ + // Setup locally attached sensors } -void presentation() { - // Present locally attached sensors +void presentation() +{ + // Present locally attached sensors } -void loop() { - // Send locally attached sensor data here +void loop() +{ + // Send locally attached sensor data here } diff --git a/examples/GatewayW5100/GatewayW5100.ino b/examples/GatewayW5100/GatewayW5100.ino index 99d0ac2..868a150 100644 --- a/examples/GatewayW5100/GatewayW5100.ino +++ b/examples/GatewayW5100/GatewayW5100.ino @@ -58,18 +58,18 @@ // The W5100 ethernet module seems to have a hard time co-operate with // radio on the same spi bus. #if !defined(MY_W5100_SPI_EN) && !defined(ARDUINO_ARCH_SAMD) - #define MY_SOFTSPI - #define MY_SOFT_SPI_SCK_PIN 14 - #define MY_SOFT_SPI_MISO_PIN 16 - #define MY_SOFT_SPI_MOSI_PIN 15 +#define MY_SOFTSPI +#define MY_SOFT_SPI_SCK_PIN 14 +#define MY_SOFT_SPI_MISO_PIN 16 +#define MY_SOFT_SPI_MOSI_PIN 15 #endif // When W5100 is connected we have to move CE/CSN pins for NRF radio #ifndef MY_RF24_CE_PIN - #define MY_RF24_CE_PIN 5 +#define MY_RF24_CE_PIN 5 #endif #ifndef MY_RF24_CS_PIN - #define MY_RF24_CS_PIN 6 +#define MY_RF24_CS_PIN 6 #endif // Enable to UDP @@ -110,7 +110,7 @@ #if defined(MY_USE_UDP) - #include +#include #endif #include #include @@ -120,5 +120,6 @@ void setup() { } -void loop() { +void loop() +{ } diff --git a/examples/GatewayW5100MQTTClient/GatewayW5100MQTTClient.ino b/examples/GatewayW5100MQTTClient/GatewayW5100MQTTClient.ino index 59dad45..2b59372 100644 --- a/examples/GatewayW5100MQTTClient/GatewayW5100MQTTClient.ino +++ b/examples/GatewayW5100MQTTClient/GatewayW5100MQTTClient.ino @@ -81,18 +81,18 @@ // The W5100 ethernet module seems to have a hard time co-operate with // radio on the same spi bus. #if !defined(MY_W5100_SPI_EN) && !defined(ARDUINO_ARCH_SAMD) - #define MY_SOFTSPI - #define MY_SOFT_SPI_SCK_PIN 14 - #define MY_SOFT_SPI_MISO_PIN 16 - #define MY_SOFT_SPI_MOSI_PIN 15 +#define MY_SOFTSPI +#define MY_SOFT_SPI_SCK_PIN 14 +#define MY_SOFT_SPI_MISO_PIN 16 +#define MY_SOFT_SPI_MOSI_PIN 15 #endif // When W5100 is connected we have to move CE/CSN pins for NRF radio #ifndef MY_RF24_CE_PIN - #define MY_RF24_CE_PIN 5 +#define MY_RF24_CE_PIN 5 #endif #ifndef MY_RF24_CS_PIN - #define MY_RF24_CS_PIN 6 +#define MY_RF24_CS_PIN 6 #endif // Enable these if your MQTT broker requires usenrame/password @@ -113,7 +113,7 @@ // The MQTT broker port to to open #define MY_PORT 1883 - /* +/* // Enable inclusion mode #define MY_INCLUSION_MODE_FEATURE // Enable Inclusion mode button on gateway @@ -136,14 +136,17 @@ #include #include -void setup() { +void setup() +{ } -void presentation() { - // Present locally attached sensors here +void presentation() +{ + // Present locally attached sensors here } -void loop() { - // Send locally attached sensors data here +void loop() +{ + // Send locally attached sensors data here } diff --git a/examples/LightSensor/LightSensor.ino b/examples/LightSensor/LightSensor.ino index baa8280..45a8ded 100644 --- a/examples/LightSensor/LightSensor.ino +++ b/examples/LightSensor/LightSensor.ino @@ -20,20 +20,20 @@ * * REVISION HISTORY * Version 1.0 - Henrik EKblad - * + * * DESCRIPTION - * Example sketch showing how to measue light level using a LM393 photo-resistor + * Example sketch showing how to measue light level using a LM393 photo-resistor * http://www.mysensors.org/build/light */ // Enable debug prints to serial monitor -#define MY_DEBUG +#define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 -#include +#include #define CHILD_ID_LIGHT 0 #define LIGHT_SENSOR_ANALOG_PIN 0 @@ -44,23 +44,24 @@ MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL); int lastLightLevel; -void presentation() { - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Light Sensor", "1.0"); +void presentation() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Light Sensor", "1.0"); - // Register all sensors to gateway (they will be created as child devices) - present(CHILD_ID_LIGHT, S_LIGHT_LEVEL); + // Register all sensors to gateway (they will be created as child devices) + present(CHILD_ID_LIGHT, S_LIGHT_LEVEL); } -void loop() -{ - int16_t lightLevel = (1023-analogRead(LIGHT_SENSOR_ANALOG_PIN))/10.23; - Serial.println(lightLevel); - if (lightLevel != lastLightLevel) { - send(msg.set(lightLevel)); - lastLightLevel = lightLevel; - } - sleep(SLEEP_TIME); +void loop() +{ + int16_t lightLevel = (1023-analogRead(LIGHT_SENSOR_ANALOG_PIN))/10.23; + Serial.println(lightLevel); + if (lightLevel != lastLightLevel) { + send(msg.set(lightLevel)); + lastLightLevel = lightLevel; + } + sleep(SLEEP_TIME); } diff --git a/examples/MockMySensors/MockMySensors.ino b/examples/MockMySensors/MockMySensors.ino index 7b801c9..6850f9a 100644 --- a/examples/MockMySensors/MockMySensors.ino +++ b/examples/MockMySensors/MockMySensors.ino @@ -92,216 +92,218 @@ long randNumber; //Instanciate Messages objects #ifdef ID_S_ARMED - bool isArmed; +bool isArmed; #endif #ifdef ID_S_DOOR // V_TRIPPED, V_ARMED - MyMessage msg_S_DOOR_T(ID_S_DOOR,V_TRIPPED); - MyMessage msg_S_DOOR_A(ID_S_DOOR,V_ARMED); +MyMessage msg_S_DOOR_T(ID_S_DOOR,V_TRIPPED); +MyMessage msg_S_DOOR_A(ID_S_DOOR,V_ARMED); #endif #ifdef ID_S_MOTION // V_TRIPPED, V_ARMED - MyMessage msg_S_MOTION_A(ID_S_MOTION,V_ARMED); - MyMessage msg_S_MOTION_T(ID_S_MOTION,V_TRIPPED); +MyMessage msg_S_MOTION_A(ID_S_MOTION,V_ARMED); +MyMessage msg_S_MOTION_T(ID_S_MOTION,V_TRIPPED); #endif #ifdef ID_S_SMOKE // V_TRIPPED, V_ARMED - MyMessage msg_S_SMOKE_T(ID_S_SMOKE,V_TRIPPED); - MyMessage msg_S_SMOKE_A(ID_S_SMOKE,V_ARMED); +MyMessage msg_S_SMOKE_T(ID_S_SMOKE,V_TRIPPED); +MyMessage msg_S_SMOKE_A(ID_S_SMOKE,V_ARMED); #endif #ifdef ID_S_LIGHT - MyMessage msg_S_LIGHT(ID_S_LIGHT,V_LIGHT); - bool isLightOn=0; +MyMessage msg_S_LIGHT(ID_S_LIGHT,V_LIGHT); +bool isLightOn=0; #endif #ifdef ID_S_DIMMER - MyMessage msg_S_DIMMER(ID_S_DIMMER,V_DIMMER); - int dimmerVal=100; +MyMessage msg_S_DIMMER(ID_S_DIMMER,V_DIMMER); +int dimmerVal=100; #endif #ifdef ID_S_COVER - MyMessage msg_S_COVER_U(ID_S_COVER,V_UP); - MyMessage msg_S_COVER_D(ID_S_COVER,V_DOWN); - MyMessage msg_S_COVER_S(ID_S_COVER,V_STOP); - MyMessage msg_S_COVER_V(ID_S_COVER,V_VAR1); - int coverState=0; //0=Stop; 1=up; -1=down +MyMessage msg_S_COVER_U(ID_S_COVER,V_UP); +MyMessage msg_S_COVER_D(ID_S_COVER,V_DOWN); +MyMessage msg_S_COVER_S(ID_S_COVER,V_STOP); +MyMessage msg_S_COVER_V(ID_S_COVER,V_VAR1); +int coverState=0; //0=Stop; 1=up; -1=down #endif #ifdef ID_S_TEMP - MyMessage msg_S_TEMP(ID_S_TEMP,V_TEMP); +MyMessage msg_S_TEMP(ID_S_TEMP,V_TEMP); #endif #ifdef ID_S_HUM - MyMessage msg_S_HUM(ID_S_HUM,V_HUM); +MyMessage msg_S_HUM(ID_S_HUM,V_HUM); #endif #ifdef ID_S_BARO - MyMessage msg_S_BARO_P(ID_S_BARO,V_PRESSURE); - MyMessage msg_S_BARO_F(ID_S_BARO,V_FORECAST); +MyMessage msg_S_BARO_P(ID_S_BARO,V_PRESSURE); +MyMessage msg_S_BARO_F(ID_S_BARO,V_FORECAST); #endif #ifdef ID_S_WIND - MyMessage msg_S_WIND_S(ID_S_WIND,V_WIND); - MyMessage msg_S_WIND_G(ID_S_WIND,V_GUST); - MyMessage msg_S_WIND_D(ID_S_WIND,V_DIRECTION); +MyMessage msg_S_WIND_S(ID_S_WIND,V_WIND); +MyMessage msg_S_WIND_G(ID_S_WIND,V_GUST); +MyMessage msg_S_WIND_D(ID_S_WIND,V_DIRECTION); #endif #ifdef ID_S_RAIN - MyMessage msg_S_RAIN_A(ID_S_RAIN,V_RAIN); - MyMessage msg_S_RAIN_R(ID_S_RAIN,V_RAINRATE); +MyMessage msg_S_RAIN_A(ID_S_RAIN,V_RAIN); +MyMessage msg_S_RAIN_R(ID_S_RAIN,V_RAINRATE); #endif #ifdef ID_S_UV - MyMessage msg_S_UV(ID_S_UV,V_UV); +MyMessage msg_S_UV(ID_S_UV,V_UV); #endif #ifdef ID_S_WEIGHT - MyMessage msg_S_WEIGHT(ID_S_WEIGHT,V_WEIGHT); +MyMessage msg_S_WEIGHT(ID_S_WEIGHT,V_WEIGHT); #endif #ifdef ID_S_POWER - MyMessage msg_S_POWER_W(ID_S_POWER,V_WATT); - MyMessage msg_S_POWER_K(ID_S_POWER,V_KWH); +MyMessage msg_S_POWER_W(ID_S_POWER,V_WATT); +MyMessage msg_S_POWER_K(ID_S_POWER,V_KWH); #endif #ifdef ID_S_HEATER - //////// REVIEW IMPLEMENTATION //////////// +//////// REVIEW IMPLEMENTATION //////////// - MyMessage msg_S_HEATER_SET_POINT(ID_S_HEATER,V_HVAC_SETPOINT_HEAT); // HVAC/Heater setpoint (Integer between 0-100). S_HEATER, S_HVAC - MyMessage msg_S_HEATER_FLOW_STATE(ID_S_HEATER,V_HVAC_FLOW_STATE); // Mode of header. One of "Off", "HeatOn", "CoolOn", or "AutoChangeOver" // S_HVAC, S_HEATER +MyMessage msg_S_HEATER_SET_POINT(ID_S_HEATER, + V_HVAC_SETPOINT_HEAT); // HVAC/Heater setpoint (Integer between 0-100). S_HEATER, S_HVAC +MyMessage msg_S_HEATER_FLOW_STATE(ID_S_HEATER, + V_HVAC_FLOW_STATE); // Mode of header. One of "Off", "HeatOn", "CoolOn", or "AutoChangeOver" // S_HVAC, S_HEATER - //MyMessage msg_S_HEATER_STATUS(ID_S_HEATER,V_STATUS); - //MyMessage msg_S_HEATER_TEMP(ID_S_HEATER,V_TEMP); +//MyMessage msg_S_HEATER_STATUS(ID_S_HEATER,V_STATUS); +//MyMessage msg_S_HEATER_TEMP(ID_S_HEATER,V_TEMP); - float heater_setpoint=21.5; - String heater_flow_state="Off"; +float heater_setpoint=21.5; +String heater_flow_state="Off"; // float heater_temp=23.5; // bool heater_status=false; - // V_TEMP // Temperature - // V_STATUS // Binary status. 0=off 1=on - // V_HVAC_FLOW_STATE // Mode of header. One of "Off", "HeatOn", "CoolOn", or "AutoChangeOver" - // V_HVAC_SPEED // HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto") - // V_HVAC_SETPOINT_HEAT // HVAC/Heater setpoint +// V_TEMP // Temperature +// V_STATUS // Binary status. 0=off 1=on +// V_HVAC_FLOW_STATE // Mode of header. One of "Off", "HeatOn", "CoolOn", or "AutoChangeOver" +// V_HVAC_SPEED // HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto") +// V_HVAC_SETPOINT_HEAT // HVAC/Heater setpoint #endif #ifdef ID_S_DISTANCE - MyMessage msg_S_DISTANCE(ID_S_DISTANCE,V_DISTANCE); +MyMessage msg_S_DISTANCE(ID_S_DISTANCE,V_DISTANCE); #endif #ifdef ID_S_LIGHT_LEVEL - MyMessage msg_S_LIGHT_LEVEL(ID_S_LIGHT_LEVEL,V_LIGHT_LEVEL); +MyMessage msg_S_LIGHT_LEVEL(ID_S_LIGHT_LEVEL,V_LIGHT_LEVEL); #endif #ifdef ID_S_LOCK - MyMessage msg_S_LOCK(ID_S_LOCK,V_LOCK_STATUS); - bool isLocked = 0; +MyMessage msg_S_LOCK(ID_S_LOCK,V_LOCK_STATUS); +bool isLocked = 0; #endif #ifdef ID_S_IR - MyMessage msg_S_IR_S(ID_S_IR,V_IR_SEND); - MyMessage msg_S_IR_R(ID_S_IR,V_IR_RECEIVE); - long irVal = 0; +MyMessage msg_S_IR_S(ID_S_IR,V_IR_SEND); +MyMessage msg_S_IR_R(ID_S_IR,V_IR_RECEIVE); +long irVal = 0; #endif #ifdef ID_S_WATER - MyMessage msg_S_WATER_F(ID_S_WATER,V_FLOW); - MyMessage msg_S_WATER_V(ID_S_WATER,V_VOLUME); +MyMessage msg_S_WATER_F(ID_S_WATER,V_FLOW); +MyMessage msg_S_WATER_V(ID_S_WATER,V_VOLUME); #endif #ifdef ID_S_AIR_QUALITY - MyMessage msg_S_AIR_QUALITY(ID_S_AIR_QUALITY,V_LEVEL); +MyMessage msg_S_AIR_QUALITY(ID_S_AIR_QUALITY,V_LEVEL); #endif #ifdef ID_S_DUST - MyMessage msg_S_DUST(ID_S_DUST,V_LEVEL); +MyMessage msg_S_DUST(ID_S_DUST,V_LEVEL); #endif #ifdef ID_S_SCENE_CONTROLLER - MyMessage msg_S_SCENE_CONTROLLER_ON(ID_S_SCENE_CONTROLLER,V_SCENE_ON); - MyMessage msg_S_SCENE_CONTROLLER_OF(ID_S_SCENE_CONTROLLER,V_SCENE_OFF); - // not sure if scene controller sends int or chars - // betting on ints as Touch Display Scen by Hek // compiler warnings - char *scenes[] = { - (char *)"Good Morning", - (char *)"Clean Up!", - (char *)"All Lights Off", - (char *)"Music On/Off" - }; +MyMessage msg_S_SCENE_CONTROLLER_ON(ID_S_SCENE_CONTROLLER,V_SCENE_ON); +MyMessage msg_S_SCENE_CONTROLLER_OF(ID_S_SCENE_CONTROLLER,V_SCENE_OFF); +// not sure if scene controller sends int or chars +// betting on ints as Touch Display Scen by Hek // compiler warnings +char *scenes[] = { + (char *)"Good Morning", + (char *)"Clean Up!", + (char *)"All Lights Off", + (char *)"Music On/Off" +}; - int sceneVal=0; - int sceneValPrevious=0; +int sceneVal=0; +int sceneValPrevious=0; #endif #ifdef ID_S_RGB_LIGHT - MyMessage msg_S_RGB_LIGHT_V_RGB(ID_S_RGB_LIGHT,V_RGB); - MyMessage msg_S_RGB_LIGHT_V_WATT(ID_S_RGB_LIGHT,V_WATT); - String rgbState="000000"; - //RGB light V_RGB, V_WATT - //RGB value transmitted as ASCII hex string (I.e "ff0000" for red) +MyMessage msg_S_RGB_LIGHT_V_RGB(ID_S_RGB_LIGHT,V_RGB); +MyMessage msg_S_RGB_LIGHT_V_WATT(ID_S_RGB_LIGHT,V_WATT); +String rgbState="000000"; +//RGB light V_RGB, V_WATT +//RGB value transmitted as ASCII hex string (I.e "ff0000" for red) #endif #ifdef ID_S_RGBW_LIGHT - MyMessage msg_S_RGBW_LIGHT_V_RGBW(ID_S_RGBW_LIGHT,V_RGBW); - MyMessage msg_S_RGBW_LIGHT_V_WATT(ID_S_RGBW_LIGHT,V_WATT); - String rgbwState="00000000"; - //RGBW light (with separate white component) V_RGBW, V_WATT - //RGBW value transmitted as ASCII hex string (I.e "ff0000ff" for red + full white) S_RGBW_LIGHT +MyMessage msg_S_RGBW_LIGHT_V_RGBW(ID_S_RGBW_LIGHT,V_RGBW); +MyMessage msg_S_RGBW_LIGHT_V_WATT(ID_S_RGBW_LIGHT,V_WATT); +String rgbwState="00000000"; +//RGBW light (with separate white component) V_RGBW, V_WATT +//RGBW value transmitted as ASCII hex string (I.e "ff0000ff" for red + full white) S_RGBW_LIGHT #endif #ifdef ID_S_COLOR_SENSOR - MyMessage msg_S_COLOR_SENSOR_V_RGB(ID_S_COLOR_SENSOR,V_RGB); - //Color sensor V_RGB - //RGB value transmitted as ASCII hex string (I.e "ff0000" for red) S_RGB_LIGHT, S_COLOR_SENSOR +MyMessage msg_S_COLOR_SENSOR_V_RGB(ID_S_COLOR_SENSOR,V_RGB); +//Color sensor V_RGB +//RGB value transmitted as ASCII hex string (I.e "ff0000" for red) S_RGB_LIGHT, S_COLOR_SENSOR #endif #ifdef ID_S_HVAC - MyMessage msg_S_HVAC_V_HVAC_SETPOINT_HEAT(ID_S_HVAC,V_HVAC_SETPOINT_HEAT); - MyMessage msg_S_HVAC_V_HVAC_SETPOINT_COOL(ID_S_HVAC,V_HVAC_SETPOINT_COOL); - MyMessage msg_S_HVAC_V_HVAC_FLOW_STATET(ID_S_HVAC,V_HVAC_FLOW_STATE); - MyMessage msg_S_HVAC_V_HVAC_FLOW_MODE(ID_S_HVAC,V_HVAC_FLOW_MODE); - MyMessage msg_S_HVAC_V_HVAC_SPEED(ID_S_HVAC,V_HVAC_SPEED); +MyMessage msg_S_HVAC_V_HVAC_SETPOINT_HEAT(ID_S_HVAC,V_HVAC_SETPOINT_HEAT); +MyMessage msg_S_HVAC_V_HVAC_SETPOINT_COOL(ID_S_HVAC,V_HVAC_SETPOINT_COOL); +MyMessage msg_S_HVAC_V_HVAC_FLOW_STATET(ID_S_HVAC,V_HVAC_FLOW_STATE); +MyMessage msg_S_HVAC_V_HVAC_FLOW_MODE(ID_S_HVAC,V_HVAC_FLOW_MODE); +MyMessage msg_S_HVAC_V_HVAC_SPEED(ID_S_HVAC,V_HVAC_SPEED); - float hvac_SetPointHeat = 16.5; - float hvac_SetPointCool = 25.5; - String hvac_FlowState = "AutoChangeOver"; - String hvac_FlowMode = "Auto"; - String hvac_Speed = "Normal"; +float hvac_SetPointHeat = 16.5; +float hvac_SetPointCool = 25.5; +String hvac_FlowState = "AutoChangeOver"; +String hvac_FlowMode = "Auto"; +String hvac_Speed = "Normal"; - //Thermostat/HVAC device - //V_HVAC_SETPOINT_HEAT, // HVAC/Heater setpoint - //V_HVAC_SETPOINT_COOL, // HVAC cold setpoint - //V_HVAC_FLOW_STATE, // Mode of header. One of "Off", "HeatOn", "CoolOn", or "AutoChangeOver" - //V_HVAC_FLOW_MODE, // Flow mode for HVAC ("Auto", "ContinuousOn", "PeriodicOn") - //V_HVAC_SPEED // HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto") +//Thermostat/HVAC device +//V_HVAC_SETPOINT_HEAT, // HVAC/Heater setpoint +//V_HVAC_SETPOINT_COOL, // HVAC cold setpoint +//V_HVAC_FLOW_STATE, // Mode of header. One of "Off", "HeatOn", "CoolOn", or "AutoChangeOver" +//V_HVAC_FLOW_MODE, // Flow mode for HVAC ("Auto", "ContinuousOn", "PeriodicOn") +//V_HVAC_SPEED // HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto") - // NOT IMPLEMENTED YET - //V_TEMP // Temperature - //V_STATUS // Binary status. 0=off 1=on +// NOT IMPLEMENTED YET +//V_TEMP // Temperature +//V_STATUS // Binary status. 0=off 1=on #endif #ifdef ID_S_MULTIMETER - MyMessage msg_S_MULTIMETER_V_IMPEDANCE(ID_S_MULTIMETER,V_IMPEDANCE); - MyMessage msg_S_MULTIMETER_V_VOLTAGE(ID_S_MULTIMETER,V_VOLTAGE); - MyMessage msg_S_MULTIMETER_V_CURRENT(ID_S_MULTIMETER,V_CURRENT); +MyMessage msg_S_MULTIMETER_V_IMPEDANCE(ID_S_MULTIMETER,V_IMPEDANCE); +MyMessage msg_S_MULTIMETER_V_VOLTAGE(ID_S_MULTIMETER,V_VOLTAGE); +MyMessage msg_S_MULTIMETER_V_CURRENT(ID_S_MULTIMETER,V_CURRENT); - // Multimeter device V_VOLTAGE, V_CURRENT, V_IMPEDANCE - // V_IMPEDANCE 14 Impedance value - // V_VOLTAGE 38 Voltage level - // V_CURRENT 39 Current level +// Multimeter device V_VOLTAGE, V_CURRENT, V_IMPEDANCE +// V_IMPEDANCE 14 Impedance value +// V_VOLTAGE 38 Voltage level +// V_CURRENT 39 Current level #endif #ifdef ID_S_SPRINKLER - // S_SPRINKLER 31 Sprinkler device V_STATUS (turn on/off), V_TRIPPED (if fire detecting device) - // V_STATUS 2 Binary status. 0=off 1=on - // V_ARMED 15 Armed status of a security sensor. 1=Armed, 0=Bypassed - // V_TRIPPED 16 Tripped status of a security sensor. 1=Tripped, 0=Untripped +// S_SPRINKLER 31 Sprinkler device V_STATUS (turn on/off), V_TRIPPED (if fire detecting device) +// V_STATUS 2 Binary status. 0=off 1=on +// V_ARMED 15 Armed status of a security sensor. 1=Armed, 0=Bypassed +// V_TRIPPED 16 Tripped status of a security sensor. 1=Tripped, 0=Untripped #endif #ifdef ID_S_WATER_LEAK @@ -314,15 +316,15 @@ long randNumber; #endif #ifdef ID_S_MOISTURE - MyMessage msg_S_MOISTURE(ID_S_MOISTURE,V_LEVEL); +MyMessage msg_S_MOISTURE(ID_S_MOISTURE,V_LEVEL); #endif #ifdef ID_S_CUSTOM - MyMessage msg_S_CUSTOM_1(ID_S_CUSTOM,V_VAR1); - MyMessage msg_S_CUSTOM_2(ID_S_CUSTOM,V_VAR2); - MyMessage msg_S_CUSTOM_3(ID_S_CUSTOM,V_VAR3); - MyMessage msg_S_CUSTOM_4(ID_S_CUSTOM,V_VAR4); - MyMessage msg_S_CUSTOM_5(ID_S_CUSTOM,V_VAR5); +MyMessage msg_S_CUSTOM_1(ID_S_CUSTOM,V_VAR1); +MyMessage msg_S_CUSTOM_2(ID_S_CUSTOM,V_VAR2); +MyMessage msg_S_CUSTOM_3(ID_S_CUSTOM,V_VAR3); +MyMessage msg_S_CUSTOM_4(ID_S_CUSTOM,V_VAR4); +MyMessage msg_S_CUSTOM_5(ID_S_CUSTOM,V_VAR5); #endif @@ -330,831 +332,861 @@ long randNumber; void setup() { - // Random SEED - randomSeed(analogRead(0)); + // Random SEED + randomSeed(analogRead(0)); - wait(LONG_WAIT); - Serial.println("GW Started"); + wait(LONG_WAIT); + Serial.println("GW Started"); } -void presentation() { - // Send the Sketch Version Information to the Gateway - Serial.print("Send Sketch Info: "); - sendSketchInfo(SKETCH_NAME, SKETCH_VERSION); - Serial.print(SKETCH_NAME); - Serial.println(SKETCH_VERSION); - wait(LONG_WAIT); +void presentation() +{ + // Send the Sketch Version Information to the Gateway + Serial.print("Send Sketch Info: "); + sendSketchInfo(SKETCH_NAME, SKETCH_VERSION); + Serial.print(SKETCH_NAME); + Serial.println(SKETCH_VERSION); + wait(LONG_WAIT); - // Get controller configuration - Serial.print("Get Config: "); - metric = getConfig().isMetric; - Serial.println(metric ? "Metric":"Imperial"); - wait(LONG_WAIT); + // Get controller configuration + Serial.print("Get Config: "); + metric = getConfig().isMetric; + Serial.println(metric ? "Metric":"Imperial"); + wait(LONG_WAIT); - // Init Armed - #ifdef ID_S_ARMED - isArmed = true; - #endif + // Init Armed +#ifdef ID_S_ARMED + isArmed = true; +#endif - // Register all sensors to gw (they will be created as child devices) - Serial.println("Presenting Nodes"); - Serial.println("________________"); + // Register all sensors to gw (they will be created as child devices) + Serial.println("Presenting Nodes"); + Serial.println("________________"); - #ifdef ID_S_DOOR - Serial.println(" S_DOOR"); - present(ID_S_DOOR,S_DOOR,"Outside Door"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_DOOR + Serial.println(" S_DOOR"); + present(ID_S_DOOR,S_DOOR,"Outside Door"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_MOTION - Serial.println(" S_MOTION"); - present(ID_S_MOTION,S_MOTION,"Outside Motion"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_MOTION + Serial.println(" S_MOTION"); + present(ID_S_MOTION,S_MOTION,"Outside Motion"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_SMOKE - Serial.println(" S_SMOKE"); - present(ID_S_SMOKE,S_SMOKE,"Kitchen Smoke"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_SMOKE + Serial.println(" S_SMOKE"); + present(ID_S_SMOKE,S_SMOKE,"Kitchen Smoke"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_LIGHT - Serial.println(" S_LIGHT"); - present(ID_S_LIGHT,S_LIGHT,"Hall Light"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_LIGHT + Serial.println(" S_LIGHT"); + present(ID_S_LIGHT,S_LIGHT,"Hall Light"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_DIMMER - Serial.println(" S_DIMMER"); - present(ID_S_DIMMER,S_DIMMER,"Living room dimmer"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_DIMMER + Serial.println(" S_DIMMER"); + present(ID_S_DIMMER,S_DIMMER,"Living room dimmer"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_COVER - Serial.println(" S_COVER"); - present(ID_S_COVER,S_COVER,"Window cover"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_COVER + Serial.println(" S_COVER"); + present(ID_S_COVER,S_COVER,"Window cover"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_TEMP - Serial.println(" S_TEMP"); - present(ID_S_TEMP,S_TEMP,"House Temperarue"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_TEMP + Serial.println(" S_TEMP"); + present(ID_S_TEMP,S_TEMP,"House Temperarue"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_HUM - Serial.println(" S_HUM"); - present(ID_S_HUM,S_HUM,"Current Humidity"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_HUM + Serial.println(" S_HUM"); + present(ID_S_HUM,S_HUM,"Current Humidity"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_BARO - Serial.println(" S_BARO"); - present(ID_S_BARO,S_BARO," Air pressure"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_BARO + Serial.println(" S_BARO"); + present(ID_S_BARO,S_BARO," Air pressure"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_WIND - Serial.println(" S_WIND"); - present(ID_S_WIND,S_WIND,"Wind Station"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_WIND + Serial.println(" S_WIND"); + present(ID_S_WIND,S_WIND,"Wind Station"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_RAIN - Serial.println(" S_RAIN"); - present(ID_S_RAIN,S_RAIN,"Rain Station"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_RAIN + Serial.println(" S_RAIN"); + present(ID_S_RAIN,S_RAIN,"Rain Station"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_UV - Serial.println(" S_UV"); - present(ID_S_UV,S_UV,"Ultra Violet"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_UV + Serial.println(" S_UV"); + present(ID_S_UV,S_UV,"Ultra Violet"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_WEIGHT - Serial.println(" S_WEIGHT"); - present(ID_S_WEIGHT,S_WEIGHT,"Outdoor Scale"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_WEIGHT + Serial.println(" S_WEIGHT"); + present(ID_S_WEIGHT,S_WEIGHT,"Outdoor Scale"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_POWER - Serial.println(" S_POWER"); - present(ID_S_POWER,S_POWER,"Power Metric"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_POWER + Serial.println(" S_POWER"); + present(ID_S_POWER,S_POWER,"Power Metric"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_HEATER - Serial.println(" S_HEATER"); - present(ID_S_HEATER,S_HEATER,"Garage Heater"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_HEATER + Serial.println(" S_HEATER"); + present(ID_S_HEATER,S_HEATER,"Garage Heater"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_DISTANCE - Serial.println(" S_DISTANCE"); - present(ID_S_DISTANCE,S_DISTANCE,"Distance Measure"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_DISTANCE + Serial.println(" S_DISTANCE"); + present(ID_S_DISTANCE,S_DISTANCE,"Distance Measure"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_LIGHT_LEVEL - Serial.println(" S_LIGHT_LEVEL"); - present(ID_S_LIGHT_LEVEL,S_LIGHT_LEVEL,"Outside Light Level"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_LIGHT_LEVEL + Serial.println(" S_LIGHT_LEVEL"); + present(ID_S_LIGHT_LEVEL,S_LIGHT_LEVEL,"Outside Light Level"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_LOCK - Serial.println(" S_LOCK"); - present(ID_S_LOCK,S_LOCK,"Front Door Lock"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_LOCK + Serial.println(" S_LOCK"); + present(ID_S_LOCK,S_LOCK,"Front Door Lock"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_IR - Serial.println(" S_IR"); - present(ID_S_IR,S_IR,"Univeral Command"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_IR + Serial.println(" S_IR"); + present(ID_S_IR,S_IR,"Univeral Command"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_WATER - Serial.println(" S_WATER"); - present(ID_S_WATER,S_WATER,"Water Level"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_WATER + Serial.println(" S_WATER"); + present(ID_S_WATER,S_WATER,"Water Level"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_AIR_QUALITY - Serial.println(" S_AIR_QUALITY"); - present(ID_S_AIR_QUALITY,S_AIR_QUALITY,"Air Station"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_AIR_QUALITY + Serial.println(" S_AIR_QUALITY"); + present(ID_S_AIR_QUALITY,S_AIR_QUALITY,"Air Station"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_DUST - Serial.println(" S_DUST"); - present(ID_S_DUST,S_DUST,"Dust Level"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_DUST + Serial.println(" S_DUST"); + present(ID_S_DUST,S_DUST,"Dust Level"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_SCENE_CONTROLLER - Serial.println(" S_SCENE_CONTROLLER"); - present(ID_S_SCENE_CONTROLLER,S_SCENE_CONTROLLER,"Scene Controller"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_SCENE_CONTROLLER + Serial.println(" S_SCENE_CONTROLLER"); + present(ID_S_SCENE_CONTROLLER,S_SCENE_CONTROLLER,"Scene Controller"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_RGB_LIGHT - Serial.println(" RGB_LIGHT"); - present(ID_S_RGB_LIGHT,S_RGB_LIGHT,"Mood Light"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_RGB_LIGHT + Serial.println(" RGB_LIGHT"); + present(ID_S_RGB_LIGHT,S_RGB_LIGHT,"Mood Light"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_RGBW_LIGHT - Serial.println(" RGBW_LIGHT"); - present(ID_S_RGBW_LIGHT,S_RGBW_LIGHT,"Mood Light 2"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_RGBW_LIGHT + Serial.println(" RGBW_LIGHT"); + present(ID_S_RGBW_LIGHT,S_RGBW_LIGHT,"Mood Light 2"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_COLOR_SENSOR - Serial.println(" COLOR_SENSOR"); - present(ID_S_COLOR_SENSOR,S_COLOR_SENSOR,"Hall Painting"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_COLOR_SENSOR + Serial.println(" COLOR_SENSOR"); + present(ID_S_COLOR_SENSOR,S_COLOR_SENSOR,"Hall Painting"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_HVAC - Serial.println(" HVAC"); - present(ID_S_HVAC,S_HVAC,"HVAC"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_HVAC + Serial.println(" HVAC"); + present(ID_S_HVAC,S_HVAC,"HVAC"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_MULTIMETER - Serial.println(" MULTIMETER"); - present(ID_S_MULTIMETER,S_MULTIMETER,"Electric Staion"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_MULTIMETER + Serial.println(" MULTIMETER"); + present(ID_S_MULTIMETER,S_MULTIMETER,"Electric Staion"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_SPRINKLER - #endif - #ifdef ID_S_WATER_LEAK - #endif - #ifdef ID_S_SOUND - #endif - #ifdef ID_S_VIBRATION - #endif - #ifdef ID_S_MOISTURE - #endif +#ifdef ID_S_SPRINKLER +#endif +#ifdef ID_S_WATER_LEAK +#endif +#ifdef ID_S_SOUND +#endif +#ifdef ID_S_VIBRATION +#endif +#ifdef ID_S_MOISTURE +#endif - #ifdef ID_S_MOISTURE - Serial.println(" S_MOISTURE"); - present(ID_S_MOISTURE,S_MOISTURE,"Basement Sensor"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_MOISTURE + Serial.println(" S_MOISTURE"); + present(ID_S_MOISTURE,S_MOISTURE,"Basement Sensor"); + wait(SHORT_WAIT); +#endif - #ifdef ID_S_CUSTOM - Serial.println(" S_CUSTOM"); - present(ID_S_CUSTOM,S_CUSTOM,"Other Stuff"); - wait(SHORT_WAIT); - #endif +#ifdef ID_S_CUSTOM + Serial.println(" S_CUSTOM"); + present(ID_S_CUSTOM,S_CUSTOM,"Other Stuff"); + wait(SHORT_WAIT); +#endif -Serial.println("________________"); + Serial.println("________________"); } void loop() { - Serial.println(""); - Serial.println(""); - Serial.println(""); - Serial.println("#########################"); - randNumber=random(0,101); + Serial.println(""); + Serial.println(""); + Serial.println(""); + Serial.println("#########################"); + randNumber=random(0,101); - Serial.print("RandomNumber:"); - Serial.println(randNumber); - // Send fake battery level - Serial.println("Send Battery Level"); - sendBatteryLevel(randNumber); - wait(LONG_WAIT); + Serial.print("RandomNumber:"); + Serial.println(randNumber); + // Send fake battery level + Serial.println("Send Battery Level"); + sendBatteryLevel(randNumber); + wait(LONG_WAIT); - // Request time - Serial.println("Request Time"); - requestTime(); - wait(LONG_WAIT); + // Request time + Serial.println("Request Time"); + requestTime(); + wait(LONG_WAIT); - //Read Sensors - #ifdef ID_S_DOOR - door(); - #endif + //Read Sensors +#ifdef ID_S_DOOR + door(); +#endif - #ifdef ID_S_MOTION - motion(); - #endif +#ifdef ID_S_MOTION + motion(); +#endif - #ifdef ID_S_SMOKE - smoke(); - #endif +#ifdef ID_S_SMOKE + smoke(); +#endif - #ifdef ID_S_LIGHT - light(); - #endif +#ifdef ID_S_LIGHT + light(); +#endif - #ifdef ID_S_DIMMER - dimmer(); - #endif +#ifdef ID_S_DIMMER + dimmer(); +#endif - #ifdef ID_S_COVER - cover(); - #endif +#ifdef ID_S_COVER + cover(); +#endif - #ifdef ID_S_TEMP - temp(); - #endif +#ifdef ID_S_TEMP + temp(); +#endif - #ifdef ID_S_HUM - hum(); - #endif +#ifdef ID_S_HUM + hum(); +#endif - #ifdef ID_S_BARO - baro(); - #endif +#ifdef ID_S_BARO + baro(); +#endif - #ifdef ID_S_WIND - wind(); - #endif +#ifdef ID_S_WIND + wind(); +#endif - #ifdef ID_S_RAIN - rain(); - #endif +#ifdef ID_S_RAIN + rain(); +#endif - #ifdef ID_S_UV - uv(); - #endif +#ifdef ID_S_UV + uv(); +#endif - #ifdef ID_S_WEIGHT - weight(); - #endif +#ifdef ID_S_WEIGHT + weight(); +#endif - #ifdef ID_S_POWER - power(); - #endif +#ifdef ID_S_POWER + power(); +#endif - #ifdef ID_S_HEATER - heater(); - #endif +#ifdef ID_S_HEATER + heater(); +#endif - #ifdef ID_S_DISTANCE - distance(); - #endif +#ifdef ID_S_DISTANCE + distance(); +#endif - #ifdef ID_S_LIGHT_LEVEL - light_level(); - #endif +#ifdef ID_S_LIGHT_LEVEL + light_level(); +#endif - #ifdef ID_S_LOCK - lock(); - #endif +#ifdef ID_S_LOCK + lock(); +#endif - #ifdef ID_S_IR - ir(); - #endif +#ifdef ID_S_IR + ir(); +#endif - #ifdef ID_S_WATER - water(); - #endif +#ifdef ID_S_WATER + water(); +#endif - #ifdef ID_S_AIR_QUALITY - air(); - #endif +#ifdef ID_S_AIR_QUALITY + air(); +#endif - #ifdef ID_S_DUST - dust(); - #endif +#ifdef ID_S_DUST + dust(); +#endif - #ifdef ID_S_SCENE_CONTROLLER - scene(); - #endif +#ifdef ID_S_SCENE_CONTROLLER + scene(); +#endif - #ifdef ID_S_RGB_LIGHT - rgbLight(); - #endif +#ifdef ID_S_RGB_LIGHT + rgbLight(); +#endif - #ifdef ID_S_RGBW_LIGHT - rgbwLight(); - #endif +#ifdef ID_S_RGBW_LIGHT + rgbwLight(); +#endif - #ifdef ID_S_COLOR_SENSOR - color(); - #endif +#ifdef ID_S_COLOR_SENSOR + color(); +#endif - #ifdef ID_S_HVAC - hvac(); - #endif +#ifdef ID_S_HVAC + hvac(); +#endif - #ifdef ID_S_MULTIMETER - multimeter(); - #endif +#ifdef ID_S_MULTIMETER + multimeter(); +#endif - #ifdef ID_S_SPRINKLER - #endif - #ifdef ID_S_WATER_LEAK - #endif - #ifdef ID_S_SOUND - #endif - #ifdef ID_S_VIBRATION - #endif - #ifdef ID_S_MOISTURE - #endif +#ifdef ID_S_SPRINKLER +#endif +#ifdef ID_S_WATER_LEAK +#endif +#ifdef ID_S_SOUND +#endif +#ifdef ID_S_VIBRATION +#endif +#ifdef ID_S_MOISTURE +#endif - #ifdef ID_S_MOISTURE - moisture(); - #endif +#ifdef ID_S_MOISTURE + moisture(); +#endif - #ifdef ID_S_CUSTOM - custom(); - #endif +#ifdef ID_S_CUSTOM + custom(); +#endif - sendBatteryLevel(randNumber); - wait(SHORT_WAIT); - Serial.println("#########################"); - wait(SLEEP_TIME); //sleep a bit + sendBatteryLevel(randNumber); + wait(SHORT_WAIT); + Serial.println("#########################"); + wait(SLEEP_TIME); //sleep a bit } // This is called when a new time value was received -void receiveTime(unsigned long controllerTime) { +void receiveTime(unsigned long controllerTime) +{ - Serial.print("Time value received: "); - Serial.println(controllerTime); + Serial.print("Time value received: "); + Serial.println(controllerTime); } //void door(){} #ifdef ID_S_DOOR -void door(){ +void door() +{ - Serial.print("Door is: " ); + Serial.print("Door is: " ); - if (randNumber <= 50) { - Serial.println("Open"); - send(msg_S_DOOR_T.set((int16_t)1)); - } else { - Serial.println("Closed"); - send(msg_S_DOOR_T.set((int16_t)0)); - } - #ifdef ID_S_ARMED - Serial.print("System is: " ); - Serial.println((isArmed ? "Armed":"Disarmed")); - send(msg_S_DOOR_A.set(isArmed)); - #endif + if (randNumber <= 50) { + Serial.println("Open"); + send(msg_S_DOOR_T.set((int16_t)1)); + } else { + Serial.println("Closed"); + send(msg_S_DOOR_T.set((int16_t)0)); + } +#ifdef ID_S_ARMED + Serial.print("System is: " ); + Serial.println((isArmed ? "Armed":"Disarmed")); + send(msg_S_DOOR_A.set(isArmed)); +#endif } #endif #ifdef ID_S_MOTION -void motion(){ +void motion() +{ - Serial.print("Motion is: " ); + Serial.print("Motion is: " ); - if (randNumber <= 50) { - Serial.println("Active"); - send(msg_S_MOTION_T.set(1)); - } else { - Serial.println("Quiet"); - send(msg_S_MOTION_T.set(0)); - } + if (randNumber <= 50) { + Serial.println("Active"); + send(msg_S_MOTION_T.set(1)); + } else { + Serial.println("Quiet"); + send(msg_S_MOTION_T.set(0)); + } - #ifdef ID_S_ARMED - Serial.print("System is: " ); - Serial.println((isArmed ? "Armed":"Disarmed")); - send(msg_S_MOTION_A.set(isArmed)); - #endif +#ifdef ID_S_ARMED + Serial.print("System is: " ); + Serial.println((isArmed ? "Armed":"Disarmed")); + send(msg_S_MOTION_A.set(isArmed)); +#endif } #endif #ifdef ID_S_SMOKE -void smoke(){ +void smoke() +{ - Serial.print("Smoke is: " ); + Serial.print("Smoke is: " ); - if (randNumber <= 50) { - Serial.println("Active"); - send(msg_S_SMOKE_T.set(1)); - } else { - Serial.println("Quiet"); - send(msg_S_SMOKE_T.set(0)); - } + if (randNumber <= 50) { + Serial.println("Active"); + send(msg_S_SMOKE_T.set(1)); + } else { + Serial.println("Quiet"); + send(msg_S_SMOKE_T.set(0)); + } - #ifdef ID_S_ARMED - Serial.print("System is: " ); - Serial.println((isArmed ? "Armed":"Disarmed")); - send(msg_S_SMOKE_A.set(isArmed)); - #endif +#ifdef ID_S_ARMED + Serial.print("System is: " ); + Serial.println((isArmed ? "Armed":"Disarmed")); + send(msg_S_SMOKE_A.set(isArmed)); +#endif } #endif #ifdef ID_S_LIGHT -void light(){ +void light() +{ - Serial.print("Light is: " ); - Serial.println((isLightOn ? "On":"Off")); + Serial.print("Light is: " ); + Serial.println((isLightOn ? "On":"Off")); - send(msg_S_LIGHT.set(isLightOn)); + send(msg_S_LIGHT.set(isLightOn)); } #endif #ifdef ID_S_DIMMER -void dimmer(){ +void dimmer() +{ - Serial.print("Dimmer is set to: " ); - Serial.println(dimmerVal); + Serial.print("Dimmer is set to: " ); + Serial.println(dimmerVal); - send(msg_S_DIMMER.set(dimmerVal)); + send(msg_S_DIMMER.set(dimmerVal)); } #endif #ifdef ID_S_COVER -void cover(){ +void cover() +{ - Serial.print("Cover is : " ); + Serial.print("Cover is : " ); - if (coverState == 1){ - Serial.println("Opening"); - send(msg_S_COVER_U.set(1)); - }else if (coverState == -1){ - Serial.println("Closing"); - send(msg_S_COVER_D.set(0)); - }else{ - Serial.println("Idle"); - send(msg_S_COVER_S.set(-1)); - } - send(msg_S_COVER_V.set(coverState)); + if (coverState == 1) { + Serial.println("Opening"); + send(msg_S_COVER_U.set(1)); + } else if (coverState == -1) { + Serial.println("Closing"); + send(msg_S_COVER_D.set(0)); + } else { + Serial.println("Idle"); + send(msg_S_COVER_S.set(-1)); + } + send(msg_S_COVER_V.set(coverState)); } #endif #ifdef ID_S_TEMP -void temp(){ +void temp() +{ - Serial.print("Temperature is: " ); - Serial.println(map(randNumber,1,100,0,45)); + Serial.print("Temperature is: " ); + Serial.println(map(randNumber,1,100,0,45)); - send(msg_S_TEMP.set(map(randNumber,1,100,0,45))); + send(msg_S_TEMP.set(map(randNumber,1,100,0,45))); } #endif #ifdef ID_S_HUM -void hum(){ +void hum() +{ - Serial.print("Humitidty is: " ); - Serial.println(randNumber); + Serial.print("Humitidty is: " ); + Serial.println(randNumber); - send(msg_S_HUM.set(randNumber)); + send(msg_S_HUM.set(randNumber)); } #endif #ifdef ID_S_BARO -void baro(){ +void baro() +{ - const char *weather[] = {"stable","sunny","cloudy","unstable","thunderstorm","unknown"}; - long pressure = map(randNumber,1,100,870,1086);// hPa? - int forecast = map(randNumber,1,100,0,5); + const char *weather[] = {"stable","sunny","cloudy","unstable","thunderstorm","unknown"}; + long pressure = map(randNumber,1,100,870,1086);// hPa? + int forecast = map(randNumber,1,100,0,5); - Serial.print("Atmosferic Pressure is: " ); - Serial.println(pressure); - send(msg_S_BARO_P.set(pressure)); + Serial.print("Atmosferic Pressure is: " ); + Serial.println(pressure); + send(msg_S_BARO_P.set(pressure)); - Serial.print("Weather forecast: " ); - Serial.println(weather[forecast]); - send(msg_S_BARO_F.set(weather[forecast])); + Serial.print("Weather forecast: " ); + Serial.println(weather[forecast]); + send(msg_S_BARO_F.set(weather[forecast])); } #endif #ifdef ID_S_WIND -void wind(){ +void wind() +{ - Serial.print("Wind Speed is: " ); - Serial.println(randNumber); - send(msg_S_WIND_S.set(randNumber)); + Serial.print("Wind Speed is: " ); + Serial.println(randNumber); + send(msg_S_WIND_S.set(randNumber)); - Serial.print("Wind Gust is: " ); - Serial.println(randNumber+10); - send(msg_S_WIND_G.set(randNumber+10)); + Serial.print("Wind Gust is: " ); + Serial.println(randNumber+10); + send(msg_S_WIND_G.set(randNumber+10)); - Serial.print("Wind Direction is: " ); - Serial.println(map(randNumber,1,100,0,360)); - send(msg_S_WIND_D.set(map(randNumber,1,100,0,360))); + Serial.print("Wind Direction is: " ); + Serial.println(map(randNumber,1,100,0,360)); + send(msg_S_WIND_D.set(map(randNumber,1,100,0,360))); } #endif #ifdef ID_S_RAIN -void rain(){ +void rain() +{ - Serial.print("Rain ammount is: " ); - Serial.println(randNumber); + Serial.print("Rain ammount is: " ); + Serial.println(randNumber); - send(msg_S_RAIN_A.set(randNumber)); + send(msg_S_RAIN_A.set(randNumber)); - Serial.print("Rain rate is: " ); - Serial.println(randNumber/60); + Serial.print("Rain rate is: " ); + Serial.println(randNumber/60); - send(msg_S_RAIN_R.set(randNumber/60,1)); + send(msg_S_RAIN_R.set(randNumber/60,1)); } #endif #ifdef ID_S_UV -void uv(){ +void uv() +{ - Serial.print("Ultra Violet level is: " ); - Serial.println(map(randNumber,1,100,0,15)); + Serial.print("Ultra Violet level is: " ); + Serial.println(map(randNumber,1,100,0,15)); - send(msg_S_UV.set(map(randNumber,1,100,0,15))); + send(msg_S_UV.set(map(randNumber,1,100,0,15))); } #endif #ifdef ID_S_WEIGHT -void weight(){ +void weight() +{ - Serial.print("Weight is: " ); - Serial.println(map(randNumber,1,100,0,150)); + Serial.print("Weight is: " ); + Serial.println(map(randNumber,1,100,0,150)); - send(msg_S_WEIGHT.set(map(randNumber,1,100,0,150))); + send(msg_S_WEIGHT.set(map(randNumber,1,100,0,150))); } #endif #ifdef ID_S_POWER -void power(){ +void power() +{ - Serial.print("Watt is: " ); - Serial.println(map(randNumber,1,100,0,150)); - send(msg_S_POWER_W.set(map(randNumber,1,100,0,150))); + Serial.print("Watt is: " ); + Serial.println(map(randNumber,1,100,0,150)); + send(msg_S_POWER_W.set(map(randNumber,1,100,0,150))); - Serial.print("KWH is: " ); - Serial.println(map(randNumber,1,100,0,150)); - send(msg_S_POWER_K.set(map(randNumber,1,100,0,150))); + Serial.print("KWH is: " ); + Serial.println(map(randNumber,1,100,0,150)); + send(msg_S_POWER_K.set(map(randNumber,1,100,0,150))); } #endif #ifdef ID_S_HEATER -void heater(){ -// float heater_setpoint=21.5; -// float heater_temp=23.5; -// bool heater_status=false; -// String heatState="Off"; +void heater() +{ + // float heater_setpoint=21.5; + // float heater_temp=23.5; + // bool heater_status=false; + // String heatState="Off"; - Serial.print("Heater flow state is: " ); - Serial.println(heater_flow_state); - send(msg_S_HEATER_FLOW_STATE.set(heater_flow_state.c_str())); + Serial.print("Heater flow state is: " ); + Serial.println(heater_flow_state); + send(msg_S_HEATER_FLOW_STATE.set(heater_flow_state.c_str())); -// Serial.print("Heater on/off is: " ); -// Serial.println((heater_status==true)?"On":"Off"); -// send(msg_S_HEATER_STATUS.set(heater_status)); + // Serial.print("Heater on/off is: " ); + // Serial.println((heater_status==true)?"On":"Off"); + // send(msg_S_HEATER_STATUS.set(heater_status)); -// Serial.print("Heater Temperature is: " ); -// Serial.println(heater_temp,1); -// send(msg_S_HEATER_TEMP.set(heater_temp,1)); + // Serial.print("Heater Temperature is: " ); + // Serial.println(heater_temp,1); + // send(msg_S_HEATER_TEMP.set(heater_temp,1)); - Serial.print("Heater Setpoint: " ); - Serial.println(heater_setpoint,1); - send(msg_S_HEATER_SET_POINT.set(heater_setpoint,1)); + Serial.print("Heater Setpoint: " ); + Serial.println(heater_setpoint,1); + send(msg_S_HEATER_SET_POINT.set(heater_setpoint,1)); } #endif #ifdef ID_S_DISTANCE -void distance(){ +void distance() +{ - Serial.print("Distance is: " ); - Serial.println(map(randNumber,1,100,0,150)); + Serial.print("Distance is: " ); + Serial.println(map(randNumber,1,100,0,150)); - send(msg_S_DISTANCE.set(map(randNumber,1,100,0,150))); + send(msg_S_DISTANCE.set(map(randNumber,1,100,0,150))); } #endif #ifdef ID_S_LIGHT_LEVEL -void light_level(){ +void light_level() +{ - Serial.print("Light is: " ); - Serial.println(map(randNumber,1,100,0,150)); + Serial.print("Light is: " ); + Serial.println(map(randNumber,1,100,0,150)); - send(msg_S_LIGHT_LEVEL.set(map(randNumber,1,100,0,150))); + send(msg_S_LIGHT_LEVEL.set(map(randNumber,1,100,0,150))); } #endif #ifdef ID_S_LOCK -void lock(){ +void lock() +{ - Serial.print("Lock is: " ); - Serial.println((isLocked ? "Locked":"Unlocked")); - send(msg_S_LOCK.set(isLocked)); + Serial.print("Lock is: " ); + Serial.println((isLocked ? "Locked":"Unlocked")); + send(msg_S_LOCK.set(isLocked)); } #endif #ifdef ID_S_IR -void ir(){ +void ir() +{ - Serial.print("Infrared is: " ); - Serial.println(irVal); + Serial.print("Infrared is: " ); + Serial.println(irVal); - send(msg_S_IR_S.set(irVal)); - send(msg_S_IR_R.set(irVal)); + send(msg_S_IR_S.set(irVal)); + send(msg_S_IR_R.set(irVal)); } #endif #ifdef ID_S_WATER -void water(){ +void water() +{ - Serial.print("Water flow is: " ); - Serial.println(map(randNumber,1,100,0,150)); + Serial.print("Water flow is: " ); + Serial.println(map(randNumber,1,100,0,150)); - send(msg_S_WATER_F.set(map(randNumber,1,100,0,150))); + send(msg_S_WATER_F.set(map(randNumber,1,100,0,150))); - Serial.print("Water volume is: " ); - Serial.println(map(randNumber,1,100,0,150)); + Serial.print("Water volume is: " ); + Serial.println(map(randNumber,1,100,0,150)); - send(msg_S_WATER_V.set(map(randNumber,1,100,0,150))); + send(msg_S_WATER_V.set(map(randNumber,1,100,0,150))); } #endif #ifdef ID_S_AIR_QUALITY -void air(){ +void air() +{ - Serial.print("Air Quality is: " ); - Serial.println(randNumber); + Serial.print("Air Quality is: " ); + Serial.println(randNumber); - send(msg_S_AIR_QUALITY.set(randNumber)); + send(msg_S_AIR_QUALITY.set(randNumber)); } #endif #ifdef ID_S_DUST -void dust(){ +void dust() +{ - Serial.print("Dust level is: " ); - Serial.println(randNumber); + Serial.print("Dust level is: " ); + Serial.println(randNumber); - send(msg_S_DUST.set(randNumber)); + send(msg_S_DUST.set(randNumber)); } #endif #ifdef ID_S_SCENE_CONTROLLER -void scene(){ +void scene() +{ - Serial.print("Scene is: " ); - Serial.println(scenes[sceneVal]); + Serial.print("Scene is: " ); + Serial.println(scenes[sceneVal]); - if(sceneValPrevious != sceneVal){ - send(msg_S_SCENE_CONTROLLER_OF.set(sceneValPrevious)); - send(msg_S_SCENE_CONTROLLER_ON.set(sceneVal)); - sceneValPrevious=sceneVal; - } + if(sceneValPrevious != sceneVal) { + send(msg_S_SCENE_CONTROLLER_OF.set(sceneValPrevious)); + send(msg_S_SCENE_CONTROLLER_ON.set(sceneVal)); + sceneValPrevious=sceneVal; + } } #endif #ifdef ID_S_RGB_LIGHT -void rgbLight(){ +void rgbLight() +{ - Serial.print("RGB Light state is: " ); - Serial.println(rgbState); - send(msg_S_RGB_LIGHT_V_RGB.set(rgbState.c_str())); + Serial.print("RGB Light state is: " ); + Serial.println(rgbState); + send(msg_S_RGB_LIGHT_V_RGB.set(rgbState.c_str())); - Serial.print("RGB Light Watt is: " ); - Serial.println(map(randNumber,1,100,0,150)); - send(msg_S_RGB_LIGHT_V_WATT.set(map(randNumber,1,100,0,150))); + Serial.print("RGB Light Watt is: " ); + Serial.println(map(randNumber,1,100,0,150)); + send(msg_S_RGB_LIGHT_V_WATT.set(map(randNumber,1,100,0,150))); } #endif #ifdef ID_S_RGBW_LIGHT -void rgbwLight(){ +void rgbwLight() +{ - Serial.print("RGBW Light state is: " ); - Serial.println(rgbwState); - send(msg_S_RGBW_LIGHT_V_RGBW.set(rgbwState.c_str())); + Serial.print("RGBW Light state is: " ); + Serial.println(rgbwState); + send(msg_S_RGBW_LIGHT_V_RGBW.set(rgbwState.c_str())); - Serial.print("RGBW Light Watt is: " ); - Serial.println(map(randNumber,1,100,0,150)); - send(msg_S_RGBW_LIGHT_V_WATT.set(map(randNumber,1,100,0,150))); + Serial.print("RGBW Light Watt is: " ); + Serial.println(map(randNumber,1,100,0,150)); + send(msg_S_RGBW_LIGHT_V_WATT.set(map(randNumber,1,100,0,150))); } #endif #ifdef ID_S_COLOR_SENSOR -void color(){ - String colorState; +void color() +{ + String colorState; - String red = String(random(0,256),HEX); - String green = String(random(0,256),HEX); - String blue = String(random(0,256),HEX); + String red = String(random(0,256),HEX); + String green = String(random(0,256),HEX); + String blue = String(random(0,256),HEX); - colorState=String(red + green + blue); + colorState=String(red + green + blue); - Serial.print("Color state is: " ); - Serial.println(colorState); - send(msg_S_COLOR_SENSOR_V_RGB.set(colorState.c_str())); + Serial.print("Color state is: " ); + Serial.println(colorState); + send(msg_S_COLOR_SENSOR_V_RGB.set(colorState.c_str())); } #endif #ifdef ID_S_HVAC -void hvac(){ +void hvac() +{ -// float hvac_SetPointHeat = 16.5; -// float hvac_SetPointCool = 25.5; -// String hvac_FlowState = "AutoChangeOver"; -// String hvac_FlowMode = "Auto"; -// String hvac_Speed = "Normal"; + // float hvac_SetPointHeat = 16.5; + // float hvac_SetPointCool = 25.5; + // String hvac_FlowState = "AutoChangeOver"; + // String hvac_FlowMode = "Auto"; + // String hvac_Speed = "Normal"; - Serial.print("HVAC Set Point Heat is: " ); - Serial.println(hvac_SetPointHeat); - send(msg_S_HVAC_V_HVAC_SETPOINT_HEAT.set(hvac_SetPointHeat,1)); + Serial.print("HVAC Set Point Heat is: " ); + Serial.println(hvac_SetPointHeat); + send(msg_S_HVAC_V_HVAC_SETPOINT_HEAT.set(hvac_SetPointHeat,1)); - Serial.print("HVAC Set Point Cool is: " ); - Serial.println(hvac_SetPointCool); - send(msg_S_HVAC_V_HVAC_SETPOINT_COOL.set(hvac_SetPointCool,1)); + Serial.print("HVAC Set Point Cool is: " ); + Serial.println(hvac_SetPointCool); + send(msg_S_HVAC_V_HVAC_SETPOINT_COOL.set(hvac_SetPointCool,1)); - Serial.print("HVAC Flow State is: " ); - Serial.println(hvac_FlowState); - send(msg_S_HVAC_V_HVAC_FLOW_STATET.set(hvac_FlowState.c_str())); + Serial.print("HVAC Flow State is: " ); + Serial.println(hvac_FlowState); + send(msg_S_HVAC_V_HVAC_FLOW_STATET.set(hvac_FlowState.c_str())); - Serial.print("HVAC Flow Mode is: " ); - Serial.println(hvac_FlowMode); - send(msg_S_HVAC_V_HVAC_FLOW_MODE.set(hvac_FlowMode.c_str())); + Serial.print("HVAC Flow Mode is: " ); + Serial.println(hvac_FlowMode); + send(msg_S_HVAC_V_HVAC_FLOW_MODE.set(hvac_FlowMode.c_str())); - Serial.print("HVAC Speed is: " ); - Serial.println(hvac_Speed); - send(msg_S_HVAC_V_HVAC_SPEED.set(hvac_Speed.c_str())); + Serial.print("HVAC Speed is: " ); + Serial.println(hvac_Speed); + send(msg_S_HVAC_V_HVAC_SPEED.set(hvac_Speed.c_str())); } #endif #ifdef ID_S_MULTIMETER -void multimeter(){ - int impedance=map(randNumber,1,100,0,15000); - int volt=map(randNumber,1,100,0,380); - int amps=map(randNumber,1,100,0,16); +void multimeter() +{ + int impedance=map(randNumber,1,100,0,15000); + int volt=map(randNumber,1,100,0,380); + int amps=map(randNumber,1,100,0,16); - Serial.print("Impedance is: " ); - Serial.println(impedance); - send(msg_S_MULTIMETER_V_IMPEDANCE.set(impedance)); + Serial.print("Impedance is: " ); + Serial.println(impedance); + send(msg_S_MULTIMETER_V_IMPEDANCE.set(impedance)); - Serial.print("Voltage is: " ); - Serial.println(volt); - send(msg_S_MULTIMETER_V_VOLTAGE.set(volt)); + Serial.print("Voltage is: " ); + Serial.println(volt); + send(msg_S_MULTIMETER_V_VOLTAGE.set(volt)); - Serial.print("Current is: " ); - Serial.println(amps); - send(msg_S_MULTIMETER_V_CURRENT.set(amps)); + Serial.print("Current is: " ); + Serial.println(amps); + send(msg_S_MULTIMETER_V_CURRENT.set(amps)); } #endif @@ -1171,288 +1203,291 @@ void multimeter(){ #endif #ifdef ID_S_MOISTURE -void moisture(){ +void moisture() +{ - Serial.print("Moisture level is: " ); - Serial.println(randNumber); + Serial.print("Moisture level is: " ); + Serial.println(randNumber); - send(msg_S_MOISTURE.set(randNumber)); + send(msg_S_MOISTURE.set(randNumber)); } #endif #ifdef ID_S_CUSTOM -void custom(){ +void custom() +{ - Serial.print("Custom value is: " ); - Serial.println(randNumber); + Serial.print("Custom value is: " ); + Serial.println(randNumber); - send(msg_S_CUSTOM_1.set(randNumber)); - send(msg_S_CUSTOM_2.set(randNumber)); - send(msg_S_CUSTOM_3.set(randNumber)); - send(msg_S_CUSTOM_4.set(randNumber)); - send(msg_S_CUSTOM_5.set(randNumber)); + send(msg_S_CUSTOM_1.set(randNumber)); + send(msg_S_CUSTOM_2.set(randNumber)); + send(msg_S_CUSTOM_3.set(randNumber)); + send(msg_S_CUSTOM_4.set(randNumber)); + send(msg_S_CUSTOM_5.set(randNumber)); } #endif -void receive(const MyMessage &message) { - switch (message.type) { - #ifdef ID_S_ARMED - case V_ARMED: - isArmed = message.getBool(); - Serial.print("Incoming change for ID_S_ARMED:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println((isArmed ? "Armed":"Disarmed" )); - #ifdef ID_S_DOOR - door();//temp ack for door - #endif - #ifdef ID_S_MOTION - motion();//temp ack - #endif - #ifdef ID_S_SMOKE - smoke();//temp ack - #endif - break; - #endif +void receive(const MyMessage &message) +{ + switch (message.type) { +#ifdef ID_S_ARMED + case V_ARMED: + isArmed = message.getBool(); + Serial.print("Incoming change for ID_S_ARMED:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println((isArmed ? "Armed":"Disarmed" )); +#ifdef ID_S_DOOR + door();//temp ack for door +#endif +#ifdef ID_S_MOTION + motion();//temp ack +#endif +#ifdef ID_S_SMOKE + smoke();//temp ack +#endif + break; +#endif - case V_STATUS: // V_LIGHT: - #ifdef ID_S_LIGHT - if(message.sensor==ID_S_LIGHT){ - isLightOn = message.getBool(); - Serial.print("Incoming change for ID_S_LIGHT:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println((isLightOn ? "On":"Off")); - light(); // temp ack - } - #endif -// #ifdef ID_S_HEATER -// if(message.sensor == ID_S_HEATER){ -// heater_status = message.getBool(); -// Serial.print("Incoming change for ID_S_HEATER:"); -// Serial.print(message.sensor); -// Serial.print(", New status: "); -// Serial.println(heater_status); -// heater();//temp ack -// } -// #endif - break; + case V_STATUS: // V_LIGHT: +#ifdef ID_S_LIGHT + if(message.sensor==ID_S_LIGHT) { + isLightOn = message.getBool(); + Serial.print("Incoming change for ID_S_LIGHT:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println((isLightOn ? "On":"Off")); + light(); // temp ack + } +#endif + // #ifdef ID_S_HEATER + // if(message.sensor == ID_S_HEATER){ + // heater_status = message.getBool(); + // Serial.print("Incoming change for ID_S_HEATER:"); + // Serial.print(message.sensor); + // Serial.print(", New status: "); + // Serial.println(heater_status); + // heater();//temp ack + // } + // #endif + break; - #ifdef ID_S_DIMMER - case V_DIMMER: - if ((message.getInt()<0)||(message.getInt()>100)) { - Serial.println( "V_DIMMER data invalid (should be 0..100)" ); - break; - } - dimmerVal= message.getInt(); - Serial.print("Incoming change for ID_S_DIMMER:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println(message.getInt()); - dimmer();// temp ack - break; - #endif +#ifdef ID_S_DIMMER + case V_DIMMER: + if ((message.getInt()<0)||(message.getInt()>100)) { + Serial.println( "V_DIMMER data invalid (should be 0..100)" ); + break; + } + dimmerVal= message.getInt(); + Serial.print("Incoming change for ID_S_DIMMER:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(message.getInt()); + dimmer();// temp ack + break; +#endif - #ifdef ID_S_COVER - case V_UP: - coverState=1; - Serial.print("Incoming change for ID_S_COVER:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println("V_UP"); - cover(); // temp ack - break; +#ifdef ID_S_COVER + case V_UP: + coverState=1; + Serial.print("Incoming change for ID_S_COVER:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println("V_UP"); + cover(); // temp ack + break; - case V_DOWN: - coverState=-1; - Serial.print("Incoming change for ID_S_COVER:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println("V_DOWN"); - cover(); //temp ack - break; + case V_DOWN: + coverState=-1; + Serial.print("Incoming change for ID_S_COVER:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println("V_DOWN"); + cover(); //temp ack + break; - case V_STOP: - coverState=0; - Serial.print("Incoming change for ID_S_COVER:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println("V_STOP"); - cover(); //temp ack - break; - #endif + case V_STOP: + coverState=0; + Serial.print("Incoming change for ID_S_COVER:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println("V_STOP"); + cover(); //temp ack + break; +#endif - case V_HVAC_SETPOINT_HEAT: + case V_HVAC_SETPOINT_HEAT: - #ifdef ID_S_HEATER - if(message.sensor == ID_S_HEATER){ - heater_setpoint=message.getFloat(); +#ifdef ID_S_HEATER + if(message.sensor == ID_S_HEATER) { + heater_setpoint=message.getFloat(); - Serial.print("Incoming set point for ID_S_HEATER:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println(heater_setpoint,1); - heater();//temp ack - } - #endif + Serial.print("Incoming set point for ID_S_HEATER:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(heater_setpoint,1); + heater();//temp ack + } +#endif - #ifdef ID_S_HVAC - if(message.sensor == ID_S_HVAC){ - hvac_SetPointHeat=message.getFloat(); - Serial.print("Incoming set point for ID_S_HVAC:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println(hvac_SetPointHeat,1); - hvac();//temp ack - } - #endif - break; +#ifdef ID_S_HVAC + if(message.sensor == ID_S_HVAC) { + hvac_SetPointHeat=message.getFloat(); + Serial.print("Incoming set point for ID_S_HVAC:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(hvac_SetPointHeat,1); + hvac();//temp ack + } +#endif + break; - case V_HVAC_FLOW_STATE: - #ifdef ID_S_HEATER - if(message.sensor == ID_S_HEATER){ - heater_flow_state=message.getString(); - Serial.print("Incoming flow state change for ID_S_HEATER:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println(heater_flow_state); - heater();//temp ack - } - #endif + case V_HVAC_FLOW_STATE: +#ifdef ID_S_HEATER + if(message.sensor == ID_S_HEATER) { + heater_flow_state=message.getString(); + Serial.print("Incoming flow state change for ID_S_HEATER:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(heater_flow_state); + heater();//temp ack + } +#endif - #ifdef ID_S_HVAC - if(message.sensor == ID_S_HVAC){ - hvac_FlowState=message.getString(); +#ifdef ID_S_HVAC + if(message.sensor == ID_S_HVAC) { + hvac_FlowState=message.getString(); - Serial.print("Incoming set point for ID_S_HVAC:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println(hvac_FlowState); - hvac();//temp ack - } - #endif - break; + Serial.print("Incoming set point for ID_S_HVAC:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(hvac_FlowState); + hvac();//temp ack + } +#endif + break; - #ifdef ID_S_LOCK - case V_LOCK_STATUS: - isLocked = message.getBool(); - Serial.print("Incoming change for ID_S_LOCK:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println(message.getBool()?"Locked":"Unlocked"); - lock(); //temp ack - break; - #endif +#ifdef ID_S_LOCK + case V_LOCK_STATUS: + isLocked = message.getBool(); + Serial.print("Incoming change for ID_S_LOCK:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(message.getBool()?"Locked":"Unlocked"); + lock(); //temp ack + break; +#endif - #ifdef ID_S_IR - case V_IR_SEND: - irVal = message.getLong(); - Serial.print("Incoming change for ID_S_IR:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println(irVal); - ir(); // temp ack - break; - case V_IR_RECEIVE: - irVal = message.getLong(); - Serial.print("Incoming change for ID_S_IR:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println(irVal); - ir(); // temp ack - break; - #endif +#ifdef ID_S_IR + case V_IR_SEND: + irVal = message.getLong(); + Serial.print("Incoming change for ID_S_IR:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(irVal); + ir(); // temp ack + break; + case V_IR_RECEIVE: + irVal = message.getLong(); + Serial.print("Incoming change for ID_S_IR:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(irVal); + ir(); // temp ack + break; +#endif - #ifdef ID_S_SCENE_CONTROLLER - case V_SCENE_ON: - sceneVal = message.getInt(); - Serial.print("Incoming change for ID_S_SCENE_CONTROLLER:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.print(scenes[sceneVal]); - Serial.println(" On"); - scene();// temp ack - break; - case V_SCENE_OFF: - sceneVal = message.getInt(); - Serial.print("Incoming change for ID_S_SCENE_CONTROLLER:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.print(scenes[sceneVal]); - Serial.println(" Off"); - scene();// temp ack - break; - #endif +#ifdef ID_S_SCENE_CONTROLLER + case V_SCENE_ON: + sceneVal = message.getInt(); + Serial.print("Incoming change for ID_S_SCENE_CONTROLLER:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.print(scenes[sceneVal]); + Serial.println(" On"); + scene();// temp ack + break; + case V_SCENE_OFF: + sceneVal = message.getInt(); + Serial.print("Incoming change for ID_S_SCENE_CONTROLLER:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.print(scenes[sceneVal]); + Serial.println(" Off"); + scene();// temp ack + break; +#endif - #ifdef ID_S_RGB_LIGHT - case V_RGB: - rgbState=message.getString(); - Serial.print("Incoming flow state change for ID_S_RGB_LIGHT:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println(rgbState); - rgbLight(); // temp ack +#ifdef ID_S_RGB_LIGHT + case V_RGB: + rgbState=message.getString(); + Serial.print("Incoming flow state change for ID_S_RGB_LIGHT:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(rgbState); + rgbLight(); // temp ack - break; - #endif + break; +#endif - #ifdef ID_S_RGBW_LIGHT - case V_RGBW: - rgbwState=message.getString(); - Serial.print("Incoming flow state change for ID_S_RGBW_LIGHT:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println(rgbwState); - rgbwLight(); - break; - #endif +#ifdef ID_S_RGBW_LIGHT + case V_RGBW: + rgbwState=message.getString(); + Serial.print("Incoming flow state change for ID_S_RGBW_LIGHT:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(rgbwState); + rgbwLight(); + break; +#endif - #ifdef ID_S_HVAC - // hvac_SetPointHeat - // hvac_SetPointCool - // hvac_FlowState - // hvac_FlowMode - // hvac_Speed +#ifdef ID_S_HVAC + // hvac_SetPointHeat + // hvac_SetPointCool + // hvac_FlowState + // hvac_FlowMode + // hvac_Speed - case V_HVAC_SETPOINT_COOL: - hvac_SetPointCool=message.getFloat(); + case V_HVAC_SETPOINT_COOL: + hvac_SetPointCool=message.getFloat(); - Serial.print("Incoming set point for ID_S_HVAC:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println(hvac_SetPointCool,1); - hvac();//temp ack - break; + Serial.print("Incoming set point for ID_S_HVAC:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(hvac_SetPointCool,1); + hvac();//temp ack + break; - case V_HVAC_FLOW_MODE: - hvac_Speed=message.getString(); + case V_HVAC_FLOW_MODE: + hvac_Speed=message.getString(); - Serial.print("Incoming set point for ID_S_HVAC:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println(hvac_Speed); - hvac();//temp ack - break; + Serial.print("Incoming set point for ID_S_HVAC:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(hvac_Speed); + hvac();//temp ack + break; - case V_HVAC_SPEED: - hvac_FlowMode=message.getString(); + case V_HVAC_SPEED: + hvac_FlowMode=message.getString(); - Serial.print("Incoming set point for ID_S_HVAC:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println(hvac_FlowMode); - hvac();//temp ack - break; - #endif + Serial.print("Incoming set point for ID_S_HVAC:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(hvac_FlowMode); + hvac();//temp ack + break; +#endif - default: - Serial.print("Unknown/UnImplemented message type: "); - Serial.println(message.type); - } + default: + Serial.print("Unknown/UnImplemented message type: "); + Serial.println(message.type); + } } diff --git a/examples/MotionSensor/MotionSensor.ino b/examples/MotionSensor/MotionSensor.ino index 17bdc48..c7cd1e5 100644 --- a/examples/MotionSensor/MotionSensor.ino +++ b/examples/MotionSensor/MotionSensor.ino @@ -20,9 +20,9 @@ * * REVISION HISTORY * Version 1.0 - Henrik Ekblad - * + * * DESCRIPTION - * Motion Sensor example using HC-SR501 + * Motion Sensor example using HC-SR501 * http://www.mysensors.org/build/motion * */ @@ -43,29 +43,30 @@ unsigned long SLEEP_TIME = 120000; // Sleep time between reports (in millisecond // Initialize motion message MyMessage msg(CHILD_ID, V_TRIPPED); -void setup() -{ - pinMode(DIGITAL_INPUT_SENSOR, INPUT); // sets the motion sensor digital pin as input +void setup() +{ + pinMode(DIGITAL_INPUT_SENSOR, INPUT); // sets the motion sensor digital pin as input } -void presentation() { - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Motion Sensor", "1.0"); +void presentation() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Motion Sensor", "1.0"); - // Register all sensors to gw (they will be created as child devices) - present(CHILD_ID, S_MOTION); + // Register all sensors to gw (they will be created as child devices) + present(CHILD_ID, S_MOTION); } -void loop() -{ - // Read digital motion value - bool tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; - - Serial.println(tripped); - send(msg.set(tripped?"1":"0")); // Send tripped value to gw +void loop() +{ + // Read digital motion value + bool tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; - // Sleep until interrupt comes in on motion sensor. Send update every two minute. - sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, SLEEP_TIME); + Serial.println(tripped); + send(msg.set(tripped?"1":"0")); // Send tripped value to gw + + // Sleep until interrupt comes in on motion sensor. Send update every two minute. + sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, SLEEP_TIME); } diff --git a/examples/MotionSensorRS485/MotionSensorRS485.ino b/examples/MotionSensorRS485/MotionSensorRS485.ino index e034ab4..5518bff 100644 --- a/examples/MotionSensorRS485/MotionSensorRS485.ino +++ b/examples/MotionSensorRS485/MotionSensorRS485.ino @@ -20,18 +20,18 @@ * * REVISION HISTORY * Version 1.0 - Henrik Ekblad - * + * * DESCRIPTION * This is an example of sensors using RS485 as transport layer - * - * Motion Sensor example using HC-SR501 + * + * Motion Sensor example using HC-SR501 * http://www.mysensors.org/build/motion - * + * * If your Arduino board has additional serial ports * you can use to connect the RS485 module. * Otherwise, the transport uses AltSoftSerial to handle two serial * links on one Arduino. Use the following pins for RS485 link - * + * * Board Transmit Receive PWM Unusable * ----- -------- ------- ------------ * Teensy 3.0 & 3.1 21 20 22 @@ -41,8 +41,8 @@ * Arduino Leonardo 5 13 (none) * Arduino Mega 46 48 44, 45 * Wiring-S 5 6 4 - * Sanguino 13 14 12 * - * + * Sanguino 13 14 12 * + * */ // Enable debug prints to serial monitor @@ -51,7 +51,7 @@ // Enable RS485 transport layer #define MY_RS485 -// Define this to enables DE-pin management on defined pin +// Define this to enables DE-pin management on defined pin #define MY_RS485_DE_PIN 2 // Set RS485 baud rate to use @@ -69,29 +69,30 @@ unsigned long SLEEP_TIME = 120000; // Sleep time between reports (in millisecond // Initialize motion message MyMessage msg(CHILD_ID, V_TRIPPED); -void setup() -{ - pinMode(DIGITAL_INPUT_SENSOR, INPUT); // sets the motion sensor digital pin as input +void setup() +{ + pinMode(DIGITAL_INPUT_SENSOR, INPUT); // sets the motion sensor digital pin as input } -void presentation() { - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Motion Sensor", "1.0"); +void presentation() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Motion Sensor", "1.0"); - // Register all sensors to gw (they will be created as child devices) - present(CHILD_ID, S_MOTION); + // Register all sensors to gw (they will be created as child devices) + present(CHILD_ID, S_MOTION); } -void loop() -{ - // Read digital motion value - bool tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; - - Serial.println(tripped); - send(msg.set(tripped?"1":"0")); // Send tripped value to gw +void loop() +{ + // Read digital motion value + bool tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; - // Sleep until interrupt comes in on motion sensor. Send update every two minute. - sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, SLEEP_TIME); + Serial.println(tripped); + send(msg.set(tripped?"1":"0")); // Send tripped value to gw + + // Sleep until interrupt comes in on motion sensor. Send update every two minute. + sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, SLEEP_TIME); } diff --git a/examples/PHSensor/PHSensor.ino b/examples/PHSensor/PHSensor.ino index 4eb7b8f..8bda2fe 100644 --- a/examples/PHSensor/PHSensor.ino +++ b/examples/PHSensor/PHSensor.ino @@ -42,37 +42,39 @@ MyMessage msg(0, V_PH); void setup() { - //Setup your PH sensor here (I2C,Serial,Phidget...) + //Setup your PH sensor here (I2C,Serial,Phidget...) } -float getPH() { - //query your PH sensor here (I2C,Serial,Phidget...) - float dummy = 7; - return dummy; +float getPH() +{ + //query your PH sensor here (I2C,Serial,Phidget...) + float dummy = 7; + return dummy; } -void presentation() { - // Send the sketch version information to the gateway and Controller - sendSketchInfo("PH Sensor", "1.1"); - present(0, S_WATER_QUALITY); +void presentation() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("PH Sensor", "1.1"); + present(0, S_WATER_QUALITY); } void loop() { - float ph = getPH(); + float ph = getPH(); #if COMPARE_PH == 1 - if (lastPH != ph) { + if (lastPH != ph) { #endif - // Send in the new PH value - send(msg.set(ph, 1)); - // Save new PH value for next compare - lastPH = ph; + // Send in the new PH value + send(msg.set(ph, 1)); + // Save new PH value for next compare + lastPH = ph; #if COMPARE_PH == 1 - } + } #endif - sleep(SLEEP_TIME); + sleep(SLEEP_TIME); } diff --git a/examples/PingPongSensor/MYSLog.h b/examples/PingPongSensor/MYSLog.h index ce4d37c..dbf7e8f 100644 --- a/examples/PingPongSensor/MYSLog.h +++ b/examples/PingPongSensor/MYSLog.h @@ -13,32 +13,34 @@ #define LOGDEBUG 1 #if defined ( LOGDEBUG ) - #define LOG(fmt, args... ) log( fmt, ## args ); +#define LOG(fmt, args... ) log( fmt, ## args ); #else - #define log(fmt, args... ) +#define log(fmt, args... ) #endif -void log(const char *fmt, ... ) { - char buff[128]; - va_list args; - va_start (args, fmt); - vsnprintf(buff, sizeof(buff), fmt, args); - va_end (args); - buff[sizeof(buff)/sizeof(buff[0])-1]='\0'; - Serial.print(buff); +void log(const char *fmt, ... ) +{ + char buff[128]; + va_list args; + va_start (args, fmt); + vsnprintf(buff, sizeof(buff), fmt, args); + va_end (args); + buff[sizeof(buff)/sizeof(buff[0])-1]='\0'; + Serial.print(buff); } -void log(const __FlashStringHelper *fmt, ... ){ - char buf[128]; // resulting string limited to 128 chars - va_list args; - va_start (args, fmt); +void log(const __FlashStringHelper *fmt, ... ) +{ + char buf[128]; // resulting string limited to 128 chars + va_list args; + va_start (args, fmt); #ifdef __AVR__ - vsnprintf_P(buf, sizeof(buf), (const char *)fmt, args); // progmem for AVR + vsnprintf_P(buf, sizeof(buf), (const char *)fmt, args); // progmem for AVR #else - vsnprintf(buf, sizeof(buf), (const char *)fmt, args); // for the rest of the world + vsnprintf(buf, sizeof(buf), (const char *)fmt, args); // for the rest of the world #endif - va_end(args); - Serial.print(buf); + va_end(args); + Serial.print(buf); } #endif diff --git a/examples/PingPongSensor/PingPongSensor.ino b/examples/PingPongSensor/PingPongSensor.ino index 67249de..b21de56 100644 --- a/examples/PingPongSensor/PingPongSensor.ino +++ b/examples/PingPongSensor/PingPongSensor.ino @@ -9,7 +9,7 @@ */ // Enable debug prints to serial monitor -#define MY_DEBUG +#define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 @@ -28,71 +28,79 @@ MyMessage mPing(CHILD, V_VAR1); //Ping message MyMessage mPong(CHILD, V_VAR2); //Pong message -void setup() { +void setup() +{ } -void presentation() { - present(CHILD, S_CUSTOM); // - - sendSketchInfo( nodeTypeAsCharRepresentation( getNodeId() ), VSN ); - LOG(F("\n%sReady.\n"), nodeTypeAsCharRepresentation(getNodeId())); +void presentation() +{ + present(CHILD, S_CUSTOM); // + + sendSketchInfo( nodeTypeAsCharRepresentation( getNodeId() ), VSN ); + LOG(F("\n%sReady.\n"), nodeTypeAsCharRepresentation(getNodeId())); } -void loop() { - - // Interactive command and control - // Entering a number from 0 or 1 will write the node 200 (YING) or 201 (YANG) to EEPROM - // Entering T on either node will initiatve a ping-pong test. - if (Serial.available()) { - byte inChar = Serial.read(); - uint8_t node = getNodeId(); - - // Manual Test Mode - if (inChar == 'T' || inChar == 't') { - LOG(F("T received - starting test...\n")); - MyMessage msg = mPong; - msg.sender = (node == YING ? YANG : YING); - sendPingOrPongResponse( msg ); - } - else if (inChar == '0' or inChar == '1') { - byte nodeID = 200 + (inChar - '0'); - setNodeId(nodeID); - } - else { - LOG("Invalid input\n"); - } - } +void loop() +{ + + // Interactive command and control + // Entering a number from 0 or 1 will write the node 200 (YING) or 201 (YANG) to EEPROM + // Entering T on either node will initiatve a ping-pong test. + if (Serial.available()) { + byte inChar = Serial.read(); + uint8_t node = getNodeId(); + + // Manual Test Mode + if (inChar == 'T' || inChar == 't') { + LOG(F("T received - starting test...\n")); + MyMessage msg = mPong; + msg.sender = (node == YING ? YANG : YING); + sendPingOrPongResponse( msg ); + } else if (inChar == '0' or inChar == '1') { + byte nodeID = 200 + (inChar - '0'); + setNodeId(nodeID); + } else { + LOG("Invalid input\n"); + } + } } -void receive(const MyMessage &message) { - - LOG(F("Received %s from %s\n"), msgTypeAsCharRepresentation((mysensor_data)message.type), nodeTypeAsCharRepresentation(message.sender)); +void receive(const MyMessage &message) +{ - delay(250); - sendPingOrPongResponse( message ); + LOG(F("Received %s from %s\n"), msgTypeAsCharRepresentation((mysensor_data)message.type), + nodeTypeAsCharRepresentation(message.sender)); + + delay(250); + sendPingOrPongResponse( message ); } -void sendPingOrPongResponse( MyMessage msg ) { - - MyMessage response = (msg.type == V_VAR1 ? mPong : mPing); - - LOG(F("Sending %s to %s\n"), msgTypeAsCharRepresentation( (mysensor_data)response.type ), nodeTypeAsCharRepresentation(msg.sender)); - - // Set payload to current time in millis to ensure each message is unique - response.set( millis() ); - response.setDestination(msg.sender); - send(response); +void sendPingOrPongResponse( MyMessage msg ) +{ + + MyMessage response = (msg.type == V_VAR1 ? mPong : mPing); + + LOG(F("Sending %s to %s\n"), msgTypeAsCharRepresentation( (mysensor_data)response.type ), + nodeTypeAsCharRepresentation(msg.sender)); + + // Set payload to current time in millis to ensure each message is unique + response.set( millis() ); + response.setDestination(msg.sender); + send(response); } -void setNodeId(byte nodeID) { - LOG(F("Setting node id to: %i.\n***Please restart the node for changes to take effect.\n"), nodeID); - eeprom_write_byte((uint8_t*)EEPROM_NODE_ID_ADDRESS, (byte)nodeID); +void setNodeId(byte nodeID) +{ + LOG(F("Setting node id to: %i.\n***Please restart the node for changes to take effect.\n"), nodeID); + eeprom_write_byte((uint8_t*)EEPROM_NODE_ID_ADDRESS, (byte)nodeID); } -const char * msgTypeAsCharRepresentation( mysensor_data mType ) { - return mType == V_VAR1 ? "Ping" : "Pong"; +const char * msgTypeAsCharRepresentation( mysensor_data mType ) +{ + return mType == V_VAR1 ? "Ping" : "Pong"; } -const char * nodeTypeAsCharRepresentation( uint8_t node ) { - return node == YING ? "Ying Node" : "Yang Node"; +const char * nodeTypeAsCharRepresentation( uint8_t node ) +{ + return node == YING ? "Ying Node" : "Yang Node"; } diff --git a/examples/RelayActuator/RelayActuator.ino b/examples/RelayActuator/RelayActuator.ino index 908cb9b..713b8af 100644 --- a/examples/RelayActuator/RelayActuator.ino +++ b/examples/RelayActuator/RelayActuator.ino @@ -20,15 +20,15 @@ * * REVISION HISTORY * Version 1.0 - Henrik Ekblad - * + * * DESCRIPTION - * Example sketch showing how to control physical relays. + * Example sketch showing how to control physical relays. * This example will remember relay state after power failure. * http://www.mysensors.org/build/relay - */ + */ // Enable debug prints to serial monitor -#define MY_DEBUG +#define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 @@ -45,48 +45,51 @@ #define RELAY_OFF 0 // GPIO value to write to turn off attached relay -void before() { - for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS;sensor++, pin++) { - // Then set relay pins in output mode - pinMode(pin, OUTPUT); - // Set relay to last known state (using eeprom storage) - digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF); - } -} - -void setup() { - -} - -void presentation() -{ - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Relay", "1.0"); - - for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS;sensor++, pin++) { - // Register all sensors to gw (they will be created as child devices) - present(sensor, S_BINARY); - } -} - - -void loop() +void before() { - + for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) { + // Then set relay pins in output mode + pinMode(pin, OUTPUT); + // Set relay to last known state (using eeprom storage) + digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF); + } } -void receive(const MyMessage &message) { - // We only expect one type of message from controller. But we better check anyway. - if (message.type==V_STATUS) { - // Change relay state - digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF); - // Store state in eeprom - saveState(message.sensor, message.getBool()); - // Write some debug info - Serial.print("Incoming change for sensor:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println(message.getBool()); - } +void setup() +{ + +} + +void presentation() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Relay", "1.0"); + + for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) { + // Register all sensors to gw (they will be created as child devices) + present(sensor, S_BINARY); + } +} + + +void loop() +{ + +} + +void receive(const MyMessage &message) +{ + // We only expect one type of message from controller. But we better check anyway. + if (message.type==V_STATUS) { + // Change relay state + digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF); + // Store state in eeprom + saveState(message.sensor, message.getBool()); + // Write some debug info + Serial.print("Incoming change for sensor:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(message.getBool()); + } } diff --git a/examples/RepeaterNode/RepeaterNode.ino b/examples/RepeaterNode/RepeaterNode.ino index 90791f6..ec76847 100644 --- a/examples/RepeaterNode/RepeaterNode.ino +++ b/examples/RepeaterNode/RepeaterNode.ino @@ -20,16 +20,16 @@ * * REVISION HISTORY * Version 1.0 - Henrik Ekblad - * + * * DESCRIPTION * Example sketch showing how to create a node thay repeates messages - * from nodes far from gateway back to gateway. - * It is important that nodes that has enabled repeater mode calls - * process() frequently. Repeaters should never sleep. + * from nodes far from gateway back to gateway. + * It is important that nodes that has enabled repeater mode calls + * process() frequently. Repeaters should never sleep. */ // Enable debug prints to serial monitor -#define MY_DEBUG +#define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 @@ -40,17 +40,18 @@ #include -void setup() { - +void setup() +{ + } -void presentation() -{ - //Send the sensor node sketch version information to the gateway - sendSketchInfo("Repeater Node", "1.0"); +void presentation() +{ + //Send the sensor node sketch version information to the gateway + sendSketchInfo("Repeater Node", "1.0"); } -void loop() +void loop() { } diff --git a/examples/SecretKnockSensor/SecretKnockSensor.ino b/examples/SecretKnockSensor/SecretKnockSensor.ino index 7859d2e..9cb40ed 100644 --- a/examples/SecretKnockSensor/SecretKnockSensor.ino +++ b/examples/SecretKnockSensor/SecretKnockSensor.ino @@ -20,67 +20,75 @@ * * REVISION HISTORY * Version 1.0 - Henrik Ekblad - * + * * DESCRIPTION * * Secret Knock Sensor * http://www.mysensors.org/build/knock * * See original instructions here (note: The MySensors adopted code might differ in wiring. The instructions below is correct): - * https://learn.adafruit.com/secret-knock-activated-drawer-lock/ + * https://learn.adafruit.com/secret-knock-activated-drawer-lock/ * Version 13.10.31 Built with Arduino IDE 1.0.5 - * + * * By Steve Hoefer http://grathio.com * Adapted to MySensors by Henrik Ekblad - * + * * Licensed under Creative Commons Attribution-Noncommercial-Share Alike 3.0 * http://creativecommons.org/licenses/by-nc-sa/3.0/us/ * (In short: Do what you want, as long as you credit me, don't relicense it, and don't sell it or use it in anything you sell without contacting me.) - * - * ------Wiring------ - * Pin 0: Program button used for recording a new Knock (connect Pin0 -> button -> GND) - * Pin 1: Optional: Connect LED here (remember resisor in series) - * Pin 2: Optional: Piezo element (for beeps). - * Pin 5: A sound sensor (digital output) for sensing knocks. See MySensors purchase guide. I used this: http://rover.ebay.com/rover/1/711-53200-19255-0/1?icep_ff3=2&pub=5575069610&toolid=10001&campid=5337433187&customid=&icep_item=200941260251&ipn=psmain&icep_vectorid=229466&kwid=902099&mtid=824&kw=lg - * Pin 4: Connects to either 1. Relay which open door or lock or - * 2. transistor that opens a solenoid lock when HIGH (see adafruit guide for this option). - * * - * Connect radio according as usual(you can skip IRQ pin) - * http://www.mysensors.org/build/connect_radio + * ------Wiring------ + * Pin 0: Program button used for recording a new Knock (connect Pin0 -> button -> GND) + * Pin 1: Optional: Connect LED here (remember resisor in series) + * Pin 2: Optional: Piezo element (for beeps). + * Pin 5: A sound sensor (digital output) for sensing knocks. See MySensors purchase guide. I used this: http://rover.ebay.com/rover/1/711-53200-19255-0/1?icep_ff3=2&pub=5575069610&toolid=10001&campid=5337433187&customid=&icep_item=200941260251&ipn=psmain&icep_vectorid=229466&kwid=902099&mtid=824&kw=lg + * Pin 4: Connects to either 1. Relay which open door or lock or + * 2. transistor that opens a solenoid lock when HIGH (see adafruit guide for this option). + * + * + * Connect radio according as usual(you can skip IRQ pin) + * http://www.mysensors.org/build/connect_radio */ // Enable debug prints to serial monitor -#define MY_DEBUG +#define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 -#include +#include #define CHILD_ID 99 // Id of the sensor child const byte eepromValid = 121; // If the first byte in eeprom is this then the data is valid. - + /*Pin definitions*/ const int programButton = 0; // (Digital 0) Record A New Knock button. const int ledPin = 1; // (Digital 1) The LED pin (if any) -const int knockSensor = 5; // (Digital 5) for using the microphone digital output (tune knob to register knock) -const int audioOut = 2; // (Digital 2) for using the peizo as an output device. (Thing that goes beep.) +const int knockSensor = + 5; // (Digital 5) for using the microphone digital output (tune knob to register knock) +const int audioOut = + 2; // (Digital 2) for using the peizo as an output device. (Thing that goes beep.) const int lockPin = 4; // (Digital 4) The pin that activates the relay/solenoid lock. - + /*Tuning constants. Changing the values below changes the behavior of the device.*/ -int threshold = 3; // Minimum signal from the piezo to register as a knock. Higher = less sensitive. Typical values 1 - 10 -const int rejectValue = 25; // If an individual knock is off by this percentage of a knock we don't unlock. Typical values 10-30 -const int averageRejectValue = 15; // If the average timing of all the knocks is off by this percent we don't unlock. Typical values 5-20 -const int knockFadeTime = 150; // Milliseconds we allow a knock to fade before we listen for another one. (Debounce timer.) -const int lockOperateTime = 2500; // Milliseconds that we operate the lock solenoid latch before releasing it. +int threshold = + 3; // Minimum signal from the piezo to register as a knock. Higher = less sensitive. Typical values 1 - 10 +const int rejectValue = + 25; // If an individual knock is off by this percentage of a knock we don't unlock. Typical values 10-30 +const int averageRejectValue = + 15; // If the average timing of all the knocks is off by this percent we don't unlock. Typical values 5-20 +const int knockFadeTime = + 150; // Milliseconds we allow a knock to fade before we listen for another one. (Debounce timer.) +const int lockOperateTime = + 2500; // Milliseconds that we operate the lock solenoid latch before releasing it. const int maximumKnocks = 20; // Maximum number of knocks to listen for. -const int knockComplete = 1200; // Longest time to wait for a knock before we assume that it's finished. (milliseconds) - +const int knockComplete = + 1200; // Longest time to wait for a knock before we assume that it's finished. (milliseconds) + byte secretCode[maximumKnocks] = {50, 25, 25, 50, 100, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Initial setup: "Shave and a Hair Cut, two bits." int knockReadings[maximumKnocks]; // When someone knocks this array fills with the delays between knocks. int knockSensorValue = 0; // Last reading of the knock sensor. @@ -90,290 +98,311 @@ bool lockStatus; MyMessage lockMsg(CHILD_ID, V_LOCK_STATUS); -void setup() { - - pinMode(ledPin, OUTPUT); - pinMode(knockSensor, INPUT); - pinMode(lockPin, OUTPUT); - pinMode(programButton, INPUT); - digitalWrite(programButton, HIGH); // Enable internal pull up +void setup() +{ - readSecretKnock(); // Load the secret knock (if any) from EEPROM. - - digitalWrite(lockPin, HIGH); // Unlock the door for a bit when we power up. For system check and to allow a way in if the key is forgotten - delay(500); // Wait a short time - - lockStatus = loadState(0); // Read last lock status from eeprom - setLockState(lockStatus, true); // Now set the last known state and send it to controller + pinMode(ledPin, OUTPUT); + pinMode(knockSensor, INPUT); + pinMode(lockPin, OUTPUT); + pinMode(programButton, INPUT); + digitalWrite(programButton, HIGH); // Enable internal pull up - delay(500); // This delay is here because the solenoid lock returning to place can otherwise trigger and inadvertent knock. + readSecretKnock(); // Load the secret knock (if any) from EEPROM. + + digitalWrite(lockPin, + HIGH); // Unlock the door for a bit when we power up. For system check and to allow a way in if the key is forgotten + delay(500); // Wait a short time + + lockStatus = loadState(0); // Read last lock status from eeprom + setLockState(lockStatus, true); // Now set the last known state and send it to controller + + delay(500); // This delay is here because the solenoid lock returning to place can otherwise trigger and inadvertent knock. } -void presentation() { - sendSketchInfo("Secret Knock", "1.0"); - present(CHILD_ID, S_LOCK); +void presentation() +{ + sendSketchInfo("Secret Knock", "1.0"); + present(CHILD_ID, S_LOCK); } - -void loop() { - // Listen for any knock at all. - knockSensorValue = digitalRead(knockSensor); - if (digitalRead(programButton) == LOW){ // is the program button pressed? - delay(100); // Cheap debounce. - if (digitalRead(programButton) == LOW){ - if (programModeActive == false){ // If we're not in programming mode, turn it on. - programModeActive = true; // Remember we're in programming mode. - digitalWrite(ledPin, HIGH); // Turn on the red light too so the user knows we're programming. - chirp(500, 1500); // And play a tone in case the user can't see the LED. - chirp(500, 1000); - } else { // If we are in programing mode, turn it off. - programModeActive = false; - digitalWrite(ledPin, LOW); - chirp(500, 1000); // Turn off the programming LED and play a sad note. - chirp(500, 1500); - delay(500); - } - while (digitalRead(programButton) == LOW){ - delay(10); // Hang around until the button is released. - } - } - delay(250); // Another cheap debounce. Longer because releasing the button can sometimes be sensed as a knock. - } - - - if (knockSensorValue == 0) { - if (programModeActive == true){ // Blink the LED when we sense a knock. - digitalWrite(ledPin, LOW); - } else { - digitalWrite(ledPin, HIGH); - } - knockDelay(); - if (programModeActive == true){ // Un-blink the LED. - digitalWrite(ledPin, HIGH); - } else { - digitalWrite(ledPin, LOW); - } - listenToSecretKnock(); // We have our first knock. Go and see what other knocks are in store... - } - -} - + +void loop() +{ + // Listen for any knock at all. + knockSensorValue = digitalRead(knockSensor); + if (digitalRead(programButton) == LOW) { // is the program button pressed? + delay(100); // Cheap debounce. + if (digitalRead(programButton) == LOW) { + if (programModeActive == false) { // If we're not in programming mode, turn it on. + programModeActive = true; // Remember we're in programming mode. + digitalWrite(ledPin, HIGH); // Turn on the red light too so the user knows we're programming. + chirp(500, 1500); // And play a tone in case the user can't see the LED. + chirp(500, 1000); + } else { // If we are in programing mode, turn it off. + programModeActive = false; + digitalWrite(ledPin, LOW); + chirp(500, 1000); // Turn off the programming LED and play a sad note. + chirp(500, 1500); + delay(500); + } + while (digitalRead(programButton) == LOW) { + delay(10); // Hang around until the button is released. + } + } + delay(250); // Another cheap debounce. Longer because releasing the button can sometimes be sensed as a knock. + } + + + if (knockSensorValue == 0) { + if (programModeActive == true) { // Blink the LED when we sense a knock. + digitalWrite(ledPin, LOW); + } else { + digitalWrite(ledPin, HIGH); + } + knockDelay(); + if (programModeActive == true) { // Un-blink the LED. + digitalWrite(ledPin, HIGH); + } else { + digitalWrite(ledPin, LOW); + } + listenToSecretKnock(); // We have our first knock. Go and see what other knocks are in store... + } + +} + // Records the timing of knocks. -void listenToSecretKnock(){ - int i = 0; - // First reset the listening array. - for (i=0; i < maximumKnocks; i++){ - knockReadings[i] = 0; - } - - int currentKnockNumber = 0; // Position counter for the array. - int startTime = millis(); // Reference for when this knock started. - int now = millis(); - - do { // Listen for the next knock or wait for it to timeout. - knockSensorValue = digitalRead(knockSensor); +void listenToSecretKnock() +{ + int i = 0; + // First reset the listening array. + for (i=0; i < maximumKnocks; i++) { + knockReadings[i] = 0; + } - if (knockSensorValue == 0){ // Here's another knock. Save the time between knocks. - Serial.println("knock"); + int currentKnockNumber = 0; // Position counter for the array. + int startTime = millis(); // Reference for when this knock started. + int now = millis(); - now=millis(); - knockReadings[currentKnockNumber] = now - startTime; - currentKnockNumber ++; - startTime = now; - - if (programModeActive==true){ // Blink the LED when we sense a knock. - digitalWrite(ledPin, LOW); - } else { - digitalWrite(ledPin, HIGH); - } - knockDelay(); - if (programModeActive == true){ // Un-blink the LED. - digitalWrite(ledPin, HIGH); - } else { - digitalWrite(ledPin, LOW); - } - } - - now = millis(); - - // Stop listening if there are too many knocks or there is too much time between knocks. - } while ((now-startTime < knockComplete) && (currentKnockNumber < maximumKnocks)); - Serial.println("end"); + do { // Listen for the next knock or wait for it to timeout. + knockSensorValue = digitalRead(knockSensor); - //we've got our knock recorded, lets see if it's valid - if (programModeActive == false){ // Only do this if we're not recording a new knock. - if (validateKnock() == true){ - // Lock/unlock door - chirp(500, 1500); // And play a tone in case the user can't see the LED. - chirp(500, 1000); - setLockState(!lockStatus, true); - } else { - Serial.println("fail unlock"); + if (knockSensorValue == 0) { // Here's another knock. Save the time between knocks. + Serial.println("knock"); - // knock is invalid. Blink the LED as a warning to others. - for (i=0; i < 4; i++){ - digitalWrite(ledPin, HIGH); - delay(50); - digitalWrite(ledPin, LOW); - delay(50); - } - } - } else { // If we're in programming mode we still validate the lock because it makes some numbers we need, we just don't do anything with the return. - validateKnock(); - } + now=millis(); + knockReadings[currentKnockNumber] = now - startTime; + currentKnockNumber ++; + startTime = now; + + if (programModeActive==true) { // Blink the LED when we sense a knock. + digitalWrite(ledPin, LOW); + } else { + digitalWrite(ledPin, HIGH); + } + knockDelay(); + if (programModeActive == true) { // Un-blink the LED. + digitalWrite(ledPin, HIGH); + } else { + digitalWrite(ledPin, LOW); + } + } + + now = millis(); + + // Stop listening if there are too many knocks or there is too much time between knocks. + } while ((now-startTime < knockComplete) && (currentKnockNumber < maximumKnocks)); + Serial.println("end"); + + //we've got our knock recorded, lets see if it's valid + if (programModeActive == false) { // Only do this if we're not recording a new knock. + if (validateKnock() == true) { + // Lock/unlock door + chirp(500, 1500); // And play a tone in case the user can't see the LED. + chirp(500, 1000); + setLockState(!lockStatus, true); + } else { + Serial.println("fail unlock"); + + // knock is invalid. Blink the LED as a warning to others. + for (i=0; i < 4; i++) { + digitalWrite(ledPin, HIGH); + delay(50); + digitalWrite(ledPin, LOW); + delay(50); + } + } + } else { // If we're in programming mode we still validate the lock because it makes some numbers we need, we just don't do anything with the return. + validateKnock(); + } } - - + + // Unlocks the door. -void setLockState(bool state, bool doSend){ - if (state) - Serial.println("open lock"); - else - Serial.println("close lock"); - if (doSend) - send(lockMsg.set(state)); - - digitalWrite(ledPin, state); - digitalWrite(lockPin, state); - saveState(0,state); - lockStatus = state; - delay(500); // This delay is here because releasing the latch can cause a vibration that will be sensed as a knock. +void setLockState(bool state, bool doSend) +{ + if (state) { + Serial.println("open lock"); + } else { + Serial.println("close lock"); + } + if (doSend) { + send(lockMsg.set(state)); + } + + digitalWrite(ledPin, state); + digitalWrite(lockPin, state); + saveState(0,state); + lockStatus = state; + delay(500); // This delay is here because releasing the latch can cause a vibration that will be sensed as a knock. } - + // Checks to see if our knock matches the secret. // Returns true if it's a good knock, false if it's not. -bool validateKnock(){ - int i = 0; - - int currentKnockCount = 0; - int secretKnockCount = 0; - int maxKnockInterval = 0; // We use this later to normalize the times. - - for (i=0;i 0){ - currentKnockCount++; - } - if (secretCode[i] > 0){ - secretKnockCount++; - } - - if (knockReadings[i] > maxKnockInterval){ // Collect normalization data while we're looping. - maxKnockInterval = knockReadings[i]; - } - } - - // If we're recording a new knock, save the info and get out of here. - if (programModeActive == true){ - for (i=0; i < maximumKnocks; i++){ // Normalize the time between knocks. (the longest time = 100) - secretCode[i] = map(knockReadings[i], 0, maxKnockInterval, 0, 100); - } - saveSecretKnock(); // save the result to EEPROM - programModeActive = false; - playbackKnock(maxKnockInterval); - return false; - } - - if (currentKnockCount != secretKnockCount){ // Easiest check first. If the number of knocks is wrong, don't unlock. - return false; - } - - /* Now we compare the relative intervals of our knocks, not the absolute time between them. - (ie: if you do the same pattern slow or fast it should still open the door.) - This makes it less picky, which while making it less secure can also make it - less of a pain to use if you're tempo is a little slow or fast. - */ - int totaltimeDifferences = 0; - int timeDiff = 0; - for (i=0; i < maximumKnocks; i++){ // Normalize the times - knockReadings[i]= map(knockReadings[i], 0, maxKnockInterval, 0, 100); - timeDiff = abs(knockReadings[i] - secretCode[i]); - if (timeDiff > rejectValue){ // Individual value too far out of whack. No access for this knock! - return false; - } - totaltimeDifferences += timeDiff; - } - // It can also fail if the whole thing is too inaccurate. - if (totaltimeDifferences / secretKnockCount > averageRejectValue){ - return false; - } - - return true; +bool validateKnock() +{ + int i = 0; + + int currentKnockCount = 0; + int secretKnockCount = 0; + int maxKnockInterval = 0; // We use this later to normalize the times. + + for (i=0; i 0) { + currentKnockCount++; + } + if (secretCode[i] > 0) { + secretKnockCount++; + } + + if (knockReadings[i] > maxKnockInterval) { // Collect normalization data while we're looping. + maxKnockInterval = knockReadings[i]; + } + } + + // If we're recording a new knock, save the info and get out of here. + if (programModeActive == true) { + for (i=0; i < maximumKnocks; i++) { // Normalize the time between knocks. (the longest time = 100) + secretCode[i] = map(knockReadings[i], 0, maxKnockInterval, 0, 100); + } + saveSecretKnock(); // save the result to EEPROM + programModeActive = false; + playbackKnock(maxKnockInterval); + return false; + } + + if (currentKnockCount != + secretKnockCount) { // Easiest check first. If the number of knocks is wrong, don't unlock. + return false; + } + + /* Now we compare the relative intervals of our knocks, not the absolute time between them. + (ie: if you do the same pattern slow or fast it should still open the door.) + This makes it less picky, which while making it less secure can also make it + less of a pain to use if you're tempo is a little slow or fast. + */ + int totaltimeDifferences = 0; + int timeDiff = 0; + for (i=0; i < maximumKnocks; i++) { // Normalize the times + knockReadings[i]= map(knockReadings[i], 0, maxKnockInterval, 0, 100); + timeDiff = abs(knockReadings[i] - secretCode[i]); + if (timeDiff > + rejectValue) { // Individual value too far out of whack. No access for this knock! + return false; + } + totaltimeDifferences += timeDiff; + } + // It can also fail if the whole thing is too inaccurate. + if (totaltimeDifferences / secretKnockCount > averageRejectValue) { + return false; + } + + return true; } - - + + // reads the secret knock from EEPROM. (if any.) -void readSecretKnock(){ - byte reading; - reading = loadState(1); - if (reading == eepromValid){ // only read EEPROM if the signature byte is correct. - for (int i=0; i < maximumKnocks ;i++){ - secretCode[i] = loadState(i+2); - } - } +void readSecretKnock() +{ + byte reading; + reading = loadState(1); + if (reading == eepromValid) { // only read EEPROM if the signature byte is correct. + for (int i=0; i < maximumKnocks ; i++) { + secretCode[i] = loadState(i+2); + } + } } - - + + //saves a new pattern too eeprom -void saveSecretKnock(){ - saveState(1, 0); // clear out the signature. That way we know if we didn't finish the write successfully. - for (int i=0; i < maximumKnocks; i++){ - saveState(i+2, secretCode[i]); - } - saveState(1, eepromValid); // all good. Write the signature so we'll know it's all good. +void saveSecretKnock() +{ + saveState(1, + 0); // clear out the signature. That way we know if we didn't finish the write successfully. + for (int i=0; i < maximumKnocks; i++) { + saveState(i+2, secretCode[i]); + } + saveState(1, eepromValid); // all good. Write the signature so we'll know it's all good. } - + // Plays back the pattern of the knock in blinks and beeps -void playbackKnock(int maxKnockInterval){ - digitalWrite(ledPin, LOW); - delay(1000); - digitalWrite(ledPin, HIGH); - chirp(200, 1800); - for (int i = 0; i < maximumKnocks ; i++){ - digitalWrite(ledPin, LOW); - // only turn it on if there's a delay - if (secretCode[i] > 0){ - delay(map(secretCode[i], 0, 100, 0, maxKnockInterval)); // Expand the time back out to what it was. Roughly. - digitalWrite(ledPin, HIGH); - chirp(200, 1800); - } - } - digitalWrite(ledPin, LOW); +void playbackKnock(int maxKnockInterval) +{ + digitalWrite(ledPin, LOW); + delay(1000); + digitalWrite(ledPin, HIGH); + chirp(200, 1800); + for (int i = 0; i < maximumKnocks ; i++) { + digitalWrite(ledPin, LOW); + // only turn it on if there's a delay + if (secretCode[i] > 0) { + delay(map(secretCode[i], 0, 100, 0, + maxKnockInterval)); // Expand the time back out to what it was. Roughly. + digitalWrite(ledPin, HIGH); + chirp(200, 1800); + } + } + digitalWrite(ledPin, LOW); } - + // Deals with the knock delay thingy. -void knockDelay(){ - int itterations = (knockFadeTime / 20); // Wait for the peak to dissipate before listening to next one. - for (int i=0; i < itterations; i++){ - delay(10); - analogRead(knockSensor); // This is done in an attempt to defuse the analog sensor's capacitor that will give false readings on high impedance sensors. - delay(10); - } +void knockDelay() +{ + int itterations = (knockFadeTime / + 20); // Wait for the peak to dissipate before listening to next one. + for (int i=0; i < itterations; i++) { + delay(10); + analogRead( + knockSensor); // This is done in an attempt to defuse the analog sensor's capacitor that will give false readings on high impedance sensors. + delay(10); + } } - + // Plays a non-musical tone on the piezo. // playTime = milliseconds to play the tone // delayTime = time in microseconds between ticks. (smaller=higher pitch tone.) -void chirp(int playTime, int delayTime){ - long loopTime = (playTime * 1000L) / delayTime; - pinMode(audioOut, OUTPUT); - for(int i=0; i < loopTime; i++){ - digitalWrite(audioOut, HIGH); - delayMicroseconds(delayTime); - digitalWrite(audioOut, LOW); - } - pinMode(audioOut, INPUT); +void chirp(int playTime, int delayTime) +{ + long loopTime = (playTime * 1000L) / delayTime; + pinMode(audioOut, OUTPUT); + for(int i=0; i < loopTime; i++) { + digitalWrite(audioOut, HIGH); + delayMicroseconds(delayTime); + digitalWrite(audioOut, LOW); + } + pinMode(audioOut, INPUT); } -void receive(const MyMessage &message) { - // We only expect one type of message from controller. But we better check anyway. - if (message.type==V_LOCK_STATUS) { - // Change relay state - setLockState(message.getBool(), false); - - // Write some debug info - Serial.print("Incoming lock status:"); - Serial.println(message.getBool()); - } +void receive(const MyMessage &message) +{ + // We only expect one type of message from controller. But we better check anyway. + if (message.type==V_LOCK_STATUS) { + // Change relay state + setLockState(message.getBool(), false); + + // Write some debug info + Serial.print("Incoming lock status:"); + Serial.println(message.getBool()); + } } diff --git a/examples/SecureActuator/SecureActuator.ino b/examples/SecureActuator/SecureActuator.ino index b3a67f9..8513c09 100644 --- a/examples/SecureActuator/SecureActuator.ino +++ b/examples/SecureActuator/SecureActuator.ino @@ -48,7 +48,7 @@ // Enable and select radio type attached #define MY_RADIO_NRF24 //!< NRF24L01 radio driver //#define MY_RADIO_RFM69 //!< RFM69 radio driver - + // Select soft/hardware signing method #define MY_SIGNING_SOFT //!< Software signing //#define MY_SIGNING_ATSHA204 //!< Hardware signing using ATSHA204A @@ -73,29 +73,30 @@ #define LOCK_LOCK 1 //!< GPIO value to write to lock attached lock #define LOCK_UNLOCK 0 //!< GPIO value to write to unlock attached lock -void setup() { - for (int lock=1, pin=LOCK_1; lock<=NOF_LOCKS;lock++, pin++) { - // Set lock pins in output mode - pinMode(pin, OUTPUT); - // Set lock to last known state (using eeprom storage) - digitalWrite(pin, loadState(lock)?LOCK_LOCK:LOCK_UNLOCK); - } +void setup() +{ + for (int lock=1, pin=LOCK_1; lock<=NOF_LOCKS; lock++, pin++) { + // Set lock pins in output mode + pinMode(pin, OUTPUT); + // Set lock to last known state (using eeprom storage) + digitalWrite(pin, loadState(lock)?LOCK_LOCK:LOCK_UNLOCK); + } } -void presentation() +void presentation() { - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Secure Lock", "1.0"); + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Secure Lock", "1.0"); - // Fetch lock status - for (int lock=1, pin=LOCK_1; lock<=NOF_LOCKS;lock++, pin++) { - // Register all locks to gw (they will be created as child devices) - present(lock, S_LOCK, "SecureActuator", false); - } + // Fetch lock status + for (int lock=1, pin=LOCK_1; lock<=NOF_LOCKS; lock++, pin++) { + // Register all locks to gw (they will be created as child devices) + present(lock, S_LOCK, "SecureActuator", false); + } } /** @brief Sketch execution code */ -void loop() +void loop() { } @@ -104,19 +105,20 @@ void loop() * * @param message The message to handle. */ -void receive(const MyMessage &message) { - // We only expect one type of message from controller. But we better check anyway. - // And acks are not accepted as control messages - if (message.type==V_LOCK_STATUS && message.sensor<=NOF_LOCKS && !mGetAck(message)) { - // Change relay state - digitalWrite(message.sensor-1+LOCK_1, message.getBool()?LOCK_LOCK:LOCK_UNLOCK); - // Store state in eeprom - saveState(message.sensor, message.getBool()); - // Write some debug info - Serial.print("Incoming change for lock:"); - Serial.print(message.sensor); - Serial.print(", New status: "); - Serial.println(message.getBool()); - } +void receive(const MyMessage &message) +{ + // We only expect one type of message from controller. But we better check anyway. + // And acks are not accepted as control messages + if (message.type==V_LOCK_STATUS && message.sensor<=NOF_LOCKS && !mGetAck(message)) { + // Change relay state + digitalWrite(message.sensor-1+LOCK_1, message.getBool()?LOCK_LOCK:LOCK_UNLOCK); + // Store state in eeprom + saveState(message.sensor, message.getBool()); + // Write some debug info + Serial.print("Incoming change for lock:"); + Serial.print(message.sensor); + Serial.print(", New status: "); + Serial.println(message.getBool()); + } } /** @}*/ \ No newline at end of file diff --git a/examples/SecurityPersonalizer/SecurityPersonalizer.ino b/examples/SecurityPersonalizer/SecurityPersonalizer.ino index 7c7954b..b03a724 100644 --- a/examples/SecurityPersonalizer/SecurityPersonalizer.ino +++ b/examples/SecurityPersonalizer/SecurityPersonalizer.ino @@ -225,8 +225,8 @@ atsha204Class sha204(sha204Pin); /** @brief Print a error notice and halt the execution */ void halt() { - Serial.println(F("Halting!")); - while(1); + Serial.println(F("Halting!")); + while(1); } #ifndef USE_SOFT_SIGNING @@ -236,126 +236,104 @@ void halt() */ uint16_t write_config_and_get_crc() { - uint16_t crc = 0; - uint8_t config_word[4]; - uint8_t tx_buffer[SHA204_CMD_SIZE_MAX]; - uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; - uint8_t ret_code; - bool do_write; + uint16_t crc = 0; + uint8_t config_word[4]; + uint8_t tx_buffer[SHA204_CMD_SIZE_MAX]; + uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; + uint8_t ret_code; + bool do_write; - // We will set default settings from datasheet on all slots. This means that we can use slot 0 for the key - // as that slot will not be readable (key will therefore be secure) and slot 8 for the payload digest - // calculationon as that slot can be written in clear text even when the datazone is locked. - // Other settings which are not relevant are kept as is. + // We will set default settings from datasheet on all slots. This means that we can use slot 0 for the key + // as that slot will not be readable (key will therefore be secure) and slot 8 for the payload digest + // calculationon as that slot can be written in clear text even when the datazone is locked. + // Other settings which are not relevant are kept as is. - for (int i=0; i < 88; i += 4) - { - do_write = true; - if (i == 20) - { - config_word[0] = 0x8F; - config_word[1] = 0x80; - config_word[2] = 0x80; - config_word[3] = 0xA1; - } - else if (i == 24) - { - config_word[0] = 0x82; - config_word[1] = 0xE0; - config_word[2] = 0xA3; - config_word[3] = 0x60; - } - else if (i == 28) - { - config_word[0] = 0x94; - config_word[1] = 0x40; - config_word[2] = 0xA0; - config_word[3] = 0x85; - } - else if (i == 32) - { - config_word[0] = 0x86; - config_word[1] = 0x40; - config_word[2] = 0x87; - config_word[3] = 0x07; - } - else if (i == 36) - { - config_word[0] = 0x0F; - config_word[1] = 0x00; - config_word[2] = 0x89; - config_word[3] = 0xF2; - } - else if (i == 40) - { - config_word[0] = 0x8A; - config_word[1] = 0x7A; - config_word[2] = 0x0B; - config_word[3] = 0x8B; - } - else if (i == 44) - { - config_word[0] = 0x0C; - config_word[1] = 0x4C; - config_word[2] = 0xDD; - config_word[3] = 0x4D; - } - else if (i == 48) - { - config_word[0] = 0xC2; - config_word[1] = 0x42; - config_word[2] = 0xAF; - config_word[3] = 0x8F; - } - else if (i == 52 || i == 56 || i == 60 || i == 64) - { - config_word[0] = 0xFF; - config_word[1] = 0x00; - config_word[2] = 0xFF; - config_word[3] = 0x00; - } - else if (i == 68 || i == 72 || i == 76 || i == 80) - { - config_word[0] = 0xFF; - config_word[1] = 0xFF; - config_word[2] = 0xFF; - config_word[3] = 0xFF; - } - else - { - // All other configs are untouched - ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, i); - if (ret_code != SHA204_SUCCESS) - { - Serial.print(F("Failed to read config. Response: ")); Serial.println(ret_code, HEX); - halt(); - } - // Set config_word to the read data - config_word[0] = rx_buffer[SHA204_BUFFER_POS_DATA+0]; - config_word[1] = rx_buffer[SHA204_BUFFER_POS_DATA+1]; - config_word[2] = rx_buffer[SHA204_BUFFER_POS_DATA+2]; - config_word[3] = rx_buffer[SHA204_BUFFER_POS_DATA+3]; - do_write = false; - } + for (int i=0; i < 88; i += 4) { + do_write = true; + if (i == 20) { + config_word[0] = 0x8F; + config_word[1] = 0x80; + config_word[2] = 0x80; + config_word[3] = 0xA1; + } else if (i == 24) { + config_word[0] = 0x82; + config_word[1] = 0xE0; + config_word[2] = 0xA3; + config_word[3] = 0x60; + } else if (i == 28) { + config_word[0] = 0x94; + config_word[1] = 0x40; + config_word[2] = 0xA0; + config_word[3] = 0x85; + } else if (i == 32) { + config_word[0] = 0x86; + config_word[1] = 0x40; + config_word[2] = 0x87; + config_word[3] = 0x07; + } else if (i == 36) { + config_word[0] = 0x0F; + config_word[1] = 0x00; + config_word[2] = 0x89; + config_word[3] = 0xF2; + } else if (i == 40) { + config_word[0] = 0x8A; + config_word[1] = 0x7A; + config_word[2] = 0x0B; + config_word[3] = 0x8B; + } else if (i == 44) { + config_word[0] = 0x0C; + config_word[1] = 0x4C; + config_word[2] = 0xDD; + config_word[3] = 0x4D; + } else if (i == 48) { + config_word[0] = 0xC2; + config_word[1] = 0x42; + config_word[2] = 0xAF; + config_word[3] = 0x8F; + } else if (i == 52 || i == 56 || i == 60 || i == 64) { + config_word[0] = 0xFF; + config_word[1] = 0x00; + config_word[2] = 0xFF; + config_word[3] = 0x00; + } else if (i == 68 || i == 72 || i == 76 || i == 80) { + config_word[0] = 0xFF; + config_word[1] = 0xFF; + config_word[2] = 0xFF; + config_word[3] = 0xFF; + } else { + // All other configs are untouched + ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, i); + if (ret_code != SHA204_SUCCESS) { + Serial.print(F("Failed to read config. Response: ")); + Serial.println(ret_code, HEX); + halt(); + } + // Set config_word to the read data + config_word[0] = rx_buffer[SHA204_BUFFER_POS_DATA+0]; + config_word[1] = rx_buffer[SHA204_BUFFER_POS_DATA+1]; + config_word[2] = rx_buffer[SHA204_BUFFER_POS_DATA+2]; + config_word[3] = rx_buffer[SHA204_BUFFER_POS_DATA+3]; + do_write = false; + } - // Update crc with CRC for the current word - crc = sha204.calculateAndUpdateCrc(4, config_word, crc); + // Update crc with CRC for the current word + crc = sha204.calculateAndUpdateCrc(4, config_word, crc); - // Write config word - if (do_write) - { - ret_code = sha204.sha204m_execute(SHA204_WRITE, SHA204_ZONE_CONFIG, - i >> 2, 4, config_word, 0, NULL, 0, NULL, - WRITE_COUNT_SHORT, tx_buffer, WRITE_RSP_SIZE, rx_buffer); - if (ret_code != SHA204_SUCCESS) - { - Serial.print(F("Failed to write config word at address ")); Serial.print(i); - Serial.print(F(". Response: ")); Serial.println(ret_code, HEX); - halt(); - } - } - } - return crc; + // Write config word + if (do_write) { + ret_code = sha204.sha204m_execute(SHA204_WRITE, SHA204_ZONE_CONFIG, + i >> 2, 4, config_word, 0, NULL, 0, NULL, + WRITE_COUNT_SHORT, tx_buffer, WRITE_RSP_SIZE, rx_buffer); + if (ret_code != SHA204_SUCCESS) { + Serial.print(F("Failed to write config word at address ")); + Serial.print(i); + Serial.print(F(". Response: ")); + Serial.println(ret_code, HEX); + halt(); + } + } + } + return crc; } /** @@ -364,991 +342,792 @@ uint16_t write_config_and_get_crc() */ void write_key(uint8_t* key) { - uint8_t tx_buffer[SHA204_CMD_SIZE_MAX]; - uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; - uint8_t ret_code; + uint8_t tx_buffer[SHA204_CMD_SIZE_MAX]; + uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; + uint8_t ret_code; - // Write key to slot 0 - ret_code = sha204.sha204m_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, - 0, SHA204_ZONE_ACCESS_32, key, 0, NULL, 0, NULL, - WRITE_COUNT_LONG, tx_buffer, WRITE_RSP_SIZE, rx_buffer); - if (ret_code != SHA204_SUCCESS) - { - Serial.print(F("Failed to write key to slot 0. Response: ")); Serial.println(ret_code, HEX); - halt(); - } + // Write key to slot 0 + ret_code = sha204.sha204m_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, + 0, SHA204_ZONE_ACCESS_32, key, 0, NULL, 0, NULL, + WRITE_COUNT_LONG, tx_buffer, WRITE_RSP_SIZE, rx_buffer); + if (ret_code != SHA204_SUCCESS) { + Serial.print(F("Failed to write key to slot 0. Response: ")); + Serial.println(ret_code, HEX); + halt(); + } } #endif // not USE_SOFT_SIGNING /** @brief Dump current configuration to UART */ void dump_configuration() { - uint8_t buffer[32]; + uint8_t buffer[32]; #ifndef USE_SOFT_SIGNING - Serial.println(F("EEPROM DATA:")); + Serial.println(F("EEPROM DATA:")); #endif - hwReadConfigBlock((void*)buffer, (void*)EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, 32); - Serial.print(F("SOFT_HMAC_KEY | ")); - for (int j=0; j<32; j++) - { - if (buffer[j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(buffer[j], HEX); - } - Serial.println(); - hwReadConfigBlock((void*)buffer, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9); - Serial.print(F("SOFT_SERIAL | ")); - for (int j=0; j<9; j++) - { - if (buffer[j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(buffer[j], HEX); - } - Serial.println(); - hwReadConfigBlock((void*)buffer, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); - Serial.print(F("AES_KEY | ")); - for (int j=0; j<16; j++) - { - if (buffer[j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(buffer[j], HEX); - } - Serial.println(); + hwReadConfigBlock((void*)buffer, (void*)EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, 32); + Serial.print(F("SOFT_HMAC_KEY | ")); + for (int j=0; j<32; j++) { + if (buffer[j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(buffer[j], HEX); + } + Serial.println(); + hwReadConfigBlock((void*)buffer, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9); + Serial.print(F("SOFT_SERIAL | ")); + for (int j=0; j<9; j++) { + if (buffer[j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(buffer[j], HEX); + } + Serial.println(); + hwReadConfigBlock((void*)buffer, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); + Serial.print(F("AES_KEY | ")); + for (int j=0; j<16; j++) { + if (buffer[j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(buffer[j], HEX); + } + Serial.println(); #ifndef USE_SOFT_SIGNING - uint8_t tx_buffer[SHA204_CMD_SIZE_MAX]; - uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; - uint8_t ret_code; - Serial.println(F("ATSHA204A DATA:")); - for (int i=0; i < 88; i += 4) - { - ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, i); - if (ret_code != SHA204_SUCCESS) - { - Serial.print(F("Failed to read config. Response: ")); Serial.println(ret_code, HEX); - halt(); - } - if (i == 0x00) - { - Serial.print(F(" SN[0:1] | SN[2:3] | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) - { - Serial.print(F(" | ")); - } - else - { - Serial.print(F(" ")); - } - } - Serial.println(); - } - else if (i == 0x04) - { - Serial.print(F(" Revnum | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - Serial.print(F(" ")); - } - Serial.println(); - } - else if (i == 0x08) - { - Serial.print(F(" SN[4:7] | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - Serial.print(F(" ")); - } - Serial.println(); - } - else if (i == 0x0C) - { - Serial.print(F(" SN[8] | Reserved13 | I2CEnable | Reserved15 | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) - { - Serial.print(F(" | ")); - } - else - { - Serial.print(F(" ")); - } - } - Serial.println(); - } - else if (i == 0x10) - { - Serial.print(F(" I2CAddress | TempOffset | OTPmode | SelectorMode | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) - { - Serial.print(F(" | ")); - } - else - { - Serial.print(F(" ")); - } - } - Serial.println(); - } - else if (i == 0x14) - { - Serial.print(F(" SlotConfig00 | SlotConfig01 | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) - { - Serial.print(F(" | ")); - } - else - { - Serial.print(F(" ")); - } - } - Serial.println(); - } - else if (i == 0x18) - { - Serial.print(F(" SlotConfig02 | SlotConfig03 | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) - { - Serial.print(F(" | ")); - } - else - { - Serial.print(F(" ")); - } - } - Serial.println(); - } - else if (i == 0x1C) - { - Serial.print(F(" SlotConfig04 | SlotConfig05 | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) - { - Serial.print(F(" | ")); - } - else - { - Serial.print(F(" ")); - } - } - Serial.println(); - } - else if (i == 0x20) - { - Serial.print(F(" SlotConfig06 | SlotConfig07 | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) - { - Serial.print(F(" | ")); - } - else - { - Serial.print(F(" ")); - } - } - Serial.println(); - } - else if (i == 0x24) - { - Serial.print(F(" SlotConfig08 | SlotConfig09 | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) - { - Serial.print(F(" | ")); - } - else - { - Serial.print(F(" ")); - } - } - Serial.println(); - } - else if (i == 0x28) - { - Serial.print(F(" SlotConfig0A | SlotConfig0B | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) - { - Serial.print(F(" | ")); - } - else - { - Serial.print(F(" ")); - } - } - Serial.println(); - } - else if (i == 0x2C) - { - Serial.print(F(" SlotConfig0C | SlotConfig0D | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) - { - Serial.print(F(" | ")); - } - else - { - Serial.print(F(" ")); - } - } - Serial.println(); - } - else if (i == 0x30) - { - Serial.print(F(" SlotConfig0E | SlotConfig0F | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j == 1) - { - Serial.print(F(" | ")); - } - else - { - Serial.print(F(" ")); - } - } - Serial.println(); - } - else if (i == 0x34) - { - Serial.print(F(" UseFlag00 | UpdateCount00 | UseFlag01 | UpdateCount01 | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) - { - Serial.print(F(" | ")); - } - else - { - Serial.print(F(" ")); - } - } - Serial.println(); - } - else if (i == 0x38) - { - Serial.print(F(" UseFlag02 | UpdateCount02 | UseFlag03 | UpdateCount03 | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) - { - Serial.print(F(" | ")); - } - else - { - Serial.print(F(" ")); - } - } - Serial.println(); - } - else if (i == 0x3C) - { - Serial.print(F(" UseFlag04 | UpdateCount04 | UseFlag05 | UpdateCount05 | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) - { - Serial.print(F(" | ")); - } - else - { - Serial.print(F(" ")); - } - } - Serial.println(); - } - else if (i == 0x40) - { - Serial.print(F(" UseFlag06 | UpdateCount06 | UseFlag07 | UpdateCount07 | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) - { - Serial.print(F(" | ")); - } - else - { - Serial.print(F(" ")); - } - } - Serial.println(); - } - else if (i == 0x44) - { - Serial.print(F(" LastKeyUse[0:3] | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - Serial.print(F(" ")); - } - Serial.println(); - } - else if (i == 0x48) - { - Serial.print(F(" LastKeyUse[4:7] | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - Serial.print(F(" ")); - } - Serial.println(); - } - else if (i == 0x4C) - { - Serial.print(F(" LastKeyUse[8:B] | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - Serial.print(F(" ")); - } - Serial.println(); - } - else if (i == 0x50) - { - Serial.print(F(" LastKeyUse[C:F] | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - Serial.print(F(" ")); - } - Serial.println(); - } - else if (i == 0x54) - { - Serial.print(F(" UserExtra | Selector | LockValue | LockConfig | ")); - for (int j=0; j<4; j++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); - if (j < 3) - { - Serial.print(F(" | ")); - } - else - { - Serial.print(F(" ")); - } - } - Serial.println(); - } - } + uint8_t tx_buffer[SHA204_CMD_SIZE_MAX]; + uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; + uint8_t ret_code; + Serial.println(F("ATSHA204A DATA:")); + for (int i=0; i < 88; i += 4) { + ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, i); + if (ret_code != SHA204_SUCCESS) { + Serial.print(F("Failed to read config. Response: ")); + Serial.println(ret_code, HEX); + halt(); + } + if (i == 0x00) { + Serial.print(F(" SN[0:1] | SN[2:3] | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) { + Serial.print(F(" | ")); + } else { + Serial.print(F(" ")); + } + } + Serial.println(); + } else if (i == 0x04) { + Serial.print(F(" Revnum | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + Serial.print(F(" ")); + } + Serial.println(); + } else if (i == 0x08) { + Serial.print(F(" SN[4:7] | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + Serial.print(F(" ")); + } + Serial.println(); + } else if (i == 0x0C) { + Serial.print(F(" SN[8] | Reserved13 | I2CEnable | Reserved15 | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j < 3) { + Serial.print(F(" | ")); + } else { + Serial.print(F(" ")); + } + } + Serial.println(); + } else if (i == 0x10) { + Serial.print(F(" I2CAddress | TempOffset | OTPmode | SelectorMode | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j < 3) { + Serial.print(F(" | ")); + } else { + Serial.print(F(" ")); + } + } + Serial.println(); + } else if (i == 0x14) { + Serial.print(F(" SlotConfig00 | SlotConfig01 | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) { + Serial.print(F(" | ")); + } else { + Serial.print(F(" ")); + } + } + Serial.println(); + } else if (i == 0x18) { + Serial.print(F(" SlotConfig02 | SlotConfig03 | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) { + Serial.print(F(" | ")); + } else { + Serial.print(F(" ")); + } + } + Serial.println(); + } else if (i == 0x1C) { + Serial.print(F(" SlotConfig04 | SlotConfig05 | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) { + Serial.print(F(" | ")); + } else { + Serial.print(F(" ")); + } + } + Serial.println(); + } else if (i == 0x20) { + Serial.print(F(" SlotConfig06 | SlotConfig07 | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) { + Serial.print(F(" | ")); + } else { + Serial.print(F(" ")); + } + } + Serial.println(); + } else if (i == 0x24) { + Serial.print(F(" SlotConfig08 | SlotConfig09 | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) { + Serial.print(F(" | ")); + } else { + Serial.print(F(" ")); + } + } + Serial.println(); + } else if (i == 0x28) { + Serial.print(F(" SlotConfig0A | SlotConfig0B | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) { + Serial.print(F(" | ")); + } else { + Serial.print(F(" ")); + } + } + Serial.println(); + } else if (i == 0x2C) { + Serial.print(F(" SlotConfig0C | SlotConfig0D | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) { + Serial.print(F(" | ")); + } else { + Serial.print(F(" ")); + } + } + Serial.println(); + } else if (i == 0x30) { + Serial.print(F(" SlotConfig0E | SlotConfig0F | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j == 1) { + Serial.print(F(" | ")); + } else { + Serial.print(F(" ")); + } + } + Serial.println(); + } else if (i == 0x34) { + Serial.print(F(" UseFlag00 | UpdateCount00 | UseFlag01 | UpdateCount01 | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j < 3) { + Serial.print(F(" | ")); + } else { + Serial.print(F(" ")); + } + } + Serial.println(); + } else if (i == 0x38) { + Serial.print(F(" UseFlag02 | UpdateCount02 | UseFlag03 | UpdateCount03 | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j < 3) { + Serial.print(F(" | ")); + } else { + Serial.print(F(" ")); + } + } + Serial.println(); + } else if (i == 0x3C) { + Serial.print(F(" UseFlag04 | UpdateCount04 | UseFlag05 | UpdateCount05 | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j < 3) { + Serial.print(F(" | ")); + } else { + Serial.print(F(" ")); + } + } + Serial.println(); + } else if (i == 0x40) { + Serial.print(F(" UseFlag06 | UpdateCount06 | UseFlag07 | UpdateCount07 | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j < 3) { + Serial.print(F(" | ")); + } else { + Serial.print(F(" ")); + } + } + Serial.println(); + } else if (i == 0x44) { + Serial.print(F(" LastKeyUse[0:3] | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + Serial.print(F(" ")); + } + Serial.println(); + } else if (i == 0x48) { + Serial.print(F(" LastKeyUse[4:7] | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + Serial.print(F(" ")); + } + Serial.println(); + } else if (i == 0x4C) { + Serial.print(F(" LastKeyUse[8:B] | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + Serial.print(F(" ")); + } + Serial.println(); + } else if (i == 0x50) { + Serial.print(F(" LastKeyUse[C:F] | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + Serial.print(F(" ")); + } + Serial.println(); + } else if (i == 0x54) { + Serial.print(F(" UserExtra | Selector | LockValue | LockConfig | ")); + for (int j=0; j<4; j++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX); + if (j < 3) { + Serial.print(F(" | ")); + } else { + Serial.print(F(" ")); + } + } + Serial.println(); + } + } #endif // not USE_SOFT_SIGNING } /** @brief Sketch setup code */ void setup() { - // Delay startup a bit for serial consoles to catch up - unsigned long enter = hwMillis(); - while (hwMillis() - enter < (unsigned long)500); + // Delay startup a bit for serial consoles to catch up + unsigned long enter = hwMillis(); + while (hwMillis() - enter < (unsigned long)500); #ifndef USE_SOFT_SIGNING - uint8_t tx_buffer[SHA204_CMD_SIZE_MAX]; - uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; - uint8_t ret_code; - uint8_t lockConfig = 0; - uint8_t lockValue = 0; - uint16_t crc; - (void)crc; + uint8_t tx_buffer[SHA204_CMD_SIZE_MAX]; + uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; + uint8_t ret_code; + uint8_t lockConfig = 0; + uint8_t lockValue = 0; + uint16_t crc; + (void)crc; #else - // initialize pseudo-RNG - randomSeed(analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN)); + // initialize pseudo-RNG + randomSeed(analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN)); #endif - uint8_t key[32]; - (void)key; + uint8_t key[32]; + (void)key; - Serial.begin(115200); - hwInit(); - Serial.println(F("Personalization sketch for MySensors usage.")); - Serial.println(F("-------------------------------------------")); + Serial.begin(115200); + hwInit(); + Serial.println(F("Personalization sketch for MySensors usage.")); + Serial.println(F("-------------------------------------------")); #ifndef USE_SOFT_SIGNING - // Wake device before starting operations - ret_code = sha204.sha204c_wakeup(rx_buffer); - if (ret_code != SHA204_SUCCESS) - { - Serial.print(F("Failed to wake device. Response: ")); Serial.println(ret_code, HEX); - halt(); - } - // Read out lock config bits to determine if locking is possible - ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2); - if (ret_code != SHA204_SUCCESS) - { - Serial.print(F("Failed to determine device lock status. Response: ")); Serial.println(ret_code, HEX); - halt(); - } - else - { - lockConfig = rx_buffer[SHA204_BUFFER_POS_DATA+3]; - lockValue = rx_buffer[SHA204_BUFFER_POS_DATA+2]; - } + // Wake device before starting operations + ret_code = sha204.sha204c_wakeup(rx_buffer); + if (ret_code != SHA204_SUCCESS) { + Serial.print(F("Failed to wake device. Response: ")); + Serial.println(ret_code, HEX); + halt(); + } + // Read out lock config bits to determine if locking is possible + ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2); + if (ret_code != SHA204_SUCCESS) { + Serial.print(F("Failed to determine device lock status. Response: ")); + Serial.println(ret_code, HEX); + halt(); + } else { + lockConfig = rx_buffer[SHA204_BUFFER_POS_DATA+3]; + lockValue = rx_buffer[SHA204_BUFFER_POS_DATA+2]; + } #endif #ifdef STORE_SOFT_KEY #ifdef USER_SOFT_KEY - memcpy(key, user_soft_key_data, 32); - Serial.println(F("Using this user supplied soft HMAC key:")); + memcpy(key, user_soft_key_data, 32); + Serial.println(F("Using this user supplied soft HMAC key:")); #else - // Retrieve random value to use as soft HMAC key + // Retrieve random value to use as soft HMAC key #ifdef USE_SOFT_SIGNING - for (int i = 0; i < 32; i++) { - key[i] = random(256) ^ micros(); - unsigned long enter = hwMillis(); - while (hwMillis() - enter < (unsigned long)2); - } - Serial.println(F("This value will be stored in EEPROM as soft HMAC key:")); + for (int i = 0; i < 32; i++) { + key[i] = random(256) ^ micros(); + unsigned long enter = hwMillis(); + while (hwMillis() - enter < (unsigned long)2); + } + Serial.println(F("This value will be stored in EEPROM as soft HMAC key:")); #else - ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE); - if (ret_code != SHA204_SUCCESS) - { - Serial.print(F("Random key generation failed. Response: ")); Serial.println(ret_code, HEX); - halt(); - } - else - { - memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 32); - } - if (lockConfig == 0x00) - { - Serial.println(F("This value will be stored in EEPROM as soft HMAC key:")); - } - else - { - Serial.println(F("Key is not randomized (configuration not locked):")); - } + ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE); + if (ret_code != SHA204_SUCCESS) { + Serial.print(F("Random key generation failed. Response: ")); + Serial.println(ret_code, HEX); + halt(); + } else { + memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 32); + } + if (lockConfig == 0x00) { + Serial.println(F("This value will be stored in EEPROM as soft HMAC key:")); + } else { + Serial.println(F("Key is not randomized (configuration not locked):")); + } #endif // not USE_SOFT_SIGNING #endif // not USER_SOFT_KEY - Serial.print("#define MY_SOFT_HMAC_KEY "); - for (int i=0; i<32; i++) - { - Serial.print("0x"); - if (key[i] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(key[i], HEX); - if (i < 31) Serial.print(','); - } - Serial.println(); - hwWriteConfigBlock((void*)key, (void*)EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, 32); + Serial.print("#define MY_SOFT_HMAC_KEY "); + for (int i=0; i<32; i++) { + Serial.print("0x"); + if (key[i] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(key[i], HEX); + if (i < 31) { + Serial.print(','); + } + } + Serial.println(); + hwWriteConfigBlock((void*)key, (void*)EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, 32); #endif // STORE_SOFT_KEY #ifdef STORE_SOFT_SERIAL #ifdef USER_SOFT_SERIAL - memcpy(key, user_soft_serial, 9); - Serial.println(F("Using this user supplied soft serial:")); + memcpy(key, user_soft_serial, 9); + Serial.println(F("Using this user supplied soft serial:")); #else - // Retrieve random value to use as serial + // Retrieve random value to use as serial #ifdef USE_SOFT_SIGNING - for (int i = 0; i < 9; i++) { - key[i] = random(256) ^ micros(); - unsigned long enter = hwMillis(); - while (hwMillis() - enter < (unsigned long)2); - } - Serial.println(F("This value will be stored in EEPROM as soft serial:")); + for (int i = 0; i < 9; i++) { + key[i] = random(256) ^ micros(); + unsigned long enter = hwMillis(); + while (hwMillis() - enter < (unsigned long)2); + } + Serial.println(F("This value will be stored in EEPROM as soft serial:")); #else - ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE); - if (ret_code != SHA204_SUCCESS) - { - Serial.print(F("Random serial generation failed. Response: ")); Serial.println(ret_code, HEX); - halt(); - } - else - { - memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 9); - } - if (lockConfig == 0x00) - { - Serial.println(F("This value will be stored in EEPROM as soft serial:")); - } - else - { - Serial.println(F("Serial is not randomized (configuration not locked):")); - } + ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE); + if (ret_code != SHA204_SUCCESS) { + Serial.print(F("Random serial generation failed. Response: ")); + Serial.println(ret_code, HEX); + halt(); + } else { + memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 9); + } + if (lockConfig == 0x00) { + Serial.println(F("This value will be stored in EEPROM as soft serial:")); + } else { + Serial.println(F("Serial is not randomized (configuration not locked):")); + } #endif // not USE_SOFT_SIGNING #endif // not USER_SOFT_SERIAL - Serial.print("#define MY_SOFT_SERIAL "); - for (int i=0; i<9; i++) - { - Serial.print("0x"); - if (key[i] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(key[i], HEX); - if (i < 8) Serial.print(','); - } - Serial.println(); - hwWriteConfigBlock((void*)key, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9); + Serial.print("#define MY_SOFT_SERIAL "); + for (int i=0; i<9; i++) { + Serial.print("0x"); + if (key[i] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(key[i], HEX); + if (i < 8) { + Serial.print(','); + } + } + Serial.println(); + hwWriteConfigBlock((void*)key, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9); #endif // STORE_SOFT_SERIAL #ifdef STORE_AES_KEY #ifdef USER_AES_KEY - memcpy(key, user_aes_key, 16); - Serial.println(F("Using this user supplied AES key:")); + memcpy(key, user_aes_key, 16); + Serial.println(F("Using this user supplied AES key:")); #else - // Retrieve random value to use as key + // Retrieve random value to use as key #ifdef USE_SOFT_SIGNING - for (int i = 0; i < 16; i++) { - key[i] = random(256) ^ micros(); - unsigned long enter = hwMillis(); - while (hwMillis() - enter < (unsigned long)2); - } - Serial.println(F("This key will be stored in EEPROM as AES key:")); + for (int i = 0; i < 16; i++) { + key[i] = random(256) ^ micros(); + unsigned long enter = hwMillis(); + while (hwMillis() - enter < (unsigned long)2); + } + Serial.println(F("This key will be stored in EEPROM as AES key:")); #else - ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE); - if (ret_code != SHA204_SUCCESS) - { - Serial.print(F("Random key generation failed. Response: ")); Serial.println(ret_code, HEX); - halt(); - } - else - { - memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 32); - } - if (lockConfig == 0x00) - { - Serial.println(F("This key will be stored in EEPROM as AES key:")); - } - else - { - Serial.println(F("Key is not randomized (configuration not locked):")); - } + ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE); + if (ret_code != SHA204_SUCCESS) { + Serial.print(F("Random key generation failed. Response: ")); + Serial.println(ret_code, HEX); + halt(); + } else { + memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 32); + } + if (lockConfig == 0x00) { + Serial.println(F("This key will be stored in EEPROM as AES key:")); + } else { + Serial.println(F("Key is not randomized (configuration not locked):")); + } #endif // not USE_SOFT_SIGNING #endif // not USER_AES_KEY - Serial.print("#define MY_AES_KEY "); - for (int i=0; i<16; i++) - { - Serial.print("0x"); - if (key[i] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(key[i], HEX); - if (i < 15) Serial.print(','); - } - Serial.println(); - hwWriteConfigBlock((void*)key, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); + Serial.print("#define MY_AES_KEY "); + for (int i=0; i<16; i++) { + Serial.print("0x"); + if (key[i] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(key[i], HEX); + if (i < 15) { + Serial.print(','); + } + } + Serial.println(); + hwWriteConfigBlock((void*)key, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); #endif // STORE_AES_KEY #ifdef USE_SOFT_SIGNING - Serial.println(F("EEPROM configuration:")); - dump_configuration(); + Serial.println(F("EEPROM configuration:")); + dump_configuration(); #else - // Output device revision on console - ret_code = sha204.sha204m_dev_rev(tx_buffer, rx_buffer); - if (ret_code != SHA204_SUCCESS) - { - Serial.print(F("Failed to determine device revision. Response: ")); Serial.println(ret_code, HEX); - halt(); - } - else - { - Serial.print(F("Device revision: ")); - for (int i=0; i<4; i++) - { - if (rx_buffer[SHA204_BUFFER_POS_DATA+i] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+i], HEX); - } - Serial.println(); - } + // Output device revision on console + ret_code = sha204.sha204m_dev_rev(tx_buffer, rx_buffer); + if (ret_code != SHA204_SUCCESS) { + Serial.print(F("Failed to determine device revision. Response: ")); + Serial.println(ret_code, HEX); + halt(); + } else { + Serial.print(F("Device revision: ")); + for (int i=0; i<4; i++) { + if (rx_buffer[SHA204_BUFFER_POS_DATA+i] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+i], HEX); + } + Serial.println(); + } - // Output serial number on console - ret_code = sha204.getSerialNumber(rx_buffer); - if (ret_code != SHA204_SUCCESS) - { - Serial.print(F("Failed to obtain device serial number. Response: ")); Serial.println(ret_code, HEX); - halt(); - } - else - { - Serial.print(F("Device serial: ")); - Serial.print('{'); - for (int i=0; i<9; i++) - { - Serial.print(F("0x")); - if (rx_buffer[i] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[i], HEX); - if (i < 8) Serial.print(','); - } - Serial.print('}'); - Serial.println(); - for (int i=0; i<9; i++) - { - if (rx_buffer[i] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[i], HEX); - } - Serial.println(); - } + // Output serial number on console + ret_code = sha204.getSerialNumber(rx_buffer); + if (ret_code != SHA204_SUCCESS) { + Serial.print(F("Failed to obtain device serial number. Response: ")); + Serial.println(ret_code, HEX); + halt(); + } else { + Serial.print(F("Device serial: ")); + Serial.print('{'); + for (int i=0; i<9; i++) { + Serial.print(F("0x")); + if (rx_buffer[i] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[i], HEX); + if (i < 8) { + Serial.print(','); + } + } + Serial.print('}'); + Serial.println(); + for (int i=0; i<9; i++) { + if (rx_buffer[i] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[i], HEX); + } + Serial.println(); + } - if (lockConfig != 0x00) - { - // Write config and get CRC for the updated config - crc = write_config_and_get_crc(); + if (lockConfig != 0x00) { + // Write config and get CRC for the updated config + crc = write_config_and_get_crc(); - // List current configuration before attempting to lock - Serial.println(F("Chip configuration:")); - dump_configuration(); + // List current configuration before attempting to lock + Serial.println(F("Chip configuration:")); + dump_configuration(); #ifdef LOCK_CONFIGURATION - // Purge serial input buffer + // Purge serial input buffer #ifndef SKIP_UART_CONFIRMATION - while (Serial.available()) - { - Serial.read(); - } - Serial.println(F("Send SPACE character now to lock the configuration...")); + while (Serial.available()) { + Serial.read(); + } + Serial.println(F("Send SPACE character now to lock the configuration...")); - while (Serial.available() == 0); - if (Serial.read() == ' ') + while (Serial.available() == 0); + if (Serial.read() == ' ') #endif //not SKIP_UART_CONFIRMATION - { - Serial.println(F("Locking configuration...")); + { + Serial.println(F("Locking configuration...")); - // Correct sequence, resync chip - ret_code = sha204.sha204c_resync(SHA204_RSP_SIZE_MAX, rx_buffer); - if (ret_code != SHA204_SUCCESS && ret_code != SHA204_RESYNC_WITH_WAKEUP) - { - Serial.print(F("Resync failed. Response: ")); Serial.println(ret_code, HEX); - halt(); - } + // Correct sequence, resync chip + ret_code = sha204.sha204c_resync(SHA204_RSP_SIZE_MAX, rx_buffer); + if (ret_code != SHA204_SUCCESS && ret_code != SHA204_RESYNC_WITH_WAKEUP) { + Serial.print(F("Resync failed. Response: ")); + Serial.println(ret_code, HEX); + halt(); + } - // Lock configuration zone - ret_code = sha204.sha204m_execute(SHA204_LOCK, SHA204_ZONE_CONFIG, - crc, 0, NULL, 0, NULL, 0, NULL, - LOCK_COUNT, tx_buffer, LOCK_RSP_SIZE, rx_buffer); - if (ret_code != SHA204_SUCCESS) - { - Serial.print(F("Configuration lock failed. Response: ")); Serial.println(ret_code, HEX); - halt(); - } - else - { - Serial.println(F("Configuration locked.")); + // Lock configuration zone + ret_code = sha204.sha204m_execute(SHA204_LOCK, SHA204_ZONE_CONFIG, + crc, 0, NULL, 0, NULL, 0, NULL, + LOCK_COUNT, tx_buffer, LOCK_RSP_SIZE, rx_buffer); + if (ret_code != SHA204_SUCCESS) { + Serial.print(F("Configuration lock failed. Response: ")); + Serial.println(ret_code, HEX); + halt(); + } else { + Serial.println(F("Configuration locked.")); - // Update lock flags after locking - ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2); - if (ret_code != SHA204_SUCCESS) - { - Serial.print(F("Failed to determine device lock status. Response: ")); Serial.println(ret_code, HEX); - halt(); - } - else - { - lockConfig = rx_buffer[SHA204_BUFFER_POS_DATA+3]; - lockValue = rx_buffer[SHA204_BUFFER_POS_DATA+2]; - } - } - } + // Update lock flags after locking + ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2); + if (ret_code != SHA204_SUCCESS) { + Serial.print(F("Failed to determine device lock status. Response: ")); + Serial.println(ret_code, HEX); + halt(); + } else { + lockConfig = rx_buffer[SHA204_BUFFER_POS_DATA+3]; + lockValue = rx_buffer[SHA204_BUFFER_POS_DATA+2]; + } + } + } #ifndef SKIP_UART_CONFIRMATION - else - { - Serial.println(F("Unexpected answer. Skipping lock.")); - } + else { + Serial.println(F("Unexpected answer. Skipping lock.")); + } #endif //not SKIP_UART_CONFIRMATION #else //LOCK_CONFIGURATION - Serial.println(F("Configuration not locked. Define LOCK_CONFIGURATION to lock for real.")); + Serial.println(F("Configuration not locked. Define LOCK_CONFIGURATION to lock for real.")); #endif - } - else - { - Serial.println(F("Skipping configuration write and lock (configuration already locked).")); - Serial.println(F("Chip configuration:")); - dump_configuration(); - } + } else { + Serial.println(F("Skipping configuration write and lock (configuration already locked).")); + Serial.println(F("Chip configuration:")); + dump_configuration(); + } #ifdef SKIP_KEY_STORAGE - Serial.println(F("Disable SKIP_KEY_STORAGE to store key.")); + Serial.println(F("Disable SKIP_KEY_STORAGE to store key.")); #else #ifdef USER_KEY - memcpy(key, user_key_data, 32); - Serial.println(F("Using this user supplied HMAC key:")); + memcpy(key, user_key_data, 32); + Serial.println(F("Using this user supplied HMAC key:")); #else - // Retrieve random value to use as key - ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE); - if (ret_code != SHA204_SUCCESS) - { - Serial.print(F("Random key generation failed. Response: ")); Serial.println(ret_code, HEX); - halt(); - } - else - { - memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 32); - } - if (lockConfig == 0x00) - { - Serial.println(F("Take note of this key, it will never be the shown again:")); - } - else - { - Serial.println(F("Key is not randomized (configuration not locked):")); - } + // Retrieve random value to use as key + ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE); + if (ret_code != SHA204_SUCCESS) { + Serial.print(F("Random key generation failed. Response: ")); + Serial.println(ret_code, HEX); + halt(); + } else { + memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 32); + } + if (lockConfig == 0x00) { + Serial.println(F("Take note of this key, it will never be the shown again:")); + } else { + Serial.println(F("Key is not randomized (configuration not locked):")); + } #endif - Serial.print("#define MY_HMAC_KEY "); - for (int i=0; i<32; i++) - { - Serial.print("0x"); - if (key[i] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(key[i], HEX); - if (i < 31) Serial.print(','); - if (i+1 == 16) Serial.print("\\\n "); - } - Serial.println(); + Serial.print("#define MY_HMAC_KEY "); + for (int i=0; i<32; i++) { + Serial.print("0x"); + if (key[i] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(key[i], HEX); + if (i < 31) { + Serial.print(','); + } + if (i+1 == 16) { + Serial.print("\\\n "); + } + } + Serial.println(); - // It will not be possible to write the key if the configuration zone is unlocked - if (lockConfig == 0x00) - { - // Write the key to the appropriate slot in the data zone - Serial.println(F("Writing key to slot 0...")); - write_key(key); - } - else - { - Serial.println(F("Skipping key storage (configuration not locked).")); - Serial.println(F("The configuration must be locked to be able to write a key.")); - } + // It will not be possible to write the key if the configuration zone is unlocked + if (lockConfig == 0x00) { + // Write the key to the appropriate slot in the data zone + Serial.println(F("Writing key to slot 0...")); + write_key(key); + } else { + Serial.println(F("Skipping key storage (configuration not locked).")); + Serial.println(F("The configuration must be locked to be able to write a key.")); + } #endif - if (lockValue != 0x00) - { + if (lockValue != 0x00) { #ifdef LOCK_DATA #ifndef SKIP_UART_CONFIRMATION - while (Serial.available()) - { - Serial.read(); - } - Serial.println(F("Send SPACE character to lock data...")); - while (Serial.available() == 0); - if (Serial.read() == ' ') + while (Serial.available()) { + Serial.read(); + } + Serial.println(F("Send SPACE character to lock data...")); + while (Serial.available() == 0); + if (Serial.read() == ' ') #endif //not SKIP_UART_CONFIRMATION - { - // Correct sequence, resync chip - ret_code = sha204.sha204c_resync(SHA204_RSP_SIZE_MAX, rx_buffer); - if (ret_code != SHA204_SUCCESS && ret_code != SHA204_RESYNC_WITH_WAKEUP) - { - Serial.print(F("Resync failed. Response: ")); Serial.println(ret_code, HEX); - halt(); - } + { + // Correct sequence, resync chip + ret_code = sha204.sha204c_resync(SHA204_RSP_SIZE_MAX, rx_buffer); + if (ret_code != SHA204_SUCCESS && ret_code != SHA204_RESYNC_WITH_WAKEUP) { + Serial.print(F("Resync failed. Response: ")); + Serial.println(ret_code, HEX); + halt(); + } - // If configuration is unlocked, key is not updated. Locking data in this case will cause - // slot 0 to contain an unknown (or factory default) key, and this is in practically any - // usecase not the desired behaviour, so ask for additional confirmation in this case. - if (lockConfig != 0x00) - { - while (Serial.available()) - { - Serial.read(); - } - Serial.println(F("*** ATTENTION ***")); - Serial.println(F("Configuration is not locked. Are you ABSULOUTELY SURE you want to lock data?")); - Serial.println(F("Locking data at this stage will cause slot 0 to contain a factory default key")); - Serial.println(F("which cannot be change after locking is done. This is in practically any usecase")); - Serial.println(F("NOT the desired behavour. Send SPACE character now to lock data anyway...")); - while (Serial.available() == 0); - if (Serial.read() != ' ') - { - Serial.println(F("Unexpected answer. Skipping lock.")); - halt(); - } - } + // If configuration is unlocked, key is not updated. Locking data in this case will cause + // slot 0 to contain an unknown (or factory default) key, and this is in practically any + // usecase not the desired behaviour, so ask for additional confirmation in this case. + if (lockConfig != 0x00) { + while (Serial.available()) { + Serial.read(); + } + Serial.println(F("*** ATTENTION ***")); + Serial.println(F("Configuration is not locked. Are you ABSULOUTELY SURE you want to lock data?")); + Serial.println(F("Locking data at this stage will cause slot 0 to contain a factory default key")); + Serial.println( + F("which cannot be change after locking is done. This is in practically any usecase")); + Serial.println(F("NOT the desired behavour. Send SPACE character now to lock data anyway...")); + while (Serial.available() == 0); + if (Serial.read() != ' ') { + Serial.println(F("Unexpected answer. Skipping lock.")); + halt(); + } + } - // Lock data zone - ret_code = sha204.sha204m_execute(SHA204_LOCK, SHA204_ZONE_DATA | LOCK_ZONE_NO_CRC, - 0x0000, 0, NULL, 0, NULL, 0, NULL, - LOCK_COUNT, tx_buffer, LOCK_RSP_SIZE, rx_buffer); - if (ret_code != SHA204_SUCCESS) - { - Serial.print(F("Data lock failed. Response: ")); Serial.println(ret_code, HEX); - halt(); - } - else - { - Serial.println(F("Data locked.")); + // Lock data zone + ret_code = sha204.sha204m_execute(SHA204_LOCK, SHA204_ZONE_DATA | LOCK_ZONE_NO_CRC, + 0x0000, 0, NULL, 0, NULL, 0, NULL, + LOCK_COUNT, tx_buffer, LOCK_RSP_SIZE, rx_buffer); + if (ret_code != SHA204_SUCCESS) { + Serial.print(F("Data lock failed. Response: ")); + Serial.println(ret_code, HEX); + halt(); + } else { + Serial.println(F("Data locked.")); - // Update lock flags after locking - ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2); - if (ret_code != SHA204_SUCCESS) - { - Serial.print(F("Failed to determine device lock status. Response: ")); Serial.println(ret_code, HEX); - halt(); - } - else - { - lockConfig = rx_buffer[SHA204_BUFFER_POS_DATA+3]; - lockValue = rx_buffer[SHA204_BUFFER_POS_DATA+2]; - } - } - } + // Update lock flags after locking + ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2); + if (ret_code != SHA204_SUCCESS) { + Serial.print(F("Failed to determine device lock status. Response: ")); + Serial.println(ret_code, HEX); + halt(); + } else { + lockConfig = rx_buffer[SHA204_BUFFER_POS_DATA+3]; + lockValue = rx_buffer[SHA204_BUFFER_POS_DATA+2]; + } + } + } #ifndef SKIP_UART_CONFIRMATION - else - { - Serial.println(F("Unexpected answer. Skipping lock.")); - } + else { + Serial.println(F("Unexpected answer. Skipping lock.")); + } #endif //not SKIP_UART_CONFIRMATION #else //LOCK_DATA - Serial.println(F("Data not locked. Define LOCK_DATA to lock for real.")); + Serial.println(F("Data not locked. Define LOCK_DATA to lock for real.")); #endif - } - else - { - Serial.println(F("Skipping OTP/data zone lock (zone already locked).")); - } + } else { + Serial.println(F("Skipping OTP/data zone lock (zone already locked).")); + } #endif // not USE_SOFT_SIGNING - Serial.println(F("--------------------------------")); - Serial.println(F("Personalization is now complete.")); + Serial.println(F("--------------------------------")); + Serial.println(F("Personalization is now complete.")); #ifndef USE_SOFT_SIGNING - Serial.print(F("Configuration is ")); - if (lockConfig == 0x00) - { - Serial.println("LOCKED"); - } - else - { - Serial.println("UNLOCKED"); - } - Serial.print(F("Data is ")); - if (lockValue == 0x00) - { - Serial.println("LOCKED"); - } - else - { - Serial.println("UNLOCKED"); - } + Serial.print(F("Configuration is ")); + if (lockConfig == 0x00) { + Serial.println("LOCKED"); + } else { + Serial.println("UNLOCKED"); + } + Serial.print(F("Data is ")); + if (lockValue == 0x00) { + Serial.println("LOCKED"); + } else { + Serial.println("UNLOCKED"); + } #endif } diff --git a/examples/SecurityPersonalizer/sha204_library.cpp b/examples/SecurityPersonalizer/sha204_library.cpp index a747c4d..a384fda 100644 --- a/examples/SecurityPersonalizer/sha204_library.cpp +++ b/examples/SecurityPersonalizer/sha204_library.cpp @@ -10,11 +10,11 @@ // For others it will only store the pin number which is used in subsequent functions atsha204Class::atsha204Class(uint8_t pin) -{ +{ #if defined(ARDUINO_ARCH_AVR) device_pin = digitalPinToBitMask(pin); // Find the bit value of the pin uint8_t port = digitalPinToPort(pin); // temoporarily used to get the next three registers - + // Point to data direction register port of pin device_port_DDR = portModeRegister(port); // Point to output register of pin @@ -26,472 +26,476 @@ atsha204Class::atsha204Class(uint8_t pin) #endif } -/* Puts a the ATSHA204's unique, 4-byte serial number in the response array +/* Puts a the ATSHA204's unique, 4-byte serial number in the response array returns an SHA204 Return code */ uint8_t atsha204Class::getSerialNumber(uint8_t * response) { uint8_t readCommand[READ_COUNT]; uint8_t readResponse[READ_4_RSP_SIZE]; - + /* read from bytes 0->3 of config zone */ uint8_t returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN03); - if (!returnCode) // should return 0 if successful - { - for (int i=0; i<4; i++) // store bytes 0-3 into respones array + if (!returnCode) { // should return 0 if successful + for (int i=0; i<4; i++) { // store bytes 0-3 into respones array response[i] = readResponse[SHA204_BUFFER_POS_DATA+i]; - + } + /* read from bytes 8->11 of config zone */ 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)]; - - if (!returnCode) - { /* Finally if last two reads were successful, read byte 8 of the SN */ + } + + if (!returnCode) { + /* Finally if last two reads were successful, read byte 8 of the SN */ returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN8); response[8] = readResponse[SHA204_BUFFER_POS_DATA]; // Byte 8 of SN should always be 0xEE } } - + return returnCode; } -/* Calculates CRC16 value of provided data (and optionally including provided existing CRC16 data) +/* Calculates CRC16 value of provided data (and optionally including provided existing CRC16 data) returns the calculated CRC16 value */ uint16_t atsha204Class::calculateAndUpdateCrc(uint8_t length, uint8_t *data, uint16_t current_crc) { - uint8_t counter; - uint16_t crc_register = current_crc; - uint16_t polynom = 0x8005; - uint8_t shift_register; - uint8_t data_bit, crc_bit; + uint8_t counter; + uint16_t crc_register = current_crc; + uint16_t polynom = 0x8005; + uint8_t shift_register; + uint8_t data_bit, crc_bit; - for (counter = 0; counter < length; counter++) - { - for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) - { - data_bit = (data[counter] & shift_register) ? 1 : 0; - crc_bit = crc_register >> 15; + for (counter = 0; counter < length; counter++) { + for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) { + data_bit = (data[counter] & shift_register) ? 1 : 0; + crc_bit = crc_register >> 15; - // Shift CRC to the left by 1. - crc_register <<= 1; + // Shift CRC to the left by 1. + crc_register <<= 1; - if ((data_bit ^ crc_bit) != 0) - crc_register ^= polynom; - } - } - return crc_register; + if ((data_bit ^ crc_bit) != 0) { + crc_register ^= polynom; + } + } + } + return crc_register; } /* SWI bit bang functions */ void atsha204Class::swi_set_signal_pin(uint8_t is_high) { - SHA204_SET_OUTPUT(); - if (is_high) { - SHA204_POUT_HIGH(); - } - else { - SHA204_POUT_LOW(); - } + SHA204_SET_OUTPUT(); + if (is_high) { + SHA204_POUT_HIGH(); + } else { + SHA204_POUT_LOW(); + } } uint8_t atsha204Class::swi_send_bytes(uint8_t count, uint8_t *buffer) { - uint8_t i, bit_mask; + uint8_t i, bit_mask; - // Disable interrupts while sending. - noInterrupts(); //swi_disable_interrupts(); + // Disable interrupts while sending. + noInterrupts(); //swi_disable_interrupts(); - // Set signal pin as output. - SHA204_POUT_HIGH(); - SHA204_SET_OUTPUT(); - // Wait turn around time. - delayMicroseconds(RX_TX_DELAY); //RX_TX_DELAY; + // Set signal pin as output. + SHA204_POUT_HIGH(); + SHA204_SET_OUTPUT(); + // Wait turn around time. + delayMicroseconds(RX_TX_DELAY); //RX_TX_DELAY; - for (i = 0; i < count; i++) - { - for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) - { - if (bit_mask & buffer[i]) - { - SHA204_POUT_LOW(); - delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; - SHA204_POUT_HIGH(); - delayMicroseconds(7*BIT_DELAY); //BIT_DELAY_7; - } - else - { - // Send a zero bit. - SHA204_POUT_LOW(); - delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; - SHA204_POUT_HIGH(); - delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; - SHA204_POUT_LOW(); - delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; - SHA204_POUT_HIGH(); - delayMicroseconds(5*BIT_DELAY); //BIT_DELAY_5; - } - } - } - interrupts(); //swi_enable_interrupts(); - return SWI_FUNCTION_RETCODE_SUCCESS; + for (i = 0; i < count; i++) { + for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) { + if (bit_mask & buffer[i]) { + SHA204_POUT_LOW(); + delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; + SHA204_POUT_HIGH(); + delayMicroseconds(7*BIT_DELAY); //BIT_DELAY_7; + } else { + // Send a zero bit. + SHA204_POUT_LOW(); + delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; + SHA204_POUT_HIGH(); + delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; + SHA204_POUT_LOW(); + delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; + SHA204_POUT_HIGH(); + delayMicroseconds(5*BIT_DELAY); //BIT_DELAY_5; + } + } + } + interrupts(); //swi_enable_interrupts(); + return SWI_FUNCTION_RETCODE_SUCCESS; } uint8_t atsha204Class::swi_send_byte(uint8_t value) { - return swi_send_bytes(1, &value); + return swi_send_bytes(1, &value); } -uint8_t atsha204Class::swi_receive_bytes(uint8_t count, uint8_t *buffer) +uint8_t atsha204Class::swi_receive_bytes(uint8_t count, uint8_t *buffer) { - uint8_t status = SWI_FUNCTION_RETCODE_SUCCESS; - uint8_t i; - uint8_t bit_mask; - uint8_t pulse_count; - uint8_t timeout_count; + uint8_t status = SWI_FUNCTION_RETCODE_SUCCESS; + uint8_t i; + uint8_t bit_mask; + uint8_t pulse_count; + uint8_t timeout_count; - // Disable interrupts while receiving. - noInterrupts(); //swi_disable_interrupts(); + // Disable interrupts while receiving. + noInterrupts(); //swi_disable_interrupts(); - // Configure signal pin as input - SHA204_SET_INPUT(); + // Configure signal pin as input + SHA204_SET_INPUT(); - // Receive bits and store in buffer. - for (i = 0; i < count; i++) - { - for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) - { - pulse_count = 0; + // Receive bits and store in buffer. + for (i = 0; i < count; i++) { + for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) { + pulse_count = 0; - // Make sure that the variable below is big enough. - // Change it to uint16_t if 255 is too small, but be aware that - // the loop resolution decreases on an 8-bit controller in that case. - timeout_count = START_PULSE_TIME_OUT; + // Make sure that the variable below is big enough. + // Change it to uint16_t if 255 is too small, but be aware that + // the loop resolution decreases on an 8-bit controller in that case. + timeout_count = START_PULSE_TIME_OUT; - // Detect start bit. - while (--timeout_count > 0) - { - // Wait for falling edge. - if (SHA204_PIN_READ() == 0) - break; - } + // Detect start bit. + while (--timeout_count > 0) { + // Wait for falling edge. + if (SHA204_PIN_READ() == 0) { + break; + } + } - if (timeout_count == 0) - { - status = SWI_FUNCTION_RETCODE_TIMEOUT; - break; - } + if (timeout_count == 0) { + status = SWI_FUNCTION_RETCODE_TIMEOUT; + break; + } - do - { - // Wait for rising edge. - if (SHA204_PIN_READ() != 0) - { - // For an Atmel microcontroller this might be faster than "pulse_count++". - pulse_count = 1; - break; - } - } while (--timeout_count > 0); + do { + // Wait for rising edge. + if (SHA204_PIN_READ() != 0) { + // For an Atmel microcontroller this might be faster than "pulse_count++". + pulse_count = 1; + break; + } + } while (--timeout_count > 0); - if (pulse_count == 0) - { - status = SWI_FUNCTION_RETCODE_TIMEOUT; - break; - } + if (pulse_count == 0) { + status = SWI_FUNCTION_RETCODE_TIMEOUT; + break; + } - // Trying to measure the time of start bit and calculating the timeout - // for zero bit detection is not accurate enough for an 8 MHz 8-bit CPU. - // So let's just wait the maximum time for the falling edge of a zero bit - // to arrive after we have detected the rising edge of the start bit. - timeout_count = ZERO_PULSE_TIME_OUT; + // Trying to measure the time of start bit and calculating the timeout + // for zero bit detection is not accurate enough for an 8 MHz 8-bit CPU. + // So let's just wait the maximum time for the falling edge of a zero bit + // to arrive after we have detected the rising edge of the start bit. + timeout_count = ZERO_PULSE_TIME_OUT; - // Detect possible edge indicating zero bit. - do - { - if (SHA204_PIN_READ() == 0) - { - // For an Atmel microcontroller this might be faster than "pulse_count++". - pulse_count = 2; - break; - } - } while (--timeout_count > 0); + // Detect possible edge indicating zero bit. + do { + if (SHA204_PIN_READ() == 0) { + // For an Atmel microcontroller this might be faster than "pulse_count++". + pulse_count = 2; + break; + } + } while (--timeout_count > 0); - // Wait for rising edge of zero pulse before returning. Otherwise we might interpret - // its rising edge as the next start pulse. - if (pulse_count == 2) - { - do - { - if (SHA204_PIN_READ() != 0) - break; - } while (timeout_count-- > 0); - } + // Wait for rising edge of zero pulse before returning. Otherwise we might interpret + // its rising edge as the next start pulse. + if (pulse_count == 2) { + do { + if (SHA204_PIN_READ() != 0) { + break; + } + } while (timeout_count-- > 0); + } - // Update byte at current buffer index. - else - buffer[i] |= bit_mask; // received "one" bit - } + // Update byte at current buffer index. + else { + buffer[i] |= bit_mask; // received "one" bit + } + } - if (status != SWI_FUNCTION_RETCODE_SUCCESS) - break; - } - interrupts(); //swi_enable_interrupts(); + if (status != SWI_FUNCTION_RETCODE_SUCCESS) { + break; + } + } + interrupts(); //swi_enable_interrupts(); - if (status == SWI_FUNCTION_RETCODE_TIMEOUT) - { - if (i > 0) - // Indicate that we timed out after having received at least one byte. - status = SWI_FUNCTION_RETCODE_RX_FAIL; - } - return status; + if (status == SWI_FUNCTION_RETCODE_TIMEOUT) { + if (i > 0) + // Indicate that we timed out after having received at least one byte. + { + status = SWI_FUNCTION_RETCODE_RX_FAIL; + } + } + return status; } /* Physical functions */ uint8_t atsha204Class::sha204p_wakeup() { - swi_set_signal_pin(0); - delayMicroseconds(10*SHA204_WAKEUP_PULSE_WIDTH); - swi_set_signal_pin(1); - delay(SHA204_WAKEUP_DELAY); + swi_set_signal_pin(0); + delayMicroseconds(10*SHA204_WAKEUP_PULSE_WIDTH); + swi_set_signal_pin(1); + delay(SHA204_WAKEUP_DELAY); - return SHA204_SUCCESS; + return SHA204_SUCCESS; } uint8_t atsha204Class::sha204p_sleep() { - return swi_send_byte(SHA204_SWI_FLAG_SLEEP); + return swi_send_byte(SHA204_SWI_FLAG_SLEEP); } uint8_t atsha204Class::sha204p_resync(uint8_t size, uint8_t *response) { - delay(SHA204_SYNC_TIMEOUT); - return sha204p_receive_response(size, response); + delay(SHA204_SYNC_TIMEOUT); + return sha204p_receive_response(size, response); } uint8_t atsha204Class::sha204p_receive_response(uint8_t size, uint8_t *response) { - uint8_t count_byte; - uint8_t i; - uint8_t ret_code; + uint8_t count_byte; + uint8_t i; + uint8_t ret_code; - for (i = 0; i < size; i++) - response[i] = 0; + for (i = 0; i < size; i++) { + response[i] = 0; + } - (void) swi_send_byte(SHA204_SWI_FLAG_TX); + (void) swi_send_byte(SHA204_SWI_FLAG_TX); - ret_code = swi_receive_bytes(size, response); - if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) - { - count_byte = response[SHA204_BUFFER_POS_COUNT]; - if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) - return SHA204_INVALID_SIZE; + ret_code = swi_receive_bytes(size, response); + if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) { + count_byte = response[SHA204_BUFFER_POS_COUNT]; + if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) { + return SHA204_INVALID_SIZE; + } - return SHA204_SUCCESS; - } + return SHA204_SUCCESS; + } - // Translate error so that the Communication layer - // can distinguish between a real error or the - // device being busy executing a command. - if (ret_code == SWI_FUNCTION_RETCODE_TIMEOUT) - return SHA204_RX_NO_RESPONSE; - else - return SHA204_RX_FAIL; + // Translate error so that the Communication layer + // can distinguish between a real error or the + // device being busy executing a command. + if (ret_code == SWI_FUNCTION_RETCODE_TIMEOUT) { + return SHA204_RX_NO_RESPONSE; + } else { + return SHA204_RX_FAIL; + } } uint8_t atsha204Class::sha204p_send_command(uint8_t count, uint8_t * command) { - uint8_t ret_code = swi_send_byte(SHA204_SWI_FLAG_CMD); - if (ret_code != SWI_FUNCTION_RETCODE_SUCCESS) - return SHA204_COMM_FAIL; + uint8_t ret_code = swi_send_byte(SHA204_SWI_FLAG_CMD); + if (ret_code != SWI_FUNCTION_RETCODE_SUCCESS) { + return SHA204_COMM_FAIL; + } - return swi_send_bytes(count, command); + return swi_send_bytes(count, command); } /* Communication functions */ uint8_t atsha204Class::sha204c_wakeup(uint8_t *response) { - uint8_t ret_code = sha204p_wakeup(); - if (ret_code != SHA204_SUCCESS) - return ret_code; + uint8_t ret_code = sha204p_wakeup(); + if (ret_code != SHA204_SUCCESS) { + return ret_code; + } - ret_code = sha204p_receive_response(SHA204_RSP_SIZE_MIN, response); - if (ret_code != SHA204_SUCCESS) - return ret_code; + ret_code = sha204p_receive_response(SHA204_RSP_SIZE_MIN, response); + if (ret_code != SHA204_SUCCESS) { + return ret_code; + } - // Verify status response. - if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN) - ret_code = SHA204_INVALID_SIZE; - else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP) - ret_code = SHA204_COMM_FAIL; - else - { - if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33) - || (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43)) - ret_code = SHA204_BAD_CRC; - } - if (ret_code != SHA204_SUCCESS) - delay(SHA204_COMMAND_EXEC_MAX); + // Verify status response. + if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN) { + ret_code = SHA204_INVALID_SIZE; + } else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP) { + ret_code = SHA204_COMM_FAIL; + } else { + if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33) + || (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43)) { + ret_code = SHA204_BAD_CRC; + } + } + if (ret_code != SHA204_SUCCESS) { + delay(SHA204_COMMAND_EXEC_MAX); + } - return ret_code; + return ret_code; } uint8_t atsha204Class::sha204c_resync(uint8_t size, uint8_t *response) { - // Try to re-synchronize without sending a Wake token - // (step 1 of the re-synchronization process). - uint8_t ret_code = sha204p_resync(size, response); - if (ret_code == SHA204_SUCCESS) - return ret_code; + // Try to re-synchronize without sending a Wake token + // (step 1 of the re-synchronization process). + uint8_t ret_code = sha204p_resync(size, response); + if (ret_code == SHA204_SUCCESS) { + return ret_code; + } - // We lost communication. Send a Wake pulse and try - // to receive a response (steps 2 and 3 of the - // re-synchronization process). - (void) sha204p_sleep(); - ret_code = sha204c_wakeup(response); + // We lost communication. Send a Wake pulse and try + // to receive a response (steps 2 and 3 of the + // re-synchronization process). + (void) sha204p_sleep(); + ret_code = sha204c_wakeup(response); - // Translate a return value of success into one - // that indicates that the device had to be woken up - // and might have lost its TempKey. - return (ret_code == SHA204_SUCCESS ? SHA204_RESYNC_WITH_WAKEUP : ret_code); + // Translate a return value of success into one + // that indicates that the device had to be woken up + // and might have lost its TempKey. + return (ret_code == SHA204_SUCCESS ? SHA204_RESYNC_WITH_WAKEUP : ret_code); } -uint8_t atsha204Class::sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, uint8_t execution_delay, uint8_t execution_timeout) +uint8_t atsha204Class::sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, + uint8_t *rx_buffer, uint8_t execution_delay, uint8_t execution_timeout) { - uint8_t ret_code = SHA204_FUNC_FAIL; - uint8_t ret_code_resync; - uint8_t n_retries_send; - uint8_t n_retries_receive; - uint8_t i; - uint8_t status_byte; - uint8_t count = tx_buffer[SHA204_BUFFER_POS_COUNT]; - uint8_t count_minus_crc = count - SHA204_CRC_SIZE; - uint16_t execution_timeout_us = (uint16_t) (execution_timeout * 1000) + SHA204_RESPONSE_TIMEOUT; - volatile uint16_t timeout_countdown; + uint8_t ret_code = SHA204_FUNC_FAIL; + uint8_t ret_code_resync; + uint8_t n_retries_send; + uint8_t n_retries_receive; + uint8_t i; + uint8_t status_byte; + uint8_t count = tx_buffer[SHA204_BUFFER_POS_COUNT]; + uint8_t count_minus_crc = count - SHA204_CRC_SIZE; + uint16_t execution_timeout_us = (uint16_t) (execution_timeout * 1000) + SHA204_RESPONSE_TIMEOUT; + volatile uint16_t timeout_countdown; - // Append CRC. - sha204c_calculate_crc(count_minus_crc, tx_buffer, tx_buffer + count_minus_crc); + // Append CRC. + sha204c_calculate_crc(count_minus_crc, tx_buffer, tx_buffer + count_minus_crc); - // Retry loop for sending a command and receiving a response. - n_retries_send = SHA204_RETRY_COUNT + 1; + // Retry loop for sending a command and receiving a response. + n_retries_send = SHA204_RETRY_COUNT + 1; - while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS)) - { - // Send command. - ret_code = sha204p_send_command(count, tx_buffer); - if (ret_code != SHA204_SUCCESS) - { - if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) - return ret_code; // The device seems to be dead in the water. - else - continue; - } + while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS)) { + // Send command. + ret_code = sha204p_send_command(count, tx_buffer); + if (ret_code != SHA204_SUCCESS) { + if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) { + return ret_code; // The device seems to be dead in the water. + } else { + continue; + } + } - // Wait minimum command execution time and then start polling for a response. - delay(execution_delay); + // Wait minimum command execution time and then start polling for a response. + delay(execution_delay); - // Retry loop for receiving a response. - n_retries_receive = SHA204_RETRY_COUNT + 1; - while (n_retries_receive-- > 0) - { - // Reset response buffer. - for (i = 0; i < rx_size; i++) - rx_buffer[i] = 0; + // Retry loop for receiving a response. + n_retries_receive = SHA204_RETRY_COUNT + 1; + while (n_retries_receive-- > 0) { + // Reset response buffer. + for (i = 0; i < rx_size; i++) { + rx_buffer[i] = 0; + } - // Poll for response. - timeout_countdown = execution_timeout_us; - do - { - ret_code = sha204p_receive_response(rx_size, rx_buffer); - timeout_countdown -= SHA204_RESPONSE_TIMEOUT; - } - while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (ret_code == SHA204_RX_NO_RESPONSE)); + // Poll for response. + timeout_countdown = execution_timeout_us; + do { + ret_code = sha204p_receive_response(rx_size, rx_buffer); + timeout_countdown -= SHA204_RESPONSE_TIMEOUT; + } while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (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. - if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) - // The device seems to be dead in the water. - return ret_code; - else - break; - } + if (ret_code == SHA204_RX_NO_RESPONSE) { + // We did not receive a response. Re-synchronize and send command again. + if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) + // The device seems to be dead in the water. + { + return ret_code; + } else { + break; + } + } - // Check whether we received a valid response. - if (ret_code == SHA204_INVALID_SIZE) - { - // We see 0xFF for the count when communication got out of sync. - ret_code_resync = sha204c_resync(rx_size, rx_buffer); - if (ret_code_resync == SHA204_SUCCESS) - // We did not have to wake up the device. Try receiving response again. - continue; - if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) - // We could re-synchronize, but only after waking up the device. - // Re-send command. - break; - else - // We failed to re-synchronize. - return ret_code; - } + // Check whether we received a valid response. + if (ret_code == SHA204_INVALID_SIZE) { + // We see 0xFF for the count when communication got out of sync. + ret_code_resync = sha204c_resync(rx_size, rx_buffer); + if (ret_code_resync == SHA204_SUCCESS) + // We did not have to wake up the device. Try receiving response again. + { + continue; + } + if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) + // We could re-synchronize, but only after waking up the device. + // Re-send command. + { + break; + } else + // We failed to re-synchronize. + { + return ret_code; + } + } - // We received a response of valid size. - // Check the consistency of the response. - ret_code = sha204c_check_crc(rx_buffer); - if (ret_code == SHA204_SUCCESS) - { - // Received valid response. - if (rx_buffer[SHA204_BUFFER_POS_COUNT] > SHA204_RSP_SIZE_MIN) - // Received non-status response. We are done. - return ret_code; + // We received a response of valid size. + // Check the consistency of the response. + ret_code = sha204c_check_crc(rx_buffer); + if (ret_code == SHA204_SUCCESS) { + // Received valid response. + if (rx_buffer[SHA204_BUFFER_POS_COUNT] > SHA204_RSP_SIZE_MIN) + // Received non-status response. We are done. + { + return ret_code; + } - // Received status response. - status_byte = rx_buffer[SHA204_BUFFER_POS_STATUS]; + // Received status response. + status_byte = rx_buffer[SHA204_BUFFER_POS_STATUS]; - // Translate the three possible device status error codes - // into library return codes. - if (status_byte == SHA204_STATUS_BYTE_PARSE) - return SHA204_PARSE_ERROR; - if (status_byte == SHA204_STATUS_BYTE_EXEC) - return SHA204_CMD_FAIL; - if (status_byte == SHA204_STATUS_BYTE_COMM) - { - // In case of the device status byte indicating a communication - // error this function exits the retry loop for receiving a response - // and enters the overall retry loop - // (send command / receive response). - ret_code = SHA204_STATUS_CRC; - break; - } + // Translate the three possible device status error codes + // into library return codes. + if (status_byte == SHA204_STATUS_BYTE_PARSE) { + return SHA204_PARSE_ERROR; + } + if (status_byte == SHA204_STATUS_BYTE_EXEC) { + return SHA204_CMD_FAIL; + } + if (status_byte == SHA204_STATUS_BYTE_COMM) { + // In case of the device status byte indicating a communication + // error this function exits the retry loop for receiving a response + // and enters the overall retry loop + // (send command / receive response). + ret_code = SHA204_STATUS_CRC; + break; + } - // Received status response from CheckMAC, DeriveKey, GenDig, - // Lock, Nonce, Pause, UpdateExtra, or Write command. - return ret_code; - } + // Received status response from CheckMAC, DeriveKey, GenDig, + // Lock, Nonce, Pause, UpdateExtra, or Write command. + return ret_code; + } - else - { - // Received response with incorrect CRC. - ret_code_resync = sha204c_resync(rx_size, rx_buffer); - if (ret_code_resync == SHA204_SUCCESS) - // We did not have to wake up the device. Try receiving response again. - continue; - if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) - // We could re-synchronize, but only after waking up the device. - // Re-send command. - break; - else - // We failed to re-synchronize. - return ret_code; - } // block end of check response consistency + else { + // Received response with incorrect CRC. + ret_code_resync = sha204c_resync(rx_size, rx_buffer); + if (ret_code_resync == SHA204_SUCCESS) + // We did not have to wake up the device. Try receiving response again. + { + continue; + } + if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) + // We could re-synchronize, but only after waking up the device. + // Re-send command. + { + break; + } else + // We failed to re-synchronize. + { + return ret_code; + } + } // block end of check response consistency - } // block end of receive retry loop + } // block end of receive retry loop - } // block end of send and receive retry loop + } // block end of send and receive retry loop - return ret_code; + return ret_code; } @@ -499,173 +503,178 @@ uint8_t atsha204Class::sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_s uint8_t atsha204Class::sha204m_random(uint8_t * tx_buffer, uint8_t * rx_buffer, uint8_t mode) { - if (!tx_buffer || !rx_buffer || (mode > RANDOM_NO_SEED_UPDATE)) - return SHA204_BAD_PARAM; + if (!tx_buffer || !rx_buffer || (mode > RANDOM_NO_SEED_UPDATE)) { + return SHA204_BAD_PARAM; + } - tx_buffer[SHA204_COUNT_IDX] = RANDOM_COUNT; - tx_buffer[SHA204_OPCODE_IDX] = SHA204_RANDOM; - tx_buffer[RANDOM_MODE_IDX] = mode & RANDOM_SEED_UPDATE; + tx_buffer[SHA204_COUNT_IDX] = RANDOM_COUNT; + tx_buffer[SHA204_OPCODE_IDX] = SHA204_RANDOM; + tx_buffer[RANDOM_MODE_IDX] = mode & RANDOM_SEED_UPDATE; - tx_buffer[RANDOM_PARAM2_IDX] = - tx_buffer[RANDOM_PARAM2_IDX + 1] = 0; + tx_buffer[RANDOM_PARAM2_IDX] = + tx_buffer[RANDOM_PARAM2_IDX + 1] = 0; - return sha204c_send_and_receive(&tx_buffer[0], RANDOM_RSP_SIZE, &rx_buffer[0], RANDOM_DELAY, RANDOM_EXEC_MAX - RANDOM_DELAY); + return sha204c_send_and_receive(&tx_buffer[0], RANDOM_RSP_SIZE, &rx_buffer[0], RANDOM_DELAY, + RANDOM_EXEC_MAX - RANDOM_DELAY); } uint8_t atsha204Class::sha204m_dev_rev(uint8_t *tx_buffer, uint8_t *rx_buffer) { - if (!tx_buffer || !rx_buffer) - return SHA204_BAD_PARAM; + if (!tx_buffer || !rx_buffer) { + return SHA204_BAD_PARAM; + } - tx_buffer[SHA204_COUNT_IDX] = DEVREV_COUNT; - tx_buffer[SHA204_OPCODE_IDX] = SHA204_DEVREV; + tx_buffer[SHA204_COUNT_IDX] = DEVREV_COUNT; + tx_buffer[SHA204_OPCODE_IDX] = SHA204_DEVREV; - // Parameters are 0. - tx_buffer[DEVREV_PARAM1_IDX] = - tx_buffer[DEVREV_PARAM2_IDX] = - tx_buffer[DEVREV_PARAM2_IDX + 1] = 0; + // Parameters are 0. + tx_buffer[DEVREV_PARAM1_IDX] = + tx_buffer[DEVREV_PARAM2_IDX] = + tx_buffer[DEVREV_PARAM2_IDX + 1] = 0; - return sha204c_send_and_receive(&tx_buffer[0], DEVREV_RSP_SIZE, &rx_buffer[0], - DEVREV_DELAY, DEVREV_EXEC_MAX - DEVREV_DELAY); + return sha204c_send_and_receive(&tx_buffer[0], DEVREV_RSP_SIZE, &rx_buffer[0], + DEVREV_DELAY, DEVREV_EXEC_MAX - DEVREV_DELAY); } -uint8_t atsha204Class::sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, uint16_t address) +uint8_t atsha204Class::sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, + uint16_t address) { - uint8_t rx_size; + uint8_t rx_size; - if (!tx_buffer || !rx_buffer || ((zone & ~READ_ZONE_MASK) != 0) - || ((zone & READ_ZONE_MODE_32_BYTES) && (zone == SHA204_ZONE_OTP))) - return SHA204_BAD_PARAM; + if (!tx_buffer || !rx_buffer || ((zone & ~READ_ZONE_MASK) != 0) + || ((zone & READ_ZONE_MODE_32_BYTES) && (zone == SHA204_ZONE_OTP))) { + return SHA204_BAD_PARAM; + } - address >>= 2; - if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_CONFIG) - { - if (address > SHA204_ADDRESS_MASK_CONFIG) - return SHA204_BAD_PARAM; - } - else if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_OTP) - { - if (address > SHA204_ADDRESS_MASK_OTP) - return SHA204_BAD_PARAM; - } - else if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_DATA) - { - if (address > SHA204_ADDRESS_MASK) - return SHA204_BAD_PARAM; - } + address >>= 2; + if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_CONFIG) { + if (address > SHA204_ADDRESS_MASK_CONFIG) { + return SHA204_BAD_PARAM; + } + } else if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_OTP) { + if (address > SHA204_ADDRESS_MASK_OTP) { + return SHA204_BAD_PARAM; + } + } else if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_DATA) { + if (address > SHA204_ADDRESS_MASK) { + return SHA204_BAD_PARAM; + } + } - tx_buffer[SHA204_COUNT_IDX] = READ_COUNT; - tx_buffer[SHA204_OPCODE_IDX] = SHA204_READ; - tx_buffer[READ_ZONE_IDX] = zone; - tx_buffer[READ_ADDR_IDX] = (uint8_t) (address & SHA204_ADDRESS_MASK); - tx_buffer[READ_ADDR_IDX + 1] = 0; + tx_buffer[SHA204_COUNT_IDX] = READ_COUNT; + tx_buffer[SHA204_OPCODE_IDX] = SHA204_READ; + tx_buffer[READ_ZONE_IDX] = zone; + tx_buffer[READ_ADDR_IDX] = (uint8_t) (address & SHA204_ADDRESS_MASK); + tx_buffer[READ_ADDR_IDX + 1] = 0; - rx_size = (zone & SHA204_ZONE_COUNT_FLAG) ? READ_32_RSP_SIZE : READ_4_RSP_SIZE; + rx_size = (zone & SHA204_ZONE_COUNT_FLAG) ? READ_32_RSP_SIZE : READ_4_RSP_SIZE; - return sha204c_send_and_receive(&tx_buffer[0], rx_size, &rx_buffer[0], READ_DELAY, READ_EXEC_MAX - READ_DELAY); + return sha204c_send_and_receive(&tx_buffer[0], rx_size, &rx_buffer[0], READ_DELAY, + READ_EXEC_MAX - READ_DELAY); } uint8_t atsha204Class::sha204m_execute(uint8_t op_code, uint8_t param1, uint16_t param2, - uint8_t datalen1, uint8_t *data1, uint8_t datalen2, uint8_t *data2, uint8_t datalen3, uint8_t *data3, - uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer) + uint8_t datalen1, uint8_t *data1, uint8_t datalen2, uint8_t *data2, uint8_t datalen3, + uint8_t *data3, + uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer) { uint8_t poll_delay, poll_timeout, response_size; uint8_t *p_buffer; uint8_t len; uint8_t ret_code = sha204m_check_parameters(op_code, param1, param2, - datalen1, data1, datalen2, data2, datalen3, data3, - tx_size, tx_buffer, rx_size, rx_buffer); - if (ret_code != SHA204_SUCCESS) + datalen1, data1, datalen2, data2, datalen3, data3, + tx_size, tx_buffer, rx_size, rx_buffer); + if (ret_code != SHA204_SUCCESS) { return ret_code; + } // Supply delays and response size. - switch (op_code) - { - case SHA204_CHECKMAC: - poll_delay = CHECKMAC_DELAY; - poll_timeout = CHECKMAC_EXEC_MAX - CHECKMAC_DELAY; - response_size = CHECKMAC_RSP_SIZE; - break; + switch (op_code) { + case SHA204_CHECKMAC: + poll_delay = CHECKMAC_DELAY; + poll_timeout = CHECKMAC_EXEC_MAX - CHECKMAC_DELAY; + response_size = CHECKMAC_RSP_SIZE; + break; - case SHA204_DERIVE_KEY: - poll_delay = DERIVE_KEY_DELAY; - poll_timeout = DERIVE_KEY_EXEC_MAX - DERIVE_KEY_DELAY; - response_size = DERIVE_KEY_RSP_SIZE; - break; + case SHA204_DERIVE_KEY: + poll_delay = DERIVE_KEY_DELAY; + poll_timeout = DERIVE_KEY_EXEC_MAX - DERIVE_KEY_DELAY; + response_size = DERIVE_KEY_RSP_SIZE; + break; - case SHA204_DEVREV: - poll_delay = DEVREV_DELAY; - poll_timeout = DEVREV_EXEC_MAX - DEVREV_DELAY; - response_size = DEVREV_RSP_SIZE; - break; + case SHA204_DEVREV: + poll_delay = DEVREV_DELAY; + poll_timeout = DEVREV_EXEC_MAX - DEVREV_DELAY; + response_size = DEVREV_RSP_SIZE; + break; - case SHA204_GENDIG: - poll_delay = GENDIG_DELAY; - poll_timeout = GENDIG_EXEC_MAX - GENDIG_DELAY; - response_size = GENDIG_RSP_SIZE; - break; + case SHA204_GENDIG: + poll_delay = GENDIG_DELAY; + poll_timeout = GENDIG_EXEC_MAX - GENDIG_DELAY; + response_size = GENDIG_RSP_SIZE; + break; - case SHA204_HMAC: - poll_delay = HMAC_DELAY; - poll_timeout = HMAC_EXEC_MAX - HMAC_DELAY; - response_size = HMAC_RSP_SIZE; - break; + case SHA204_HMAC: + poll_delay = HMAC_DELAY; + poll_timeout = HMAC_EXEC_MAX - HMAC_DELAY; + response_size = HMAC_RSP_SIZE; + break; - case SHA204_LOCK: - poll_delay = LOCK_DELAY; - poll_timeout = LOCK_EXEC_MAX - LOCK_DELAY; - response_size = LOCK_RSP_SIZE; - break; + case SHA204_LOCK: + poll_delay = LOCK_DELAY; + poll_timeout = LOCK_EXEC_MAX - LOCK_DELAY; + response_size = LOCK_RSP_SIZE; + break; - case SHA204_MAC: - poll_delay = MAC_DELAY; - poll_timeout = MAC_EXEC_MAX - MAC_DELAY; - response_size = MAC_RSP_SIZE; - break; + case SHA204_MAC: + poll_delay = MAC_DELAY; + poll_timeout = MAC_EXEC_MAX - MAC_DELAY; + response_size = MAC_RSP_SIZE; + break; - case SHA204_NONCE: - poll_delay = NONCE_DELAY; - poll_timeout = NONCE_EXEC_MAX - NONCE_DELAY; - response_size = param1 == NONCE_MODE_PASSTHROUGH - ? NONCE_RSP_SIZE_SHORT : NONCE_RSP_SIZE_LONG; - break; + case SHA204_NONCE: + poll_delay = NONCE_DELAY; + poll_timeout = NONCE_EXEC_MAX - NONCE_DELAY; + response_size = param1 == NONCE_MODE_PASSTHROUGH + ? NONCE_RSP_SIZE_SHORT : NONCE_RSP_SIZE_LONG; + break; - case SHA204_PAUSE: - poll_delay = PAUSE_DELAY; - poll_timeout = PAUSE_EXEC_MAX - PAUSE_DELAY; - response_size = PAUSE_RSP_SIZE; - break; + case SHA204_PAUSE: + poll_delay = PAUSE_DELAY; + poll_timeout = PAUSE_EXEC_MAX - PAUSE_DELAY; + response_size = PAUSE_RSP_SIZE; + break; - case SHA204_RANDOM: - poll_delay = RANDOM_DELAY; - poll_timeout = RANDOM_EXEC_MAX - RANDOM_DELAY; - response_size = RANDOM_RSP_SIZE; - break; + case SHA204_RANDOM: + poll_delay = RANDOM_DELAY; + poll_timeout = RANDOM_EXEC_MAX - RANDOM_DELAY; + response_size = RANDOM_RSP_SIZE; + break; - case SHA204_READ: - poll_delay = READ_DELAY; - poll_timeout = READ_EXEC_MAX - READ_DELAY; - response_size = (param1 & SHA204_ZONE_COUNT_FLAG) - ? READ_32_RSP_SIZE : READ_4_RSP_SIZE; - break; + case SHA204_READ: + poll_delay = READ_DELAY; + poll_timeout = READ_EXEC_MAX - READ_DELAY; + response_size = (param1 & SHA204_ZONE_COUNT_FLAG) + ? READ_32_RSP_SIZE : READ_4_RSP_SIZE; + break; - case SHA204_UPDATE_EXTRA: - poll_delay = UPDATE_DELAY; - poll_timeout = UPDATE_EXEC_MAX - UPDATE_DELAY; - response_size = UPDATE_RSP_SIZE; - break; + case SHA204_UPDATE_EXTRA: + poll_delay = UPDATE_DELAY; + poll_timeout = UPDATE_EXEC_MAX - UPDATE_DELAY; + response_size = UPDATE_RSP_SIZE; + break; - case SHA204_WRITE: - poll_delay = WRITE_DELAY; - poll_timeout = WRITE_EXEC_MAX - WRITE_DELAY; - response_size = WRITE_RSP_SIZE; - break; + case SHA204_WRITE: + poll_delay = WRITE_DELAY; + poll_timeout = WRITE_EXEC_MAX - WRITE_DELAY; + response_size = WRITE_RSP_SIZE; + break; - default: - poll_delay = 0; - poll_timeout = SHA204_COMMAND_EXEC_MAX; - response_size = rx_size; + default: + poll_delay = 0; + poll_timeout = SHA204_COMMAND_EXEC_MAX; + response_size = rx_size; } // Assemble command. @@ -694,146 +703,159 @@ uint8_t atsha204Class::sha204m_execute(uint8_t op_code, uint8_t param1, uint16_t // Send command and receive response. return sha204c_send_and_receive(&tx_buffer[0], response_size, - &rx_buffer[0], poll_delay, poll_timeout); + &rx_buffer[0], poll_delay, poll_timeout); } uint8_t atsha204Class::sha204m_check_parameters(uint8_t op_code, uint8_t param1, uint16_t param2, - uint8_t datalen1, uint8_t *data1, uint8_t datalen2, uint8_t *data2, uint8_t datalen3, uint8_t *data3, - uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer) + uint8_t datalen1, uint8_t *data1, uint8_t datalen2, uint8_t *data2, uint8_t datalen3, + uint8_t *data3, + uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer) { #ifdef SHA204_CHECK_PARAMETERS uint8_t len = datalen1 + datalen2 + datalen3 + SHA204_CMD_SIZE_MIN; - if (!tx_buffer || tx_size < len || rx_size < SHA204_RSP_SIZE_MIN || !rx_buffer) + if (!tx_buffer || tx_size < len || rx_size < SHA204_RSP_SIZE_MIN || !rx_buffer) { return SHA204_BAD_PARAM; + } - if ((datalen1 > 0 && !data1) || (datalen2 > 0 && !data2) || (datalen3 > 0 && !data3)) + if ((datalen1 > 0 && !data1) || (datalen2 > 0 && !data2) || (datalen3 > 0 && !data3)) { return SHA204_BAD_PARAM; + } // Check parameters depending on op-code. - switch (op_code) - { - case SHA204_CHECKMAC: - if ( - // no null pointers allowed - !data1 || !data2 - // No reserved bits should be set. - || (param1 | CHECKMAC_MODE_MASK) != CHECKMAC_MODE_MASK - // key_id > 15 not allowed - || param2 > SHA204_KEY_ID_MAX - ) - return SHA204_BAD_PARAM; - break; - - case SHA204_DERIVE_KEY: - if (param2 > SHA204_KEY_ID_MAX) - return SHA204_BAD_PARAM; - break; - - case SHA204_DEVREV: - break; - - case SHA204_GENDIG: - if ((param1 != GENDIG_ZONE_OTP) && (param1 != GENDIG_ZONE_DATA)) - return SHA204_BAD_PARAM; - break; - - case SHA204_HMAC: - if ((param1 & ~HMAC_MODE_MASK) != 0) - return SHA204_BAD_PARAM; - break; - - case SHA204_LOCK: - if (((param1 & ~LOCK_ZONE_MASK) != 0) - || ((param1 & LOCK_ZONE_NO_CRC) && (param2 != 0))) - return SHA204_BAD_PARAM; - break; - - case SHA204_MAC: - if (((param1 & ~MAC_MODE_MASK) != 0) - || (((param1 & MAC_MODE_BLOCK2_TEMPKEY) == 0) && !data1)) - return SHA204_BAD_PARAM; - break; - - case SHA204_NONCE: - if ( !data1 - || (param1 > NONCE_MODE_PASSTHROUGH) - || (param1 == NONCE_MODE_INVALID) - ) - return SHA204_BAD_PARAM; - break; - - case SHA204_PAUSE: - break; - - case SHA204_RANDOM: - if (param1 > RANDOM_NO_SEED_UPDATE) - return SHA204_BAD_PARAM; - break; - - case SHA204_READ: - if (((param1 & ~READ_ZONE_MASK) != 0) - || ((param1 & READ_ZONE_MODE_32_BYTES) && (param1 == SHA204_ZONE_OTP))) - return SHA204_BAD_PARAM; - break; - - case SHA204_TEMPSENSE: - break; - - case SHA204_UPDATE_EXTRA: - if (param1 > UPDATE_CONFIG_BYTE_86) - return SHA204_BAD_PARAM; - break; - - case SHA204_WRITE: - if (!data1 || ((param1 & ~WRITE_ZONE_MASK) != 0)) - return SHA204_BAD_PARAM; - break; - - default: - // unknown op-code + switch (op_code) { + case SHA204_CHECKMAC: + if ( + // no null pointers allowed + !data1 || !data2 + // No reserved bits should be set. + || (param1 | CHECKMAC_MODE_MASK) != CHECKMAC_MODE_MASK + // key_id > 15 not allowed + || param2 > SHA204_KEY_ID_MAX + ) { return SHA204_BAD_PARAM; + } + break; + + case SHA204_DERIVE_KEY: + if (param2 > SHA204_KEY_ID_MAX) { + return SHA204_BAD_PARAM; + } + break; + + case SHA204_DEVREV: + break; + + case SHA204_GENDIG: + if ((param1 != GENDIG_ZONE_OTP) && (param1 != GENDIG_ZONE_DATA)) { + return SHA204_BAD_PARAM; + } + break; + + case SHA204_HMAC: + if ((param1 & ~HMAC_MODE_MASK) != 0) { + return SHA204_BAD_PARAM; + } + break; + + case SHA204_LOCK: + if (((param1 & ~LOCK_ZONE_MASK) != 0) + || ((param1 & LOCK_ZONE_NO_CRC) && (param2 != 0))) { + return SHA204_BAD_PARAM; + } + break; + + case SHA204_MAC: + if (((param1 & ~MAC_MODE_MASK) != 0) + || (((param1 & MAC_MODE_BLOCK2_TEMPKEY) == 0) && !data1)) { + return SHA204_BAD_PARAM; + } + break; + + case SHA204_NONCE: + if ( !data1 + || (param1 > NONCE_MODE_PASSTHROUGH) + || (param1 == NONCE_MODE_INVALID) + ) { + return SHA204_BAD_PARAM; + } + break; + + case SHA204_PAUSE: + break; + + case SHA204_RANDOM: + if (param1 > RANDOM_NO_SEED_UPDATE) { + return SHA204_BAD_PARAM; + } + break; + + case SHA204_READ: + if (((param1 & ~READ_ZONE_MASK) != 0) + || ((param1 & READ_ZONE_MODE_32_BYTES) && (param1 == SHA204_ZONE_OTP))) { + return SHA204_BAD_PARAM; + } + break; + + case SHA204_TEMPSENSE: + break; + + case SHA204_UPDATE_EXTRA: + if (param1 > UPDATE_CONFIG_BYTE_86) { + return SHA204_BAD_PARAM; + } + break; + + case SHA204_WRITE: + if (!data1 || ((param1 & ~WRITE_ZONE_MASK) != 0)) { + return SHA204_BAD_PARAM; + } + break; + + default: + // unknown op-code + return SHA204_BAD_PARAM; } return SHA204_SUCCESS; #else - (void)rx_size; - (void)tx_size; - (void)tx_buffer; - (void)rx_buffer; - (void)param1; - (void)param2; - (void)data1; - (void)data2; - (void)data3; - (void)datalen1; - (void)datalen2; - (void)datalen3; - (void)op_code; + (void)rx_size; + (void)tx_size; + (void)tx_buffer; + (void)rx_buffer; + (void)param1; + (void)param2; + (void)data1; + (void)data2; + (void)data3; + (void)datalen1; + (void)datalen2; + (void)datalen3; + (void)op_code; return SHA204_SUCCESS; #endif } /* CRC Calculator and Checker */ -void atsha204Class::sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc) +void atsha204Class::sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc) { - uint16_t crc_register = 0; + uint16_t crc_register = 0; - crc_register = calculateAndUpdateCrc(length, data, crc_register); - crc[0] = (uint8_t) (crc_register & 0x00FF); - crc[1] = (uint8_t) (crc_register >> 8); + crc_register = calculateAndUpdateCrc(length, data, crc_register); + crc[0] = (uint8_t) (crc_register & 0x00FF); + crc[1] = (uint8_t) (crc_register >> 8); } uint8_t atsha204Class::sha204c_check_crc(uint8_t *response) { - uint8_t crc[SHA204_CRC_SIZE]; - uint8_t count = response[SHA204_BUFFER_POS_COUNT]; + uint8_t crc[SHA204_CRC_SIZE]; + uint8_t count = response[SHA204_BUFFER_POS_COUNT]; - count -= SHA204_CRC_SIZE; - sha204c_calculate_crc(count, response, crc); + count -= SHA204_CRC_SIZE; + sha204c_calculate_crc(count, response, crc); - return (crc[0] == response[count] && crc[1] == response[count + 1]) - ? SHA204_SUCCESS : SHA204_BAD_CRC; + return (crc[0] == response[count] && crc[1] == response[count + 1]) + ? SHA204_SUCCESS : SHA204_BAD_CRC; } diff --git a/examples/SecurityPersonalizer/sha204_library.h b/examples/SecurityPersonalizer/sha204_library.h index e9682bb..fb0beb2 100644 --- a/examples/SecurityPersonalizer/sha204_library.h +++ b/examples/SecurityPersonalizer/sha204_library.h @@ -260,7 +260,7 @@ #define SHA204_COMMAND_EXEC_MAX ((uint8_t) (69.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) //! maximum command delay #define SHA204_CMD_SIZE_MIN ((uint8_t) 7) //! minimum number of bytes in command (from count byte to second CRC byte) #ifndef SHA204_CMD_SIZE_MAX - #define SHA204_CMD_SIZE_MAX ((uint8_t) 84) //! maximum size of command packet (CheckMac) +#define SHA204_CMD_SIZE_MAX ((uint8_t) 84) //! maximum size of command packet (CheckMac) #endif #define SHA204_CRC_SIZE ((uint8_t) 2) //! number of CRC bytes #define SHA204_BUFFER_POS_STATUS (1) //! buffer index of status byte in status response @@ -284,17 +284,17 @@ /* Low level HW access macros */ /* function calls is not working, as it will have too much overhead */ #if !defined(ARDUINO_ARCH_AVR) // For everything else than AVR use pinMode / digitalWrite - #define SHA204_SET_OUTPUT() pinMode(device_pin, OUTPUT) - #define SHA204_SET_INPUT() pinMode(device_pin, INPUT) - #define SHA204_POUT_HIGH() digitalWrite(device_pin, HIGH) - #define SHA204_POUT_LOW() digitalWrite(device_pin, LOW) - #define SHA204_PIN_READ() digitalRead(device_pin) +#define SHA204_SET_OUTPUT() pinMode(device_pin, OUTPUT) +#define SHA204_SET_INPUT() pinMode(device_pin, INPUT) +#define SHA204_POUT_HIGH() digitalWrite(device_pin, HIGH) +#define SHA204_POUT_LOW() digitalWrite(device_pin, LOW) +#define SHA204_PIN_READ() digitalRead(device_pin) #else - #define SHA204_SET_INPUT() *device_port_DDR &= ~device_pin - #define SHA204_SET_OUTPUT() *device_port_DDR |= device_pin - #define SHA204_POUT_HIGH() *device_port_OUT |= device_pin - #define SHA204_POUT_LOW() *device_port_OUT &= ~device_pin - #define SHA204_PIN_READ() (*device_port_IN & device_pin) +#define SHA204_SET_INPUT() *device_port_DDR &= ~device_pin +#define SHA204_SET_OUTPUT() *device_port_DDR |= device_pin +#define SHA204_POUT_HIGH() *device_port_OUT |= device_pin +#define SHA204_POUT_LOW() *device_port_OUT &= ~device_pin +#define SHA204_PIN_READ() (*device_port_IN & device_pin) #endif /** diff --git a/examples/SensebenderGatewaySerial/SensebenderGatewaySerial.ino b/examples/SensebenderGatewaySerial/SensebenderGatewaySerial.ino index d5492f5..d7a57db 100644 --- a/examples/SensebenderGatewaySerial/SensebenderGatewaySerial.ino +++ b/examples/SensebenderGatewaySerial/SensebenderGatewaySerial.ino @@ -1,40 +1,40 @@ - /** - * 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. - * - * This GW code is designed for Sensebender GateWay / (Arduino Zero variant) - * - * Wire connections (OPTIONAL): - * - Inclusion button should be connected to SW2 - * - * LEDs on board (default assignments): - * - Orange: USB RX/TX - Blink when receiving / transmitting on USB CDC device - * - Yellow: RX - Blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved - * - Green : TX - Blink fast on radio message transmitted. In inclusion mode will blink slowly - * - Red : ERR - Fast blink on error during transmission error or recieve crc error - * - Blue : free - (use with LED_BLUE macro) - * - */ +/** +* 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. +* +* This GW code is designed for Sensebender GateWay / (Arduino Zero variant) +* +* Wire connections (OPTIONAL): +* - Inclusion button should be connected to SW2 +* +* LEDs on board (default assignments): +* - Orange: USB RX/TX - Blink when receiving / transmitting on USB CDC device +* - Yellow: RX - Blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved +* - Green : TX - Blink fast on radio message transmitted. In inclusion mode will blink slowly +* - Red : ERR - Fast blink on error during transmission error or recieve crc error +* - Blue : free - (use with LED_BLUE macro) +* +*/ #define SKETCH_VERSION "0.2" // Enable debug prints to serial monitor @@ -92,177 +92,189 @@ Sd2Card card; static uint8_t num_of_leds = 5; static uint8_t leds[] = {LED_BLUE, LED_RED, LED_GREEN, LED_YELLOW, LED_ORANGE}; -void setup() { - // Setup locally attached sensors +void setup() +{ + // Setup locally attached sensors } -void presentation() { - // Present locally attached sensors +void presentation() +{ + // Present locally attached sensors } -void loop() { - // Send locally attached sensor data here +void loop() +{ + // Send locally attached sensor data here } -void preHwInit() { +void preHwInit() +{ - pinMode(MY_SWC1, INPUT_PULLUP); - pinMode(MY_SWC2, INPUT_PULLUP); - if (digitalRead(MY_SWC1) && digitalRead(MY_SWC2)) return; + pinMode(MY_SWC1, INPUT_PULLUP); + pinMode(MY_SWC2, INPUT_PULLUP); + if (digitalRead(MY_SWC1) && digitalRead(MY_SWC2)) { + return; + } - uint8_t tests = 0; + uint8_t tests = 0; - for (int i=0; i< num_of_leds; i++) { - pinMode(leds[i], OUTPUT); - } - uint8_t led_state = 0; - if (digitalRead(MY_SWC1)) { - while (!Serial) { - digitalWrite(LED_BLUE, led_state); - led_state ^= 0x01; - delay(500); - } // Wait for USB to be connected, before spewing out data. - } - digitalWrite(LED_BLUE, LOW); - if (Serial) { - Serial.println("Sensebender GateWay test routine"); - Serial.print("Mysensors core version : "); - Serial.println(MYSENSORS_LIBRARY_VERSION); - Serial.print("GateWay sketch version : "); - Serial.println(SKETCH_VERSION); - Serial.println("----------------------------------"); - Serial.println(); - } - if (testSha204()) { - digitalWrite(LED_GREEN, HIGH); - tests++; - } - if (testSDCard()) { - digitalWrite(LED_YELLOW, HIGH); - tests++; - } + for (int i=0; i< num_of_leds; i++) { + pinMode(leds[i], OUTPUT); + } + uint8_t led_state = 0; + if (digitalRead(MY_SWC1)) { + while (!Serial) { + digitalWrite(LED_BLUE, led_state); + led_state ^= 0x01; + delay(500); + } // Wait for USB to be connected, before spewing out data. + } + digitalWrite(LED_BLUE, LOW); + if (Serial) { + Serial.println("Sensebender GateWay test routine"); + Serial.print("Mysensors core version : "); + Serial.println(MYSENSORS_LIBRARY_VERSION); + Serial.print("GateWay sketch version : "); + Serial.println(SKETCH_VERSION); + Serial.println("----------------------------------"); + Serial.println(); + } + if (testSha204()) { + digitalWrite(LED_GREEN, HIGH); + tests++; + } + if (testSDCard()) { + digitalWrite(LED_YELLOW, HIGH); + tests++; + } - if (testEEProm()) { - digitalWrite(LED_ORANGE, HIGH); - tests++; - } - if (testAnalog()) { - digitalWrite(LED_BLUE, HIGH); - tests++; - } - if (tests == 4) { - while(1) { - for (int i=0; i SHA204 "); - atsha204_init(MY_SIGNING_ATSHA204_PIN); - ret_code = atsha204_wakeup(rx_buffer); +bool testSha204() +{ + uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; + uint8_t ret_code; + if (Serial) { + Serial.print("- > SHA204 "); + } + atsha204_init(MY_SIGNING_ATSHA204_PIN); + ret_code = atsha204_wakeup(rx_buffer); - if (ret_code == SHA204_SUCCESS) - { - ret_code = atsha204_getSerialNumber(rx_buffer); - if (ret_code != SHA204_SUCCESS) - { - if (Serial) Serial.println(F("Failed to obtain device serial number. Response: ")); Serial.println(ret_code, HEX); - } - else - { - if (Serial) { - Serial.print(F("Ok (serial : ")); - for (int i=0; i<9; i++) - { - if (rx_buffer[i] < 0x10) - { - Serial.print('0'); // Because Serial.print does not 0-pad HEX - } - Serial.print(rx_buffer[i], HEX); - } - Serial.println(")"); - } - return true; - } - } - else { - if (Serial) Serial.println(F("Failed to wakeup SHA204")); - } - return false; + if (ret_code == SHA204_SUCCESS) { + ret_code = atsha204_getSerialNumber(rx_buffer); + if (ret_code != SHA204_SUCCESS) { + if (Serial) { + Serial.println(F("Failed to obtain device serial number. Response: ")); + } + Serial.println(ret_code, HEX); + } else { + if (Serial) { + Serial.print(F("Ok (serial : ")); + for (int i=0; i<9; i++) { + if (rx_buffer[i] < 0x10) { + Serial.print('0'); // Because Serial.print does not 0-pad HEX + } + Serial.print(rx_buffer[i], HEX); + } + Serial.println(")"); + } + return true; + } + } else { + if (Serial) { + Serial.println(F("Failed to wakeup SHA204")); + } + } + return false; } -bool testSDCard() { - if (Serial) Serial.print("- > SD CARD "); - if (!card.init(SPI_HALF_SPEED, MY_SDCARD_CS)) { - if (Serial) Serial.println("SD CARD did not initialize!"); - } - else { - if (Serial) { - Serial.print("SD Card initialized correct! - "); - Serial.print("type detected : "); - switch(card.type()) { - case SD_CARD_TYPE_SD1: - Serial.println("SD1"); - break; - case SD_CARD_TYPE_SD2: - Serial.println("SD2"); - break; - case SD_CARD_TYPE_SDHC: - Serial.println("SDHC"); - break; - default: - Serial.println("Unknown"); - } - } - return true; - } - return false; +bool testSDCard() +{ + if (Serial) { + Serial.print("- > SD CARD "); + } + if (!card.init(SPI_HALF_SPEED, MY_SDCARD_CS)) { + if (Serial) { + Serial.println("SD CARD did not initialize!"); + } + } else { + if (Serial) { + Serial.print("SD Card initialized correct! - "); + Serial.print("type detected : "); + switch(card.type()) { + case SD_CARD_TYPE_SD1: + Serial.println("SD1"); + break; + case SD_CARD_TYPE_SD2: + Serial.println("SD2"); + break; + case SD_CARD_TYPE_SDHC: + Serial.println("SDHC"); + break; + default: + Serial.println("Unknown"); + } + } + return true; + } + return false; } -bool testEEProm() { - uint8_t eeprom_d1, eeprom_d2; - SerialUSB.print(" -> EEPROM "); - Wire.begin(); - eeprom_d1 = i2c_eeprom_read_byte(EEPROM_VERIFICATION_ADDRESS); - delay(500); - eeprom_d1 = ~eeprom_d1; // invert the bits - i2c_eeprom_write_byte(EEPROM_VERIFICATION_ADDRESS, eeprom_d1); - delay(500); - eeprom_d2 = i2c_eeprom_read_byte(EEPROM_VERIFICATION_ADDRESS); - if (eeprom_d1 == eeprom_d2) { - SerialUSB.println("PASSED"); - i2c_eeprom_write_byte(EEPROM_VERIFICATION_ADDRESS, ~eeprom_d1); - return true; - } - SerialUSB.println("FAILED!"); - return false; +bool testEEProm() +{ + uint8_t eeprom_d1, eeprom_d2; + SerialUSB.print(" -> EEPROM "); + Wire.begin(); + eeprom_d1 = i2c_eeprom_read_byte(EEPROM_VERIFICATION_ADDRESS); + delay(500); + eeprom_d1 = ~eeprom_d1; // invert the bits + i2c_eeprom_write_byte(EEPROM_VERIFICATION_ADDRESS, eeprom_d1); + delay(500); + eeprom_d2 = i2c_eeprom_read_byte(EEPROM_VERIFICATION_ADDRESS); + if (eeprom_d1 == eeprom_d2) { + SerialUSB.println("PASSED"); + i2c_eeprom_write_byte(EEPROM_VERIFICATION_ADDRESS, ~eeprom_d1); + return true; + } + SerialUSB.println("FAILED!"); + return false; } -bool testAnalog() { - int bat_detect = analogRead(MY_BAT_DETECT); - Serial.print("-> analog : "); - Serial.print(bat_detect); - if (bat_detect < 400 || bat_detect > 650) { - Serial.println(" Failed"); - return false; - } - Serial.println(" Passed"); - return true; +bool testAnalog() +{ + int bat_detect = analogRead(MY_BAT_DETECT); + Serial.print("-> analog : "); + Serial.print(bat_detect); + if (bat_detect < 400 || bat_detect > 650) { + Serial.println(" Failed"); + return false; + } + Serial.println(" Passed"); + return true; } diff --git a/examples/SoilMoistSensor/SoilMoistSensor.ino b/examples/SoilMoistSensor/SoilMoistSensor.ino index 0d45d08..b43deb3 100644 --- a/examples/SoilMoistSensor/SoilMoistSensor.ino +++ b/examples/SoilMoistSensor/SoilMoistSensor.ino @@ -22,24 +22,24 @@ * * Arduino soil moisture based on gypsum sensor/resistive sensor to avoid electric catalyse in soil * Required to interface the sensor: 2 * 4.7kOhm + 2 * 1N4148 - * - * Gypsum sensor and calibration: + * + * Gypsum sensor and calibration: * DIY: See http://vanderleevineyard.com/1/category/vinduino/1.html - * Built: Davis / Watermark 200SS + * Built: Davis / Watermark 200SS * http://www.cooking-hacks.com/watermark-soil-moisture-sensor?_bksrc=item2item&_bkloc=product * http://www.irrometer.com/pdf/supportmaterial/sensors/voltage-WM-chart.pdf * cb (centibar) http://www.irrometer.com/basics.html - * 0-10 Saturated Soil. Occurs for a day or two after irrigation - * 10-20 Soil is adequately wet (except coarse sands which are drying out at this range) - * 30-60 Usual range to irrigate or water (except heavy clay soils). - * 60-100 Usual range to irrigate heavy clay soils - * 100-200 Soil is becoming dangerously dry for maximum production. Proceed with caution. - * + * 0-10 Saturated Soil. Occurs for a day or two after irrigation + * 10-20 Soil is adequately wet (except coarse sands which are drying out at this range) + * 30-60 Usual range to irrigate or water (except heavy clay soils). + * 60-100 Usual range to irrigate heavy clay soils + * 100-200 Soil is becoming dangerously dry for maximum production. Proceed with caution. + * * Connection: * D6, D7: alternative powering to avoid sensor degradation * A0, A1: alternative resistance mesuring * - * Based on: + * Based on: * "Vinduino" portable soil moisture sensor code V3.00 * Date December 31, 2012 * Reinier van der Lee and Theodore Kaskalis @@ -61,7 +61,7 @@ // GNU General Public License for more details. // Enable debug prints to serial monitor -#define MY_DEBUG +#define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 @@ -74,7 +74,7 @@ #define NUM_READS 10 // Number of sensor reads for filtering #define CHILD_ID 0 -MyMessage msg(CHILD_ID, V_LEVEL); +MyMessage msg(CHILD_ID, V_LEVEL); unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds) long buffer[NUM_READS]; @@ -82,8 +82,8 @@ int index; /// @brief Structure to be used in percentage and resistance values matrix to be filtered (have to be in pairs) typedef struct { - int moisture; //!< Moisture - long resistance; //!< Resistance + int moisture; //!< Moisture + long resistance; //!< Resistance } values; const long knownResistor = 4700; // Constant value of known resistor in Ohms @@ -95,24 +95,27 @@ values valueOf[NUM_READS]; // Calculated moisture percentages and resista int i; // Simple index variable -void setup() { - // initialize the digital pins as an output. - // Pin 6,7 is for sensor 1 - // initialize the digital pin as an output. - // Pin 6 is sense resistor voltage supply 1 - pinMode(6, OUTPUT); +void setup() +{ + // initialize the digital pins as an output. + // Pin 6,7 is for sensor 1 + // initialize the digital pin as an output. + // Pin 6 is sense resistor voltage supply 1 + pinMode(6, OUTPUT); - // initialize the digital pin as an output. - // Pin 7 is sense resistor voltage supply 2 - pinMode(7, OUTPUT); + // initialize the digital pin as an output. + // Pin 7 is sense resistor voltage supply 2 + pinMode(7, OUTPUT); } -void presentation() { - sendSketchInfo("Soil Moisture Sensor Reverse Polarity", "1.0"); - present(CHILD_ID, S_HUM); +void presentation() +{ + sendSketchInfo("Soil Moisture Sensor Reverse Polarity", "1.0"); + present(CHILD_ID, S_HUM); } -void loop() { +void loop() +{ measure(6,7,1); Serial.print ("\t"); @@ -131,59 +134,63 @@ void loop() { Serial.print ("sensor bias compensated value = "); Serial.println (sensor1); Serial.println (); - + //send back the values send(msg.set((long int)ceil(sensor1))); // delay until next measurement (msec) - sleep(SLEEP_TIME); + sleep(SLEEP_TIME); } void measure (int phase_b, int phase_a, int analog_input) { - // read sensor, filter, and calculate resistance value - // Noise filter: median filter + // read sensor, filter, and calculate resistance value + // Noise filter: median filter - for (i=0; i= NUM_READS) index = 0; +void addReading(long resistance) +{ + buffer[index] = resistance; + index++; + if (index >= NUM_READS) { + index = 0; + } } -long average(){ - long sum = 0; - for (int i = 0; i < NUM_READS; i++){ - sum += buffer[i]; - } - return (long)(sum / NUM_READS); +long average() +{ + long sum = 0; + for (int i = 0; i < NUM_READS; i++) { + sum += buffer[i]; + } + return (long)(sum / NUM_READS); } diff --git a/examples/UVSensor/UVSensor.ino b/examples/UVSensor/UVSensor.ino index e22451d..0a6ea52 100644 --- a/examples/UVSensor/UVSensor.ino +++ b/examples/UVSensor/UVSensor.ino @@ -21,29 +21,29 @@ * REVISION HISTORY * Version 1.0 - epierre * Contribution: bulldoglowell, gizmocuz - * + * * DESCRIPTION * Arduino UVM-30A * Index table taken from: http://www.elecrow.com/sensors-c-111/environment-c-111_112/uv-sensor-moduleuvm30a-p-716.html - * Because this table is pretty lineair, we can calculate a UVI with one decimal + * Because this table is pretty lineair, we can calculate a UVI with one decimal * * Connect sensor: * * + >>> 5V * - >>> GND - * out >>> A0 - * + * out >>> A0 + * * License: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) */ // Enable debug prints to serial monitor -#define MY_DEBUG +#define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 -#include +#include #define UV_SENSOR_ANALOG_PIN 0 @@ -53,57 +53,57 @@ unsigned long SLEEP_TIME = 30*1000; // Sleep time between reads (in milliseconds MyMessage uvMsg(CHILD_ID_UV, V_UV); -unsigned long lastSend =0; +unsigned long lastSend =0; float uvIndex; float lastUV = -1; uint16_t uvIndexValue [12] = { 50, 227, 318, 408, 503, 606, 696, 795, 881, 976, 1079, 1170}; -void presentation() { - // Send the sketch version information to the gateway and Controller - sendSketchInfo("UV Sensor", "1.2"); - - // Register all sensors to gateway (they will be created as child devices) - present(CHILD_ID_UV, S_UV); -} - -void loop() +void presentation() { - unsigned long currentTime = millis(); - - uint16_t uv = analogRead(UV_SENSOR_ANALOG_PIN);// Get UV value - if (uv>1170) - uv=1170; - - //Serial.print("UV Analog reading: "); - //Serial.println(uv); - - int i; - for (i = 0; i < 12; i++) - { - if (uv <= uvIndexValue[i]) - { - uvIndex = i; - break; - } - } - - //calculate 1 decimal if possible - if (i>0) { - float vRange=uvIndexValue[i]-uvIndexValue[i-1]; - float vCalc=uv-uvIndexValue[i-1]; - uvIndex+=(1.0/vRange)*vCalc-1.0; - } + // Send the sketch version information to the gateway and Controller + sendSketchInfo("UV Sensor", "1.2"); - //Serial.print("UVI: "); - //Serial.println(uvIndex,2); - - //Send value to gateway if changed, or at least every 5 minutes - if ((uvIndex != lastUV)||(currentTime-lastSend >= 5UL*60UL*1000UL)) { - lastSend=currentTime; - send(uvMsg.set(uvIndex,2)); - lastUV = uvIndex; - } - - sleep(SLEEP_TIME); + // Register all sensors to gateway (they will be created as child devices) + present(CHILD_ID_UV, S_UV); +} + +void loop() +{ + unsigned long currentTime = millis(); + + uint16_t uv = analogRead(UV_SENSOR_ANALOG_PIN);// Get UV value + if (uv>1170) { + uv=1170; + } + + //Serial.print("UV Analog reading: "); + //Serial.println(uv); + + int i; + for (i = 0; i < 12; i++) { + if (uv <= uvIndexValue[i]) { + uvIndex = i; + break; + } + } + + //calculate 1 decimal if possible + if (i>0) { + float vRange=uvIndexValue[i]-uvIndexValue[i-1]; + float vCalc=uv-uvIndexValue[i-1]; + uvIndex+=(1.0/vRange)*vCalc-1.0; + } + + //Serial.print("UVI: "); + //Serial.println(uvIndex,2); + + //Send value to gateway if changed, or at least every 5 minutes + if ((uvIndex != lastUV)||(currentTime-lastSend >= 5UL*60UL*1000UL)) { + lastSend=currentTime; + send(uvMsg.set(uvIndex,2)); + lastUV = uvIndex; + } + + sleep(SLEEP_TIME); } diff --git a/examples/VibrationSensor/VibrationSensor.ino b/examples/VibrationSensor/VibrationSensor.ino index eaefa59..a07d7bd 100644 --- a/examples/VibrationSensor/VibrationSensor.ino +++ b/examples/VibrationSensor/VibrationSensor.ino @@ -58,40 +58,42 @@ MyMessage vibrationMsg(CHILD_ID_VIBRATION, V_LEVEL); void setup() { - pinMode(VIBRATION_SENSOR_DIGITAL_PIN, INPUT); - attachInterrupt(digitalPinToInterrupt(VIBRATION_SENSOR_DIGITAL_PIN), blink, FALLING); // Trigger the blink function when the falling edge is detected - pinMode(SensorLED, OUTPUT); + pinMode(VIBRATION_SENSOR_DIGITAL_PIN, INPUT); + attachInterrupt(digitalPinToInterrupt(VIBRATION_SENSOR_DIGITAL_PIN), blink, + FALLING); // Trigger the blink function when the falling edge is detected + pinMode(SensorLED, OUTPUT); } -void presentation() { - // Send the sketch version information to the gateway and Controller - sendSketchInfo("VIBRATION Sensor", "1.0"); +void presentation() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("VIBRATION Sensor", "1.0"); - // Register all sensors to gateway (they will be created as child devices) - present(CHILD_ID_VIBRATION, S_VIBRATION); + // Register all sensors to gateway (they will be created as child devices) + present(CHILD_ID_VIBRATION, S_VIBRATION); } void loop() { - if(state>=40){ // basically below 40 so ignire basic level - send(vibrationMsg.set(int16_t(state))); - state = 0; - digitalWrite(SensorLED,HIGH); - } else { - state = 0; - digitalWrite(SensorLED,LOW); - } + if(state>=40) { // basically below 40 so ignire basic level + send(vibrationMsg.set(int16_t(state))); + state = 0; + digitalWrite(SensorLED,HIGH); + } else { + state = 0; + digitalWrite(SensorLED,LOW); + } - // Power down the radio. Note that the radio will get powered back up - // on the next write() call. - delay(1000); //delay to allow serial to fully print before sleep + // Power down the radio. Note that the radio will get powered back up + // on the next write() call. + delay(1000); //delay to allow serial to fully print before sleep - sleep(SLEEP_TIME); //sleep for: sleepTime + sleep(SLEEP_TIME); //sleep for: sleepTime } void blink()//Interrupts function { - state++; + state++; } diff --git a/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino b/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino index 2a07105..fbf99e0 100644 --- a/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino +++ b/examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino @@ -21,27 +21,27 @@ * REVISION HISTORY * Version 1.0 - Henrik Ekblad * Version 1.1 - GizMoCuz - * + * * DESCRIPTION * Use this sensor to measure volume and flow of your house watermeter. * You need to set the correct pulsefactor of your meter (pulses per m3). * The sensor starts by fetching current volume reading from gateway (VAR 1). * Reports both volume and flow back to gateway. * - * Unfortunately millis() won't increment when the Arduino is in - * sleepmode. So we cannot make this sensor sleep if we also want + * Unfortunately millis() won't increment when the Arduino is in + * sleepmode. So we cannot make this sensor sleep if we also want * to calculate/report flow. * http://www.mysensors.org/build/pulse_water */ // Enable debug prints to serial monitor -#define MY_DEBUG +#define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 -#include +#include #define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your sensor. (Only 2 and 3 generates interrupt!) @@ -53,7 +53,8 @@ #define CHILD_ID 1 // Id of the sensor child -unsigned long SEND_FREQUENCY = 30000; // Minimum time between send (in milliseconds). We don't want to spam the gateway. +unsigned long SEND_FREQUENCY = + 30000; // Minimum time between send (in milliseconds). We don't want to spam the gateway. MyMessage flowMsg(CHILD_ID,V_FLOW); MyMessage volumeMsg(CHILD_ID,V_VOLUME); @@ -61,127 +62,126 @@ MyMessage lastCounterMsg(CHILD_ID,V_VAR1); double ppl = ((double)PULSE_FACTOR)/1000; // Pulses per liter -volatile unsigned long pulseCount = 0; +volatile unsigned long pulseCount = 0; volatile unsigned long lastBlink = 0; -volatile double flow = 0; +volatile double flow = 0; bool pcReceived = false; unsigned long oldPulseCount = 0; -unsigned long newBlink = 0; +unsigned long newBlink = 0; double oldflow = 0; -double volume =0; +double volume =0; double oldvolume =0; unsigned long lastSend =0; unsigned long lastPulse =0; -void setup() -{ - // initialize our digital pins internal pullup resistor so one pulse switches from high to low (less distortion) - pinMode(DIGITAL_INPUT_SENSOR, INPUT_PULLUP); - - pulseCount = oldPulseCount = 0; - - // Fetch last known pulse count value from gw - request(CHILD_ID, V_VAR1); - - lastSend = lastPulse = millis(); - - attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), onPulse, FALLING); -} - -void presentation() { - // Send the sketch version information to the gateway and Controller - sendSketchInfo("Water Meter", "1.1"); - - // Register this device as Waterflow sensor - present(CHILD_ID, S_WATER); -} - -void loop() -{ - unsigned long currentTime = millis(); - - // Only send values at a maximum frequency or woken up from sleep - if (SLEEP_MODE || (currentTime - lastSend > SEND_FREQUENCY)) - { - lastSend=currentTime; - - if (!pcReceived) { - //Last Pulsecount not yet received from controller, request it again - request(CHILD_ID, V_VAR1); - return; - } - - if (!SLEEP_MODE && flow != oldflow) { - oldflow = flow; - - Serial.print("l/min:"); - Serial.println(flow); - - // Check that we dont get unresonable large flow value. - // could hapen when long wraps or false interrupt triggered - if (flow<((unsigned long)MAX_FLOW)) { - send(flowMsg.set(flow, 2)); // Send flow value to gw - } - } - - // No Pulse count received in 2min - if(currentTime - lastPulse > 120000){ - flow = 0; - } - - // Pulse count has changed - if ((pulseCount != oldPulseCount)||(!SLEEP_MODE)) { - oldPulseCount = pulseCount; - - Serial.print("pulsecount:"); - Serial.println(pulseCount); - - send(lastCounterMsg.set(pulseCount)); // Send pulsecount value to gw in VAR1 - - double volume = ((double)pulseCount/((double)PULSE_FACTOR)); - if ((volume != oldvolume)||(!SLEEP_MODE)) { - oldvolume = volume; - - Serial.print("volume:"); - Serial.println(volume, 3); - - send(volumeMsg.set(volume, 3)); // Send volume value to gw - } - } - } - if (SLEEP_MODE) { - sleep(SEND_FREQUENCY); - } -} - -void receive(const MyMessage &message) { - if (message.type==V_VAR1) { - unsigned long gwPulseCount=message.getULong(); - pulseCount += gwPulseCount; - flow=oldflow=0; - Serial.print("Received last pulse count from gw:"); - Serial.println(pulseCount); - pcReceived = true; - } -} - -void onPulse() +void setup() { - if (!SLEEP_MODE) - { - unsigned long newBlink = micros(); - unsigned long interval = newBlink-lastBlink; - - if (interval!=0) - { - lastPulse = millis(); - if (interval<500000L) { - // Sometimes we get interrupt on RISING, 500000 = 0.5sek debounce ( max 120 l/min) - return; - } - flow = (60000000.0 /interval) / ppl; - } - lastBlink = newBlink; - } - pulseCount++; + // initialize our digital pins internal pullup resistor so one pulse switches from high to low (less distortion) + pinMode(DIGITAL_INPUT_SENSOR, INPUT_PULLUP); + + pulseCount = oldPulseCount = 0; + + // Fetch last known pulse count value from gw + request(CHILD_ID, V_VAR1); + + lastSend = lastPulse = millis(); + + attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), onPulse, FALLING); +} + +void presentation() +{ + // Send the sketch version information to the gateway and Controller + sendSketchInfo("Water Meter", "1.1"); + + // Register this device as Waterflow sensor + present(CHILD_ID, S_WATER); +} + +void loop() +{ + unsigned long currentTime = millis(); + + // Only send values at a maximum frequency or woken up from sleep + if (SLEEP_MODE || (currentTime - lastSend > SEND_FREQUENCY)) { + lastSend=currentTime; + + if (!pcReceived) { + //Last Pulsecount not yet received from controller, request it again + request(CHILD_ID, V_VAR1); + return; + } + + if (!SLEEP_MODE && flow != oldflow) { + oldflow = flow; + + Serial.print("l/min:"); + Serial.println(flow); + + // Check that we dont get unresonable large flow value. + // could hapen when long wraps or false interrupt triggered + if (flow<((unsigned long)MAX_FLOW)) { + send(flowMsg.set(flow, 2)); // Send flow value to gw + } + } + + // No Pulse count received in 2min + if(currentTime - lastPulse > 120000) { + flow = 0; + } + + // Pulse count has changed + if ((pulseCount != oldPulseCount)||(!SLEEP_MODE)) { + oldPulseCount = pulseCount; + + Serial.print("pulsecount:"); + Serial.println(pulseCount); + + send(lastCounterMsg.set(pulseCount)); // Send pulsecount value to gw in VAR1 + + double volume = ((double)pulseCount/((double)PULSE_FACTOR)); + if ((volume != oldvolume)||(!SLEEP_MODE)) { + oldvolume = volume; + + Serial.print("volume:"); + Serial.println(volume, 3); + + send(volumeMsg.set(volume, 3)); // Send volume value to gw + } + } + } + if (SLEEP_MODE) { + sleep(SEND_FREQUENCY); + } +} + +void receive(const MyMessage &message) +{ + if (message.type==V_VAR1) { + unsigned long gwPulseCount=message.getULong(); + pulseCount += gwPulseCount; + flow=oldflow=0; + Serial.print("Received last pulse count from gw:"); + Serial.println(pulseCount); + pcReceived = true; + } +} + +void onPulse() +{ + if (!SLEEP_MODE) { + unsigned long newBlink = micros(); + unsigned long interval = newBlink-lastBlink; + + if (interval!=0) { + lastPulse = millis(); + if (interval<500000L) { + // Sometimes we get interrupt on RISING, 500000 = 0.5sek debounce ( max 120 l/min) + return; + } + flow = (60000000.0 /interval) / ppl; + } + lastBlink = newBlink; + } + pulseCount++; } diff --git a/examples_linux/mysgw.cpp b/examples_linux/mysgw.cpp index 7ada2f0..9812c4f 100644 --- a/examples_linux/mysgw.cpp +++ b/examples_linux/mysgw.cpp @@ -16,7 +16,7 @@ * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. */ - + #include #include #include @@ -78,14 +78,17 @@ #undef ARDUINO -void setup() { +void setup() +{ // Setup locally attached sensors } -void presentation() { - // Present locally attached sensors here +void presentation() +{ + // Present locally attached sensors here } -void loop() { +void loop() +{ // Send locally attached sensors data here } diff --git a/projects/SublimeText/MySensors.sublime-project b/projects/SublimeText/MySensors.sublime-project index 8b2d268..6817c1e 100644 --- a/projects/SublimeText/MySensors.sublime-project +++ b/projects/SublimeText/MySensors.sublime-project @@ -28,11 +28,11 @@ // The coding style is documented here: https://www.mysensors.org/download/contributing "AStyleFormatter": { - "debug": true, - "autoformat_on_save": false, + "debug": false, + "autoformat_on_save": true, "options_c": { - "additional_options_file": "$project_path/../../.astylerc", + "additional_options_file": "$project_path/../../.tools/astyle/config/style.cfg", "use_only_additional_options": true }, "options_c++": diff --git a/tests/Arduino/sketches/serial_gateway_no_transport_full_debug/serial_gateway_no_transport_full_debug.ino b/tests/Arduino/sketches/serial_gateway_no_transport_full_debug/serial_gateway_no_transport_full_debug.ino index 4db3a70..dcc685f 100644 --- a/tests/Arduino/sketches/serial_gateway_no_transport_full_debug/serial_gateway_no_transport_full_debug.ino +++ b/tests/Arduino/sketches/serial_gateway_no_transport_full_debug/serial_gateway_no_transport_full_debug.ino @@ -18,7 +18,7 @@ * ******************************* */ - + #define MY_DEBUG #define MY_GATEWAY_SERIAL #include \ No newline at end of file