Repo restyled using astyle (#683)

The rules are in .tools/astyle/config/style.cfg
and can also be reviewed at
https://www.mysensors.org/view/260#coding-guidelines-core-library
This commit is contained in:
Patrick Fallberg
2016-12-07 23:44:29 +01:00
committed by GitHub
parent d4c4ab82ea
commit 8e1ef13804
167 changed files with 16103 additions and 15168 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ max-code-length=100
break-after-logical break-after-logical
# Preprocessor blocks should be indented # Preprocessor blocks should be indented
indent-preproc-block #indent-preproc-block
# Preprocessor definitions should be indented if linebroken # Preprocessor definitions should be indented if linebroken
indent-preproc-define indent-preproc-define
+91 -91
View File
@@ -67,10 +67,10 @@
#ifndef MY_BAUD_RATE #ifndef MY_BAUD_RATE
#define MY_BAUD_RATE 115200 #define MY_BAUD_RATE 115200
#endif #endif
/** /**
* @def MY_SERIAL_OUTPUT_SIZE * @def MY_SERIAL_OUTPUT_SIZE
* @brief Max. characters for serial output. * @brief Max. characters for serial output.
*/ */
#ifndef MY_SERIAL_OUTPUT_SIZE #ifndef MY_SERIAL_OUTPUT_SIZE
#define MY_SERIAL_OUTPUT_SIZE (120u) #define MY_SERIAL_OUTPUT_SIZE (120u)
#endif #endif
@@ -145,34 +145,34 @@
*/ */
#define MY_REGISTRATION_FEATURE #define MY_REGISTRATION_FEATURE
/** /**
* @def MY_REGISTRATION_RETRIES * @def MY_REGISTRATION_RETRIES
* @brief Number of registration retries if no reply received from GW/controller * @brief Number of registration retries if no reply received from GW/controller
*/ */
#ifndef MY_REGISTRATION_RETRIES #ifndef MY_REGISTRATION_RETRIES
#define MY_REGISTRATION_RETRIES (3u) #define MY_REGISTRATION_RETRIES (3u)
#endif #endif
/** /**
* @def MY_REGISTRATION_DEFAULT * @def MY_REGISTRATION_DEFAULT
* @brief Node registration default - this applies if no registration response is received from controller * @brief Node registration default - this applies if no registration response is received from controller
*/ */
#define MY_REGISTRATION_DEFAULT true #define MY_REGISTRATION_DEFAULT true
/** /**
* @def MY_REGISTRATION_CONTROLLER * @def MY_REGISTRATION_CONTROLLER
* @brief If enabled, node registration request has to be handled by controller * @brief If enabled, node registration request has to be handled by controller
*/ */
// #define MY_REGISTRATION_CONTROLLER // #define MY_REGISTRATION_CONTROLLER
/** /**
* @def MY_CORE_COMPATIBILITY_CHECK * @def MY_CORE_COMPATIBILITY_CHECK
* @brief If enabled, library compatibility is checked during node registration. Incompatible libraries are unable to send sensor data. * @brief If enabled, library compatibility is checked during node registration. Incompatible libraries are unable to send sensor data.
*/ */
#define MY_CORE_COMPATIBILITY_CHECK #define MY_CORE_COMPATIBILITY_CHECK
/** /**
* @def MY_TRANSPORT_WAIT_READY_MS * @def MY_TRANSPORT_WAIT_READY_MS
* @brief Timeout in MS until transport is ready during startup, set to 0 for no timeout * @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. * @brief The default input pin used for the inclusion mode button.
*/ */
#ifndef MY_INCLUSION_MODE_BUTTON_PIN #ifndef MY_INCLUSION_MODE_BUTTON_PIN
#if defined(ARDUINO_ARCH_ESP8266) #if defined(ARDUINO_ARCH_ESP8266)
#define MY_INCLUSION_MODE_BUTTON_PIN 5 #define MY_INCLUSION_MODE_BUTTON_PIN 5
#else #else
#define MY_INCLUSION_MODE_BUTTON_PIN 3 #define MY_INCLUSION_MODE_BUTTON_PIN 3
#endif #endif
#endif #endif
/** /**
@@ -488,15 +488,15 @@
* @brief Default RF24 chip enable pin setting. Override in sketch if needed. * @brief Default RF24 chip enable pin setting. Override in sketch if needed.
*/ */
#ifndef MY_RF24_CE_PIN #ifndef MY_RF24_CE_PIN
#if defined(ARDUINO_ARCH_ESP8266) #if defined(ARDUINO_ARCH_ESP8266)
#define MY_RF24_CE_PIN 4 #define MY_RF24_CE_PIN 4
#elif defined(ARDUINO_ARCH_SAMD) #elif defined(ARDUINO_ARCH_SAMD)
#define MY_RF24_CE_PIN 27 #define MY_RF24_CE_PIN 27
#elif defined(LINUX_ARCH_RASPBERRYPI) #elif defined(LINUX_ARCH_RASPBERRYPI)
#define MY_RF24_CE_PIN 22 #define MY_RF24_CE_PIN 22
#else #else
#define MY_RF24_CE_PIN 9 #define MY_RF24_CE_PIN 9
#endif #endif
#endif #endif
/** /**
@@ -504,15 +504,15 @@
* @brief Default RF24 chip select pin setting. Override in sketch if needed. * @brief Default RF24 chip select pin setting. Override in sketch if needed.
*/ */
#ifndef MY_RF24_CS_PIN #ifndef MY_RF24_CS_PIN
#if defined(ARDUINO_ARCH_ESP8266) #if defined(ARDUINO_ARCH_ESP8266)
#define MY_RF24_CS_PIN 15 #define MY_RF24_CS_PIN 15
#elif defined(ARDUINO_ARCH_SAMD) #elif defined(ARDUINO_ARCH_SAMD)
#define MY_RF24_CS_PIN 3 #define MY_RF24_CS_PIN 3
#elif defined(LINUX_ARCH_RASPBERRYPI) #elif defined(LINUX_ARCH_RASPBERRYPI)
#define MY_RF24_CS_PIN 24 #define MY_RF24_CS_PIN 24
#else #else
#define MY_RF24_CS_PIN 10 #define MY_RF24_CS_PIN 10
#endif #endif
#endif #endif
/** /**
@@ -528,9 +528,9 @@
* @brief Declare the amount of incoming messages that can be buffered. * @brief Declare the amount of incoming messages that can be buffered.
*/ */
#ifdef MY_RX_MESSAGE_BUFFER_FEATURE #ifdef MY_RX_MESSAGE_BUFFER_FEATURE
#ifndef MY_RX_MESSAGE_BUFFER_SIZE #ifndef MY_RX_MESSAGE_BUFFER_SIZE
#define MY_RX_MESSAGE_BUFFER_SIZE (20) #define MY_RX_MESSAGE_BUFFER_SIZE (20)
#endif #endif
#endif #endif
/** /**
@@ -639,9 +639,9 @@
* @brief Set to true if @ref MY_IS_RFM69HW is set. * @brief Set to true if @ref MY_IS_RFM69HW is set.
*/ */
#ifdef MY_IS_RFM69HW #ifdef MY_IS_RFM69HW
#define MY_RFM69HW true #define MY_RFM69HW true
#else #else
#define MY_RFM69HW false #define MY_RFM69HW false
#endif #endif
/** /**
@@ -673,11 +673,11 @@
* @brief RF69 IRQ pin number. * @brief RF69 IRQ pin number.
*/ */
#ifndef MY_RF69_IRQ_NUM #ifndef MY_RF69_IRQ_NUM
#if defined(ARDUINO_ARCH_ESP8266) #if defined(ARDUINO_ARCH_ESP8266)
#define MY_RF69_IRQ_NUM RF69_IRQ_PIN #define MY_RF69_IRQ_NUM RF69_IRQ_PIN
#else #else
#define MY_RF69_IRQ_NUM RF69_IRQ_NUM #define MY_RF69_IRQ_NUM RF69_IRQ_NUM
#endif #endif
#endif #endif
// Enables RFM69 encryption (all nodes and gateway must have this enabled, and all must be personalized with the same AES key) // 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. * This must match the hardware version of the RFM95 radio.
*/ */
#ifndef MY_RFM95_FREQUENCY #ifndef MY_RFM95_FREQUENCY
#define MY_RFM95_FREQUENCY (868.1f) #define MY_RFM95_FREQUENCY (868.1f)
#endif #endif
/** /**
* @def MY_RFM95_MODEM_CONFIGRUATION * @def MY_RFM95_MODEM_CONFIGRUATION
* @brief RFM95 modem configuration, see table * @brief RFM95 modem configuration, see table
* *
* BW = Bandwidth in kHz * BW = Bandwidth in kHz
* CR = Error correction code * CR = Error correction code
* SF = Spreading factor, chips / symbol * SF = Spreading factor, chips / symbol
* *
* | CONFIG | BW | CR | SF | Comment * | CONFIG | BW | CR | SF | Comment
* |------------------------|-------|-----|------|----------------------------- * |------------------------|-------|-----|------|-----------------------------
* | RFM95_BW125CR45SF128 | 125 | 4/5 | 128 | Default, medium range * | RFM95_BW125CR45SF128 | 125 | 4/5 | 128 | Default, medium range
* | RFM95_BW500CR45SF128 | 500 | 4/5 | 128 | Fast, short range * | RFM95_BW500CR45SF128 | 500 | 4/5 | 128 | Fast, short range
* | RFM95_BW31_25CR48SF512 | 31.25 | 4/8 | 512 | Slow, long range * | RFM95_BW31_25CR48SF512 | 31.25 | 4/8 | 512 | Slow, long range
* | RFM95_BW125CR48SF4096 | 125 | 4/8 | 4096 | Slow, long range * | RFM95_BW125CR48SF4096 | 125 | 4/8 | 4096 | Slow, long range
* *
*/ */
#ifndef MY_RFM95_MODEM_CONFIGRUATION #ifndef MY_RFM95_MODEM_CONFIGRUATION
// default // default
#define MY_RFM95_MODEM_CONFIGRUATION RFM95_BW125CR45SF128 #define MY_RFM95_MODEM_CONFIGRUATION RFM95_BW125CR45SF128
#endif #endif
/** /**
@@ -729,7 +729,7 @@
* @brief RFM95 IRQ pin * @brief RFM95 IRQ pin
*/ */
#ifndef MY_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 #endif
/** /**
@@ -737,7 +737,7 @@
* @brief RFM95 SPI chip select pin * @brief RFM95 SPI chip select pin
*/ */
#ifndef MY_RFM95_SPI_CS #ifndef MY_RFM95_SPI_CS
#define MY_RFM95_SPI_CS RFM95_SPI_CS #define MY_RFM95_SPI_CS RFM95_SPI_CS
#endif #endif
/** /**
@@ -745,21 +745,21 @@
* @brief RFM95 TX power level. * @brief RFM95 TX power level.
*/ */
#ifndef MY_RFM95_TX_POWER #ifndef MY_RFM95_TX_POWER
#define MY_RFM95_TX_POWER 13 #define MY_RFM95_TX_POWER 13
#endif #endif
/** /**
* @def MY_RFM95_ATC_MODE_DISABLED * @def MY_RFM95_ATC_MODE_DISABLED
* @brief Enable to disable ATC mode * @brief Enable to disable ATC mode
*/ */
//#define MY_RFM95_ATC_MODE_DISABLED //#define MY_RFM95_ATC_MODE_DISABLED
/** /**
* @def MY_RFM95_ATC_TARGET_RSSI * @def MY_RFM95_ATC_TARGET_RSSI
* @brief Traget RSSI level for ATC mode * @brief Traget RSSI level for ATC mode
*/ */
#ifndef MY_RFM95_ATC_TARGET_RSSI #ifndef MY_RFM95_ATC_TARGET_RSSI
#define MY_RFM95_ATC_TARGET_RSSI (-60) #define MY_RFM95_ATC_TARGET_RSSI (-60)
#endif #endif
@@ -779,11 +779,11 @@
* @brief The Ethernet TCP/UDP port to open on controller or gateway. * @brief The Ethernet TCP/UDP port to open on controller or gateway.
*/ */
#ifndef MY_PORT #ifndef MY_PORT
#ifdef MY_GATEWAY_MQTT_CLIENT #ifdef MY_GATEWAY_MQTT_CLIENT
#define MY_PORT 1883 #define MY_PORT 1883
#else #else
#define MY_PORT 5003 #define MY_PORT 5003
#endif #endif
#endif #endif
// Static ip address of gateway (if this is disabled, DHCP will be used) // Static ip address of gateway (if this is disabled, DHCP will be used)
+189 -189
View File
@@ -41,60 +41,60 @@
* @brief Contain a string describing the class of sketch/node (gateway/repeater/sensor). * @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) #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_GATEWAY_FEATURE
#define MY_IS_GATEWAY (true) #define MY_IS_GATEWAY (true)
#define MY_NODE_TYPE "GW" #define MY_NODE_TYPE "GW"
#elif defined(MY_REPEATER_FEATURE) #elif defined(MY_REPEATER_FEATURE)
#define MY_IS_GATEWAY (false) #define MY_IS_GATEWAY (false)
#define MY_NODE_TYPE "REPEATER" #define MY_NODE_TYPE "REPEATER"
#else #else
#define MY_IS_GATEWAY (false) #define MY_IS_GATEWAY (false)
#define MY_NODE_TYPE "NODE" #define MY_NODE_TYPE "NODE"
#endif #endif
// Enable radio "feature" if one of the radio types was enabled // 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) #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 #endif
// HARDWARE // HARDWARE
#if defined(ARDUINO_ARCH_ESP8266) #if defined(ARDUINO_ARCH_ESP8266)
// Remove PSTR macros from debug prints // Remove PSTR macros from debug prints
#undef PSTR #undef PSTR
#define PSTR(x) (x) #define PSTR(x) (x)
//#undef F //#undef F
//#define F(x) (x) //#define F(x) (x)
#include "core/MyHwESP8266.cpp" #include "core/MyHwESP8266.cpp"
#elif defined(ARDUINO_ARCH_AVR) #elif defined(ARDUINO_ARCH_AVR)
#include "drivers/AVR/DigitalWriteFast/digitalWriteFast.h" #include "drivers/AVR/DigitalWriteFast/digitalWriteFast.h"
#include "core/MyHwATMega328.cpp" #include "core/MyHwATMega328.cpp"
#elif defined(ARDUINO_ARCH_SAMD) #elif defined(ARDUINO_ARCH_SAMD)
#include "core/MyHwSAMD.cpp" #include "core/MyHwSAMD.cpp"
#elif defined(__linux__) #elif defined(__linux__)
#ifdef LINUX_ARCH_RASPBERRYPI #ifdef LINUX_ARCH_RASPBERRYPI
#include "core/MyHwRPi.cpp" #include "core/MyHwRPi.cpp"
#else #else
#include "core/MyHwLinuxGeneric.cpp" #include "core/MyHwLinuxGeneric.cpp"
#endif #endif
#endif #endif
// LEDS // LEDS
#if !defined(MY_DEFAULT_ERR_LED_PIN) && defined(MY_HW_ERR_LED_PIN) #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 #endif
#if !defined(MY_DEFAULT_TX_LED_PIN) && defined(MY_HW_TX_LED_PIN) #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 #endif
#if !defined(MY_DEFAULT_RX_LED_PIN) && defined(MY_HW_TX_LED_PIN) #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 #endif
#if defined(MY_LEDS_BLINKING_FEATURE) #if defined(MY_LEDS_BLINKING_FEATURE)
#error MY_LEDS_BLINKING_FEATURE is now removed from MySensors core,\ #error MY_LEDS_BLINKING_FEATURE is now removed from MySensors core,\
define MY_DEFAULT_ERR_LED_PIN, MY_DEFAULT_TX_LED_PIN or\ define MY_DEFAULT_ERR_LED_PIN, MY_DEFAULT_TX_LED_PIN or\
MY_DEFAULT_RX_LED_PIN in your sketch instead to enable LEDs MY_DEFAULT_RX_LED_PIN in your sketch instead to enable LEDs
#endif #endif
/** /**
@@ -106,9 +106,9 @@
#endif #endif
#if defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) #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 #else
#include "core/MyLeds.h" #include "core/MyLeds.h"
#endif #endif
#include "core/MyIndication.cpp" #include "core/MyIndication.cpp"
@@ -116,221 +116,221 @@
// INCLUSION MODE // INCLUSION MODE
#if defined(MY_INCLUSION_MODE_FEATURE) #if defined(MY_INCLUSION_MODE_FEATURE)
#include "core/MyInclusionMode.cpp" #include "core/MyInclusionMode.cpp"
#endif #endif
// SIGNING // SIGNING
#if defined(MY_SIGNING_ATSHA204) || defined(MY_SIGNING_SOFT) #if defined(MY_SIGNING_ATSHA204) || defined(MY_SIGNING_SOFT)
#define MY_SIGNING_FEATURE #define MY_SIGNING_FEATURE
#endif #endif
#include "core/MySigning.cpp" #include "core/MySigning.cpp"
#include "drivers/ATSHA204/sha256.cpp" #include "drivers/ATSHA204/sha256.cpp"
#if defined(MY_SIGNING_FEATURE) #if defined(MY_SIGNING_FEATURE)
// SIGNING COMMON FUNCTIONS // SIGNING COMMON FUNCTIONS
#if defined(MY_SIGNING_ATSHA204) && defined(MY_SIGNING_SOFT) #if defined(MY_SIGNING_ATSHA204) && defined(MY_SIGNING_SOFT)
#error Only one signing engine can be activated #error Only one signing engine can be activated
#endif #endif
#if defined(MY_SIGNING_ATSHA204) && defined(__linux__) #if defined(MY_SIGNING_ATSHA204) && defined(__linux__)
#error No support for ATSHA204 on this platform #error No support for ATSHA204 on this platform
#endif #endif
#if defined(MY_SIGNING_ATSHA204) #if defined(MY_SIGNING_ATSHA204)
#include "core/MySigningAtsha204.cpp" #include "core/MySigningAtsha204.cpp"
#include "drivers/ATSHA204/ATSHA204.cpp" #include "drivers/ATSHA204/ATSHA204.cpp"
#elif defined(MY_SIGNING_SOFT) #elif defined(MY_SIGNING_SOFT)
#include "core/MySigningAtsha204Soft.cpp" #include "core/MySigningAtsha204Soft.cpp"
#endif #endif
#endif #endif
// FLASH // FLASH
#if defined(MY_OTA_FIRMWARE_FEATURE) #if defined(MY_OTA_FIRMWARE_FEATURE)
#include "drivers/SPIFlash/SPIFlash.cpp" #include "drivers/SPIFlash/SPIFlash.cpp"
#include "core/MyOTAFirmwareUpdate.cpp" #include "core/MyOTAFirmwareUpdate.cpp"
#endif #endif
// GATEWAY - TRANSPORT // GATEWAY - TRANSPORT
#if defined(MY_CONTROLLER_IP_ADDRESS) || defined(MY_CONTROLLER_URL_ADDRESS) #if defined(MY_CONTROLLER_IP_ADDRESS) || defined(MY_CONTROLLER_URL_ADDRESS)
#define MY_GATEWAY_CLIENT_MODE #define MY_GATEWAY_CLIENT_MODE
#endif #endif
#if defined(MY_USE_UDP) && !defined(MY_GATEWAY_CLIENT_MODE) #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 #endif
#if defined(MY_GATEWAY_MQTT_CLIENT) #if defined(MY_GATEWAY_MQTT_CLIENT)
#if defined(MY_SENSOR_NETWORK) #if defined(MY_SENSOR_NETWORK)
// We assume that a gateway having a radio also should act as repeater // We assume that a gateway having a radio also should act as repeater
#define MY_REPEATER_FEATURE #define MY_REPEATER_FEATURE
#endif #endif
// GATEWAY - COMMON FUNCTIONS // GATEWAY - COMMON FUNCTIONS
// We support MQTT Client using W5100, ESP8266 and Linux // We support MQTT Client using W5100, ESP8266 and Linux
#if !defined(MY_GATEWAY_CLIENT_MODE) #if !defined(MY_GATEWAY_CLIENT_MODE)
#error You must specify MY_CONTROLLER_IP_ADDRESS or MY_CONTROLLER_URL_ADDRESS #error You must specify MY_CONTROLLER_IP_ADDRESS or MY_CONTROLLER_URL_ADDRESS
#endif #endif
#if !defined(MY_MQTT_PUBLISH_TOPIC_PREFIX) #if !defined(MY_MQTT_PUBLISH_TOPIC_PREFIX)
#error You must specify a topic publish prefix MY_MQTT_PUBLISH_TOPIC_PREFIX for this MQTT client #error You must specify a topic publish prefix MY_MQTT_PUBLISH_TOPIC_PREFIX for this MQTT client
#endif #endif
#if !defined(MY_MQTT_SUBSCRIBE_TOPIC_PREFIX) #if !defined(MY_MQTT_SUBSCRIBE_TOPIC_PREFIX)
#error You must specify a topic subscribe prefix MY_MQTT_SUBSCRIBE_TOPIC_PREFIX for this MQTT client #error You must specify a topic subscribe prefix MY_MQTT_SUBSCRIBE_TOPIC_PREFIX for this MQTT client
#endif #endif
#if !defined(MY_MQTT_CLIENT_ID) #if !defined(MY_MQTT_CLIENT_ID)
#error You must define a unique MY_MQTT_CLIENT_ID for this MQTT client #error You must define a unique MY_MQTT_CLIENT_ID for this MQTT client
#endif #endif
#include "core/MyGatewayTransport.cpp" #include "core/MyGatewayTransport.cpp"
#include "core/MyProtocolMySensors.cpp" #include "core/MyProtocolMySensors.cpp"
#if defined(MY_GATEWAY_LINUX) #if defined(MY_GATEWAY_LINUX)
#include "drivers/Linux/EthernetClient.h" #include "drivers/Linux/EthernetClient.h"
#include "drivers/Linux/EthernetServer.h" #include "drivers/Linux/EthernetServer.h"
#include "drivers/Linux/IPAddress.h" #include "drivers/Linux/IPAddress.h"
#endif #endif
#include "drivers/PubSubClient/PubSubClient.cpp" #include "drivers/PubSubClient/PubSubClient.cpp"
#include "core/MyGatewayTransportMQTTClient.cpp" #include "core/MyGatewayTransportMQTTClient.cpp"
#elif defined(MY_GATEWAY_FEATURE) #elif defined(MY_GATEWAY_FEATURE)
// GATEWAY - COMMON FUNCTIONS // GATEWAY - COMMON FUNCTIONS
#include "core/MyGatewayTransport.cpp" #include "core/MyGatewayTransport.cpp"
#include "core/MyProtocolMySensors.cpp" #include "core/MyProtocolMySensors.cpp"
// GATEWAY - CONFIGURATION // GATEWAY - CONFIGURATION
#if defined(MY_SENSOR_NETWORK) #if defined(MY_SENSOR_NETWORK)
// We assume that a gateway having a radio also should act as repeater // We assume that a gateway having a radio also should act as repeater
#define MY_REPEATER_FEATURE #define MY_REPEATER_FEATURE
#endif #endif
#if !defined(MY_PORT) #if !defined(MY_PORT)
#error You must define MY_PORT (controller or gatway port to open) #error You must define MY_PORT (controller or gatway port to open)
#endif #endif
#if defined(MY_GATEWAY_ESP8266) #if defined(MY_GATEWAY_ESP8266)
// GATEWAY - ESP8266 // GATEWAY - ESP8266
#include "core/MyGatewayTransportEthernet.cpp" #include "core/MyGatewayTransportEthernet.cpp"
#elif defined(MY_GATEWAY_LINUX) #elif defined(MY_GATEWAY_LINUX)
// GATEWAY - Generic Linux // GATEWAY - Generic Linux
#include "drivers/Linux/EthernetClient.h" #include "drivers/Linux/EthernetClient.h"
#include "drivers/Linux/EthernetServer.h" #include "drivers/Linux/EthernetServer.h"
#include "drivers/Linux/IPAddress.h" #include "drivers/Linux/IPAddress.h"
#include "core/MyGatewayTransportEthernet.cpp" #include "core/MyGatewayTransportEthernet.cpp"
#elif defined(MY_GATEWAY_W5100) #elif defined(MY_GATEWAY_W5100)
// GATEWAY - W5100 // GATEWAY - W5100
#include "core/MyGatewayTransportEthernet.cpp" #include "core/MyGatewayTransportEthernet.cpp"
#elif defined(MY_GATEWAY_ENC28J60) #elif defined(MY_GATEWAY_ENC28J60)
// GATEWAY - ENC28J60 // GATEWAY - ENC28J60
#if defined(MY_USE_UDP) #if defined(MY_USE_UDP)
#error UDP mode is not available for ENC28J60 #error UDP mode is not available for ENC28J60
#endif #endif
#include "core/MyGatewayTransportEthernet.cpp" #include "core/MyGatewayTransportEthernet.cpp"
#elif defined(MY_GATEWAY_SERIAL) #elif defined(MY_GATEWAY_SERIAL)
// GATEWAY - SERIAL // GATEWAY - SERIAL
#include "core/MyGatewayTransportSerial.cpp" #include "core/MyGatewayTransportSerial.cpp"
#endif #endif
#endif #endif
// RAM ROUTING TABLE // RAM ROUTING TABLE
#if defined(MY_RAM_ROUTING_TABLE_FEATURE) && defined(MY_REPEATER_FEATURE) #if defined(MY_RAM_ROUTING_TABLE_FEATURE) && defined(MY_REPEATER_FEATURE)
// activate feature based on architecture // activate feature based on architecture
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_SAMD) || defined(LINUX_ARCH_RASPBERRYPI) #if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_SAMD) || defined(LINUX_ARCH_RASPBERRYPI)
#define MY_RAM_ROUTING_TABLE_ENABLED #define MY_RAM_ROUTING_TABLE_ENABLED
#elif defined(ARDUINO_ARCH_AVR) #elif defined(ARDUINO_ARCH_AVR)
// memory limited, enable with care // memory limited, enable with care
// #define MY_RAM_ROUTING_TABLE_ENABLED // #define MY_RAM_ROUTING_TABLE_ENABLED
#endif #endif
#endif #endif
#if defined(MY_TRANSPORT_DONT_CARE_MODE) #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 #endif
// RADIO // RADIO
#if defined(MY_RADIO_NRF24) || defined(MY_RADIO_RFM69) || defined(MY_RADIO_RFM95) ||defined(MY_RS485) #if defined(MY_RADIO_NRF24) || defined(MY_RADIO_RFM69) || defined(MY_RADIO_RFM95) ||defined(MY_RS485)
// SOFTSPI // SOFTSPI
#ifdef MY_SOFTSPI #ifdef MY_SOFTSPI
#if defined(ARDUINO_ARCH_ESP8266) #if defined(ARDUINO_ARCH_ESP8266)
#error Soft SPI is not available on ESP8266 #error Soft SPI is not available on ESP8266
#endif #endif
#include "drivers/AVR/DigitalIO/DigitalIO.h" #include "drivers/AVR/DigitalIO/DigitalIO.h"
#endif #endif
#if defined(MY_RADIO_NRF24) && defined(__linux__) && !defined(LINUX_ARCH_RASPBERRYPI) #if defined(MY_RADIO_NRF24) && defined(__linux__) && !defined(LINUX_ARCH_RASPBERRYPI)
#error No support for nRF24 radio on this platform #error No support for nRF24 radio on this platform
#endif #endif
#include "core/MyTransport.cpp" #include "core/MyTransport.cpp"
// count enabled transports // count enabled transports
#if defined(MY_RADIO_NRF24) #if defined(MY_RADIO_NRF24)
#define __RF24CNT 1 #define __RF24CNT 1
#else #else
#define __RF24CNT 0 #define __RF24CNT 0
#endif #endif
#if defined(MY_RADIO_RFM69) #if defined(MY_RADIO_RFM69)
#define __RFM69CNT 1 #define __RFM69CNT 1
#else #else
#define __RFM69CNT 0 #define __RFM69CNT 0
#endif #endif
#if defined(MY_RADIO_RFM95) #if defined(MY_RADIO_RFM95)
#define __RFM95CNT 1 #define __RFM95CNT 1
#else #else
#define __RFM95CNT 0 #define __RFM95CNT 0
#endif #endif
#if defined(MY_RS485) #if defined(MY_RS485)
#define __RS485CNT 1 #define __RS485CNT 1
#else #else
#define __RS485CNT 0 #define __RS485CNT 0
#endif #endif
#if (__RF24CNT + __RFM69CNT + __RFM95CNT + __RS485CNT > 1) #if (__RF24CNT + __RFM69CNT + __RFM95CNT + __RS485CNT > 1)
#error Only one forward link driver can be activated #error Only one forward link driver can be activated
#endif #endif
#if defined(MY_RADIO_NRF24) #if defined(MY_RADIO_NRF24)
#if defined(MY_RF24_ENABLE_ENCRYPTION) #if defined(MY_RF24_ENABLE_ENCRYPTION)
#include "drivers/AES/AES.cpp" #include "drivers/AES/AES.cpp"
#endif #endif
#include "drivers/RF24/RF24.cpp" #include "drivers/RF24/RF24.cpp"
#include "core/MyTransportNRF24.cpp" #include "core/MyTransportNRF24.cpp"
#elif defined(MY_RS485) #elif defined(MY_RS485)
#if !defined(MY_RS485_HWSERIAL) #if !defined(MY_RS485_HWSERIAL)
#if defined(__linux__) #if defined(__linux__)
#error You must specify MY_RS485_HWSERIAL for RS485 transport #error You must specify MY_RS485_HWSERIAL for RS485 transport
#endif #endif
#include "drivers/AltSoftSerial/AltSoftSerial.cpp" #include "drivers/AltSoftSerial/AltSoftSerial.cpp"
#endif #endif
#include "core/MyTransportRS485.cpp" #include "core/MyTransportRS485.cpp"
#elif defined(MY_RADIO_RFM69) #elif defined(MY_RADIO_RFM69)
#include "drivers/RFM69/RFM69.cpp" #include "drivers/RFM69/RFM69.cpp"
#include "core/MyTransportRFM69.cpp" #include "core/MyTransportRFM69.cpp"
#elif defined(MY_RADIO_RFM95) #elif defined(MY_RADIO_RFM95)
#include "drivers/RFM95/RFM95.cpp" #include "drivers/RFM95/RFM95.cpp"
#include "core/MyTransportRFM95.cpp" #include "core/MyTransportRFM95.cpp"
#endif #endif
#endif #endif
#if defined(MY_PARENT_NODE_IS_STATIC) && (MY_PARENT_NODE_ID == AUTO) #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 #endif
// Make sure to disable child features when parent feature is disabled // Make sure to disable child features when parent feature is disabled
#if !defined(MY_SENSOR_NETWORK) #if !defined(MY_SENSOR_NETWORK)
#undef MY_OTA_FIRMWARE_FEATURE #undef MY_OTA_FIRMWARE_FEATURE
#undef MY_REPEATER_FEATURE #undef MY_REPEATER_FEATURE
#undef MY_SIGNING_NODE_WHITELISTING #undef MY_SIGNING_NODE_WHITELISTING
#undef MY_SIGNING_FEATURE #undef MY_SIGNING_FEATURE
#endif #endif
#if !defined(MY_GATEWAY_FEATURE) #if !defined(MY_GATEWAY_FEATURE)
#undef MY_INCLUSION_MODE_FEATURE #undef MY_INCLUSION_MODE_FEATURE
#undef MY_INCLUSION_BUTTON_FEATURE #undef MY_INCLUSION_BUTTON_FEATURE
#endif #endif
#if !defined(MY_CORE_ONLY) #if !defined(MY_CORE_ONLY)
#if !defined(MY_GATEWAY_FEATURE) && !defined(MY_SENSOR_NETWORK) #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. #error No forward link or gateway feature activated. This means nowhere to send messages! Pretty pointless.
#endif #endif
#endif #endif
#include "core/MyCapabilities.h" #include "core/MyCapabilities.h"
@@ -340,13 +340,13 @@
#include <Arduino.h> #include <Arduino.h>
#if !defined(MY_CORE_ONLY) #if !defined(MY_CORE_ONLY)
#if defined(ARDUINO_ARCH_ESP8266) #if defined(ARDUINO_ARCH_ESP8266)
#include "core/MyMainESP8266.cpp" #include "core/MyMainESP8266.cpp"
#elif defined(__linux__) #elif defined(__linux__)
#include "core/MyMainLinux.cpp" #include "core/MyMainLinux.cpp"
#else #else
#include "core/MyMainDefault.cpp" #include "core/MyMainDefault.cpp"
#endif #endif
#endif #endif
#endif #endif
+21 -21
View File
@@ -22,60 +22,60 @@
#define MyCapabilities_h #define MyCapabilities_h
#if defined(MY_DISABLE_REMOTE_RESET) #if defined(MY_DISABLE_REMOTE_RESET)
#define MY_CAP_RESET "N" #define MY_CAP_RESET "N"
#else #else
#define MY_CAP_RESET "R" #define MY_CAP_RESET "R"
#endif #endif
#if defined(MY_OTA_FIRMWARE_FEATURE) #if defined(MY_OTA_FIRMWARE_FEATURE)
#define MY_CAP_OTA_FW "O" #define MY_CAP_OTA_FW "O"
#else #else
#define MY_CAP_OTA_FW "N" #define MY_CAP_OTA_FW "N"
#endif #endif
#if defined(MY_RADIO_NRF24) #if defined(MY_RADIO_NRF24)
#define MY_CAP_RADIO "N" #define MY_CAP_RADIO "N"
#elif defined(MY_RADIO_RFM69) #elif defined(MY_RADIO_RFM69)
#define MY_CAP_RADIO "R" #define MY_CAP_RADIO "R"
#elif defined(MY_RADIO_RFM95) #elif defined(MY_RADIO_RFM95)
#define MY_CAP_RADIO "L" #define MY_CAP_RADIO "L"
#elif defined(MY_RS485) #elif defined(MY_RS485)
#define MY_CAP_RADIO "S" #define MY_CAP_RADIO "S"
#else #else
#define MY_CAP_RADIO "-" #define MY_CAP_RADIO "-"
#endif #endif
#if defined(MY_GATEWAY_FEATURE) #if defined(MY_GATEWAY_FEATURE)
#define MY_CAP_TYPE "G" #define MY_CAP_TYPE "G"
#elif defined(MY_REPEATER_FEATURE) #elif defined(MY_REPEATER_FEATURE)
#define MY_CAP_TYPE "R" #define MY_CAP_TYPE "R"
#else #else
#define MY_CAP_TYPE "N" #define MY_CAP_TYPE "N"
#endif #endif
#if defined(ARDUINO_ARCH_SAMD) #if defined(ARDUINO_ARCH_SAMD)
#define MY_CAP_ARCH "S" #define MY_CAP_ARCH "S"
#elif defined(ARDUINO_ARCH_ESP8266) #elif defined(ARDUINO_ARCH_ESP8266)
#define MY_CAP_ARCH "E" #define MY_CAP_ARCH "E"
#elif defined(ARDUINO_ARCH_AVR) #elif defined(ARDUINO_ARCH_AVR)
#define MY_CAP_ARCH "A" #define MY_CAP_ARCH "A"
#else #else
#define MY_CAP_ARCH "-" #define MY_CAP_ARCH "-"
#endif #endif
#if defined(MY_SIGNING_ATSHA204) #if defined(MY_SIGNING_ATSHA204)
#define MY_CAP_SIGN "A" #define MY_CAP_SIGN "A"
#elif defined(MY_SIGNING_SOFT) #elif defined(MY_SIGNING_SOFT)
#define MY_CAP_SIGN "S" #define MY_CAP_SIGN "S"
#else #else
#define MY_CAP_SIGN "-" #define MY_CAP_SIGN "-"
#endif #endif
#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) #if defined(MY_RX_MESSAGE_BUFFER_FEATURE)
#define MY_CAP_RXBUF "Q" #define MY_CAP_RXBUF "Q"
#else #else
#define MY_CAP_RXBUF "-" #define MY_CAP_RXBUF "-"
#endif #endif
+9 -9
View File
@@ -17,15 +17,15 @@
* version 2 as published by the Free Software Foundation. * version 2 as published by the Free Software Foundation.
*/ */
/** /**
* @file MyEepromAddresses.h * @file MyEepromAddresses.h
* @brief Eeprom addresses for MySensors library data * @brief Eeprom addresses for MySensors library data
* *
* @defgroup MyEepromAddressesgrp MyEepromAddresses * @defgroup MyEepromAddressesgrp MyEepromAddresses
* @ingroup internals * @ingroup internals
* @{ * @{
* *
*/ */
#ifndef MyEepromAddresses_h #ifndef MyEepromAddresses_h
+8 -6
View File
@@ -25,7 +25,8 @@ extern bool transportSendRoute(MyMessage &message);
extern MyMessage _msg; extern MyMessage _msg;
extern MyMessage _msgTmp; extern MyMessage _msgTmp;
inline void gatewayTransportProcess() { inline void gatewayTransportProcess()
{
if (gatewayTransportAvailable()) { if (gatewayTransportAvailable()) {
_msg = gatewayTransportReceive(); _msg = gatewayTransportReceive();
if (_msg.destination == GATEWAY_ADDRESS) { if (_msg.destination == GATEWAY_ADDRESS) {
@@ -34,7 +35,8 @@ inline void gatewayTransportProcess() {
if (mGetRequestAck(_msg)) { if (mGetRequestAck(_msg)) {
// Copy message // Copy message
_msgTmp = _msg; _msgTmp = _msg;
mSetRequestAck(_msgTmp, false); // Reply without ack flag (otherwise we would end up in an eternal loop) mSetRequestAck(_msgTmp,
false); // Reply without ack flag (otherwise we would end up in an eternal loop)
mSetAck(_msgTmp, true); mSetAck(_msgTmp, true);
_msgTmp.sender = getNodeId(); _msgTmp.sender = getNodeId();
_msgTmp.destination = _msg.sender; _msgTmp.destination = _msg.sender;
@@ -44,11 +46,11 @@ inline void gatewayTransportProcess() {
if (_msg.type == I_VERSION) { if (_msg.type == I_VERSION) {
// Request for version. Create the response // Request for version. Create the response
gatewayTransportSend(buildGw(_msgTmp, I_VERSION).set(MYSENSORS_LIBRARY_VERSION)); 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) { } else if (_msg.type == I_INCLUSION_MODE) {
// Request to change inclusion mode // Request to change inclusion mode
inclusionModeSet(atoi(_msg.data) == 1); inclusionModeSet(atoi(_msg.data) == 1);
#endif #endif
} else { } else {
_processInternalMessages(); _processInternalMessages();
} }
@@ -59,9 +61,9 @@ inline void gatewayTransportProcess() {
} }
} }
} else { } else {
#if defined(MY_SENSOR_NETWORK) #if defined(MY_SENSOR_NETWORK)
transportSendRoute(_msg); transportSendRoute(_msg);
#endif #endif
} }
} }
} }
+95 -100
View File
@@ -19,15 +19,15 @@
#include "MyGatewayTransport.h" #include "MyGatewayTransport.h"
// global variables // global variables
extern MyMessage _msgTmp; extern MyMessage _msgTmp;
#if defined(MY_CONTROLLER_IP_ADDRESS) #if defined(MY_CONTROLLER_IP_ADDRESS)
IPAddress _ethernetControllerIP(MY_CONTROLLER_IP_ADDRESS); IPAddress _ethernetControllerIP(MY_CONTROLLER_IP_ADDRESS);
#endif #endif
#if defined(MY_IP_ADDRESS) #if defined(MY_IP_ADDRESS)
IPAddress _ethernetGatewayIP(MY_IP_ADDRESS); IPAddress _ethernetGatewayIP(MY_IP_ADDRESS);
#endif #endif
uint8_t _ethernetGatewayMAC[] = { MY_MAC_ADDRESS }; uint8_t _ethernetGatewayMAC[] = { MY_MAC_ADDRESS };
uint16_t _ethernetGatewayPort = MY_PORT; uint16_t _ethernetGatewayPort = MY_PORT;
@@ -35,120 +35,116 @@ MyMessage _ethernetMsg;
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
typedef struct typedef struct {
{
char string[MY_GATEWAY_MAX_RECEIVE_LENGTH]; char string[MY_GATEWAY_MAX_RECEIVE_LENGTH];
uint8_t idx; uint8_t idx;
} inputBuffer; } inputBuffer;
#if defined(MY_GATEWAY_ESP8266) #if defined(MY_GATEWAY_ESP8266)
// Some re-defines to make code more readable below // Some re-defines to make code more readable below
#define EthernetServer WiFiServer #define EthernetServer WiFiServer
#define EthernetClient WiFiClient #define EthernetClient WiFiClient
#define EthernetUDP WiFiUDP #define EthernetUDP WiFiUDP
#if defined(MY_IP_ADDRESS) #if defined(MY_IP_ADDRESS)
IPAddress _gatewayIp(MY_IP_GATEWAY_ADDRESS); IPAddress _gatewayIp(MY_IP_GATEWAY_ADDRESS);
IPAddress _subnetIp(MY_IP_SUBNET_ADDRESS); IPAddress _subnetIp(MY_IP_SUBNET_ADDRESS);
#endif #endif
#endif #endif
#if defined(MY_USE_UDP) #if defined(MY_USE_UDP)
EthernetUDP _ethernetServer; EthernetUDP _ethernetServer;
#elif defined(MY_GATEWAY_LINUX) #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) #elif defined(MY_GATEWAY_CLIENT_MODE)
// Nothing to do here // Nothing to do here
#else #else
EthernetServer _ethernetServer(_ethernetGatewayPort); EthernetServer _ethernetServer(_ethernetGatewayPort);
#endif #endif
#if defined(MY_GATEWAY_CLIENT_MODE) #if defined(MY_GATEWAY_CLIENT_MODE)
static EthernetClient client = EthernetClient(); static EthernetClient client = EthernetClient();
static inputBuffer inputString; static inputBuffer inputString;
#elif defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_LINUX) #elif defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_LINUX)
static EthernetClient clients[MY_GATEWAY_MAX_CLIENTS]; static EthernetClient clients[MY_GATEWAY_MAX_CLIENTS];
static bool clientsConnected[MY_GATEWAY_MAX_CLIENTS]; static bool clientsConnected[MY_GATEWAY_MAX_CLIENTS];
static inputBuffer inputString[MY_GATEWAY_MAX_CLIENTS]; static inputBuffer inputString[MY_GATEWAY_MAX_CLIENTS];
#else #else
static EthernetClient client = EthernetClient(); static EthernetClient client = EthernetClient();
static inputBuffer inputString; static inputBuffer inputString;
#endif #endif
#ifndef MY_IP_ADDRESS #ifndef MY_IP_ADDRESS
void gatewayTransportRenewIP(); void gatewayTransportRenewIP();
#endif #endif
// On W5100 boards with SPI_EN exposed we can use the real SPI bus together with radio // On W5100 boards with SPI_EN exposed we can use the real SPI bus together with radio
// (if we enable it during usage) // (if we enable it during usage)
#ifdef MY_W5100_SPI_EN #ifdef MY_W5100_SPI_EN
void _w5100_spi_en(bool enable) void _w5100_spi_en(bool enable)
{ {
if (enable) if (enable) {
{
// Pull up pin // Pull up pin
hwPinMode(MY_W5100_SPI_EN, INPUT); hwPinMode(MY_W5100_SPI_EN, INPUT);
hwDigitalWrite(MY_W5100_SPI_EN, HIGH); hwDigitalWrite(MY_W5100_SPI_EN, HIGH);
} } else {
else
{
// Ground pin // Ground pin
hwPinMode(MY_W5100_SPI_EN, OUTPUT); hwPinMode(MY_W5100_SPI_EN, OUTPUT);
hwDigitalWrite(MY_W5100_SPI_EN, LOW); hwDigitalWrite(MY_W5100_SPI_EN, LOW);
} }
} }
#else #else
#define _w5100_spi_en(x) #define _w5100_spi_en(x)
#endif #endif
bool gatewayTransportInit() { bool gatewayTransportInit()
{
_w5100_spi_en(true); _w5100_spi_en(true);
#if defined(MY_GATEWAY_ESP8266) #if defined(MY_GATEWAY_ESP8266)
#if defined(MY_ESP8266_SSID) #if defined(MY_ESP8266_SSID)
// Turn off access point // Turn off access point
WiFi.mode (WIFI_STA); WiFi.mode (WIFI_STA);
#if defined(MY_ESP8266_HOSTNAME) #if defined(MY_ESP8266_HOSTNAME)
WiFi.hostname(MY_ESP8266_HOSTNAME); WiFi.hostname(MY_ESP8266_HOSTNAME);
#endif #endif
#ifdef MY_IP_ADDRESS #ifdef MY_IP_ADDRESS
WiFi.config(_ethernetGatewayIP, _gatewayIp, _subnetIp); WiFi.config(_ethernetGatewayIP, _gatewayIp, _subnetIp);
#endif #endif
(void)WiFi.begin(MY_ESP8266_SSID, MY_ESP8266_PASSWORD); (void)WiFi.begin(MY_ESP8266_SSID, MY_ESP8266_PASSWORD);
while (WiFi.status() != WL_CONNECTED) while (WiFi.status() != WL_CONNECTED) {
{
wait(500); wait(500);
MY_SERIALDEVICE.print(F(".")); MY_SERIALDEVICE.print(F("."));
} }
MY_SERIALDEVICE.print(F("IP: ")); MY_SERIALDEVICE.print(F("IP: "));
MY_SERIALDEVICE.println(WiFi.localIP()); MY_SERIALDEVICE.println(WiFi.localIP());
#endif #endif
#elif defined(MY_GATEWAY_LINUX) #elif defined(MY_GATEWAY_LINUX)
// Nothing to do here // Nothing to do here
#else #else
#ifdef MY_IP_ADDRESS #ifdef MY_IP_ADDRESS
Ethernet.begin(_ethernetGatewayMAC, _ethernetGatewayIP); Ethernet.begin(_ethernetGatewayMAC, _ethernetGatewayIP);
#else #else
// Get IP address from DHCP // Get IP address from DHCP
if (!Ethernet.begin(_ethernetGatewayMAC)) { if (!Ethernet.begin(_ethernetGatewayMAC)) {
MY_SERIALDEVICE.print(F("DHCP FAILURE...")); MY_SERIALDEVICE.print(F("DHCP FAILURE..."));
_w5100_spi_en(false); _w5100_spi_en(false);
return false; return false;
} }
#endif #endif
MY_SERIALDEVICE.print(F("IP: ")); MY_SERIALDEVICE.print(F("IP: "));
MY_SERIALDEVICE.println(Ethernet.localIP()); MY_SERIALDEVICE.println(Ethernet.localIP());
// give the Ethernet interface a second to initialize // give the Ethernet interface a second to initialize
delay(1000); delay(1000);
#endif /* MY_GATEWAY_ESP8266 */ #endif /* MY_GATEWAY_ESP8266 */
#ifdef MY_USE_UDP #ifdef MY_USE_UDP
_ethernetServer.begin(_ethernetGatewayPort); _ethernetServer.begin(_ethernetGatewayPort);
#elif defined(MY_GATEWAY_CLIENT_MODE) #elif defined(MY_GATEWAY_CLIENT_MODE)
#if defined(MY_CONTROLLER_URL_ADDRESS) #if defined(MY_CONTROLLER_URL_ADDRESS)
if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) { if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) {
#else #else
if (client.connect(_ethernetControllerIP, MY_PORT)) { if (client.connect(_ethernetControllerIP, MY_PORT)) {
#endif #endif
debug(PSTR("Eth: connect\n")); debug(PSTR("Eth: connect\n"));
_w5100_spi_en(false); _w5100_spi_en(false);
gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete.")); gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete."));
@@ -158,14 +154,14 @@ bool gatewayTransportInit() {
client.stop(); client.stop();
debug(PSTR("Eth: Failed to connect\n")); debug(PSTR("Eth: Failed to connect\n"));
} }
#else #else
#if defined(MY_GATEWAY_LINUX) && defined(MY_IP_ADDRESS) #if defined(MY_GATEWAY_LINUX) && defined(MY_IP_ADDRESS)
_ethernetServer.begin(_ethernetGatewayIP); _ethernetServer.begin(_ethernetGatewayIP);
#else #else
// we have to use pointers due to the constructor of EthernetServer // we have to use pointers due to the constructor of EthernetServer
_ethernetServer.begin(); _ethernetServer.begin();
#endif #endif
#endif /* USE_UDP */ #endif /* USE_UDP */
_w5100_spi_en(false); _w5100_spi_en(false);
return true; return true;
} }
@@ -178,24 +174,24 @@ bool gatewayTransportSend(MyMessage &message)
setIndication(INDICATION_GW_TX); setIndication(INDICATION_GW_TX);
_w5100_spi_en(true); _w5100_spi_en(true);
#if defined(MY_GATEWAY_CLIENT_MODE) #if defined(MY_GATEWAY_CLIENT_MODE)
#if defined(MY_USE_UDP) #if defined(MY_USE_UDP)
#if defined(MY_CONTROLLER_URL_ADDRESS) #if defined(MY_CONTROLLER_URL_ADDRESS)
_ethernetServer.beginPacket(MY_CONTROLLER_URL_ADDRESS, MY_PORT); _ethernetServer.beginPacket(MY_CONTROLLER_URL_ADDRESS, MY_PORT);
#else #else
_ethernetServer.beginPacket(_ethernetControllerIP, MY_PORT); _ethernetServer.beginPacket(_ethernetControllerIP, MY_PORT);
#endif #endif
_ethernetServer.write(_ethernetMsg, strlen(_ethernetMsg)); _ethernetServer.write(_ethernetMsg, strlen(_ethernetMsg));
// returns 1 if the packet was sent successfully // returns 1 if the packet was sent successfully
nbytes = _ethernetServer.endPacket(); nbytes = _ethernetServer.endPacket();
#else #else
if (!client.connected()) { if (!client.connected()) {
client.stop(); client.stop();
#if defined(MY_CONTROLLER_URL_ADDRESS) #if defined(MY_CONTROLLER_URL_ADDRESS)
if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) { if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) {
#else #else
if (client.connect(_ethernetControllerIP, MY_PORT)) { if (client.connect(_ethernetControllerIP, MY_PORT)) {
#endif #endif
debug(PSTR("Eth: connect\n")); debug(PSTR("Eth: connect\n"));
_w5100_spi_en(false); _w5100_spi_en(false);
gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete.")); gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete."));
@@ -209,27 +205,26 @@ bool gatewayTransportSend(MyMessage &message)
} }
} }
nbytes = client.write(_ethernetMsg, strlen(_ethernetMsg)); nbytes = client.write(_ethernetMsg, strlen(_ethernetMsg));
#endif #endif
#else #else
// Send message to connected clients // Send message to connected clients
#if defined(MY_GATEWAY_ESP8266) #if defined(MY_GATEWAY_ESP8266)
for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) {
{ if (clients[i] && clients[i].connected()) {
if (clients[i] && clients[i].connected())
{
nbytes += clients[i].write((uint8_t*)_ethernetMsg, strlen(_ethernetMsg)); nbytes += clients[i].write((uint8_t*)_ethernetMsg, strlen(_ethernetMsg));
} }
} }
#else #else
nbytes = _ethernetServer.write(_ethernetMsg); nbytes = _ethernetServer.write(_ethernetMsg);
#endif #endif
#endif /* MY_GATEWAY_CLIENT_MODE */ #endif /* MY_GATEWAY_CLIENT_MODE */
_w5100_spi_en(false); _w5100_spi_en(false);
return (nbytes > 0); return (nbytes > 0);
} }
#if (defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_LINUX)) && !defined(MY_GATEWAY_CLIENT_MODE) #if (defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_LINUX)) && !defined(MY_GATEWAY_CLIENT_MODE)
bool _readFromClient(uint8_t i) { bool _readFromClient(uint8_t i)
{
while (clients[i].connected() && clients[i].available()) { while (clients[i].connected() && clients[i].available()) {
char inChar = clients[i].read(); char inChar = clients[i].read();
if (inputString[i].idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) { if (inputString[i].idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) {
@@ -256,9 +251,10 @@ bool gatewayTransportSend(MyMessage &message)
} }
} }
return false; return false;
} }
#else #else
bool _readFromClient() { bool _readFromClient()
{
while (client.connected() && client.available()) { while (client.connected() && client.available()) {
char inChar = client.read(); char inChar = client.read();
if (inputString.idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) { if (inputString.idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) {
@@ -285,49 +281,48 @@ bool gatewayTransportSend(MyMessage &message)
} }
} }
return false; return false;
} }
#endif #endif
bool gatewayTransportAvailable() bool gatewayTransportAvailable()
{ {
_w5100_spi_en(true); _w5100_spi_en(true);
#if !defined(MY_IP_ADDRESS) && defined(MY_GATEWAY_W5100) #if !defined(MY_IP_ADDRESS) && defined(MY_GATEWAY_W5100)
// renew IP address using DHCP // renew IP address using DHCP
gatewayTransportRenewIP(); gatewayTransportRenewIP();
#endif #endif
#ifdef MY_USE_UDP #ifdef MY_USE_UDP
int packet_size = _ethernetServer.parsePacket(); int packet_size = _ethernetServer.parsePacket();
if (packet_size) { if (packet_size) {
//debug(PSTR("UDP packet available. Size:%d\n"), packet_size); //debug(PSTR("UDP packet available. Size:%d\n"), packet_size);
#if defined(MY_GATEWAY_ESP8266) #if defined(MY_GATEWAY_ESP8266)
_ethernetServer.read(inputString[0].string, MY_GATEWAY_MAX_RECEIVE_LENGTH); _ethernetServer.read(inputString[0].string, MY_GATEWAY_MAX_RECEIVE_LENGTH);
inputString[0].string[packet_size] = 0; inputString[0].string[packet_size] = 0;
debug(PSTR("UDP packet received: %s\n"), inputString[0].string); debug(PSTR("UDP packet received: %s\n"), inputString[0].string);
const bool ok = protocolParse(_ethernetMsg, inputString[0].string); const bool ok = protocolParse(_ethernetMsg, inputString[0].string);
#else #else
_ethernetServer.read(inputString.string, MY_GATEWAY_MAX_RECEIVE_LENGTH); _ethernetServer.read(inputString.string, MY_GATEWAY_MAX_RECEIVE_LENGTH);
inputString.string[packet_size] = 0; inputString.string[packet_size] = 0;
debug(PSTR("UDP packet received: %s\n"), inputString.string); debug(PSTR("UDP packet received: %s\n"), inputString.string);
_w5100_spi_en(false); _w5100_spi_en(false);
const bool ok = protocolParse(_ethernetMsg, inputString.string); const bool ok = protocolParse(_ethernetMsg, inputString.string);
#endif #endif
if (ok) if (ok) {
{
setIndication(INDICATION_GW_RX); setIndication(INDICATION_GW_RX);
} }
return ok; return ok;
} }
#elif defined(MY_GATEWAY_CLIENT_MODE) #elif defined(MY_GATEWAY_CLIENT_MODE)
if (!client.connected()) { if (!client.connected()) {
client.stop(); client.stop();
#if defined(MY_CONTROLLER_URL_ADDRESS) #if defined(MY_CONTROLLER_URL_ADDRESS)
if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) { if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) {
#else #else
if (client.connect(_ethernetControllerIP, MY_PORT)) { if (client.connect(_ethernetControllerIP, MY_PORT)) {
#endif #endif
debug(PSTR("Eth: connect\n")); debug(PSTR("Eth: connect\n"));
_w5100_spi_en(false); _w5100_spi_en(false);
gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete.")); gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete."));
@@ -344,8 +339,8 @@ bool gatewayTransportAvailable()
_w5100_spi_en(false); _w5100_spi_en(false);
return true; return true;
} }
#else #else
#if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_LINUX) #if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_LINUX)
// ESP8266: Go over list of clients and stop any that are no longer connected. // 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. // If the server has a new client connection it will be assigned to a free slot.
bool allSlotsOccupied = true; bool allSlotsOccupied = true;
@@ -383,7 +378,7 @@ bool gatewayTransportAvailable()
return true; return true;
} }
} }
#else #else
// W5100/ENC module does not have hasClient-method. We can only serve one client at the time. // W5100/ENC module does not have hasClient-method. We can only serve one client at the time.
EthernetClient newclient = _ethernetServer.available(); EthernetClient newclient = _ethernetServer.available();
// if a new client connects make sure to dispose any previous existing sockets // if a new client connects make sure to dispose any previous existing sockets
@@ -410,8 +405,8 @@ bool gatewayTransportAvailable()
} }
} }
} }
#endif /* MY_GATEWAY_ESP8266 */ #endif /* MY_GATEWAY_ESP8266 */
#endif #endif
_w5100_spi_en(false); _w5100_spi_en(false);
return false; return false;
} }
+41 -34
View File
@@ -23,23 +23,23 @@
#include "MyGatewayTransport.h" #include "MyGatewayTransport.h"
#if defined MY_CONTROLLER_IP_ADDRESS #if defined MY_CONTROLLER_IP_ADDRESS
IPAddress _brokerIp(MY_CONTROLLER_IP_ADDRESS); IPAddress _brokerIp(MY_CONTROLLER_IP_ADDRESS);
#endif #endif
#if defined(MY_GATEWAY_ESP8266) #if defined(MY_GATEWAY_ESP8266)
#define EthernetClient WiFiClient #define EthernetClient WiFiClient
#if defined(MY_IP_ADDRESS) #if defined(MY_IP_ADDRESS)
IPAddress _gatewayIp(MY_IP_GATEWAY_ADDRESS); IPAddress _gatewayIp(MY_IP_GATEWAY_ADDRESS);
IPAddress _subnetIp(MY_IP_SUBNET_ADDRESS); IPAddress _subnetIp(MY_IP_SUBNET_ADDRESS);
#endif #endif
#elif defined(MY_GATEWAY_LINUX) #elif defined(MY_GATEWAY_LINUX)
// Nothing to do here // Nothing to do here
#else #else
uint8_t _MQTT_clientMAC[] = { MY_MAC_ADDRESS }; uint8_t _MQTT_clientMAC[] = { MY_MAC_ADDRESS };
#endif #endif
#if defined(MY_IP_ADDRESS) #if defined(MY_IP_ADDRESS)
IPAddress _MQTT_clientIp(MY_IP_ADDRESS); IPAddress _MQTT_clientIp(MY_IP_ADDRESS);
#endif #endif
static EthernetClient _MQTT_ethClient; static EthernetClient _MQTT_ethClient;
@@ -48,7 +48,8 @@ static bool _MQTT_connecting = true;
static bool _MQTT_available = false; static bool _MQTT_available = false;
static MyMessage _MQTT_msg; static MyMessage _MQTT_msg;
bool gatewayTransportSend(MyMessage &message) { bool gatewayTransportSend(MyMessage &message)
{
if (!_MQTT_client.connected()) { if (!_MQTT_client.connected()) {
return false; return false;
} }
@@ -58,12 +59,14 @@ bool gatewayTransportSend(MyMessage &message) {
return _MQTT_client.publish(topic, message.getString(_convBuffer)); return _MQTT_client.publish(topic, message.getString(_convBuffer));
} }
void incomingMQTT(char* topic, uint8_t* payload, unsigned int length) { void incomingMQTT(char* topic, uint8_t* payload, unsigned int length)
{
debug(PSTR("Message arrived on topic: %s\n"), topic); debug(PSTR("Message arrived on topic: %s\n"), topic);
_MQTT_available = protocolMQTTParse(_MQTT_msg, topic, payload, length); _MQTT_available = protocolMQTTParse(_MQTT_msg, topic, payload, length);
} }
bool reconnectMQTT() { bool reconnectMQTT()
{
debug(PSTR("Attempting MQTT connection...\n")); debug(PSTR("Attempting MQTT connection...\n"));
// Attempt to connect // Attempt to connect
if (_MQTT_client.connect(MY_MQTT_CLIENT_ID if (_MQTT_client.connect(MY_MQTT_CLIENT_ID
@@ -85,58 +88,60 @@ bool reconnectMQTT() {
return false; return false;
} }
bool gatewayTransportConnect() { bool gatewayTransportConnect()
#if defined(MY_GATEWAY_ESP8266) {
#if defined(MY_GATEWAY_ESP8266)
while (WiFi.status() != WL_CONNECTED) { while (WiFi.status() != WL_CONNECTED) {
wait(500); wait(500);
MY_SERIALDEVICE.print("."); MY_SERIALDEVICE.print(".");
} }
MY_SERIALDEVICE.print("IP: "); MY_SERIALDEVICE.print("IP: ");
MY_SERIALDEVICE.println(WiFi.localIP()); MY_SERIALDEVICE.println(WiFi.localIP());
#elif defined(MY_GATEWAY_LINUX) #elif defined(MY_GATEWAY_LINUX)
#if defined(MY_IP_ADDRESS) #if defined(MY_IP_ADDRESS)
//TODO //TODO
#endif #endif
#else #else
#ifdef MY_IP_ADDRESS #ifdef MY_IP_ADDRESS
Ethernet.begin(_MQTT_clientMAC, _MQTT_clientIp); Ethernet.begin(_MQTT_clientMAC, _MQTT_clientIp);
#else #else
// Get IP address from DHCP // Get IP address from DHCP
if (!Ethernet.begin(_MQTT_clientMAC)) { if (!Ethernet.begin(_MQTT_clientMAC)) {
MY_SERIALDEVICE.print("DHCP FAILURE..."); MY_SERIALDEVICE.print("DHCP FAILURE...");
_MQTT_connecting = false; _MQTT_connecting = false;
return false; return false;
} }
#endif #endif
MY_SERIALDEVICE.print("IP: "); MY_SERIALDEVICE.print("IP: ");
MY_SERIALDEVICE.println(Ethernet.localIP()); MY_SERIALDEVICE.println(Ethernet.localIP());
// give the Ethernet interface a second to initialize // give the Ethernet interface a second to initialize
delay(1000); delay(1000);
#endif #endif
return true; return true;
} }
bool gatewayTransportInit() { bool gatewayTransportInit()
{
_MQTT_connecting = true; _MQTT_connecting = true;
#if defined(MY_CONTROLLER_IP_ADDRESS) #if defined(MY_CONTROLLER_IP_ADDRESS)
_MQTT_client.setServer(_brokerIp, MY_PORT); _MQTT_client.setServer(_brokerIp, MY_PORT);
#else #else
_MQTT_client.setServer(MY_CONTROLLER_URL_ADDRESS, MY_PORT); _MQTT_client.setServer(MY_CONTROLLER_URL_ADDRESS, MY_PORT);
#endif #endif
_MQTT_client.setCallback(incomingMQTT); _MQTT_client.setCallback(incomingMQTT);
#if defined(MY_GATEWAY_ESP8266) #if defined(MY_GATEWAY_ESP8266)
// Turn off access point // Turn off access point
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
#if defined(MY_ESP8266_HOSTNAME) #if defined(MY_ESP8266_HOSTNAME)
WiFi.hostname(MY_ESP8266_HOSTNAME); WiFi.hostname(MY_ESP8266_HOSTNAME);
#endif #endif
(void)WiFi.begin(MY_ESP8266_SSID, MY_ESP8266_PASSWORD); (void)WiFi.begin(MY_ESP8266_SSID, MY_ESP8266_PASSWORD);
#ifdef MY_IP_ADDRESS #ifdef MY_IP_ADDRESS
WiFi.config(_MQTT_clientIp, _gatewayIp, _subnetIp); WiFi.config(_MQTT_clientIp, _gatewayIp, _subnetIp);
#endif #endif
#endif #endif
gatewayTransportConnect(); gatewayTransportConnect();
@@ -144,7 +149,8 @@ bool gatewayTransportInit() {
return true; return true;
} }
bool gatewayTransportAvailable() { bool gatewayTransportAvailable()
{
if (_MQTT_connecting) { if (_MQTT_connecting) {
return false; return false;
} }
@@ -161,7 +167,8 @@ bool gatewayTransportAvailable() {
return _MQTT_available; return _MQTT_available;
} }
MyMessage & gatewayTransportReceive() { MyMessage & gatewayTransportReceive()
{
// Return the last parsed message // Return the last parsed message
_MQTT_available = false; _MQTT_available = false;
return _MQTT_msg; return _MQTT_msg;
+10 -7
View File
@@ -23,21 +23,23 @@
#include "MyMessage.h" #include "MyMessage.h"
#include "MyProtocol.h" #include "MyProtocol.h"
// global variables // global variables
extern MyMessage _msgTmp; extern MyMessage _msgTmp;
char _serialInputString[MY_GATEWAY_MAX_RECEIVE_LENGTH]; // A buffer for incoming commands from serial interface char _serialInputString[MY_GATEWAY_MAX_RECEIVE_LENGTH]; // A buffer for incoming commands from serial interface
uint8_t _serialInputPos; uint8_t _serialInputPos;
MyMessage _serialMsg; MyMessage _serialMsg;
bool gatewayTransportSend(MyMessage &message) { bool gatewayTransportSend(MyMessage &message)
{
setIndication(INDICATION_GW_TX); setIndication(INDICATION_GW_TX);
MY_SERIALDEVICE.print(protocolFormat(message)); MY_SERIALDEVICE.print(protocolFormat(message));
// Serial print is always successful // Serial print is always successful
return true; return true;
} }
bool gatewayTransportInit() { bool gatewayTransportInit()
{
gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete.")); gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete."));
// Send presentation of locally attached sensors (and node if applicable) // Send presentation of locally attached sensors (and node if applicable)
presentNode(); presentNode();
@@ -45,7 +47,8 @@ bool gatewayTransportInit() {
return true; return true;
} }
bool gatewayTransportAvailable() { bool gatewayTransportAvailable()
{
while (MY_SERIALDEVICE.available()) { while (MY_SERIALDEVICE.available()) {
// get the new byte: // get the new byte:
char inChar = (char) MY_SERIALDEVICE.read(); char inChar = (char) MY_SERIALDEVICE.read();
@@ -55,8 +58,7 @@ bool gatewayTransportAvailable() {
if (inChar == '\n') { if (inChar == '\n') {
_serialInputString[_serialInputPos] = 0; _serialInputString[_serialInputPos] = 0;
bool ok = protocolParse(_serialMsg, _serialInputString); bool ok = protocolParse(_serialMsg, _serialInputString);
if (ok) if (ok) {
{
setIndication(INDICATION_GW_RX); setIndication(INDICATION_GW_RX);
} }
_serialInputPos = 0; _serialInputPos = 0;
@@ -74,7 +76,8 @@ bool gatewayTransportAvailable() {
return false; return false;
} }
MyMessage & gatewayTransportReceive() { MyMessage & gatewayTransportReceive()
{
// Return the last parsed message // Return the last parsed message
return _serialMsg; return _serialMsg;
} }
+8 -7
View File
@@ -17,11 +17,11 @@
* version 2 as published by the Free Software Foundation. * version 2 as published by the Free Software Foundation.
*/ */
/** /**
* @file MyHw.h * @file MyHw.h
* *
* MySensors hardware abstraction layer * MySensors hardware abstraction layer
*/ */
#ifndef MyHw_h #ifndef MyHw_h
#define 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]. * @param ms Time to sleep, in [ms].
* @return -1 when woken by timer, or interrupt number when woken by interrupt. * @return -1 when woken by timer, or interrupt number when woken by interrupt.
*/ */
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms); int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
unsigned long ms);
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG) #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
/** /**
@@ -131,7 +132,7 @@ void hwDebugPrint(const char *fmt, ... );
* interrupted during execution. * interrupted during execution.
*/ */
#ifdef DOXYGEN #ifdef DOXYGEN
#define MY_CRITICAL_SECTION #define MY_CRITICAL_SECTION
#endif /* DOXYGEN */ #endif /* DOXYGEN */
#endif // #ifdef MyHw_h #endif // #ifdef MyHw_h
+83 -43
View File
@@ -23,15 +23,17 @@
#define INVALID_INTERRUPT_NUM (0xFFu) #define INVALID_INTERRUPT_NUM (0xFFu)
volatile uint8_t _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; // Interrupt number that woke the mcu. volatile uint8_t _wokeUpByInterrupt =
volatile uint8_t _wakeUp1Interrupt = INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp1-callback. INVALID_INTERRUPT_NUM; // Interrupt number that woke the mcu.
volatile uint8_t _wakeUp2Interrupt = INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp2-callback. volatile uint8_t _wakeUp1Interrupt =
INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp1-callback.
volatile uint8_t _wakeUp2Interrupt =
INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp2-callback.
void wakeUp1() //place to send the interrupts void wakeUp1() //place to send the interrupts
{ {
detachInterrupt(_wakeUp1Interrupt); detachInterrupt(_wakeUp1Interrupt);
if (_wakeUp2Interrupt != INVALID_INTERRUPT_NUM) if (_wakeUp2Interrupt != INVALID_INTERRUPT_NUM) {
{
detachInterrupt(_wakeUp2Interrupt); detachInterrupt(_wakeUp2Interrupt);
} }
_wokeUpByInterrupt = _wakeUp1Interrupt; _wokeUpByInterrupt = _wakeUp1Interrupt;
@@ -39,8 +41,7 @@ void wakeUp1() //place to send the interrupts
void wakeUp2() //place to send the second interrupts void wakeUp2() //place to send the second interrupts
{ {
detachInterrupt(_wakeUp2Interrupt); detachInterrupt(_wakeUp2Interrupt);
if (_wakeUp1Interrupt != INVALID_INTERRUPT_NUM) if (_wakeUp1Interrupt != INVALID_INTERRUPT_NUM) {
{
detachInterrupt(_wakeUp1Interrupt); detachInterrupt(_wakeUp1Interrupt);
} }
_wokeUpByInterrupt = _wakeUp2Interrupt; _wokeUpByInterrupt = _wakeUp2Interrupt;
@@ -57,13 +58,13 @@ ISR (WDT_vect)
{ {
} }
void hwPowerDown(period_t period) { void hwPowerDown(period_t period)
{
// disable ADC for power saving // disable ADC for power saving
ADCSRA &= ~(1 << ADEN); ADCSRA &= ~(1 << ADEN);
// save WDT settings // save WDT settings
uint8_t WDTsave = WDTCSR; uint8_t WDTsave = WDTCSR;
if (period != SLEEP_FOREVER) if (period != SLEEP_FOREVER) {
{
wdt_enable(period); wdt_enable(period);
// enable WDT interrupt before system reset // enable WDT interrupt before system reset
WDTCSR |= (1 << WDCE) | (1 << WDIE); WDTCSR |= (1 << WDCE) | (1 << WDIE);
@@ -74,9 +75,9 @@ void hwPowerDown(period_t period) {
set_sleep_mode(SLEEP_MODE_PWR_DOWN); set_sleep_mode(SLEEP_MODE_PWR_DOWN);
cli(); cli();
sleep_enable(); sleep_enable();
#if defined __AVR_ATmega328P__ #if defined __AVR_ATmega328P__
sleep_bod_disable(); sleep_bod_disable();
#endif #endif
// Enable interrupts & sleep until WDT or ext. interrupt // Enable interrupts & sleep until WDT or ext. interrupt
sei(); sei();
// Directly sleep CPU, to prevent race conditions! (see chapter 7.7 of ATMega328P datasheet) // Directly sleep CPU, to prevent race conditions! (see chapter 7.7 of ATMega328P datasheet)
@@ -94,33 +95,68 @@ void hwPowerDown(period_t period) {
ADCSRA |= (1 << ADEN); ADCSRA |= (1 << ADEN);
} }
void hwInternalSleep(unsigned long ms) { void hwInternalSleep(unsigned long ms)
{
// Let serial prints finish (debug, log etc) // Let serial prints finish (debug, log etc)
#ifndef MY_DISABLED_SERIAL #ifndef MY_DISABLED_SERIAL
MY_SERIALDEVICE.flush(); MY_SERIALDEVICE.flush();
#endif #endif
while (!interruptWakeUp() && ms >= 8000) { hwPowerDown(SLEEP_8S); ms -= 8000; } while (!interruptWakeUp() && ms >= 8000) {
if (!interruptWakeUp() && ms >= 4000) { hwPowerDown(SLEEP_4S); ms -= 4000; } hwPowerDown(SLEEP_8S);
if (!interruptWakeUp() && ms >= 2000) { hwPowerDown(SLEEP_2S); ms -= 2000; } ms -= 8000;
if (!interruptWakeUp() && ms >= 1000) { hwPowerDown(SLEEP_1S); ms -= 1000; } }
if (!interruptWakeUp() && ms >= 500) { hwPowerDown(SLEEP_500MS); ms -= 500; } if (!interruptWakeUp() && ms >= 4000) {
if (!interruptWakeUp() && ms >= 250) { hwPowerDown(SLEEP_250MS); ms -= 250; } hwPowerDown(SLEEP_4S);
if (!interruptWakeUp() && ms >= 125) { hwPowerDown(SLEEP_120MS); ms -= 120; } ms -= 4000;
if (!interruptWakeUp() && ms >= 64) { hwPowerDown(SLEEP_60MS); ms -= 60; } }
if (!interruptWakeUp() && ms >= 32) { hwPowerDown(SLEEP_30MS); ms -= 30; } if (!interruptWakeUp() && ms >= 2000) {
if (!interruptWakeUp() && ms >= 16) { hwPowerDown(SLEEP_15MS); ms -= 15; } hwPowerDown(SLEEP_2S);
ms -= 2000;
}
if (!interruptWakeUp() && ms >= 1000) {
hwPowerDown(SLEEP_1S);
ms -= 1000;
}
if (!interruptWakeUp() && ms >= 500) {
hwPowerDown(SLEEP_500MS);
ms -= 500;
}
if (!interruptWakeUp() && ms >= 250) {
hwPowerDown(SLEEP_250MS);
ms -= 250;
}
if (!interruptWakeUp() && ms >= 125) {
hwPowerDown(SLEEP_120MS);
ms -= 120;
}
if (!interruptWakeUp() && ms >= 64) {
hwPowerDown(SLEEP_60MS);
ms -= 60;
}
if (!interruptWakeUp() && ms >= 32) {
hwPowerDown(SLEEP_30MS);
ms -= 30;
}
if (!interruptWakeUp() && ms >= 16) {
hwPowerDown(SLEEP_15MS);
ms -= 15;
}
} }
int8_t hwSleep(unsigned long ms) { int8_t hwSleep(unsigned long ms)
{
hwInternalSleep(ms); hwInternalSleep(ms);
return MY_WAKE_UP_BY_TIMER; return MY_WAKE_UP_BY_TIMER;
} }
int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
{
return hwSleep(interrupt,mode,INVALID_INTERRUPT_NUM,0u,ms); return hwSleep(interrupt,mode,INVALID_INTERRUPT_NUM,0u,ms);
} }
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
unsigned long ms)
{
// Disable interrupts until going to sleep, otherwise interrupts occurring between attachInterrupt() // Disable interrupts until going to sleep, otherwise interrupts occurring between attachInterrupt()
// and sleep might cause the ATMega to not wakeup from sleep as interrupt has already be handled! // and sleep might cause the ATMega to not wakeup from sleep as interrupt has already be handled!
cli(); cli();
@@ -162,17 +198,18 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo
} }
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG) #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
uint16_t hwCPUVoltage() { uint16_t hwCPUVoltage()
{
// Measure Vcc against 1.1V Vref // Measure Vcc against 1.1V Vref
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ADMUX = (_BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1)); ADMUX = (_BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1));
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = (_BV(MUX5) | _BV(MUX0)); ADMUX = (_BV(MUX5) | _BV(MUX0));
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
ADMUX = (_BV(MUX3) | _BV(MUX2)); ADMUX = (_BV(MUX3) | _BV(MUX2));
#else #else
ADMUX = (_BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1)); ADMUX = (_BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1));
#endif #endif
// Vref settle // Vref settle
delay(70); delay(70);
// Do conversion // Do conversion
@@ -182,7 +219,8 @@ uint16_t hwCPUVoltage() {
return (1125300UL) / ADC; return (1125300UL) / ADC;
} }
uint16_t hwCPUFrequency() { uint16_t hwCPUFrequency()
{
cli(); cli();
// setup timer1 // setup timer1
TIFR1 = 0xFF; TIFR1 = 0xFF;
@@ -210,7 +248,8 @@ uint16_t hwCPUFrequency() {
return TCNT1 * 2048UL / 100000UL; return TCNT1 * 2048UL / 100000UL;
} }
uint16_t hwFreeMem() { uint16_t hwFreeMem()
{
extern int __heap_start, *__brkval; extern int __heap_start, *__brkval;
int v; int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
@@ -218,27 +257,28 @@ uint16_t hwFreeMem() {
#endif #endif
#ifdef MY_DEBUG #ifdef MY_DEBUG
void hwDebugPrint(const char *fmt, ... ) { void hwDebugPrint(const char *fmt, ... )
{
char fmtBuffer[MY_SERIAL_OUTPUT_SIZE]; char fmtBuffer[MY_SERIAL_OUTPUT_SIZE];
#ifdef MY_GATEWAY_FEATURE #ifdef MY_GATEWAY_FEATURE
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
snprintf_P(fmtBuffer, sizeof(fmtBuffer), PSTR("0;255;%d;0;%d;"), 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); MY_SERIALDEVICE.print(fmtBuffer);
#else #else
// prepend timestamp (AVR nodes) // prepend timestamp (AVR nodes)
MY_SERIALDEVICE.print(hwMillis()); MY_SERIALDEVICE.print(hwMillis());
MY_SERIALDEVICE.print(" "); MY_SERIALDEVICE.print(" ");
#endif #endif
va_list args; va_list args;
va_start (args, fmt ); va_start (args, fmt );
#ifdef MY_GATEWAY_FEATURE #ifdef MY_GATEWAY_FEATURE
// Truncate message if this is gateway node // Truncate message if this is gateway node
vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args); vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args);
fmtBuffer[sizeof(fmtBuffer) - 2] = '\n'; fmtBuffer[sizeof(fmtBuffer) - 2] = '\n';
fmtBuffer[sizeof(fmtBuffer) - 1] = '\0'; fmtBuffer[sizeof(fmtBuffer) - 1] = '\0';
#else #else
vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args); vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args);
#endif #endif
va_end (args); va_end (args);
MY_SERIALDEVICE.print(fmtBuffer); MY_SERIALDEVICE.print(fmtBuffer);
MY_SERIALDEVICE.flush(); MY_SERIALDEVICE.flush();
+5 -5
View File
@@ -39,7 +39,7 @@
#if defined __AVR_ATmega328P__ #if defined __AVR_ATmega328P__
#ifndef sleep_bod_disable #ifndef sleep_bod_disable
#define sleep_bod_disable() \ #define sleep_bod_disable() \
do { \ do { \
unsigned char tempreg; \ unsigned char tempreg; \
__asm__ __volatile__("in %[tempreg], %[mcucr]" "\n\t" \ __asm__ __volatile__("in %[tempreg], %[mcucr]" "\n\t" \
"ori %[tempreg], %[bods_bodse]" "\n\t" \ "ori %[tempreg], %[bods_bodse]" "\n\t" \
@@ -50,7 +50,7 @@ do { \
: [mcucr] "I" _SFR_IO_ADDR(MCUCR), \ : [mcucr] "I" _SFR_IO_ADDR(MCUCR), \
[bods_bodse] "i" (_BV(BODS) | _BV(BODSE)), \ [bods_bodse] "i" (_BV(BODS) | _BV(BODSE)), \
[not_bodse] "i" (~_BV(BODSE))); \ [not_bodse] "i" (~_BV(BODSE))); \
} while (0) } while (0)
#endif #endif
#endif #endif
@@ -63,9 +63,9 @@ do { \
#if defined(MY_DISABLED_SERIAL) #if defined(MY_DISABLED_SERIAL)
#define hwInit() #define hwInit()
#else #else
#define hwInit() MY_SERIALDEVICE.begin(MY_BAUD_RATE) #define hwInit() MY_SERIALDEVICE.begin(MY_BAUD_RATE)
#endif #endif
#define hwWatchdogReset() wdt_reset() #define hwWatchdogReset() wdt_reset()
@@ -96,7 +96,7 @@ enum period_t {
void hwInternalSleep(unsigned long ms); void hwInternalSleep(unsigned long ms);
#ifndef DOXYGEN #ifndef DOXYGEN
#define MY_CRITICAL_SECTION ATOMIC_BLOCK(ATOMIC_RESTORESTATE) #define MY_CRITICAL_SECTION ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
#endif /* DOXYGEN */ #endif /* DOXYGEN */
#endif #endif
+21 -14
View File
@@ -33,8 +33,7 @@ void hwReadConfigBlock(void* buf, void* addr, size_t length)
{ {
uint8_t* dst = static_cast<uint8_t*>(buf); uint8_t* dst = static_cast<uint8_t*>(buf);
int pos = reinterpret_cast<int>(addr); int pos = reinterpret_cast<int>(addr);
while (length-- > 0) while (length-- > 0) {
{
*dst++ = EEPROM.read(pos++); *dst++ = EEPROM.read(pos++);
} }
} }
@@ -63,13 +62,15 @@ void hwWriteConfig(const int addr, uint8_t value)
} }
int8_t hwSleep(unsigned long ms) { int8_t hwSleep(unsigned long ms)
{
// TODO: Not supported! // TODO: Not supported!
(void)ms; (void)ms;
return MY_SLEEP_NOT_POSSIBLE; return MY_SLEEP_NOT_POSSIBLE;
} }
int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
{
// TODO: Not supported! // TODO: Not supported!
(void)interrupt; (void)interrupt;
(void)mode; (void)mode;
@@ -77,7 +78,9 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) {
return MY_SLEEP_NOT_POSSIBLE; return MY_SLEEP_NOT_POSSIBLE;
} }
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
unsigned long ms)
{
// TODO: Not supported! // TODO: Not supported!
(void)interrupt1; (void)interrupt1;
(void)mode1; (void)mode1;
@@ -90,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) #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
ADC_MODE(ADC_VCC); ADC_MODE(ADC_VCC);
uint16_t hwCPUVoltage() { uint16_t hwCPUVoltage()
{
// in mV // in mV
return ESP.getVcc(); return ESP.getVcc();
} }
uint16_t hwCPUFrequency() { uint16_t hwCPUFrequency()
{
// in 1/10Mhz // in 1/10Mhz
return ESP.getCpuFreqMHz()*10; return ESP.getCpuFreqMHz()*10;
} }
uint16_t hwFreeMem() { uint16_t hwFreeMem()
{
return ESP.getFreeHeap(); return ESP.getFreeHeap();
} }
#endif #endif
#ifdef MY_DEBUG #ifdef MY_DEBUG
void hwDebugPrint(const char *fmt, ... ) { void hwDebugPrint(const char *fmt, ... )
{
char fmtBuffer[MY_SERIAL_OUTPUT_SIZE]; char fmtBuffer[MY_SERIAL_OUTPUT_SIZE];
#ifdef MY_GATEWAY_FEATURE #ifdef MY_GATEWAY_FEATURE
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
snprintf_P(fmtBuffer, sizeof(fmtBuffer), PSTR("0;255;%d;0;%d;"), 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); MY_SERIALDEVICE.print(fmtBuffer);
#endif #endif
va_list args; va_list args;
va_start (args, fmt ); va_start (args, fmt );
#ifdef MY_GATEWAY_FEATURE #ifdef MY_GATEWAY_FEATURE
// Truncate message if this is gateway node // Truncate message if this is gateway node
vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args); vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args);
fmtBuffer[sizeof(fmtBuffer) - 2] = '\n'; fmtBuffer[sizeof(fmtBuffer) - 2] = '\n';
fmtBuffer[sizeof(fmtBuffer) - 1] = '\0'; fmtBuffer[sizeof(fmtBuffer) - 1] = '\0';
#else #else
vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args); vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args);
#endif #endif
va_end (args); va_end (args);
MY_SERIALDEVICE.print(fmtBuffer); MY_SERIALDEVICE.print(fmtBuffer);
MY_SERIALDEVICE.flush(); MY_SERIALDEVICE.flush();
+1 -1
View File
@@ -58,7 +58,7 @@ static __inline__ void __psRestore(const uint32_t *__s)
} }
#ifndef DOXYGEN #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 /* DOXYGEN */
#endif // #ifdef ARDUINO_ARCH_ESP8266 #endif // #ifdef ARDUINO_ARCH_ESP8266
+4 -3
View File
@@ -30,12 +30,12 @@ void hwInit()
{ {
#ifdef MY_GATEWAY_SERIAL #ifdef MY_GATEWAY_SERIAL
MY_SERIALDEVICE.begin(MY_BAUD_RATE); MY_SERIALDEVICE.begin(MY_BAUD_RATE);
#ifdef MY_LINUX_SERIAL_GROUPNAME #ifdef MY_LINUX_SERIAL_GROUPNAME
if (!MY_SERIALDEVICE.setGroupPerm(MY_LINUX_SERIAL_GROUPNAME)) { if (!MY_SERIALDEVICE.setGroupPerm(MY_LINUX_SERIAL_GROUPNAME)) {
logError("Unable to change permission for serial port device.\n"); logError("Unable to change permission for serial port device.\n");
exit(1); exit(1);
} }
#endif #endif
#endif #endif
} }
@@ -88,7 +88,8 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
} }
// Not supported! // Not supported!
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
unsigned long ms)
{ {
(void)interrupt1; (void)interrupt1;
(void)mode1; (void)mode1;
+16 -14
View File
@@ -26,9 +26,9 @@
#include "SerialPort.h" #include "SerialPort.h"
#ifdef MY_IS_SERIAL_PTY #ifdef MY_IS_SERIAL_PTY
SerialPort Serial = SerialPort(MY_LINUX_SERIAL_PTY, true); SerialPort Serial = SerialPort(MY_LINUX_SERIAL_PTY, true);
#else #else
SerialPort Serial = SerialPort(MY_LINUX_SERIAL_PORT); SerialPort Serial = SerialPort(MY_LINUX_SERIAL_PORT);
#endif #endif
#define MY_SERIALDEVICE Serial #define MY_SERIALDEVICE Serial
@@ -50,38 +50,40 @@ inline void hwRandomNumberInit();
inline unsigned long hwMillis(); inline unsigned long hwMillis();
#ifdef MY_RF24_IRQ_PIN #ifdef MY_RF24_IRQ_PIN
static pthread_mutex_t hw_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t hw_mutex = PTHREAD_MUTEX_INITIALIZER;
static __inline__ void __hwUnlock(const uint8_t *__s) { static __inline__ void __hwUnlock(const uint8_t *__s)
{
pthread_mutex_unlock(&hw_mutex); pthread_mutex_unlock(&hw_mutex);
(void)__s; (void)__s;
} }
static __inline__ void __hwLock() { static __inline__ void __hwLock()
{
pthread_mutex_lock(&hw_mutex); pthread_mutex_lock(&hw_mutex);
} }
#endif #endif
#if defined(DOXYGEN) #if defined(DOXYGEN)
#define ATOMIC_BLOCK_CLEANUP #define ATOMIC_BLOCK_CLEANUP
#elif defined(MY_RF24_IRQ_PIN) #elif defined(MY_RF24_IRQ_PIN)
#define ATOMIC_BLOCK_CLEANUP uint8_t __atomic_loop \ #define ATOMIC_BLOCK_CLEANUP uint8_t __atomic_loop \
__attribute__((__cleanup__( __hwUnlock ))) = 1 __attribute__((__cleanup__( __hwUnlock ))) = 1
#else #else
#define ATOMIC_BLOCK_CLEANUP #define ATOMIC_BLOCK_CLEANUP
#endif /* DOXYGEN */ #endif /* DOXYGEN */
#if defined(DOXYGEN) #if defined(DOXYGEN)
#define ATOMIC_BLOCK #define ATOMIC_BLOCK
#elif defined(MY_RF24_IRQ_PIN) #elif defined(MY_RF24_IRQ_PIN)
#define ATOMIC_BLOCK for ( ATOMIC_BLOCK_CLEANUP, __hwLock(); \ #define ATOMIC_BLOCK for ( ATOMIC_BLOCK_CLEANUP, __hwLock(); \
__atomic_loop ; __atomic_loop = 0 ) __atomic_loop ; __atomic_loop = 0 )
#else #else
#define ATOMIC_BLOCK #define ATOMIC_BLOCK
#endif /* DOXYGEN */ #endif /* DOXYGEN */
#ifndef DOXYGEN #ifndef DOXYGEN
#define MY_CRITICAL_SECTION ATOMIC_BLOCK #define MY_CRITICAL_SECTION ATOMIC_BLOCK
#endif /* DOXYGEN */ #endif /* DOXYGEN */
#endif #endif
+16 -15
View File
@@ -29,12 +29,12 @@ void hwInit()
{ {
#ifdef MY_GATEWAY_SERIAL #ifdef MY_GATEWAY_SERIAL
MY_SERIALDEVICE.begin(MY_BAUD_RATE); MY_SERIALDEVICE.begin(MY_BAUD_RATE);
#ifdef MY_LINUX_SERIAL_GROUPNAME #ifdef MY_LINUX_SERIAL_GROUPNAME
if (!MY_SERIALDEVICE.setGroupPerm(MY_LINUX_SERIAL_GROUPNAME)) { if (!MY_SERIALDEVICE.setGroupPerm(MY_LINUX_SERIAL_GROUPNAME)) {
logError("Unable to change permission for serial port device.\n"); logError("Unable to change permission for serial port device.\n");
exit(1); exit(1);
} }
#endif #endif
#endif #endif
} }
@@ -87,7 +87,8 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
} }
// Not supported! // Not supported!
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
unsigned long ms)
{ {
(void)interrupt1; (void)interrupt1;
(void)mode1; (void)mode1;
@@ -99,34 +100,34 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo
} }
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG) #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
uint16_t hwCPUVoltage() uint16_t hwCPUVoltage()
{ {
// TODO: Not supported! // TODO: Not supported!
return 0; return 0;
} }
uint16_t hwCPUFrequency() uint16_t hwCPUFrequency()
{ {
// TODO: Not supported! // TODO: Not supported!
return 0; return 0;
} }
uint16_t hwFreeMem() uint16_t hwFreeMem()
{ {
// TODO: Not supported! // TODO: Not supported!
return 0; return 0;
} }
#endif #endif
#ifdef MY_DEBUG #ifdef MY_DEBUG
void hwDebugPrint(const char *fmt, ...) void hwDebugPrint(const char *fmt, ...)
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
vlogDebug(fmt, args); vlogDebug(fmt, args);
va_end(args); va_end(args);
} }
#endif #endif
void hwDigitalWrite(uint8_t pin, uint8_t value) void hwDigitalWrite(uint8_t pin, uint8_t value)
+6 -3
View File
@@ -26,15 +26,18 @@
#include "log.h" #include "log.h"
#include "bcm2835.h" #include "bcm2835.h"
class Bcm2835Init { class Bcm2835Init
{
public: public:
Bcm2835Init() { Bcm2835Init()
{
if (!bcm2835_init()) { if (!bcm2835_init()) {
logError("Failed to initialized bcm2835.\n"); logError("Failed to initialized bcm2835.\n");
exit(1); exit(1);
} }
} }
~Bcm2835Init() { ~Bcm2835Init()
{
bcm2835_close(); bcm2835_close();
} }
}; };
+36 -26
View File
@@ -42,7 +42,8 @@ ISR (WDT_vect)
void i2c_eeprom_write_byte(unsigned int eeaddress, byte data ) { void i2c_eeprom_write_byte(unsigned int eeaddress, byte data )
{
int rdata = data; int rdata = data;
Wire.beginTransmission(I2C_EEP_ADDRESS); Wire.beginTransmission(I2C_EEP_ADDRESS);
Wire.write((int)(eeaddress >> 8)); // MSB Wire.write((int)(eeaddress >> 8)); // MSB
@@ -51,7 +52,8 @@ void i2c_eeprom_write_byte(unsigned int eeaddress, byte data ) {
Wire.endTransmission(); Wire.endTransmission();
} }
byte i2c_eeprom_read_byte(unsigned int eeaddress ) { byte i2c_eeprom_read_byte(unsigned int eeaddress )
{
byte rdata = 0xFF; byte rdata = 0xFF;
Wire.beginTransmission(I2C_EEP_ADDRESS); Wire.beginTransmission(I2C_EEP_ADDRESS);
Wire.write((int)(eeaddress >> 8)); // MSB Wire.write((int)(eeaddress >> 8)); // MSB
@@ -68,8 +70,7 @@ void hwReadConfigBlock(void* buf, void* adr, size_t length)
{ {
uint8_t* dst = static_cast<uint8_t*>(buf); uint8_t* dst = static_cast<uint8_t*>(buf);
int offs = reinterpret_cast<int>(adr); int offs = reinterpret_cast<int>(adr);
while (length-- > 0) while (length-- > 0) {
{
*dst++ = i2c_eeprom_read_byte(offs++); *dst++ = i2c_eeprom_read_byte(offs++);
} }
} }
@@ -78,8 +79,7 @@ void hwWriteConfigBlock(void* buf, void* adr, size_t length)
{ {
uint8_t* src = static_cast<uint8_t*>(buf); uint8_t* src = static_cast<uint8_t*>(buf);
int offs = reinterpret_cast<int>(adr); int offs = reinterpret_cast<int>(adr);
while (length-- > 0) while (length-- > 0) {
{
i2c_eeprom_write_byte(offs++, *src++); i2c_eeprom_write_byte(offs++, *src++);
} }
} }
@@ -94,36 +94,40 @@ uint8_t hwReadConfig(int adr)
void hwWriteConfig(int adr, uint8_t value) void hwWriteConfig(int adr, uint8_t value)
{ {
uint8_t curr = hwReadConfig(adr); uint8_t curr = hwReadConfig(adr);
if (curr != value) if (curr != value) {
{
hwWriteConfigBlock(&value, reinterpret_cast<void*>(adr), 1); hwWriteConfigBlock(&value, reinterpret_cast<void*>(adr), 1);
} }
} }
void hwInit() { void hwInit()
{
MY_SERIALDEVICE.begin(MY_BAUD_RATE); MY_SERIALDEVICE.begin(MY_BAUD_RATE);
#if defined(MY_GATEWAY_SERIAL) #if defined(MY_GATEWAY_SERIAL)
while (!MY_SERIALDEVICE) {} while (!MY_SERIALDEVICE) {}
#endif #endif
Wire.begin(); Wire.begin();
} }
void hwWatchdogReset() { void hwWatchdogReset()
{
// TODO: Not supported! // TODO: Not supported!
} }
void hwReboot() { void hwReboot()
{
NVIC_SystemReset(); NVIC_SystemReset();
while (true); while (true);
} }
int8_t hwSleep(unsigned long ms) { int8_t hwSleep(unsigned long ms)
{
// TODO: Not supported! // TODO: Not supported!
(void)ms; (void)ms;
return MY_SLEEP_NOT_POSSIBLE; return MY_SLEEP_NOT_POSSIBLE;
} }
int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
{
// TODO: Not supported! // TODO: Not supported!
(void)interrupt; (void)interrupt;
(void)mode; (void)mode;
@@ -131,7 +135,9 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) {
return MY_SLEEP_NOT_POSSIBLE; return MY_SLEEP_NOT_POSSIBLE;
} }
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
unsigned long ms)
{
// TODO: Not supported! // TODO: Not supported!
(void)interrupt1; (void)interrupt1;
(void)mode1; (void)mode1;
@@ -142,7 +148,8 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo
} }
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG) #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
uint16_t hwCPUVoltage() { uint16_t hwCPUVoltage()
{
// disable ADC // disable ADC
while (ADC->STATUS.bit.SYNCBUSY); while (ADC->STATUS.bit.SYNCBUSY);
@@ -178,39 +185,42 @@ uint16_t hwCPUVoltage() {
return valueRead * 4; return valueRead * 4;
} }
uint16_t hwCPUFrequency() { uint16_t hwCPUFrequency()
{
// TODO: currently reporting compile time frequency (in 1/10MHz) // TODO: currently reporting compile time frequency (in 1/10MHz)
return F_CPU / 100000UL; return F_CPU / 100000UL;
} }
uint16_t hwFreeMem() { uint16_t hwFreeMem()
{
// TODO: Not supported! // TODO: Not supported!
return 0; return 0;
} }
#endif #endif
#ifdef MY_DEBUG #ifdef MY_DEBUG
void hwDebugPrint(const char *fmt, ... ) { void hwDebugPrint(const char *fmt, ... )
{
if (MY_SERIALDEVICE) { if (MY_SERIALDEVICE) {
char fmtBuffer[MY_SERIAL_OUTPUT_SIZE]; char fmtBuffer[MY_SERIAL_OUTPUT_SIZE];
#ifdef MY_GATEWAY_FEATURE #ifdef MY_GATEWAY_FEATURE
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
snprintf(fmtBuffer, sizeof(fmtBuffer), PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE); snprintf(fmtBuffer, sizeof(fmtBuffer), PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE);
MY_SERIALDEVICE.print(fmtBuffer); MY_SERIALDEVICE.print(fmtBuffer);
#endif #endif
va_list args; va_list args;
va_start (args, fmt ); va_start (args, fmt );
#ifdef MY_GATEWAY_FEATURE #ifdef MY_GATEWAY_FEATURE
// Truncate message if this is gateway node // Truncate message if this is gateway node
vsnprintf(fmtBuffer, sizeof(fmtBuffer), fmt, args); vsnprintf(fmtBuffer, sizeof(fmtBuffer), fmt, args);
fmtBuffer[sizeof(fmtBuffer) - 2] = '\n'; fmtBuffer[sizeof(fmtBuffer) - 2] = '\n';
fmtBuffer[sizeof(fmtBuffer) - 1] = '\0'; fmtBuffer[sizeof(fmtBuffer) - 1] = '\0';
#else #else
vsnprintf(fmtBuffer, sizeof(fmtBuffer), fmt, args); vsnprintf(fmtBuffer, sizeof(fmtBuffer), fmt, args);
#endif #endif
va_end (args); va_end (args);
MY_SERIALDEVICE.print(fmtBuffer); MY_SERIALDEVICE.print(fmtBuffer);
// MY_SERIALDEVICE.flush(); // MY_SERIALDEVICE.flush();
//MY_SERIALDEVICE.write(freeRam()); //MY_SERIALDEVICE.write(freeRam());
} }
+1 -1
View File
@@ -73,7 +73,7 @@ static __inline__ void __priMaskRestore(const uint32_t *priMask)
} }
#ifndef DOXYGEN #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 /* DOXYGEN */
#endif // #ifdef ARDUINO_ARCH_SAMD #endif // #ifdef ARDUINO_ARCH_SAMD
+11 -8
View File
@@ -19,24 +19,26 @@
#include "MyInclusionMode.h" #include "MyInclusionMode.h"
// global variables // global variables
extern MyMessage _msgTmp; extern MyMessage _msgTmp;
unsigned long _inclusionStartTime; unsigned long _inclusionStartTime;
bool _inclusionMode; bool _inclusionMode;
inline void inclusionInit() { inline void inclusionInit()
{
_inclusionMode = false; _inclusionMode = false;
#if defined(MY_INCLUSION_BUTTON_FEATURE) #if defined(MY_INCLUSION_BUTTON_FEATURE)
// Setup digital in that triggers inclusion mode // Setup digital in that triggers inclusion mode
hwPinMode(MY_INCLUSION_MODE_BUTTON_PIN, INPUT); hwPinMode(MY_INCLUSION_MODE_BUTTON_PIN, INPUT);
hwDigitalWrite(MY_INCLUSION_MODE_BUTTON_PIN, HIGH); hwDigitalWrite(MY_INCLUSION_MODE_BUTTON_PIN, HIGH);
#endif #endif
} }
void inclusionModeSet(bool newMode) { void inclusionModeSet(bool newMode)
{
if (newMode != _inclusionMode) { if (newMode != _inclusionMode) {
_inclusionMode = newMode; _inclusionMode = newMode;
// Send back mode change to controller // Send back mode change to controller
@@ -47,13 +49,14 @@ void inclusionModeSet(bool newMode) {
} }
} }
inline void inclusionProcess() { inline void inclusionProcess()
#ifdef MY_INCLUSION_BUTTON_FEATURE {
#ifdef MY_INCLUSION_BUTTON_FEATURE
if (!_inclusionMode && hwDigitalRead(MY_INCLUSION_MODE_BUTTON_PIN) == MY_INCLUSION_BUTTON_PRESSED) { if (!_inclusionMode && hwDigitalRead(MY_INCLUSION_MODE_BUTTON_PIN) == MY_INCLUSION_BUTTON_PRESSED) {
// Start inclusion mode // Start inclusion mode
inclusionModeSet(true); inclusionModeSet(true);
} }
#endif #endif
if (_inclusionMode && hwMillis()-_inclusionStartTime>MY_INCLUSION_MODE_DURATION*1000L) { if (_inclusionMode && hwMillis()-_inclusionStartTime>MY_INCLUSION_MODE_DURATION*1000L) {
// inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode // inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode
+3 -6
View File
@@ -25,20 +25,17 @@
void setIndication( const indication_t ind ) void setIndication( const indication_t ind )
{ {
#if defined(MY_DEFAULT_TX_LED_PIN) #if defined(MY_DEFAULT_TX_LED_PIN)
if ((INDICATION_TX == ind) || (INDICATION_GW_TX == ind)) if ((INDICATION_TX == ind) || (INDICATION_GW_TX == ind)) {
{
ledsBlinkTx(1); ledsBlinkTx(1);
} else } else
#endif #endif
#if defined(MY_DEFAULT_RX_LED_PIN) #if defined(MY_DEFAULT_RX_LED_PIN)
if ((INDICATION_RX == ind) || (INDICATION_GW_RX == ind)) if ((INDICATION_RX == ind) || (INDICATION_GW_RX == ind)) {
{
ledsBlinkRx(1); ledsBlinkRx(1);
} else } else
#endif #endif
#if defined(MY_DEFAULT_ERR_LED_PIN) #if defined(MY_DEFAULT_ERR_LED_PIN)
if (ind > INDICATION_ERR_START) if (ind > INDICATION_ERR_START) {
{
// Number of blinks indicates which error occurred. // Number of blinks indicates which error occurred.
ledsBlinkErr(ind-INDICATION_ERR_START); ledsBlinkErr(ind-INDICATION_ERR_START);
} }
+24 -18
View File
@@ -36,20 +36,22 @@ inline void ledsInit()
countErr = 0; countErr = 0;
// Setup led pins // Setup led pins
#if defined(MY_DEFAULT_RX_LED_PIN) #if defined(MY_DEFAULT_RX_LED_PIN)
hwPinMode(MY_DEFAULT_RX_LED_PIN, OUTPUT); hwPinMode(MY_DEFAULT_RX_LED_PIN, OUTPUT);
#endif #endif
#if defined(MY_DEFAULT_TX_LED_PIN) #if defined(MY_DEFAULT_TX_LED_PIN)
hwPinMode(MY_DEFAULT_TX_LED_PIN, OUTPUT); hwPinMode(MY_DEFAULT_TX_LED_PIN, OUTPUT);
#endif #endif
#if defined(MY_DEFAULT_ERR_LED_PIN) #if defined(MY_DEFAULT_ERR_LED_PIN)
hwPinMode(MY_DEFAULT_ERR_LED_PIN, OUTPUT); hwPinMode(MY_DEFAULT_ERR_LED_PIN, OUTPUT);
#endif #endif
prevTime = hwMillis() - LED_PROCESS_INTERVAL_MS; // Substract some, to make sure leds gets updated on first run. prevTime = hwMillis() -
LED_PROCESS_INTERVAL_MS; // Substract some, to make sure leds gets updated on first run.
ledsProcess(); ledsProcess();
} }
void ledsProcess() { void ledsProcess()
{
// Just return if it is not the time... // Just return if it is not the time...
if ((hwMillis() - prevTime) < LED_PROCESS_INTERVAL_MS) { if ((hwMillis() - prevTime) < LED_PROCESS_INTERVAL_MS) {
return; return;
@@ -60,52 +62,56 @@ void ledsProcess() {
// For an On/Off ratio of 4, the pattern repeated will be [on, on, on, off] // For an On/Off ratio of 4, the pattern repeated will be [on, on, on, off]
// until the counter becomes 0. // until the counter becomes 0.
#if defined(MY_DEFAULT_RX_LED_PIN) #if defined(MY_DEFAULT_RX_LED_PIN)
if (countRx) { if (countRx) {
--countRx; --countRx;
} }
state = (countRx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; state = (countRx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF;
hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, state); hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, state);
#endif #endif
#if defined(MY_DEFAULT_TX_LED_PIN) #if defined(MY_DEFAULT_TX_LED_PIN)
if (countTx) { if (countTx) {
--countTx; --countTx;
} }
state = (countTx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; state = (countTx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF;
hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, state); hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, state);
#endif #endif
#if defined(MY_DEFAULT_ERR_LED_PIN) #if defined(MY_DEFAULT_ERR_LED_PIN)
if (countErr) { if (countErr) {
--countErr; --countErr;
} }
state = (countErr & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; state = (countErr & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF;
hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, state); hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, state);
#endif #endif
} }
void ledsBlinkRx(uint8_t cnt) { void ledsBlinkRx(uint8_t cnt)
{
if (!countRx) { if (!countRx) {
countRx = cnt*LED_ON_OFF_RATIO; countRx = cnt*LED_ON_OFF_RATIO;
} }
ledsProcess(); ledsProcess();
} }
void ledsBlinkTx(uint8_t cnt) { void ledsBlinkTx(uint8_t cnt)
{
if(!countTx) { if(!countTx) {
countTx = cnt*LED_ON_OFF_RATIO; countTx = cnt*LED_ON_OFF_RATIO;
} }
ledsProcess(); ledsProcess();
} }
void ledsBlinkErr(uint8_t cnt) { void ledsBlinkErr(uint8_t cnt)
{
if(!countErr) { if(!countErr) {
countErr = cnt*LED_ON_OFF_RATIO; countErr = cnt*LED_ON_OFF_RATIO;
} }
ledsProcess(); ledsProcess();
} }
bool ledsBlinking() { bool ledsBlinking()
{
return countRx || countTx || countErr; return countRx || countTx || countErr;
} }
+15 -15
View File
@@ -30,30 +30,30 @@
#endif #endif
#if defined(MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) #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 ledBlinkTx(x,...) ledsBlinkTx(x)
#define ledBlinkRx(x,...) ledsBlinkRx(x) #define ledBlinkRx(x,...) ledsBlinkRx(x)
#define ledBlinkErr(x,...) ledsBlinkErr(x) #define ledBlinkErr(x,...) ledsBlinkErr(x)
/** /**
* Blink with LEDs * Blink with LEDs
* @param cnt how many blink cycles to keep the LED on. Default cycle is 300ms * @param cnt how many blink cycles to keep the LED on. Default cycle is 300ms
*/ */
void ledsInit(); void ledsInit();
void ledsBlinkRx(uint8_t cnt); void ledsBlinkRx(uint8_t cnt);
void ledsBlinkTx(uint8_t cnt); void ledsBlinkTx(uint8_t cnt);
void ledsBlinkErr(uint8_t cnt); void ledsBlinkErr(uint8_t cnt);
void ledsProcess(); // do the actual blinking void ledsProcess(); // do the actual blinking
/** /**
* Test if any LED is currently blinking. * Test if any LED is currently blinking.
* @return true when one or more LEDs are blinking, false otherwise. * @return true when one or more LEDs are blinking, false otherwise.
*/ */
bool ledsBlinking(); bool ledsBlinking();
#else #else
// Remove led functions if feature is disabled // Remove led functions if feature is disabled
#define ledBlinkTx(x,...) #define ledBlinkTx(x,...)
#define ledBlinkRx(x,...) #define ledBlinkRx(x,...)
#define ledBlinkErr(x,...) #define ledBlinkErr(x,...)
#endif #endif
#endif #endif
+6 -5
View File
@@ -21,15 +21,16 @@
extern "C" void __libc_init_array(void); extern "C" void __libc_init_array(void);
int main(void) { int main(void)
{
init(); init();
#if defined(USBCON) #if defined(USBCON)
#if defined(ARDUINO_ARCH_SAMD) #if defined(ARDUINO_ARCH_SAMD)
__libc_init_array(); __libc_init_array();
USBDevice.init(); USBDevice.init();
#endif #endif
USBDevice.attach(); USBDevice.attach();
#endif #endif
_begin(); // Startup MySensors library _begin(); // Startup MySensors library
for(;;) { for(;;) {
+28 -17
View File
@@ -38,7 +38,8 @@ extern "C" {
struct rst_info resetInfo; struct rst_info resetInfo;
extern "C" { extern "C" {
extern const uint32_t __attribute__((section(".ver_number"))) core_version = ARDUINO_ESP8266_GIT_VER; extern const uint32_t __attribute__((section(".ver_number"))) core_version =
ARDUINO_ESP8266_GIT_VER;
const char* core_release = const char* core_release =
#ifdef ARDUINO_ESP8266_RELEASE #ifdef ARDUINO_ESP8266_RELEASE
ARDUINO_ESP8266_RELEASE; ARDUINO_ESP8266_RELEASE;
@@ -47,18 +48,21 @@ extern "C" {
#endif #endif
} // extern "C" } // extern "C"
int atexit(void(*func)()) { int atexit(void(*func)())
{
(void)func; (void)func;
return 0; return 0;
} }
extern "C" void ets_update_cpu_frequency(int freqmhz); extern "C" void ets_update_cpu_frequency(int freqmhz);
void initVariant() __attribute__((weak)); void initVariant() __attribute__((weak));
void initVariant() { void initVariant()
{
} }
void preloop_update_frequency() __attribute__((weak)); void preloop_update_frequency() __attribute__((weak));
void preloop_update_frequency() { void preloop_update_frequency()
{
#if defined(F_CPU) && (F_CPU == 160000000L) #if defined(F_CPU) && (F_CPU == 160000000L)
REG_SET_BIT(0x3ff00014, BIT(0)); REG_SET_BIT(0x3ff00014, BIT(0));
ets_update_cpu_frequency(160); ets_update_cpu_frequency(160);
@@ -73,37 +77,40 @@ static os_event_t g_loop_queue[LOOP_QUEUE_SIZE];
static uint32_t g_micros_at_task_start; static uint32_t g_micros_at_task_start;
extern "C" void esp_yield() { extern "C" void esp_yield()
{
if (cont_can_yield(&g_cont)) { if (cont_can_yield(&g_cont)) {
cont_yield(&g_cont); cont_yield(&g_cont);
} }
} }
extern "C" void esp_schedule() { extern "C" void esp_schedule()
{
ets_post(LOOP_TASK_PRIORITY, 0, 0); ets_post(LOOP_TASK_PRIORITY, 0, 0);
} }
extern "C" void __yield() { extern "C" void __yield()
{
if (cont_can_yield(&g_cont)) { if (cont_can_yield(&g_cont)) {
esp_schedule(); esp_schedule();
esp_yield(); esp_yield();
} } else {
else {
panic(); panic();
} }
} }
extern "C" void yield(void) __attribute__((weak, alias("__yield"))); extern "C" void yield(void) __attribute__((weak, alias("__yield")));
extern "C" void optimistic_yield(uint32_t interval_us) { extern "C" void optimistic_yield(uint32_t interval_us)
{
if (cont_can_yield(&g_cont) && 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(); yield();
} }
} }
static void loop_wrapper() { static void loop_wrapper()
{
static bool setup_done = false; static bool setup_done = false;
preloop_update_frequency(); preloop_update_frequency();
if (!setup_done) { if (!setup_done) {
@@ -116,7 +123,8 @@ static void loop_wrapper() {
esp_schedule(); esp_schedule();
} }
static void loop_task(os_event_t *events) { static void loop_task(os_event_t *events)
{
(void)events; (void)events;
g_micros_at_task_start = system_get_time(); g_micros_at_task_start = system_get_time();
cont_run(&g_cont, &loop_wrapper); cont_run(&g_cont, &loop_wrapper);
@@ -125,7 +133,8 @@ static void loop_task(os_event_t *events) {
} }
} }
static void do_global_ctors(void) { static void do_global_ctors(void)
{
void(**p)(void) = &__init_array_end; void(**p)(void) = &__init_array_end;
while (p != &__init_array_start) { while (p != &__init_array_start) {
(*--p)(); (*--p)();
@@ -138,7 +147,8 @@ extern "C" void gdb_init(void) __attribute__((weak, alias("__gdb_init")));
extern "C" void __gdb_do_break() {} extern "C" void __gdb_do_break() {}
extern "C" void gdb_do_break(void) __attribute__((weak, alias("__gdb_do_break"))); extern "C" void gdb_do_break(void) __attribute__((weak, alias("__gdb_do_break")));
void init_done() { void init_done()
{
system_set_os_print(1); system_set_os_print(1);
gdb_init(); gdb_init();
do_global_ctors(); do_global_ctors();
@@ -146,7 +156,8 @@ void init_done() {
} }
extern "C" void user_init(void) { extern "C" void user_init(void)
{
struct rst_info *rtc_info_ptr = system_get_rst_info(); struct rst_info *rtc_info_ptr = system_get_rst_info();
memcpy((void *)&resetInfo, (void *)rtc_info_ptr, sizeof(resetInfo)); memcpy((void *)&resetInfo, (void *)rtc_info_ptr, sizeof(resetInfo));
+26 -17
View File
@@ -16,7 +16,7 @@
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation. * version 2 as published by the Free Software Foundation.
*/ */
// Initialize library and handle sketch functions like we want to // Initialize library and handle sketch functions like we want to
#include <stdio.h> #include <stdio.h>
#include <csignal> #include <csignal>
@@ -40,13 +40,13 @@ void handle_sigint(int sig)
return; return;
} }
#ifdef MY_RF24_IRQ_PIN #ifdef MY_RF24_IRQ_PIN
detachInterrupt(MY_RF24_IRQ_PIN); detachInterrupt(MY_RF24_IRQ_PIN);
#endif #endif
#if defined(MY_GATEWAY_SERIAL) #if defined(MY_GATEWAY_SERIAL)
MY_SERIALDEVICE.end(); MY_SERIALDEVICE.end();
#endif #endif
closelog(); closelog();
@@ -137,7 +137,9 @@ void print_soft_sign_hmac_key(uint8_t *key_ptr = NULL)
printf("#define MY_SOFT_HMAC_KEY "); printf("#define MY_SOFT_HMAC_KEY ");
for (int i=0; i<32; i++) { for (int i=0; i<32; i++) {
printf("%#02X", key_ptr[i]); printf("%#02X", key_ptr[i]);
if (i < 31) printf(","); if (i < 31) {
printf(",");
}
} }
printf("\n\n"); printf("\n\n");
} }
@@ -172,12 +174,13 @@ void set_soft_sign_hmac_key(char *key_str)
} else { } else {
for (int i = 0; i < 64; ++i) { for (int i = 0; i < 64; ++i) {
char c = key_str[i]; char c = key_str[i];
if (c <= '9') if (c <= '9') {
n = c - '0'; n = c - '0';
else if (c >= 'a') } else if (c >= 'a') {
n = c - 'a' + 10; n = c - 'a' + 10;
else } else {
n = c - 'A' + 10; n = c - 'A' + 10;
}
if ((i & 0x1) == 0) { if ((i & 0x1) == 0) {
key[i/2] = n * 16; key[i/2] = n * 16;
@@ -209,7 +212,9 @@ void print_soft_sign_serial_key(uint8_t *key_ptr = NULL)
printf("#define MY_SOFT_SERIAL "); printf("#define MY_SOFT_SERIAL ");
for (int i=0; i<9; i++) { for (int i=0; i<9; i++) {
printf("%#02X", key_ptr[i]); printf("%#02X", key_ptr[i]);
if (i < 8) printf(","); if (i < 8) {
printf(",");
}
} }
printf("\n\n"); printf("\n\n");
} }
@@ -244,12 +249,13 @@ void set_soft_sign_serial_key(char *key_str)
} else { } else {
for (int i = 0; i < 18; ++i) { for (int i = 0; i < 18; ++i) {
char c = key_str[i]; char c = key_str[i];
if (c <= '9') if (c <= '9') {
n = c - '0'; n = c - '0';
else if (c >= 'a') } else if (c >= 'a') {
n = c - 'a' + 10; n = c - 'a' + 10;
else } else {
n = c - 'A' + 10; n = c - 'A' + 10;
}
if ((i & 0x1) == 0) { if ((i & 0x1) == 0) {
key[i/2] = n * 16; key[i/2] = n * 16;
@@ -281,7 +287,9 @@ void print_aes_key(uint8_t *key_ptr = NULL)
printf("#define MY_AES_KEY "); printf("#define MY_AES_KEY ");
for (int i=0; i<16; i++) { for (int i=0; i<16; i++) {
printf("%#02X", key_ptr[i]); printf("%#02X", key_ptr[i]);
if (i < 15) printf(","); if (i < 15) {
printf(",");
}
} }
printf("\n\n"); printf("\n\n");
} }
@@ -316,12 +324,13 @@ void set_aes_key(char *key_str)
} else { } else {
for (int i = 0; i < 32; ++i) { for (int i = 0; i < 32; ++i) {
char c = key_str[i]; char c = key_str[i];
if (c <= '9') if (c <= '9') {
n = c - '0'; n = c - '0';
else if (c >= 'a') } else if (c >= 'a') {
n = c - 'a' + 10; n = c - 'a' + 10;
else } else {
n = c - 'A' + 10; n = c - 'A' + 10;
}
if ((i & 0x1) == 0) { if ((i & 0x1) == 0) {
key[i/2] = n * 16; key[i/2] = n * 16;
+56 -31
View File
@@ -50,20 +50,24 @@ void MyMessage::clear()
miSetVersion(PROTOCOL_VERSION); miSetVersion(PROTOCOL_VERSION);
} }
bool MyMessage::isAck() const { bool MyMessage::isAck() const
{
return miGetAck(); return miGetAck();
} }
uint8_t MyMessage::getCommand() const { uint8_t MyMessage::getCommand() const
{
return miGetCommand(); return miGetCommand();
} }
/* Getters for payload converted to desired form */ /* Getters for payload converted to desired form */
void* MyMessage::getCustom() const { void* MyMessage::getCustom() const
{
return (void *)data; return (void *)data;
} }
const char* MyMessage::getString() const { const char* MyMessage::getString() const
{
uint8_t payloadType = miGetPayloadType(); uint8_t payloadType = miGetPayloadType();
if (payloadType == P_STRING) { if (payloadType == P_STRING) {
return data; return data;
@@ -73,19 +77,19 @@ const char* MyMessage::getString() const {
} }
// handles single character hex (0 - 15) // handles single character hex (0 - 15)
char MyMessage::i2h(uint8_t i) const { char MyMessage::i2h(uint8_t i) const
{
uint8_t k = i & 0x0F; uint8_t k = i & 0x0F;
if (k <= 9) { if (k <= 9) {
return '0' + k; return '0' + k;
} } else {
else {
return 'A' + k - 10; return 'A' + k - 10;
} }
} }
char* MyMessage::getCustomString(char *buffer) const { char* MyMessage::getCustomString(char *buffer) const
for (uint8_t i = 0; i < miGetLength(); i++) {
{ for (uint8_t i = 0; i < miGetLength(); i++) {
buffer[i * 2] = i2h(data[i] >> 4); buffer[i * 2] = i2h(data[i] >> 4);
buffer[(i * 2) + 1] = i2h(data[i]); buffer[(i * 2) + 1] = i2h(data[i]);
} }
@@ -93,7 +97,8 @@ char* MyMessage::getCustomString(char *buffer) const {
return buffer; return buffer;
} }
char* MyMessage::getStream(char *buffer) const { char* MyMessage::getStream(char *buffer) const
{
uint8_t cmd = miGetCommand(); uint8_t cmd = miGetCommand();
if ((cmd == C_STREAM) && (buffer != NULL)) { if ((cmd == C_STREAM) && (buffer != NULL)) {
return getCustomString(buffer); return getCustomString(buffer);
@@ -102,7 +107,8 @@ char* MyMessage::getStream(char *buffer) const {
} }
} }
char* MyMessage::getString(char *buffer) const { char* MyMessage::getString(char *buffer) const
{
uint8_t payloadType = miGetPayloadType(); uint8_t payloadType = miGetPayloadType();
if (buffer != NULL) { if (buffer != NULL) {
if (payloadType == P_STRING) { if (payloadType == P_STRING) {
@@ -129,11 +135,13 @@ char* MyMessage::getString(char *buffer) const {
} }
} }
bool MyMessage::getBool() const { bool MyMessage::getBool() const
{
return getByte(); return getByte();
} }
uint8_t MyMessage::getByte() const { uint8_t MyMessage::getByte() const
{
if (miGetPayloadType() == P_BYTE) { if (miGetPayloadType() == P_BYTE) {
return data[0]; return data[0];
} else if (miGetPayloadType() == P_STRING) { } else if (miGetPayloadType() == P_STRING) {
@@ -144,7 +152,8 @@ uint8_t MyMessage::getByte() const {
} }
float MyMessage::getFloat() const { float MyMessage::getFloat() const
{
if (miGetPayloadType() == P_FLOAT32) { if (miGetPayloadType() == P_FLOAT32) {
return fValue; return fValue;
} else if (miGetPayloadType() == P_STRING) { } else if (miGetPayloadType() == P_STRING) {
@@ -154,7 +163,8 @@ float MyMessage::getFloat() const {
} }
} }
int32_t MyMessage::getLong() const { int32_t MyMessage::getLong() const
{
if (miGetPayloadType() == P_LONG32) { if (miGetPayloadType() == P_LONG32) {
return lValue; return lValue;
} else if (miGetPayloadType() == P_STRING) { } else if (miGetPayloadType() == P_STRING) {
@@ -164,7 +174,8 @@ int32_t MyMessage::getLong() const {
} }
} }
uint32_t MyMessage::getULong() const { uint32_t MyMessage::getULong() const
{
if (miGetPayloadType() == P_ULONG32) { if (miGetPayloadType() == P_ULONG32) {
return ulValue; return ulValue;
} else if (miGetPayloadType() == P_STRING) { } else if (miGetPayloadType() == P_STRING) {
@@ -174,7 +185,8 @@ uint32_t MyMessage::getULong() const {
} }
} }
int16_t MyMessage::getInt() const { int16_t MyMessage::getInt() const
{
if (miGetPayloadType() == P_INT16) { if (miGetPayloadType() == P_INT16) {
return iValue; return iValue;
} else if (miGetPayloadType() == P_STRING) { } else if (miGetPayloadType() == P_STRING) {
@@ -184,7 +196,8 @@ int16_t MyMessage::getInt() const {
} }
} }
uint16_t MyMessage::getUInt() const { uint16_t MyMessage::getUInt() const
{
if (miGetPayloadType() == P_UINT16) { if (miGetPayloadType() == P_UINT16) {
return uiValue; return uiValue;
} else if (miGetPayloadType() == P_STRING) { } else if (miGetPayloadType() == P_STRING) {
@@ -195,23 +208,27 @@ uint16_t MyMessage::getUInt() const {
} }
MyMessage& MyMessage::setType(uint8_t _type) { MyMessage& MyMessage::setType(uint8_t _type)
{
type = _type; type = _type;
return *this; return *this;
} }
MyMessage& MyMessage::setSensor(uint8_t _sensor) { MyMessage& MyMessage::setSensor(uint8_t _sensor)
{
sensor = _sensor; sensor = _sensor;
return *this; return *this;
} }
MyMessage& MyMessage::setDestination(uint8_t _destination) { MyMessage& MyMessage::setDestination(uint8_t _destination)
{
destination = _destination; destination = _destination;
return *this; return *this;
} }
// Set payload // Set payload
MyMessage& MyMessage::set(void* value, uint8_t length) { MyMessage& MyMessage::set(void* value, uint8_t length)
{
uint8_t payloadLength = value == NULL ? 0 : min(length, (uint8_t)MAX_PAYLOAD); uint8_t payloadLength = value == NULL ? 0 : min(length, (uint8_t)MAX_PAYLOAD);
miSetLength(payloadLength); miSetLength(payloadLength);
miSetPayloadType(P_CUSTOM); miSetPayloadType(P_CUSTOM);
@@ -219,7 +236,8 @@ MyMessage& MyMessage::set(void* value, uint8_t length) {
return *this; return *this;
} }
MyMessage& MyMessage::set(const char* value) { MyMessage& MyMessage::set(const char* value)
{
uint8_t length = value == NULL ? 0 : min(strlen(value), (size_t)MAX_PAYLOAD); uint8_t length = value == NULL ? 0 : min(strlen(value), (size_t)MAX_PAYLOAD);
miSetLength(length); miSetLength(length);
miSetPayloadType(P_STRING); miSetPayloadType(P_STRING);
@@ -231,21 +249,24 @@ MyMessage& MyMessage::set(const char* value) {
return *this; return *this;
} }
MyMessage& MyMessage::set(bool value) { MyMessage& MyMessage::set(bool value)
{
miSetLength(1); miSetLength(1);
miSetPayloadType(P_BYTE); miSetPayloadType(P_BYTE);
data[0] = value; data[0] = value;
return *this; return *this;
} }
MyMessage& MyMessage::set(uint8_t value) { MyMessage& MyMessage::set(uint8_t value)
{
miSetLength(1); miSetLength(1);
miSetPayloadType(P_BYTE); miSetPayloadType(P_BYTE);
data[0] = value; data[0] = value;
return *this; return *this;
} }
MyMessage& MyMessage::set(float value, uint8_t decimals) { MyMessage& MyMessage::set(float value, uint8_t decimals)
{
miSetLength(5); // 32 bit float + persi miSetLength(5); // 32 bit float + persi
miSetPayloadType(P_FLOAT32); miSetPayloadType(P_FLOAT32);
fValue=value; fValue=value;
@@ -253,28 +274,32 @@ MyMessage& MyMessage::set(float value, uint8_t decimals) {
return *this; return *this;
} }
MyMessage& MyMessage::set(uint32_t value) { MyMessage& MyMessage::set(uint32_t value)
{
miSetPayloadType(P_ULONG32); miSetPayloadType(P_ULONG32);
miSetLength(4); miSetLength(4);
ulValue = value; ulValue = value;
return *this; return *this;
} }
MyMessage& MyMessage::set(int32_t value) { MyMessage& MyMessage::set(int32_t value)
{
miSetPayloadType(P_LONG32); miSetPayloadType(P_LONG32);
miSetLength(4); miSetLength(4);
lValue = value; lValue = value;
return *this; return *this;
} }
MyMessage& MyMessage::set(uint16_t value) { MyMessage& MyMessage::set(uint16_t value)
{
miSetPayloadType(P_UINT16); miSetPayloadType(P_UINT16);
miSetLength(2); miSetLength(2);
uiValue = value; uiValue = value;
return *this; return *this;
} }
MyMessage& MyMessage::set(int16_t value) { MyMessage& MyMessage::set(int16_t value)
{
miSetPayloadType(P_INT16); miSetPayloadType(P_INT16);
miSetLength(2); miSetLength(2);
iValue = value; iValue = value;
+1 -2
View File
@@ -331,8 +331,7 @@ public:
#else #else
typedef union { typedef union {
struct struct {
{
#endif #endif
uint8_t last; // 8 bit - Id of last node this message passed uint8_t last; // 8 bit - Id of last node this message passed
+13 -8
View File
@@ -33,7 +33,8 @@ uint8_t _firmwareRetry;
void readFirmwareSettings(void) void readFirmwareSettings(void)
{ {
hwReadConfigBlock((void*)&_nodeFirmwareConfig, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(nodeFirmwareConfig_t)); hwReadConfigBlock((void*)&_nodeFirmwareConfig, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS,
sizeof(nodeFirmwareConfig_t));
} }
void firmwareOTAUpdateRequest(void) void firmwareOTAUpdateRequest(void)
@@ -54,8 +55,10 @@ void firmwareOTAUpdateRequest(void)
firmwareRequest.type = _nodeFirmwareConfig.type; firmwareRequest.type = _nodeFirmwareConfig.type;
firmwareRequest.version = _nodeFirmwareConfig.version; firmwareRequest.version = _nodeFirmwareConfig.version;
firmwareRequest.block = (_firmwareBlock - 1); firmwareRequest.block = (_firmwareBlock - 1);
OTA_DEBUG(PSTR("OTA:FRQ:FW REQ,T=%04X,V=%04X,B=%04X\n"), _nodeFirmwareConfig.type, _nodeFirmwareConfig.version, _firmwareBlock - 1); // request FW update block OTA_DEBUG(PSTR("OTA:FRQ:FW REQ,T=%04X,V=%04X,B=%04X\n"), _nodeFirmwareConfig.type,
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_REQUEST, false).set(&firmwareRequest, sizeof(requestFirmwareBlock_t))); _nodeFirmwareConfig.version, _firmwareBlock - 1); // request FW update block
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_REQUEST,
false).set(&firmwareRequest, sizeof(requestFirmwareBlock_t)));
} }
} }
@@ -96,7 +99,8 @@ bool firmwareOTAUpdateProcess(void)
// extract FW block // extract FW block
replyFirmwareBlock_t *firmwareResponse = (replyFirmwareBlock_t *)_msg.data; replyFirmwareBlock_t *firmwareResponse = (replyFirmwareBlock_t *)_msg.data;
// write to flash // write to flash
_flash.writeBytes( ((_firmwareBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET, firmwareResponse->data, FIRMWARE_BLOCK_SIZE); _flash.writeBytes( ((_firmwareBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET,
firmwareResponse->data, FIRMWARE_BLOCK_SIZE);
// wait until flash written // wait until flash written
while (_flash.busy()) {} while (_flash.busy()) {}
_firmwareBlock--; _firmwareBlock--;
@@ -107,7 +111,8 @@ bool firmwareOTAUpdateProcess(void)
if (transportIsValidFirmware()) { if (transportIsValidFirmware()) {
OTA_DEBUG(PSTR("OTA:FWP:CRC OK\n")); // FW checksum ok OTA_DEBUG(PSTR("OTA:FWP:CRC OK\n")); // FW checksum ok
// Write the new firmware config to eeprom // Write the new firmware config to eeprom
hwWriteConfigBlock((void*)&_nodeFirmwareConfig, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(nodeFirmwareConfig_t)); hwWriteConfigBlock((void*)&_nodeFirmwareConfig, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS,
sizeof(nodeFirmwareConfig_t));
// All seems ok, write size and signature to flash (DualOptiboot will pick this up and flash it) // All seems ok, write size and signature to flash (DualOptiboot will pick this up and flash it)
const uint16_t firmwareSize = FIRMWARE_BLOCK_SIZE * _nodeFirmwareConfig.blocks; const uint16_t firmwareSize = FIRMWARE_BLOCK_SIZE * _nodeFirmwareConfig.blocks;
const uint8_t OTAbuffer[FIRMWARE_START_OFFSET] = {'F','L','X','I','M','G',':', (uint8_t)(firmwareSize >> 8), (uint8_t)(firmwareSize & 0xff),':'}; const uint8_t OTAbuffer[FIRMWARE_START_OFFSET] = {'F','L','X','I','M','G',':', (uint8_t)(firmwareSize >> 8), (uint8_t)(firmwareSize & 0xff),':'};
@@ -142,7 +147,8 @@ void presentBootloaderInformation(void)
// add bootloader information // add bootloader information
requestFirmwareConfig->BLVersion = MY_OTA_BOOTLOADER_VERSION; requestFirmwareConfig->BLVersion = MY_OTA_BOOTLOADER_VERSION;
_firmwareUpdateOngoing = false; _firmwareUpdateOngoing = false;
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_CONFIG_REQUEST, false)); (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM,
ST_FIRMWARE_CONFIG_REQUEST, false));
} }
bool isFirmwareUpdateOngoing(void) bool isFirmwareUpdateOngoing(void)
{ {
@@ -158,8 +164,7 @@ bool transportIsValidFirmware(void)
for (int8_t j = 0; j < 8; ++j) { for (int8_t j = 0; j < 8; ++j) {
if (crc & 1) { if (crc & 1) {
crc = (crc >> 1) ^ 0xA001; crc = (crc >> 1) ^ 0xA001;
} } else {
else {
crc = (crc >> 1); crc = (crc >> 1);
} }
} }
+34 -34
View File
@@ -17,38 +17,38 @@
* version 2 as published by the Free Software Foundation. * version 2 as published by the Free Software Foundation.
*/ */
/** /**
* @file MyOTAFirmwareUpdate.h * @file MyOTAFirmwareUpdate.h
* *
* @defgroup MyOTAFirmwaregrp MyOTAFirmwareUpdate * @defgroup MyOTAFirmwaregrp MyOTAFirmwareUpdate
* @ingroup internals * @ingroup internals
* @{ * @{
* *
* MyOTAFirmwareUpdate-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE * MyOTAFirmwareUpdate-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE
* - [!] Exclamation mark is prepended in case of error or warning * - [!] Exclamation mark is prepended in case of error or warning
* - SYSTEM: * - SYSTEM:
* - <b>OTA</b> messages emitted by MyOTAFirmwareUpdate * - <b>OTA</b> messages emitted by MyOTAFirmwareUpdate
* - SUB SYSTEMS: * - SUB SYSTEMS:
* - OTA:<b>FRQ</b> from @ref firmwareOTAUpdateRequest() * - OTA:<b>FRQ</b> from @ref firmwareOTAUpdateRequest()
* - OTA:<b>FWP</b> from @ref firmwareOTAUpdateProcess() * - OTA:<b>FWP</b> from @ref firmwareOTAUpdateProcess()
* *
* MyOTAFirmwareUpdate debug log messages: * MyOTAFirmwareUpdate debug log messages:
* *
* |E| SYS | SUB | Message | Comment * |E| SYS | SUB | Message | Comment
* |-|------|-------|-------------------------------------------|---------------------------------------------------------------------------- * |-|------|-------|-------------------------------------------|----------------------------------------------------------------------------
* | | OTA | FWP | UPDATE | FW update initiated * | | OTA | FWP | UPDATE | FW update initiated
* |!| OTA | FWP | FLASH INIT FAIL | Failed to initialise flash * |!| OTA | FWP | FLASH INIT FAIL | Failed to initialise flash
* | | OTA | FWP | UPDATE SKIPPED | FW update skipped, no newer version available * | | OTA | FWP | UPDATE SKIPPED | FW update skipped, no newer version available
* | | OTA | FWP | RECV B=%04X | Received FW block (B) * | | OTA | FWP | RECV B=%04X | Received FW block (B)
* | | OTA | FWP | FW END | FW received, proceed to CRC verification * | | OTA | FWP | FW END | FW received, proceed to CRC verification
* | | OTA | FWP | CRC OK | FW CRC verification OK * | | OTA | FWP | CRC OK | FW CRC verification OK
* |!| OTA | FWP | CRC FAIL | FW CRC verification failed * |!| 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 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 * |!| OTA | FRQ | FW UPD FAIL | FW update failed
* *
* *
* @brief API declaration for MyOTAFirmwareUpdate * @brief API declaration for MyOTAFirmwareUpdate
*/ */
#ifndef MyOTAFirmwareUpdate_h #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 #define MY_OTA_BOOTLOADER_VERSION (MY_OTA_BOOTLOADER_MINOR_VERSION * 256 + MY_OTA_BOOTLOADER_MAJOR_VERSION) //!< Bootloader version
#if defined(MY_DEBUG) #if defined(MY_DEBUG)
#define OTA_DEBUG(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug #define OTA_DEBUG(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug
#else #else
#define OTA_DEBUG(x,...) //!< debug NULL #define OTA_DEBUG(x,...) //!< debug NULL
#endif #endif
/** /**
* @brief FW config structure, stored in eeprom * @brief FW config structure, stored in eeprom
+20 -14
View File
@@ -27,7 +27,8 @@ uint8_t protocolH2i(char c);
char _fmtBuffer[MY_GATEWAY_MAX_SEND_LENGTH]; char _fmtBuffer[MY_GATEWAY_MAX_SEND_LENGTH];
char _convBuffer[MAX_PAYLOAD*2+1]; char _convBuffer[MAX_PAYLOAD*2+1];
bool protocolParse(MyMessage &message, char *inputString) { bool protocolParse(MyMessage &message, char *inputString)
{
char *str, *p, *value=NULL; char *str, *p, *value=NULL;
uint8_t bvalue[MAX_PAYLOAD]; uint8_t bvalue[MAX_PAYLOAD];
uint8_t blen = 0; uint8_t blen = 0;
@@ -91,30 +92,36 @@ bool protocolParse(MyMessage &message, char *inputString) {
mSetAck(message, false); mSetAck(message, false);
if (command == C_STREAM) { if (command == C_STREAM) {
message.set(bvalue, blen); message.set(bvalue, blen);
} } else {
else {
message.set(value); message.set(value);
} }
return true; return true;
} }
char * protocolFormat(MyMessage &message) { char * protocolFormat(MyMessage &message)
snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%d;%d;%d;%d;%d;%s\n"), message.sender, message.sensor, (uint8_t)mGetCommand(message), (uint8_t)mGetAck(message), message.type, message.getString(_convBuffer)); {
snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%d;%d;%d;%d;%d;%s\n"), message.sender,
message.sensor, (uint8_t)mGetCommand(message), (uint8_t)mGetAck(message), message.type,
message.getString(_convBuffer));
return _fmtBuffer; return _fmtBuffer;
} }
char * protocolFormatMQTTTopic(const char* prefix, MyMessage &message) { char * protocolFormatMQTTTopic(const char* prefix, MyMessage &message)
snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%s/%d/%d/%d/%d/%d"), prefix, message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type); {
snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%s/%d/%d/%d/%d/%d"), prefix,
message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type);
return _fmtBuffer; return _fmtBuffer;
} }
char * protocolFormatMQTTSubscribe(const char* prefix) { char * protocolFormatMQTTSubscribe(const char* prefix)
{
snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%s/+/+/+/+/+"), prefix); snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%s/+/+/+/+/+"), prefix);
return _fmtBuffer; return _fmtBuffer;
} }
#ifdef MY_GATEWAY_MQTT_CLIENT #ifdef MY_GATEWAY_MQTT_CLIENT
bool protocolMQTTParse(MyMessage &message, char* topic, uint8_t* payload, unsigned int length) { bool protocolMQTTParse(MyMessage &message, char* topic, uint8_t* payload, unsigned int length)
{
char *str, *p; char *str, *p;
uint8_t i = 0; uint8_t i = 0;
uint8_t bvalue[MAX_PAYLOAD]; uint8_t bvalue[MAX_PAYLOAD];
@@ -188,15 +195,14 @@ bool protocolMQTTParse(MyMessage &message, char* topic, uint8_t* payload, unsign
} }
#endif #endif
uint8_t protocolH2i(char c) { uint8_t protocolH2i(char c)
{
uint8_t i = 0; uint8_t i = 0;
if (c <= '9') { if (c <= '9') {
i += c - '0'; i += c - '0';
} } else if (c >= 'a') {
else if (c >= 'a') {
i += c - 'a' + 10; i += c - 'a' + 10;
} } else {
else {
i += c - 'A' + 10; i += c - 'A' + 10;
} }
return i; return i;
+198 -165
View File
@@ -20,8 +20,8 @@
#include "MySensorsCore.h" #include "MySensorsCore.h"
#if defined(__linux__) #if defined(__linux__)
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
// message buffers // message buffers
@@ -32,7 +32,7 @@ MyMessage _msgTmp; // Buffer for temporary messages (acks and nonces among othe
static coreConfig_t _coreConfig; static coreConfig_t _coreConfig;
#if defined(MY_DEBUG) #if defined(MY_DEBUG)
char _convBuf[MAX_PAYLOAD*2+1]; char _convBuf[MAX_PAYLOAD*2+1];
#endif #endif
// Callback for transport=ok transition // Callback for transport=ok transition
@@ -47,37 +47,40 @@ void _callbackTransportReady(void)
} }
} }
void _process(void) { void _process(void)
{
doYield(); doYield();
#if defined(MY_INCLUSION_MODE_FEATURE) #if defined(MY_INCLUSION_MODE_FEATURE)
inclusionProcess(); inclusionProcess();
#endif #endif
#if defined(MY_GATEWAY_FEATURE) #if defined(MY_GATEWAY_FEATURE)
gatewayTransportProcess(); gatewayTransportProcess();
#endif #endif
#if defined(MY_SENSOR_NETWORK) #if defined(MY_SENSOR_NETWORK)
transportProcess(); transportProcess();
#endif #endif
#if defined(__linux__) #if defined(__linux__)
// To avoid high cpu usage // To avoid high cpu usage
usleep(10000); // 10ms usleep(10000); // 10ms
#endif #endif
} }
void _infiniteLoop(void) { void _infiniteLoop(void)
{
while(1) { while(1) {
doYield(); doYield();
#if defined(__linux__) #if defined(__linux__)
exit(1); exit(1);
#endif #endif
} }
} }
void _begin(void) { void _begin(void)
{
// reset wdt // reset wdt
hwWatchdogReset(); hwWatchdogReset();
@@ -87,7 +90,8 @@ void _begin(void) {
hwInit(); hwInit();
CORE_DEBUG(PSTR("MCO:BGN:INIT " MY_NODE_TYPE ",CP=" MY_CAPABILITIES ",VER=" MYSENSORS_LIBRARY_VERSION "\n")); CORE_DEBUG(PSTR("MCO:BGN:INIT " MY_NODE_TYPE ",CP=" MY_CAPABILITIES ",VER="
MYSENSORS_LIBRARY_VERSION "\n"));
// set defaults // set defaults
_coreConfig.presentationSent = false; _coreConfig.presentationSent = false;
@@ -98,22 +102,23 @@ void _begin(void) {
before(); before();
} }
#if defined(MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) #if defined(MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN)
ledsInit(); ledsInit();
#endif #endif
signerInit(); signerInit();
// Read latest received controller configuration from EEPROM // Read latest received controller configuration from EEPROM
// Note: _coreConfig.isMetric is bool, hence empty EEPROM (=0xFF) evaluates to true (default) // Note: _coreConfig.isMetric is bool, hence empty EEPROM (=0xFF) evaluates to true (default)
hwReadConfigBlock((void*)&_coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(controllerConfig_t)); hwReadConfigBlock((void*)&_coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS,
sizeof(controllerConfig_t));
#if defined(MY_OTA_FIRMWARE_FEATURE) #if defined(MY_OTA_FIRMWARE_FEATURE)
// Read firmware config from EEPROM, i.e. type, version, CRC, blocks // Read firmware config from EEPROM, i.e. type, version, CRC, blocks
readFirmwareSettings(); readFirmwareSettings();
#endif #endif
#if defined(MY_SENSOR_NETWORK) #if defined(MY_SENSOR_NETWORK)
// Save static parent ID in eeprom (used by bootloader) // Save static parent ID in eeprom (used by bootloader)
hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, MY_PARENT_NODE_ID); hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, MY_PARENT_NODE_ID);
// Initialise transport layer // Initialise transport layer
@@ -122,14 +127,14 @@ void _begin(void) {
transportRegisterReadyCallback(_callbackTransportReady); transportRegisterReadyCallback(_callbackTransportReady);
// wait until transport is ready // wait until transport is ready
(void)transportWaitUntilReady(MY_TRANSPORT_WAIT_READY_MS); (void)transportWaitUntilReady(MY_TRANSPORT_WAIT_READY_MS);
#endif #endif
_checkNodeLock(); _checkNodeLock();
#if defined(MY_GATEWAY_FEATURE) #if defined(MY_GATEWAY_FEATURE)
#if defined(MY_INCLUSION_BUTTON_FEATURE) #if defined(MY_INCLUSION_BUTTON_FEATURE)
inclusionInit(); inclusionInit();
#endif #endif
// initialise the transport driver // initialise the transport driver
if (!gatewayTransportInit()) { if (!gatewayTransportInit()) {
@@ -138,7 +143,7 @@ void _begin(void) {
// Nothing more we can do // Nothing more we can do
_infiniteLoop(); _infiniteLoop();
} }
#endif #endif
// Call sketch setup // Call sketch setup
if (setup) { if (setup) {
@@ -164,7 +169,8 @@ void _registerNode(void)
uint8_t counter = MY_REGISTRATION_RETRIES; uint8_t counter = MY_REGISTRATION_RETRIES;
// only proceed if register response received or retries exceeded // only proceed if register response received or retries exceeded
do { do {
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_REGISTRATION_REQUEST).set(MY_CORE_VERSION)); (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
I_REGISTRATION_REQUEST).set(MY_CORE_VERSION));
} while (!wait(2000, C_INTERNAL, I_REGISTRATION_RESPONSE) && counter--); } while (!wait(2000, C_INTERNAL, I_REGISTRATION_RESPONSE) && counter--);
#else #else
_coreConfig.nodeRegistered = true; _coreConfig.nodeRegistered = true;
@@ -172,40 +178,42 @@ void _registerNode(void)
#endif #endif
} }
void presentNode(void) { void presentNode(void)
{
setIndication(INDICATION_PRESENT); setIndication(INDICATION_PRESENT);
// Present node and request config // Present node and request config
#if defined(MY_GATEWAY_FEATURE) #if defined(MY_GATEWAY_FEATURE)
// Send presentation for this gateway device // Send presentation for this gateway device
#if defined(MY_REPEATER_FEATURE) #if defined(MY_REPEATER_FEATURE)
(void)present(NODE_SENSOR_ID, S_ARDUINO_REPEATER_NODE); (void)present(NODE_SENSOR_ID, S_ARDUINO_REPEATER_NODE);
#else #else
(void)present(NODE_SENSOR_ID, S_ARDUINO_NODE); (void)present(NODE_SENSOR_ID, S_ARDUINO_NODE);
#endif #endif
#else #else
#if defined(MY_OTA_FIRMWARE_FEATURE) #if defined(MY_OTA_FIRMWARE_FEATURE)
presentBootloaderInformation(); presentBootloaderInformation();
#endif #endif
// Send signing preferences for this node to the GW // Send signing preferences for this node to the GW
signerPresentation(_msgTmp, GATEWAY_ADDRESS); signerPresentation(_msgTmp, GATEWAY_ADDRESS);
// Send presentation for this radio node // Send presentation for this radio node
#if defined(MY_REPEATER_FEATURE) #if defined(MY_REPEATER_FEATURE)
(void)present(NODE_SENSOR_ID, S_ARDUINO_REPEATER_NODE); (void)present(NODE_SENSOR_ID, S_ARDUINO_REPEATER_NODE);
#else #else
(void)present(NODE_SENSOR_ID, S_ARDUINO_NODE); (void)present(NODE_SENSOR_ID, S_ARDUINO_NODE);
#endif #endif
// Send a configuration exchange request to controller // Send a configuration exchange request to controller
// Node sends parent node. Controller answers with latest node configuration // Node sends parent node. Controller answers with latest node configuration
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CONFIG).set(getParentNodeId())); (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
I_CONFIG).set(getParentNodeId()));
// Wait configuration reply. // Wait configuration reply.
(void)wait(2000, C_INTERNAL, I_CONFIG); (void)wait(2000, C_INTERNAL, I_CONFIG);
#endif #endif
if (presentation) { if (presentation) {
presentation(); presentation();
@@ -240,157 +248,167 @@ uint8_t getDistanceGW(void)
#endif #endif
} }
controllerConfig_t getConfig(void) { controllerConfig_t getConfig(void)
{
return _coreConfig.controllerConfig; return _coreConfig.controllerConfig;
} }
bool _sendRoute(MyMessage &message) { bool _sendRoute(MyMessage &message)
#if defined(MY_CORE_ONLY) {
#if defined(MY_CORE_ONLY)
(void)message; (void)message;
#endif #endif
#if defined(MY_GATEWAY_FEATURE) #if defined(MY_GATEWAY_FEATURE)
if (message.destination == getNodeId()) { if (message.destination == getNodeId()) {
// This is a message sent from a sensor attached on the gateway node. // This is a message sent from a sensor attached on the gateway node.
// Pass it directly to the gateway transport layer. // Pass it directly to the gateway transport layer.
return gatewayTransportSend(message); return gatewayTransportSend(message);
} }
#endif #endif
#if defined(MY_SENSOR_NETWORK) #if defined(MY_SENSOR_NETWORK)
return transportSendRoute(message); return transportSendRoute(message);
#else #else
return false; return false;
#endif #endif
} }
bool send(MyMessage &message, const bool enableAck) { bool send(MyMessage &message, const bool enableAck)
{
message.sender = getNodeId(); message.sender = getNodeId();
mSetCommand(message, C_SET); mSetCommand(message, C_SET);
mSetRequestAck(message, enableAck); mSetRequestAck(message, enableAck);
#if defined(MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE) #if defined(MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE)
if (_coreConfig.nodeRegistered) { if (_coreConfig.nodeRegistered) {
return _sendRoute(message); return _sendRoute(message);
} } else {
else {
CORE_DEBUG(PSTR("!MCO:SND:NODE NOT REG\n")); // node not registered CORE_DEBUG(PSTR("!MCO:SND:NODE NOT REG\n")); // node not registered
return false; return false;
} }
#else #else
return _sendRoute(message); return _sendRoute(message);
#endif #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) { bool sendBatteryLevel(const uint8_t value, const bool ack)
#if defined(MY_SENSOR_NETWORK) {
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(); const uint32_t heartbeat = transportGetHeartbeat();
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT_RESPONSE, ack).set(heartbeat)); return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT_RESPONSE,
#else ack).set(heartbeat));
#else
(void)ack; (void)ack;
return false; return false;
#endif #endif
} }
bool present(const uint8_t childSensorId, const uint8_t sensorType, const char *description, const bool ack) { bool present(const uint8_t childSensorId, const uint8_t sensorType, const char *description,
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType, ack).set(childSensorId==NODE_SENSOR_ID?MYSENSORS_LIBRARY_VERSION:description)); const bool ack)
{
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType,
ack).set(childSensorId==NODE_SENSOR_ID?MYSENSORS_LIBRARY_VERSION:description));
} }
bool sendSketchInfo(const char *name, const char *version, const bool ack) { bool sendSketchInfo(const char *name, const char *version, const bool ack)
{
bool result = true; bool result = true;
if (name) { if (name) {
result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME, ack).set(name)); result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME,
ack).set(name));
} }
if (version) { if (version) {
result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION, ack).set(version)); result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION,
ack).set(version));
} }
return result; return result;
} }
bool request(const uint8_t childSensorId, const uint8_t variableType, const uint8_t destination) { bool request(const uint8_t childSensorId, const uint8_t variableType, const uint8_t destination)
{
return _sendRoute(build(_msgTmp, destination, childSensorId, C_REQ, variableType).set("")); return _sendRoute(build(_msgTmp, destination, childSensorId, C_REQ, variableType).set(""));
} }
bool requestTime(const bool ack) { bool requestTime(const bool ack)
{
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_TIME, ack).set("")); return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_TIME, ack).set(""));
} }
// Message delivered through _msg // Message delivered through _msg
bool _processInternalMessages(void) { bool _processInternalMessages(void)
{
const uint8_t type = _msg.type; const uint8_t type = _msg.type;
if (_msg.sender == GATEWAY_ADDRESS) { if (_msg.sender == GATEWAY_ADDRESS) {
if (type == I_REBOOT) { if (type == I_REBOOT) {
#if !defined(MY_DISABLE_REMOTE_RESET) #if !defined(MY_DISABLE_REMOTE_RESET)
// Requires MySensors or other bootloader with watchdogs enabled // Requires MySensors or other bootloader with watchdogs enabled
setIndication(INDICATION_REBOOT); setIndication(INDICATION_REBOOT);
hwReboot(); hwReboot();
#endif #endif
} } else if (type == I_REGISTRATION_RESPONSE) {
else if (type == I_REGISTRATION_RESPONSE) { #if defined (MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE)
#if defined (MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE)
_coreConfig.nodeRegistered = _msg.getBool(); _coreConfig.nodeRegistered = _msg.getBool();
setIndication(INDICATION_GOT_REGISTRATION); setIndication(INDICATION_GOT_REGISTRATION);
CORE_DEBUG(PSTR("MCO:PIM:NODE REG=%d\n"), _coreConfig.nodeRegistered); // node registration CORE_DEBUG(PSTR("MCO:PIM:NODE REG=%d\n"), _coreConfig.nodeRegistered); // node registration
#endif #endif
} } else if (type == I_CONFIG) {
else if (type == I_CONFIG) {
// Pick up configuration from controller (currently only metric/imperial) and store it in eeprom if changed // Pick up configuration from controller (currently only metric/imperial) and store it in eeprom if changed
_coreConfig.controllerConfig.isMetric = _msg.data[0] == 0x00 || _msg.data[0] == 'M'; // metric if null terminated or M _coreConfig.controllerConfig.isMetric = _msg.data[0] == 0x00 ||
hwWriteConfigBlock((void*)&_coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(controllerConfig_t)); _msg.data[0] == 'M'; // metric if null terminated or M
} hwWriteConfigBlock((void*)&_coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS,
else if (type == I_PRESENTATION) { sizeof(controllerConfig_t));
} else if (type == I_PRESENTATION) {
// Re-send node presentation to controller // Re-send node presentation to controller
presentNode(); presentNode();
} } else if (type == I_HEARTBEAT_REQUEST) {
else if (type == I_HEARTBEAT_REQUEST) {
(void)sendHeartbeat(); (void)sendHeartbeat();
} } else if (type == I_TIME) {
else if (type == I_TIME) {
// Deliver time to callback // Deliver time to callback
if (receiveTime) { if (receiveTime) {
receiveTime(_msg.getULong()); receiveTime(_msg.getULong());
} }
} } else if (type == I_CHILDREN) {
else if (type == I_CHILDREN) { #if defined(MY_REPEATER_FEATURE)
#if defined(MY_REPEATER_FEATURE)
if (_msg.data[0] == 'C') { if (_msg.data[0] == 'C') {
// Clears child relay data for this node // Clears child relay data for this node
setIndication(INDICATION_CLEAR_ROUTING); setIndication(INDICATION_CLEAR_ROUTING);
transportClearRoutingTable(); transportClearRoutingTable();
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN).set("OK")); (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN).set("OK"));
} }
#endif #endif
} } else if (type == I_DEBUG) {
else if (type == I_DEBUG) { #if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
const char debug_msg = _msg.data[0]; const char debug_msg = _msg.data[0];
if (debug_msg == 'R') { // routing table if (debug_msg == 'R') { // routing table
#if defined(MY_REPEATER_FEATURE) #if defined(MY_REPEATER_FEATURE)
for (uint16_t cnt = 0; cnt < SIZE_ROUTES; cnt++) { for (uint16_t cnt = 0; cnt < SIZE_ROUTES; cnt++) {
const uint8_t route = transportGetRoute(cnt); const uint8_t route = transportGetRoute(cnt);
if (route != BROADCAST_ADDRESS) { if (route != BROADCAST_ADDRESS) {
CORE_DEBUG(PSTR("MCO:PIM:ROUTE N=%d,R=%d\n"), cnt, route); CORE_DEBUG(PSTR("MCO:PIM:ROUTE N=%d,R=%d\n"), cnt, route);
uint8_t outBuf[2] = { (uint8_t)cnt,route }; uint8_t outBuf[2] = { (uint8_t)cnt,route };
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(outBuf, 2)); (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(outBuf,
2));
wait(200); wait(200);
} }
} }
#endif #endif
} } else if (debug_msg == 'V') { // CPU voltage
else if (debug_msg == 'V') { // CPU voltage (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(hwCPUVoltage())); I_DEBUG).set(hwCPUVoltage()));
} } else if (debug_msg == 'F') { // CPU frequency in 1/10Mhz
else if (debug_msg == 'F') { // CPU frequency in 1/10Mhz (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(hwCPUFrequency())); I_DEBUG).set(hwCPUFrequency()));
} } else if (debug_msg == 'M') { // free memory
else if (debug_msg == 'M') { // free memory (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(hwFreeMem())); I_DEBUG).set(hwFreeMem()));
} } else if (debug_msg == 'E') { // clear MySensors eeprom area and reboot
else if (debug_msg == 'E') { // clear MySensors eeprom area and reboot
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set("OK")); (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set("OK"));
for (int i = EEPROM_START; i<EEPROM_LOCAL_CONFIG_ADDRESS; i++) { for (int i = EEPROM_START; i<EEPROM_LOCAL_CONFIG_ADDRESS; i++) {
hwWriteConfig(i, 0xFF); hwWriteConfig(i, 0xFF);
@@ -398,55 +416,61 @@ bool _processInternalMessages(void) {
setIndication(INDICATION_REBOOT); setIndication(INDICATION_REBOOT);
hwReboot(); hwReboot();
} }
#endif #endif
} else {
return false;
} }
else return false; } else {
}
else {
// sender is a node // sender is a node
if (type == I_REGISTRATION_REQUEST) { if (type == I_REGISTRATION_REQUEST) {
#if defined(MY_GATEWAY_FEATURE) #if defined(MY_GATEWAY_FEATURE)
// registeration requests are exclusively handled by GW/Controller // registeration requests are exclusively handled by GW/Controller
#if !defined(MY_REGISTRATION_CONTROLLER) #if !defined(MY_REGISTRATION_CONTROLLER)
// auto registration if version compatible // auto registration if version compatible
bool approveRegistration = true; bool approveRegistration = true;
#if defined(MY_CORE_COMPATIBILITY_CHECK) #if defined(MY_CORE_COMPATIBILITY_CHECK)
approveRegistration = (_msg.getByte() >= MY_CORE_MIN_VERSION); approveRegistration = (_msg.getByte() >= MY_CORE_MIN_VERSION);
#endif #endif
#if (F_CPU>16000000) #if (F_CPU>16000000)
// delay for fast GW and slow nodes // delay for fast GW and slow nodes
delay(5); delay(5);
#endif #endif
(void)_sendRoute(build(_msgTmp, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_REGISTRATION_RESPONSE).set(approveRegistration)); (void)_sendRoute(build(_msgTmp, _msg.sender, NODE_SENSOR_ID, C_INTERNAL,
#else I_REGISTRATION_RESPONSE).set(approveRegistration));
#else
return false; // processing of this request via controller return false; // processing of this request via controller
#endif #endif
#endif #endif
} else {
return false;
} }
else return false;
} }
return true; return true;
} }
void saveState(const uint8_t pos, const uint8_t value) { void saveState(const uint8_t pos, const uint8_t value)
{
hwWriteConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos, value); hwWriteConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos, value);
} }
uint8_t loadState(const uint8_t pos) { uint8_t loadState(const uint8_t pos)
{
return hwReadConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos); return hwReadConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos);
} }
void wait(const uint32_t waitingMS) { void wait(const uint32_t waitingMS)
{
const uint32_t enteringMS = hwMillis(); const uint32_t enteringMS = hwMillis();
while (hwMillis() - enteringMS < waitingMS) { while (hwMillis() - enteringMS < waitingMS) {
_process(); _process();
} }
} }
bool wait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType) { bool wait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType)
{
const uint32_t enteringMS = hwMillis(); const uint32_t enteringMS = hwMillis();
// invalidate msg type // invalidate msg type
_msg.type = !msgType; _msg.type = !msgType;
@@ -458,28 +482,32 @@ bool wait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType) {
return expectedResponse; return expectedResponse;
} }
void doYield(void) { void doYield(void)
{
hwWatchdogReset(); hwWatchdogReset();
yield(); yield();
#if defined (MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) #if defined (MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN)
ledsProcess(); ledsProcess();
#endif #endif
} }
int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2) { int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t interrupt1,
CORE_DEBUG(PSTR("MCO:SLP:MS=%lu,SMS=%d,I1=%d,M1=%d,I2=%d,M2=%d\n"), sleepingMS, smartSleep, interrupt1, mode1, interrupt2, mode2); const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2)
{
CORE_DEBUG(PSTR("MCO:SLP:MS=%lu,SMS=%d,I1=%d,M1=%d,I2=%d,M2=%d\n"), sleepingMS, smartSleep,
interrupt1, mode1, interrupt2, mode2);
// OTA FW feature: do not sleep if FW update ongoing // OTA FW feature: do not sleep if FW update ongoing
#if defined(MY_OTA_FIRMWARE_FEATURE) #if defined(MY_OTA_FIRMWARE_FEATURE)
if (isFirmwareUpdateOngoing()) { if (isFirmwareUpdateOngoing()) {
debug(PSTR("!MCO:SLP:FWUPD\n")); // sleeping not possible, FW update ongoing debug(PSTR("!MCO:SLP:FWUPD\n")); // sleeping not possible, FW update ongoing
wait(sleepingMS); wait(sleepingMS);
return MY_SLEEP_NOT_POSSIBLE; return MY_SLEEP_NOT_POSSIBLE;
} }
#endif #endif
// repeater feature: sleeping not possible // repeater feature: sleeping not possible
#if defined(MY_REPEATER_FEATURE) #if defined(MY_REPEATER_FEATURE)
(void)smartSleep; (void)smartSleep;
(void)interrupt1; (void)interrupt1;
(void)mode1; (void)mode1;
@@ -489,15 +517,16 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
CORE_DEBUG(PSTR("!MCO:SLP:REP\n")); // sleeping not possible, repeater feature enabled CORE_DEBUG(PSTR("!MCO:SLP:REP\n")); // sleeping not possible, repeater feature enabled
wait(sleepingMS); wait(sleepingMS);
return MY_SLEEP_NOT_POSSIBLE; return MY_SLEEP_NOT_POSSIBLE;
#else #else
uint32_t sleepingTimeMS = sleepingMS; uint32_t sleepingTimeMS = sleepingMS;
#if defined(MY_SENSOR_NETWORK) #if defined(MY_SENSOR_NETWORK)
// Do not sleep if transport not ready // Do not sleep if transport not ready
if (!isTransportReady()) { if (!isTransportReady()) {
CORE_DEBUG(PSTR("!MCO:SLP:TNR\n")); // sleeping not possible, transport not ready CORE_DEBUG(PSTR("!MCO:SLP:TNR\n")); // sleeping not possible, transport not ready
const uint32_t sleepEnterMS = hwMillis(); const uint32_t sleepEnterMS = hwMillis();
uint32_t sleepDeltaMS = 0; uint32_t sleepDeltaMS = 0;
while (!isTransportReady() && (sleepDeltaMS < sleepingTimeMS) && (sleepDeltaMS < MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS)) { while (!isTransportReady() && (sleepDeltaMS < sleepingTimeMS) &&
(sleepDeltaMS < MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS)) {
_process(); _process();
sleepDeltaMS = hwMillis() - sleepEnterMS; sleepDeltaMS = hwMillis() - sleepEnterMS;
} }
@@ -505,13 +534,12 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
if (sleepDeltaMS < sleepingTimeMS) { if (sleepDeltaMS < sleepingTimeMS) {
sleepingTimeMS -= sleepDeltaMS; // calculate remaining sleeping time sleepingTimeMS -= sleepDeltaMS; // calculate remaining sleeping time
CORE_DEBUG(PSTR("MCO:SLP:MS=%lu\n"), sleepingTimeMS); CORE_DEBUG(PSTR("MCO:SLP:MS=%lu\n"), sleepingTimeMS);
} } else {
else {
// no sleeping time left // no sleeping time left
return MY_SLEEP_NOT_POSSIBLE; return MY_SLEEP_NOT_POSSIBLE;
} }
} }
#endif #endif
if (smartSleep) { if (smartSleep) {
// notify controller about going to sleep // notify controller about going to sleep
@@ -519,17 +547,17 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
wait(MY_SMART_SLEEP_WAIT_DURATION_MS); // listen for incoming messages wait(MY_SMART_SLEEP_WAIT_DURATION_MS); // listen for incoming messages
} }
#if defined(MY_SENSOR_NETWORK) #if defined(MY_SENSOR_NETWORK)
CORE_DEBUG(PSTR("MCO:SLP:TPD\n")); // sleep, power down transport CORE_DEBUG(PSTR("MCO:SLP:TPD\n")); // sleep, power down transport
transportPowerDown(); transportPowerDown();
#endif #endif
#if defined (MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) #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 // Wait until leds finish their blinking pattern
while (ledsBlinking()) { while (ledsBlinking()) {
doYield(); doYield();
} }
#endif #endif
setIndication(INDICATION_SLEEP); setIndication(INDICATION_SLEEP);
@@ -538,12 +566,10 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 != INTERRUPT_NOT_DEFINED) { if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 != INTERRUPT_NOT_DEFINED) {
// both IRQs // both IRQs
result = hwSleep(interrupt1, mode1, interrupt2, mode2, sleepingTimeMS); result = hwSleep(interrupt1, mode1, interrupt2, mode2, sleepingTimeMS);
} } else if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) {
else if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) {
// one IRQ // one IRQ
result = hwSleep(interrupt1, mode1, sleepingTimeMS); result = hwSleep(interrupt1, mode1, sleepingTimeMS);
} } else if (interrupt1 == INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) {
else if (interrupt1 == INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) {
// no IRQ // no IRQ
result = hwSleep(sleepingTimeMS); result = hwSleep(sleepingTimeMS);
} }
@@ -551,34 +577,43 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
setIndication(INDICATION_WAKEUP); setIndication(INDICATION_WAKEUP);
CORE_DEBUG(PSTR("MCO:SLP:WUP=%d\n"), result); // sleep wake-up CORE_DEBUG(PSTR("MCO:SLP:WUP=%d\n"), result); // sleep wake-up
return result; return result;
#endif #endif
} }
// sleep functions // sleep functions
int8_t sleep(const uint32_t sleepingMS, const bool smartSleep) { int8_t sleep(const uint32_t sleepingMS, const bool smartSleep)
{
return _sleep(sleepingMS, smartSleep); return _sleep(sleepingMS, smartSleep);
} }
int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS, const bool smartSleep) { int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS,
const bool smartSleep)
{
return _sleep(sleepingMS, smartSleep, interrupt, mode); return _sleep(sleepingMS, smartSleep, interrupt, mode);
} }
int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t sleepingMS, const bool smartSleep) { int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2,
const uint8_t mode2, const uint32_t sleepingMS, const bool smartSleep)
{
return _sleep(sleepingMS, smartSleep, interrupt1, mode1, interrupt2, mode2); return _sleep(sleepingMS, smartSleep, interrupt1, mode1, interrupt2, mode2);
} }
// deprecated smartSleep() functions // deprecated smartSleep() functions
int8_t smartSleep(const uint32_t sleepingMS) { int8_t smartSleep(const uint32_t sleepingMS)
{
// compatibility // compatibility
return _sleep(sleepingMS, true); return _sleep(sleepingMS, true);
} }
int8_t smartSleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS) { int8_t smartSleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS)
{
// compatibility // compatibility
return _sleep(sleepingMS, true, interrupt, mode); return _sleep(sleepingMS, true, interrupt, mode);
} }
int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t sleepingMS) { int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2,
const uint8_t mode2, const uint32_t sleepingMS)
{
// compatibility // compatibility
return _sleep(sleepingMS, true, interrupt1, mode1, interrupt2, mode2); return _sleep(sleepingMS, true, interrupt1, mode1, interrupt2, mode2);
} }
@@ -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); CORE_DEBUG(PSTR("MCO:NLK:NODE LOCKED. TO UNLOCK, GND PIN %d AND RESET\n"), MY_NODE_UNLOCK_PIN);
doYield(); doYield();
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID,C_INTERNAL, I_LOCKED).set(str)); (void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID,C_INTERNAL, I_LOCKED).set(str));
#if defined(MY_SENSOR_NETWORK) #if defined(MY_SENSOR_NETWORK)
transportPowerDown(); transportPowerDown();
CORE_DEBUG(PSTR("MCO:NLK:TPD\n")); // power down transport CORE_DEBUG(PSTR("MCO:NLK:TPD\n")); // power down transport
#endif #endif
setIndication(INDICATION_SLEEP); setIndication(INDICATION_SLEEP);
(void)hwSleep((unsigned long)1000*60*30); // Sleep for 30 min before resending LOCKED message (void)hwSleep((unsigned long)1000*60*30); // Sleep for 30 min before resending LOCKED message
setIndication(INDICATION_WAKEUP); setIndication(INDICATION_WAKEUP);
@@ -625,14 +660,12 @@ void _checkNodeLock(void)
hwPinMode(MY_NODE_UNLOCK_PIN, INPUT); hwPinMode(MY_NODE_UNLOCK_PIN, INPUT);
setIndication(INDICATION_ERR_LOCKED); setIndication(INDICATION_ERR_LOCKED);
CORE_DEBUG(PSTR("MCO:BGN:NODE UNLOCKED\n")); CORE_DEBUG(PSTR("MCO:BGN:NODE UNLOCKED\n"));
} } else {
else {
// Disable pullup // Disable pullup
hwPinMode(MY_NODE_UNLOCK_PIN, INPUT); hwPinMode(MY_NODE_UNLOCK_PIN, INPUT);
_nodeLock("LDB"); //Locked during boot _nodeLock("LDB"); //Locked during boot
} }
} } else if (hwReadConfig(EEPROM_NODE_LOCK_COUNTER) == 0xFF) {
else if (hwReadConfig(EEPROM_NODE_LOCK_COUNTER) == 0xFF) {
// Reset walue // Reset walue
hwWriteConfig(EEPROM_NODE_LOCK_COUNTER, MY_NODE_LOCK_COUNTER_MAX); hwWriteConfig(EEPROM_NODE_LOCK_COUNTER, MY_NODE_LOCK_COUNTER_MAX);
} }
+67 -57
View File
@@ -17,51 +17,51 @@
* version 2 as published by the Free Software Foundation. * version 2 as published by the Free Software Foundation.
*/ */
/** /**
* @file MySensorsCore.h * @file MySensorsCore.h
* *
* @defgroup MySensorsCoregrp MySensorsCore * @defgroup MySensorsCoregrp MySensorsCore
* @ingroup internals * @ingroup internals
* @{ * @{
* *
* MySensorsCore-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE * MySensorsCore-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE
* - [!] Exclamation mark is prepended in case of error or warning * - [!] Exclamation mark is prepended in case of error or warning
* - SYSTEM: * - SYSTEM:
* - <b>MCO</b> messages emitted by MySensorsCore * - <b>MCO</b> messages emitted by MySensorsCore
* - SUB SYSTEMS: * - SUB SYSTEMS:
* - MCO:<b>BGN</b> from @ref _begin() * - MCO:<b>BGN</b> from @ref _begin()
* - MCO:<b>REG</b> from @ref _registerNode() * - MCO:<b>REG</b> from @ref _registerNode()
* - MCO:<b>SND</b> from @ref send() * - MCO:<b>SND</b> from @ref send()
* - MCO:<b>PIM</b> from @ref _processInternalMessages() * - MCO:<b>PIM</b> from @ref _processInternalMessages()
* - MCO:<b>NLK</b> from nodeLock() * - MCO:<b>NLK</b> from nodeLock()
* *
* MySensorsCore debug log messages: * MySensorsCore debug log messages:
* *
* |E| SYS | SUB | Message | Comment * |E| SYS | SUB | Message | Comment
* |-|------|-------|-----------------------------------------------|---------------------------------------------------------------------------- * |-|------|-------|-----------------------------------------------|----------------------------------------------------------------------------
* | | MCO | BGN | INIT %%s,CP=%%s,LIB=%%s | Core initialization, capabilities (CP), library version (VER) * | | MCO | BGN | INIT %%s,CP=%%s,LIB=%%s | Core initialization, capabilities (CP), library version (VER)
* | | MCO | BGN | BFR | Callback before() * | | MCO | BGN | BFR | Callback before()
* | | MCO | BGN | MTR | MY_TRANSPORT_RELAXED enabled * | | MCO | BGN | MTR | MY_TRANSPORT_RELAXED enabled
* | | MCO | BGN | STP | Callback setup() * | | 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 | 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 | NODE UNLOCKED | Node successfully unlocked (see signing chapter)
* |!| MCO | BGN | TSP FAIL | Transport initialization failed * |!| MCO | BGN | TSP FAIL | Transport initialization failed
* | | MCO | REG | REQ | Registration request * | | MCO | REG | REQ | Registration request
* | | MCO | REG | NOT NEEDED | No registration needed (i.e. GW) * | | MCO | REG | NOT NEEDED | No registration needed (i.e. GW)
* |!| MCO | SND | NODE NOT REG | Node is not registered, cannot send message * |!| 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 | 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 | 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 | 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 | TPD | Sleep node, powerdown transport
* | | MCO | SLP | WUP=%%d | Node woke-up, reason/IRQ (WUP) * | | MCO | SLP | WUP=%%d | Node woke-up, reason/IRQ (WUP)
* |!| MCO | SLP | FWUPD | Sleeping not possible, FW update ongoing * |!| MCO | SLP | FWUPD | Sleeping not possible, FW update ongoing
* |!| MCO | SLP | REP | Sleeping not possible, repeater feature enabled * |!| 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 | NODE LOCKED. UNLOCK: GND PIN %%d AND RESET | Node locked during booting, see signing chapter for additional information
* | | MCO | NLK | TPD | Powerdown transport * | | MCO | NLK | TPD | Powerdown transport
* *
* *
* @brief API declaration for MySensorsCore * @brief API declaration for MySensorsCore
*/ */
#ifndef MySensorsCore_h #ifndef MySensorsCore_h
@@ -86,11 +86,11 @@
#ifdef MY_DEBUG #ifdef MY_DEBUG
#define debug(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug, to be removed (follow-up PR) #define debug(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug, to be removed (follow-up PR)
#define CORE_DEBUG(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug #define CORE_DEBUG(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug
#else #else
#define debug(x,...) //!< debug NULL, to be removed (follow-up PR) #define debug(x,...) //!< debug NULL, to be removed (follow-up PR)
#define CORE_DEBUG(x,...) //!< debug NULL #define CORE_DEBUG(x,...) //!< debug NULL
#endif #endif
@@ -143,7 +143,8 @@ void presentNode(void);
* @param description A textual description of the sensor. * @param description A textual description of the sensor.
* @return true Returns true if message reached the first stop on its way to destination. * @return true Returns true if message reached the first stop on its way to destination.
*/ */
bool present(const uint8_t sensorId, const uint8_t sensorType, const char *description="", const bool ack = false); bool present(const uint8_t sensorId, const uint8_t sensorType, const char *description="",
const bool ack = false);
/** /**
* Sends sketch meta information to the gateway. Not mandatory but a nice thing to do. * Sends sketch meta information to the gateway. Not mandatory but a nice thing to do.
@@ -189,7 +190,8 @@ bool sendHeartbeat(const bool ack = false);
* @param destination The nodeId of other node in radio network. Default is gateway * @param destination The nodeId of other node in radio network. Default is gateway
* @return true Returns true if message reached the first stop on its way to destination. * @return true Returns true if message reached the first stop on its way to destination.
*/ */
bool request(const uint8_t childSensorId, const uint8_t variableType, const uint8_t destination = GATEWAY_ADDRESS); bool request(const uint8_t childSensorId, const uint8_t variableType,
const uint8_t destination = GATEWAY_ADDRESS);
/** /**
* Requests time from controller. Answer will be delivered to receiveTime function in sketch. * Requests time from controller. Answer will be delivered to receiveTime function in sketch.
@@ -269,7 +271,8 @@ int8_t sleep(const uint32_t sleepingMS, const bool smartSleep = false);
* @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep * @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep
* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) * @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update)
*/ */
int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS = 0, const bool smartSleep = false); int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS = 0,
const bool smartSleep = false);
/** /**
* Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts. * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts.
@@ -283,7 +286,8 @@ int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepin
* @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep. * @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep.
* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) * @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update)
*/ */
int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t sleepingMS = 0, const bool smartSleep = false); int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2,
const uint8_t mode2, const uint32_t sleepingMS = 0, const bool smartSleep = false);
/** /**
* \deprecated Use sleep(ms, true) instead * \deprecated Use sleep(ms, true) instead
@@ -316,7 +320,8 @@ int8_t smartSleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sl
* @param sleepingMS Number of milliseconds to sleep or 0 to sleep forever * @param sleepingMS Number of milliseconds to sleep or 0 to sleep forever
* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) * @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update)
*/ */
int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t sleepingMS = 0); int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2,
const uint8_t mode2, const uint32_t sleepingMS = 0);
/** /**
* Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts. * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts.
@@ -330,7 +335,9 @@ int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t i
* @param smartSleep (optional) Set True if sending heartbeat and process incoming messages before going to sleep. * @param smartSleep (optional) Set True if sending heartbeat and process incoming messages before going to sleep.
* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) * @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update)
*/ */
int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep = false, const uint8_t interrupt1 = INTERRUPT_NOT_DEFINED, const uint8_t mode1 = MODE_NOT_DEFINED, const uint8_t interrupt2 = INTERRUPT_NOT_DEFINED, const uint8_t mode2 = MODE_NOT_DEFINED); int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep = false,
const uint8_t interrupt1 = INTERRUPT_NOT_DEFINED, const uint8_t mode1 = MODE_NOT_DEFINED,
const uint8_t interrupt2 = INTERRUPT_NOT_DEFINED, const uint8_t mode2 = MODE_NOT_DEFINED);
/** /**
@@ -412,7 +419,9 @@ void loop(void) __attribute__((weak));
// Inline function and macros // Inline function and macros
static inline MyMessage& build(MyMessage &msg, const uint8_t destination, const uint8_t sensor, const uint8_t command, const uint8_t type, const bool ack = false) { static inline MyMessage& build(MyMessage &msg, const uint8_t destination, const uint8_t sensor,
const uint8_t command, const uint8_t type, const bool ack = false)
{
msg.sender = getNodeId(); msg.sender = getNodeId();
msg.destination = destination; msg.destination = destination;
msg.sensor = sensor; msg.sensor = sensor;
@@ -423,7 +432,8 @@ static inline MyMessage& build(MyMessage &msg, const uint8_t destination, const
return msg; return msg;
} }
static inline MyMessage& buildGw(MyMessage &msg, const uint8_t type) { static inline MyMessage& buildGw(MyMessage &msg, const uint8_t type)
{
msg.sender = GATEWAY_ADDRESS; msg.sender = GATEWAY_ADDRESS;
msg.destination = GATEWAY_ADDRESS; msg.destination = GATEWAY_ADDRESS;
msg.sensor = NODE_SENSOR_ID; msg.sensor = NODE_SENSOR_ID;
+23 -13
View File
@@ -82,12 +82,14 @@ extern bool signerAtsha204SignMsg(MyMessage &msg);
#endif #endif
// Helper function to centralize signing/verification exceptions // Helper function to centralize signing/verification exceptions
static bool skipSign(MyMessage &msg) { static bool skipSign(MyMessage &msg)
{
if mGetAck(msg) { if mGetAck(msg) {
SIGN_DEBUG(PSTR("Skipping security for ACK on command %d type %d\n"), mGetCommand(msg), msg.type); SIGN_DEBUG(PSTR("Skipping security for ACK on command %d type %d\n"), mGetCommand(msg), msg.type);
return true; return true;
} else if (mGetCommand(msg) == C_INTERNAL && } else if (mGetCommand(msg) == C_INTERNAL &&
(msg.type == I_NONCE_REQUEST || msg.type == I_NONCE_RESPONSE || msg.type == I_SIGNING_PRESENTATION || (msg.type == I_NONCE_REQUEST || msg.type == I_NONCE_RESPONSE ||
msg.type == I_SIGNING_PRESENTATION ||
msg.type == I_ID_REQUEST || msg.type == I_ID_RESPONSE || msg.type == I_ID_REQUEST || msg.type == I_ID_RESPONSE ||
msg.type == I_FIND_PARENT_REQUEST || msg.type == I_FIND_PARENT_RESPONSE || msg.type == I_FIND_PARENT_REQUEST || msg.type == I_FIND_PARENT_RESPONSE ||
msg.type == I_HEARTBEAT_REQUEST || msg.type == I_HEARTBEAT_RESPONSE || msg.type == I_HEARTBEAT_REQUEST || msg.type == I_HEARTBEAT_RESPONSE ||
@@ -107,7 +109,8 @@ static bool skipSign(MyMessage &msg) {
#endif // MY_SIGNING_FEATURE #endif // MY_SIGNING_FEATURE
// Helper to prepare a signing presentation message // Helper to prepare a signing presentation message
static void prepareSigningPresentation(MyMessage &msg, uint8_t destination) { static void prepareSigningPresentation(MyMessage &msg, uint8_t destination)
{
// Only supports version 1 for now // Only supports version 1 for now
(void)build(msg, destination, NODE_SENSOR_ID, C_INTERNAL, I_SIGNING_PRESENTATION).set(""); (void)build(msg, destination, NODE_SENSOR_ID, C_INTERNAL, I_SIGNING_PRESENTATION).set("");
mSetLength(msg, 2); mSetLength(msg, 2);
@@ -116,7 +119,8 @@ static void prepareSigningPresentation(MyMessage &msg, uint8_t destination) {
msg.data[1] = 0; msg.data[1] = 0;
} }
void signerInit(void) { void signerInit(void)
{
#if defined(MY_SIGNING_FEATURE) #if defined(MY_SIGNING_FEATURE)
// Read out the signing requirements from EEPROM // Read out the signing requirements from EEPROM
hwReadConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, hwReadConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS,
@@ -135,7 +139,8 @@ void signerInit(void) {
#endif #endif
} }
void signerPresentation(MyMessage &msg, uint8_t destination) { void signerPresentation(MyMessage &msg, uint8_t destination)
{
prepareSigningPresentation(msg, destination); prepareSigningPresentation(msg, destination);
#if defined(MY_SIGNING_REQUEST_SIGNATURES) #if defined(MY_SIGNING_REQUEST_SIGNATURES)
@@ -157,7 +162,8 @@ void signerPresentation(MyMessage &msg, uint8_t destination) {
} }
} }
bool signerProcessInternal(MyMessage &msg) { bool signerProcessInternal(MyMessage &msg)
{
uint8_t sender = msg.sender; uint8_t sender = msg.sender;
(void)sender; (void)sender;
#if !defined(MY_SIGNING_FEATURE) #if !defined(MY_SIGNING_FEATURE)
@@ -166,7 +172,8 @@ bool signerProcessInternal(MyMessage &msg) {
// If we act as gateway and do not have the signing feature and receive a signing request we still // If we act as gateway and do not have the signing feature and receive a signing request we still
// need to do make sure the requester does not believe the gateway still require signatures // need to do make sure the requester does not believe the gateway still require signatures
prepareSigningPresentation(msg, sender); prepareSigningPresentation(msg, sender);
SIGN_DEBUG(PSTR("Informing node %d that we do not require signatures because we do not support it\n"), SIGN_DEBUG(
PSTR("Informing node %d that we do not require signatures because we do not support it\n"),
sender); sender);
if (!_sendRoute(msg)) { if (!_sendRoute(msg)) {
SIGN_DEBUG(PSTR("Failed to transmit signing presentation!\n")); SIGN_DEBUG(PSTR("Failed to transmit signing presentation!\n"));
@@ -183,7 +190,8 @@ bool signerProcessInternal(MyMessage &msg) {
if (msg.type == I_NONCE_REQUEST) { if (msg.type == I_NONCE_REQUEST) {
#if defined(MY_NODE_LOCK_FEATURE) #if defined(MY_NODE_LOCK_FEATURE)
nof_nonce_requests++; nof_nonce_requests++;
SIGN_DEBUG(PSTR("Nonce requests left until lockdown: %d\n"), MY_NODE_LOCK_COUNTER_MAX-nof_nonce_requests); SIGN_DEBUG(PSTR("Nonce requests left until lockdown: %d\n"),
MY_NODE_LOCK_COUNTER_MAX-nof_nonce_requests);
if (nof_nonce_requests >= MY_NODE_LOCK_COUNTER_MAX) { if (nof_nonce_requests >= MY_NODE_LOCK_COUNTER_MAX) {
_nodeLock("TMNR"); //Too many nonces requested _nodeLock("TMNR"); //Too many nonces requested
} }
@@ -323,7 +331,8 @@ bool signerSignMsg(MyMessage &msg) {
} else { } else {
// Send nonce-request // Send nonce-request
_signingNonceStatus=SIGN_WAITING_FOR_NONCE; _signingNonceStatus=SIGN_WAITING_FOR_NONCE;
if (!_sendRoute(build(_msgSign, msg.destination, msg.sensor, C_INTERNAL, I_NONCE_REQUEST).set(""))) { if (!_sendRoute(build(_msgSign, msg.destination, msg.sensor, C_INTERNAL,
I_NONCE_REQUEST).set(""))) {
SIGN_DEBUG(PSTR("Failed to transmit nonce request!\n")); SIGN_DEBUG(PSTR("Failed to transmit nonce request!\n"));
return false; return false;
} }
@@ -332,7 +341,8 @@ bool signerSignMsg(MyMessage &msg) {
// Other messages could come in-between. We trust _process() takes care of them // Other messages could come in-between. We trust _process() takes care of them
unsigned long enter = hwMillis(); unsigned long enter = hwMillis();
_msgSign = msg; // Copy the message to sign since message buffer might be touched in _process() _msgSign = msg; // Copy the message to sign since message buffer might be touched in _process()
while (hwMillis() - enter < MY_VERIFICATION_TIMEOUT_MS && _signingNonceStatus==SIGN_WAITING_FOR_NONCE) { while (hwMillis() - enter < MY_VERIFICATION_TIMEOUT_MS &&
_signingNonceStatus==SIGN_WAITING_FOR_NONCE) {
_process(); _process();
} }
if (hwMillis() - enter > MY_VERIFICATION_TIMEOUT_MS) { if (hwMillis() - enter > MY_VERIFICATION_TIMEOUT_MS) {
@@ -375,8 +385,7 @@ bool signerVerifyMsg(MyMessage &msg) {
// Internal messages of certain types are not verified // Internal messages of certain types are not verified
if (skipSign(msg)) { if (skipSign(msg)) {
verificationResult = true; verificationResult = true;
} } else if (!mGetSigned(msg)) {
else if (!mGetSigned(msg)) {
// Got unsigned message that should have been signed // Got unsigned message that should have been signed
SIGN_DEBUG(PSTR("Message is not signed, but it should have been!\n")); SIGN_DEBUG(PSTR("Message is not signed, but it should have been!\n"));
verificationResult = false; verificationResult = false;
@@ -397,7 +406,8 @@ bool signerVerifyMsg(MyMessage &msg) {
nof_failed_verifications = 0; nof_failed_verifications = 0;
} else { } else {
nof_failed_verifications++; nof_failed_verifications++;
SIGN_DEBUG(PSTR("Failed verification attempts left until lockdown: %d\n"), MY_NODE_LOCK_COUNTER_MAX-nof_failed_verifications); SIGN_DEBUG(PSTR("Failed verification attempts left until lockdown: %d\n"),
MY_NODE_LOCK_COUNTER_MAX-nof_failed_verifications);
if (nof_failed_verifications >= MY_NODE_LOCK_COUNTER_MAX) { if (nof_failed_verifications >= MY_NODE_LOCK_COUNTER_MAX) {
_nodeLock("TMFV"); //Too many failed verifications _nodeLock("TMFV"); //Too many failed verifications
} }
+52 -31
View File
@@ -41,7 +41,7 @@ uint8_t _signing_tx_buffer[SHA204_CMD_SIZE_MAX];
extern uint8_t _doWhitelist[32]; extern uint8_t _doWhitelist[32];
#ifdef MY_SIGNING_NODE_WHITELISTING #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 #endif
static void signerCalculateSignature(MyMessage &msg, bool signing); static void signerCalculateSignature(MyMessage &msg, bool signing);
@@ -54,21 +54,20 @@ static char i2h(uint8_t i)
uint8_t k = i & 0x0F; uint8_t k = i & 0x0F;
if (k <= 9) { if (k <= 9) {
return '0' + k; return '0' + k;
} } else {
else {
return 'A' + k - 10; return 'A' + k - 10;
} }
} }
static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz) { static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz)
{
static char printBuffer[300]; static char printBuffer[300];
#ifdef MY_GATEWAY_FEATURE #ifdef MY_GATEWAY_FEATURE
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
snprintf_P(printBuffer, 299, PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE); snprintf_P(printBuffer, 299, PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE);
MY_SERIALDEVICE.print(printBuffer); MY_SERIALDEVICE.print(printBuffer);
#endif #endif
for (int i=0; i<sz; i++) for (int i=0; i<sz; i++) {
{
printBuffer[i * 2] = i2h(buf[i] >> 4); printBuffer[i * 2] = i2h(buf[i] >> 4);
printBuffer[(i * 2) + 1] = i2h(buf[i]); printBuffer[(i * 2) + 1] = i2h(buf[i]);
} }
@@ -78,8 +77,7 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf,
printBuffer[MY_GATEWAY_MAX_SEND_LENGTH-1-strlen_P((const char*)str)] = '\0'; printBuffer[MY_GATEWAY_MAX_SEND_LENGTH-1-strlen_P((const char*)str)] = '\0';
#endif #endif
MY_SERIALDEVICE.print(str); MY_SERIALDEVICE.print(str);
if (sz > 0) if (sz > 0) {
{
MY_SERIALDEVICE.print(printBuffer); MY_SERIALDEVICE.print(printBuffer);
} }
MY_SERIALDEVICE.println(""); MY_SERIALDEVICE.println("");
@@ -88,13 +86,16 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf,
#define DEBUG_SIGNING_PRINTBUF(str, buf, sz) #define DEBUG_SIGNING_PRINTBUF(str, buf, sz)
#endif #endif
void signerAtsha204Init(void) { void signerAtsha204Init(void)
{
atsha204_init(MY_SIGNING_ATSHA204_PIN); atsha204_init(MY_SIGNING_ATSHA204_PIN);
} }
bool signerAtsha204CheckTimer(void) { bool signerAtsha204CheckTimer(void)
{
if (_signing_verification_ongoing) { if (_signing_verification_ongoing) {
if (hwMillis() < _signing_timestamp || hwMillis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) { if (hwMillis() < _signing_timestamp ||
hwMillis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) {
DEBUG_SIGNING_PRINTBUF(F("Verification timeout"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Verification timeout"), NULL, 0);
// Purge nonce // Purge nonce
memset(_signing_signing_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH); memset(_signing_signing_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH);
@@ -106,7 +107,8 @@ bool signerAtsha204CheckTimer(void) {
return true; return true;
} }
bool signerAtsha204GetNonce(MyMessage &msg) { bool signerAtsha204GetNonce(MyMessage &msg)
{
DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204"), NULL, 0);
// Generate random number for use as nonce // Generate random number for use as nonce
// We used a basic whitening technique that XORs each byte in a 32byte random value with current hwMillis() counter // We used a basic whitening technique that XORs each byte in a 32byte random value with current hwMillis() counter
@@ -140,7 +142,8 @@ bool signerAtsha204GetNonce(MyMessage &msg) {
return true; return true;
} }
void signerAtsha204PutNonce(MyMessage &msg) { void signerAtsha204PutNonce(MyMessage &msg)
{
DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204"), NULL, 0);
memcpy(_signing_signing_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD); memcpy(_signing_signing_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD);
@@ -148,7 +151,8 @@ void signerAtsha204PutNonce(MyMessage &msg) {
memset(&_signing_signing_nonce[MAX_PAYLOAD], 0xAA, sizeof(_signing_signing_nonce)-MAX_PAYLOAD); memset(&_signing_signing_nonce[MAX_PAYLOAD], 0xAA, sizeof(_signing_signing_nonce)-MAX_PAYLOAD);
} }
bool signerAtsha204SignMsg(MyMessage &msg) { bool signerAtsha204SignMsg(MyMessage &msg)
{
// If we cannot fit any signature in the message, refuse to sign it // If we cannot fit any signature in the message, refuse to sign it
if (mGetLength(msg) > MAX_PAYLOAD-2) { if (mGetLength(msg) > MAX_PAYLOAD-2) {
DEBUG_SIGNING_PRINTBUF(F("Message too large"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Message too large"), NULL, 0);
@@ -161,10 +165,12 @@ bool signerAtsha204SignMsg(MyMessage &msg) {
if (DO_WHITELIST(msg.destination)) { if (DO_WHITELIST(msg.destination)) {
// Salt the signature with the senders nodeId and the unique serial of the ATSHA device // Salt the signature with the senders nodeId and the unique serial of the ATSHA device
memcpy(_signing_signing_nonce, &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed memcpy(_signing_signing_nonce, &_signing_rx_buffer[SHA204_BUFFER_POS_DATA],
32); // We can reuse the nonce buffer now since it is no longer needed
_signing_signing_nonce[32] = msg.sender; _signing_signing_nonce[32] = msg.sender;
atsha204_getSerialNumber(&_signing_signing_nonce[33]); atsha204_getSerialNumber(&_signing_signing_nonce[33]);
(void)signerSha256(_signing_signing_nonce, 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place (void)signerSha256(_signing_signing_nonce,
32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place
DEBUG_SIGNING_PRINTBUF(F("Signature salted with serial"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Signature salted with serial"), NULL, 0);
} }
@@ -175,13 +181,16 @@ bool signerAtsha204SignMsg(MyMessage &msg) {
_signing_rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER; _signing_rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER;
// Transfer as much signature data as the remaining space in the message permits // Transfer as much signature data as the remaining space in the message permits
memcpy(&msg.data[mGetLength(msg)], &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg)); memcpy(&msg.data[mGetLength(msg)], &_signing_rx_buffer[SHA204_BUFFER_POS_DATA],
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg)); MAX_PAYLOAD-mGetLength(msg));
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)],
MAX_PAYLOAD-mGetLength(msg));
return true; return true;
} }
bool signerAtsha204VerifyMsg(MyMessage &msg) { bool signerAtsha204VerifyMsg(MyMessage &msg)
{
if (!_signing_verification_ongoing) { if (!_signing_verification_ongoing) {
DEBUG_SIGNING_PRINTBUF(F("No active verification session"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("No active verification session"), NULL, 0);
return false; return false;
@@ -198,7 +207,8 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) {
return false; return false;
} }
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg)); DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)],
MAX_PAYLOAD-mGetLength(msg));
signerCalculateSignature(msg, false); // Get signature of message signerCalculateSignature(msg, false); // Get signature of message
#ifdef MY_SIGNING_NODE_WHITELISTING #ifdef MY_SIGNING_NODE_WHITELISTING
@@ -207,10 +217,12 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) {
for (j=0; j < NUM_OF(_signing_whitelist); j++) { for (j=0; j < NUM_OF(_signing_whitelist); j++) {
if (_signing_whitelist[j].nodeId == msg.sender) { if (_signing_whitelist[j].nodeId == msg.sender) {
DEBUG_SIGNING_PRINTBUF(F("Sender found in whitelist"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Sender found in whitelist"), NULL, 0);
memcpy(_signing_verifying_nonce, &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed memcpy(_signing_verifying_nonce, &_signing_rx_buffer[SHA204_BUFFER_POS_DATA],
32); // We can reuse the nonce buffer now since it is no longer needed
_signing_verifying_nonce[32] = msg.sender; _signing_verifying_nonce[32] = msg.sender;
memcpy(&_signing_verifying_nonce[33], _signing_whitelist[j].serial, SHA204_SERIAL_SZ); memcpy(&_signing_verifying_nonce[33], _signing_whitelist[j].serial, SHA204_SERIAL_SZ);
(void)signerSha256(_signing_verifying_nonce, 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place (void)signerSha256(_signing_verifying_nonce,
32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place
break; break;
} }
} }
@@ -229,8 +241,10 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) {
_signing_rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER; _signing_rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER;
// Compare the caluclated signature with the provided signature // Compare the caluclated signature with the provided signature
if (signerMemcmp(&msg.data[mGetLength(msg)], &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg))) { if (signerMemcmp(&msg.data[mGetLength(msg)], &_signing_rx_buffer[SHA204_BUFFER_POS_DATA],
DEBUG_SIGNING_PRINTBUF(F("Signature bad: "), &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg)); MAX_PAYLOAD-mGetLength(msg))) {
DEBUG_SIGNING_PRINTBUF(F("Signature bad: "), &_signing_rx_buffer[SHA204_BUFFER_POS_DATA],
MAX_PAYLOAD-mGetLength(msg));
#ifdef MY_SIGNING_NODE_WHITELISTING #ifdef MY_SIGNING_NODE_WHITELISTING
DEBUG_SIGNING_PRINTBUF(F("Is the sender whitelisted and serial correct?"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Is the sender whitelisted and serial correct?"), NULL, 0);
#endif #endif
@@ -243,15 +257,20 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) {
} }
// Helper to calculate signature of msg (returned in _signing_rx_buffer[SHA204_BUFFER_POS_DATA]) // Helper to calculate signature of msg (returned in _signing_rx_buffer[SHA204_BUFFER_POS_DATA])
static void signerCalculateSignature(MyMessage &msg, bool signing) { static void signerCalculateSignature(MyMessage &msg, bool signing)
{
(void)atsha204_wakeup(_signing_temp_message); (void)atsha204_wakeup(_signing_temp_message);
memset(_signing_temp_message, 0, 32); memset(_signing_temp_message, 0, 32);
memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE],
MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
// Program the data to sign into the ATSHA204 // Program the data to sign into the ATSHA204
DEBUG_SIGNING_PRINTBUF(F("Message to process: "), (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); DEBUG_SIGNING_PRINTBUF(F("Message to process: "), (uint8_t*)&msg.data[1-HEADER_SIZE],
DEBUG_SIGNING_PRINTBUF(F("Current nonce: "), signing ? _signing_signing_nonce : _signing_verifying_nonce, 32); MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
(void)atsha204_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, 8 << 3, 32, _signing_temp_message, DEBUG_SIGNING_PRINTBUF(F("Current nonce: "),
signing ? _signing_signing_nonce : _signing_verifying_nonce, 32);
(void)atsha204_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, 8 << 3, 32,
_signing_temp_message,
WRITE_COUNT_LONG, _signing_tx_buffer, WRITE_RSP_SIZE, _signing_rx_buffer); WRITE_COUNT_LONG, _signing_tx_buffer, WRITE_RSP_SIZE, _signing_rx_buffer);
// Program the nonce to use for the signature (has to be done just before GENDIG due to chip limitations) // Program the nonce to use for the signature (has to be done just before GENDIG due to chip limitations)
@@ -260,7 +279,8 @@ static void signerCalculateSignature(MyMessage &msg, bool signing) {
NONCE_COUNT_LONG, _signing_tx_buffer, NONCE_RSP_SIZE_SHORT, _signing_rx_buffer); NONCE_COUNT_LONG, _signing_tx_buffer, NONCE_RSP_SIZE_SHORT, _signing_rx_buffer);
// Purge nonce when used // Purge nonce when used
memset(signing ? _signing_signing_nonce : _signing_verifying_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH); memset(signing ? _signing_signing_nonce : _signing_verifying_nonce, 0x00,
NONCE_NUMIN_SIZE_PASSTHROUGH);
// Generate digest of data and nonce // Generate digest of data and nonce
(void)atsha204_execute(SHA204_GENDIG, GENDIG_ZONE_DATA, 8, 0, NULL, (void)atsha204_execute(SHA204_GENDIG, GENDIG_ZONE_DATA, 8, 0, NULL,
@@ -275,7 +295,8 @@ static void signerCalculateSignature(MyMessage &msg, bool signing) {
// Helper to calculate a generic SHA256 digest of provided buffer (only supports one block) // Helper to calculate a generic SHA256 digest of provided buffer (only supports one block)
// The pointer to the hash is returned, but the hash is also stored in _signing_rx_buffer[SHA204_BUFFER_POS_DATA]) // The pointer to the hash is returned, but the hash is also stored in _signing_rx_buffer[SHA204_BUFFER_POS_DATA])
static uint8_t* signerSha256(const uint8_t* data, size_t sz) { static uint8_t* signerSha256(const uint8_t* data, size_t sz)
{
// Initiate SHA256 calculator // Initiate SHA256 calculator
(void)atsha204_execute(SHA204_SHA, SHA_INIT, 0, 0, NULL, (void)atsha204_execute(SHA204_SHA, SHA_INIT, 0, 0, NULL,
SHA_COUNT_SHORT, _signing_tx_buffer, SHA_RSP_SIZE_SHORT, _signing_rx_buffer); SHA_COUNT_SHORT, _signing_tx_buffer, SHA_RSP_SIZE_SHORT, _signing_rx_buffer);
+37 -27
View File
@@ -47,49 +47,47 @@ extern uint8_t _doWhitelist[32];
static uint8_t _signing_node_serial_info[9]; static uint8_t _signing_node_serial_info[9];
#ifdef MY_SIGNING_NODE_WHITELISTING #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 #endif
static void signerCalculateSignature(MyMessage &msg, bool signing); static void signerCalculateSignature(MyMessage &msg, bool signing);
#ifdef MY_DEBUG_VERBOSE_SIGNING #ifdef MY_DEBUG_VERBOSE_SIGNING
static char i2h(uint8_t i) static char i2h(uint8_t i)
{ {
uint8_t k = i & 0x0F; uint8_t k = i & 0x0F;
if (k <= 9) { if (k <= 9) {
return '0' + k; return '0' + k;
} } else {
else {
return 'A' + k - 10; return 'A' + k - 10;
} }
} }
#ifdef __linux__ #ifdef __linux__
static void DEBUG_SIGNING_PRINTBUF(const char *str, uint8_t* buf, uint8_t sz) { static void DEBUG_SIGNING_PRINTBUF(const char *str, uint8_t* buf, uint8_t sz)
{
static char printBuffer[300]; static char printBuffer[300];
for (int i=0; i<sz; i++) for (int i=0; i<sz; i++) {
{
printBuffer[i * 2] = i2h(buf[i] >> 4); printBuffer[i * 2] = i2h(buf[i] >> 4);
printBuffer[(i * 2) + 1] = i2h(buf[i]); printBuffer[(i * 2) + 1] = i2h(buf[i]);
} }
printBuffer[sz * 2] = '\0'; printBuffer[sz * 2] = '\0';
debug(str); debug(str);
if (sz > 0) if (sz > 0) {
{
debug(printBuffer); debug(printBuffer);
} }
} }
#else #else
static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz) { static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz)
{
static char printBuffer[300]; static char printBuffer[300];
#ifdef MY_GATEWAY_FEATURE #ifdef MY_GATEWAY_FEATURE
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
snprintf_P(printBuffer, 299, PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE); snprintf_P(printBuffer, 299, PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE);
MY_SERIALDEVICE.print(printBuffer); MY_SERIALDEVICE.print(printBuffer);
#endif #endif
for (int i=0; i<sz; i++) for (int i=0; i<sz; i++) {
{
printBuffer[i * 2] = i2h(buf[i] >> 4); printBuffer[i * 2] = i2h(buf[i] >> 4);
printBuffer[(i * 2) + 1] = i2h(buf[i]); printBuffer[(i * 2) + 1] = i2h(buf[i]);
} }
@@ -99,8 +97,7 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf,
printBuffer[MY_GATEWAY_MAX_SEND_LENGTH-1-strlen_P((const char*)str)] = '\0'; printBuffer[MY_GATEWAY_MAX_SEND_LENGTH-1-strlen_P((const char*)str)] = '\0';
#endif #endif
MY_SERIALDEVICE.print(str); MY_SERIALDEVICE.print(str);
if (sz > 0) if (sz > 0) {
{
MY_SERIALDEVICE.print(printBuffer); MY_SERIALDEVICE.print(printBuffer);
} }
MY_SERIALDEVICE.println(""); MY_SERIALDEVICE.println("");
@@ -110,7 +107,8 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf,
#define DEBUG_SIGNING_PRINTBUF(str, buf, sz) #define DEBUG_SIGNING_PRINTBUF(str, buf, sz)
#endif #endif
void signerAtsha204SoftInit(void) { void signerAtsha204SoftInit(void)
{
// initialize pseudo-RNG // initialize pseudo-RNG
hwRandomNumberInit(); hwRandomNumberInit();
// Set secrets // Set secrets
@@ -118,9 +116,11 @@ void signerAtsha204SoftInit(void) {
hwReadConfigBlock((void*)_signing_node_serial_info, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9); hwReadConfigBlock((void*)_signing_node_serial_info, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9);
} }
bool signerAtsha204SoftCheckTimer(void) { bool signerAtsha204SoftCheckTimer(void)
{
if (_signing_verification_ongoing) { if (_signing_verification_ongoing) {
if (hwMillis() < _signing_timestamp || hwMillis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) { if (hwMillis() < _signing_timestamp ||
hwMillis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) {
DEBUG_SIGNING_PRINTBUF(F("Verification timeout"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Verification timeout"), NULL, 0);
// Purge nonce // Purge nonce
memset(_signing_signing_nonce, 0xAA, 32); memset(_signing_signing_nonce, 0xAA, 32);
@@ -132,7 +132,8 @@ bool signerAtsha204SoftCheckTimer(void) {
return true; return true;
} }
bool signerAtsha204SoftGetNonce(MyMessage &msg) { bool signerAtsha204SoftGetNonce(MyMessage &msg)
{
DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204Soft"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204Soft"), NULL, 0);
// We used a basic whitening technique that XORs a random byte with the current hwMillis() counter and then the byte is // We used a basic whitening technique that XORs a random byte with the current hwMillis() counter and then the byte is
@@ -160,7 +161,8 @@ bool signerAtsha204SoftGetNonce(MyMessage &msg) {
return true; return true;
} }
void signerAtsha204SoftPutNonce(MyMessage &msg) { void signerAtsha204SoftPutNonce(MyMessage &msg)
{
DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204Soft"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204Soft"), NULL, 0);
memcpy(_signing_signing_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD); memcpy(_signing_signing_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD);
@@ -168,7 +170,8 @@ void signerAtsha204SoftPutNonce(MyMessage &msg) {
memset(&_signing_signing_nonce[MAX_PAYLOAD], 0xAA, sizeof(_signing_signing_nonce)-MAX_PAYLOAD); memset(&_signing_signing_nonce[MAX_PAYLOAD], 0xAA, sizeof(_signing_signing_nonce)-MAX_PAYLOAD);
} }
bool signerAtsha204SoftSignMsg(MyMessage &msg) { bool signerAtsha204SoftSignMsg(MyMessage &msg)
{
// If we cannot fit any signature in the message, refuse to sign it // If we cannot fit any signature in the message, refuse to sign it
if (mGetLength(msg) > MAX_PAYLOAD-2) { if (mGetLength(msg) > MAX_PAYLOAD-2) {
DEBUG_SIGNING_PRINTBUF(F("Message too large"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("Message too large"), NULL, 0);
@@ -199,12 +202,14 @@ bool signerAtsha204SoftSignMsg(MyMessage &msg) {
// Transfer as much signature data as the remaining space in the message permits // Transfer as much signature data as the remaining space in the message permits
memcpy(&msg.data[mGetLength(msg)], _signing_hmac, MAX_PAYLOAD-mGetLength(msg)); memcpy(&msg.data[mGetLength(msg)], _signing_hmac, MAX_PAYLOAD-mGetLength(msg));
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg)); DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)],
MAX_PAYLOAD-mGetLength(msg));
return true; return true;
} }
bool signerAtsha204SoftVerifyMsg(MyMessage &msg) { bool signerAtsha204SoftVerifyMsg(MyMessage &msg)
{
if (!_signing_verification_ongoing) { if (!_signing_verification_ongoing) {
DEBUG_SIGNING_PRINTBUF(F("No active verification session"), NULL, 0); DEBUG_SIGNING_PRINTBUF(F("No active verification session"), NULL, 0);
return false; return false;
@@ -222,7 +227,8 @@ bool signerAtsha204SoftVerifyMsg(MyMessage &msg) {
} }
// Get signature of message // Get signature of message
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg)); DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)],
MAX_PAYLOAD-mGetLength(msg));
signerCalculateSignature(msg, false); signerCalculateSignature(msg, false);
#ifdef MY_SIGNING_NODE_WHITELISTING #ifdef MY_SIGNING_NODE_WHITELISTING
@@ -268,11 +274,15 @@ bool signerAtsha204SoftVerifyMsg(MyMessage &msg) {
} }
// Helper to calculate signature of msg (returned in hmac) // Helper to calculate signature of msg (returned in hmac)
static void signerCalculateSignature(MyMessage &msg, bool signing) { static void signerCalculateSignature(MyMessage &msg, bool signing)
{
memset(_signing_temp_message, 0, 32); memset(_signing_temp_message, 0, 32);
memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE],
DEBUG_SIGNING_PRINTBUF(F("Message to process: "), (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
DEBUG_SIGNING_PRINTBUF(F("Current nonce: "), signing ? _signing_signing_nonce : _signing_verifying_nonce, 32); DEBUG_SIGNING_PRINTBUF(F("Message to process: "), (uint8_t*)&msg.data[1-HEADER_SIZE],
MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
DEBUG_SIGNING_PRINTBUF(F("Current nonce: "),
signing ? _signing_signing_nonce : _signing_verifying_nonce, 32);
// ATSHA204 calculates the HMAC with a PSK and a SHA256 digest of the following data: // ATSHA204 calculates the HMAC with a PSK and a SHA256 digest of the following data:
// 32 bytes zeroes // 32 bytes zeroes
+244 -204
View File
File diff suppressed because it is too large Load Diff
+141 -141
View File
@@ -17,166 +17,166 @@
* version 2 as published by the Free Software Foundation. * version 2 as published by the Free Software Foundation.
*/ */
/** /**
* @file MyTransport.h * @file MyTransport.h
* *
* @defgroup MyTransportgrp MyTransport * @defgroup MyTransportgrp MyTransport
* @ingroup internals * @ingroup internals
* @{ * @{
* *
* Transport-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE * Transport-related log messages, format: [!]SYSTEM:[SUB SYSTEM:]MESSAGE
* - [!] Exclamation mark is prepended in case of error * - [!] Exclamation mark is prepended in case of error
* - SYSTEM: * - SYSTEM:
* - <b>TSM</b>: messages emitted by the transport state machine * - <b>TSM</b>: messages emitted by the transport state machine
* - <b>TSF</b>: messages emitted by transport support functions * - <b>TSF</b>: messages emitted by transport support functions
* - SUB SYSTEMS: * - SUB SYSTEMS:
* - Transport state machine (<b>TSM</b>) * - Transport state machine (<b>TSM</b>)
* - TSM:INIT from <b>stInit</b> Initialize transport and radio * - TSM:INIT from <b>stInit</b> Initialize transport and radio
* - TSM:FPAR from <b>stParent</b> Find parent * - TSM:FPAR from <b>stParent</b> Find parent
* - TSM:ID from <b>stID</b> Check/request node ID, if dynamic node ID set * - TSM:ID from <b>stID</b> Check/request node ID, if dynamic node ID set
* - TSM:UPL from <b>stUplink</b> Verify uplink connection by pinging GW * - TSM:UPL from <b>stUplink</b> Verify uplink connection by pinging GW
* - TSM:READY from <b>stReady</b> Transport is ready and fully operational * - TSM:READY from <b>stReady</b> Transport is ready and fully operational
* - TSM:FAIL from <b>stFailure</b> Failure in transport link or transport HW * - TSM:FAIL from <b>stFailure</b> Failure in transport link or transport HW
* - Transport support function (<b>TSF</b>) * - Transport support function (<b>TSF</b>)
* - TSF:CHKUPL from @ref transportCheckUplink(), checks connection to GW * - TSF:CHKUPL from @ref transportCheckUplink(), checks connection to GW
* - TSF:ASID from @ref transportAssignNodeID(), assigns node ID * - TSF:ASID from @ref transportAssignNodeID(), assigns node ID
* - TSF:PING from @ref transportPingNode(), pings a node * - TSF:PING from @ref transportPingNode(), pings a node
* - TSF:WUR from @ref transportWaitUntilReady(), waits until transport is ready * - TSF:WUR from @ref transportWaitUntilReady(), waits until transport is ready
* - TSF:CRT from @ref transportClearRoutingTable(), clears routing table stored in EEPROM * - 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: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:SRT from @ref transportSaveRoutingTable(), saves RAM routing table to EEPROM (only GW/repeaters)
* - TSF:MSG from @ref transportProcessMessage(), processes incoming message * - TSF:MSG from @ref transportProcessMessage(), processes incoming message
* - TSF:SANCHK from @ref transportInvokeSanityCheck(), calls transport-specific sanity check * - TSF:SANCHK from @ref transportInvokeSanityCheck(), calls transport-specific sanity check
* - TSF:ROUTE from @ref transportRouteMessage(), sends message * - TSF:ROUTE from @ref transportRouteMessage(), sends message
* - TSF:SEND from @ref transportSendRoute(), sends message if transport is ready (exposed) * - TSF:SEND from @ref transportSendRoute(), sends message if transport is ready (exposed)
* *
* Transport debug log messages: * Transport debug log messages:
* *
* |E| SYS | SUB | Message | Comment * |E| SYS | SUB | Message | Comment
* |-|------|-----------|-----------------------|--------------------------------------------------------------------- * |-|------|-----------|-----------------------|---------------------------------------------------------------------
* | | TSM | INIT | | <b>Transition to stInit state</b> * | | TSM | INIT | | <b>Transition to stInit state</b>
* | | TSM | INIT | STATID=%%d | Node ID is static * | | TSM | INIT | STATID=%%d | Node ID is static
* | | TSM | INIT | TSP OK | Transport device configured and fully operational * | | 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 | GW MODE | Node is set up as GW, thus omitting ID and findParent states
* |!| TSM | INIT | TSP FAIL | Transport device initialization failed * |!| TSM | INIT | TSP FAIL | Transport device initialization failed
* | | TSM | FPAR | | <b>Transition to stParent state</b> * | | TSM | FPAR | | <b>Transition to stParent state</b>
* | | TSM | FPAR | STATP=%%d | Static parent set, skip finding parent * | | TSM | FPAR | STATP=%%d | Static parent set, skip finding parent
* | | TSM | FPAR | OK | Parent node identified * | | TSM | FPAR | OK | Parent node identified
* |!| TSM | FPAR | NO REPLY | No potential parents replied to find parent request * |!| TSM | FPAR | NO REPLY | No potential parents replied to find parent request
* |!| TSM | FPAR | FAIL | Finding parent failed * |!| TSM | FPAR | FAIL | Finding parent failed
* | | TSM | ID | | <b>Transition to stID state</b> * | | TSM | ID | | <b>Transition to stID state</b>
* | | TSM | ID | OK,ID=%%d | Node ID is valid * | | TSM | ID | OK,ID=%%d | Node ID is valid
* | | TSM | ID | REQ | Request node ID from controller * | | TSM | ID | REQ | Request node ID from controller
* |!| TSM | ID | FAIL,ID=%%d | ID verification failed, ID invalid * |!| TSM | ID | FAIL,ID=%%d | ID verification failed, ID invalid
* | | TSM | UPL | | <b>Transition to stUplink state</b> * | | TSM | UPL | | <b>Transition to stUplink state</b>
* | | TSM | UPL | OK | Uplink OK, GW returned ping * | | 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) * | | 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 | UPL | FAIL | Uplink check failed, i.e. GW could not be pinged
* | | TSM | READY | SRT | Save routing table * | | TSM | READY | SRT | Save routing table
* | | TSM | READY | ID=%%d,PAR=%%d,DIS=%%d| <b>Transition to stReady</b> Transport ready, node ID (ID), parent node ID (PAR), distance to GW (DIS) * | | TSM | READY | ID=%%d,PAR=%%d,DIS=%%d| <b>Transition to stReady</b> 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 | UPL FAIL,SNP | Too many failed uplink transmissions, search new parent
* |!| TSM | READY | FAIL,STATP | Too many failed uplink transmissions, static parent enforced * |!| TSM | READY | FAIL,STATP | Too many failed uplink transmissions, static parent enforced
* | | TSM | FAIL | CNT=%%d | <b>Transition to stFailure state</b>, consecutive failure counter (CNT) * | | TSM | FAIL | CNT=%%d | <b>Transition to stFailure state</b>, consecutive failure counter (CNT)
* | | TSM | FAIL | PDT | Power-down transport * | | TSM | FAIL | PDT | Power-down transport
* | | TSM | FAIL | RE-INIT | Attempt to re-initialize transport * | | TSM | FAIL | RE-INIT | Attempt to re-initialize transport
* | | TSF | CHKUPL | OK | Uplink OK * | | TSF | CHKUPL | OK | Uplink OK
* | | TSF | CHKUPL | OK,FCTRL | Uplink OK, flood control prevents pinging GW in too short intervals * | | 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 | 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 | CHKUPL | FAIL | No reply received when checking uplink
* | | TSF | ASID | OK,ID=%%d | Node ID assigned * | | TSF | ASID | OK,ID=%%d | Node ID assigned
* |!| TSF | ASID | FAIL,ID=%%d | Assigned ID is invalid * |!| TSF | ASID | FAIL,ID=%%d | Assigned ID is invalid
* | | TSF | PING | SEND,TO=%%d | Send ping to destination (TO) * | | TSF | PING | SEND,TO=%%d | Send ping to destination (TO)
* | | TSF | WUR | MS=%%lu | Wait until transport ready, timeout (MS) * | | TSF | WUR | MS=%%lu | Wait until transport ready, timeout (MS)
* | | TSF | MSG | ACK REQ | ACK message requested * | | TSF | MSG | ACK REQ | ACK message requested
* | | TSF | MSG | ACK | ACK message, do not proceed but forward to callback * | | 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 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 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 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 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 | 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 | 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 | PONG RECV,HP=%%d | Pinged node replied with (HP) hops
* | | TSF | MSG | BC | Broadcast message received * | | TSF | MSG | BC | Broadcast message received
* | | TSF | MSG | GWL OK | Link to GW ok * | | TSF | MSG | GWL OK | Link to GW ok
* | | TSF | MSG | FWD BC MSG | Controlled broadcast message forwarding * | | TSF | MSG | FWD BC MSG | Controlled broadcast message forwarding
* | | TSF | MSG | REL MSG | Relay message * | | TSF | MSG | REL MSG | Relay message
* | | TSF | MSG | REL PxNG,HP=%%d | Relay PING/PONG message, increment hop counter (HP) * | | 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 | LEN,%%d!=%%d | Invalid message length, (actual!=expected)
* |!| TSF | MSG | PVER,%%d!=%%d | Message protocol version mismatch (actual!=expected) * |!| TSF | MSG | PVER,%%d!=%%d | Message protocol version mismatch (actual!=expected)
* |!| TSF | MSG | SIGN VERIFY FAIL | Signing verification failed * |!| 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 | 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 | SIGN FAIL | Signing message failed
* |!| TSF | MSG | GWL FAIL | GW uplink failed * |!| TSF | MSG | GWL FAIL | GW uplink failed
* | | TSF | SANCHK | OK | Sanity check passed * | | TSF | SANCHK | OK | Sanity check passed
* |!| TSF | SANCHK | FAIL | Sanity check failed, attempt to re-initialize radio * |!| TSF | SANCHK | FAIL | Sanity check failed, attempt to re-initialize radio
* | | TSF | CRT | OK | Clearing routing table successful * | | TSF | CRT | OK | Clearing routing table successful
* | | TSF | LRT | OK | Loading routing table successful * | | TSF | LRT | OK | Loading routing table successful
* | | TSF | SRT | OK | Saving routing table successful * | | TSF | SRT | OK | Saving routing table successful
* |!| TSF | ROUTE | FPAR ACTIVE | Finding parent active, message not sent * |!| 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 | ROUTE | DST %%d UNKNOWN | Routing for destination (DST) unknown, send message to parent
* |!| TSF | SEND | TNR | Transport not ready, message cannot be sent * |!| TSF | SEND | TNR | Transport not ready, message cannot be sent
* *
* Incoming / outgoing messages: * Incoming / outgoing messages:
* *
* See <a href="https://www.mysensors.org/download/serial_api_20">here</a> for more detail on the format and definitons. * See <a href="https://www.mysensors.org/download/serial_api_20">here</a> for more detail on the format and definitons.
* *
* Receiving a message * Receiving a message
* - TSF:MSG:READ,sender-last-destination,s=%%d,c=%%d,t=%%d,pt=%%d,l=%%d,sg=%%d:%%s * - TSF:MSG:READ,sender-last-destination,s=%%d,c=%%d,t=%%d,pt=%%d,l=%%d,sg=%%d:%%s
* *
* Sending a message * 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 * - [!]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: * Message fields:
* - <b>s</b>=sensor ID * - <b>s</b>=sensor ID
* - <b>c</b>=command * - <b>c</b>=command
* - <b>t</b>=msg type * - <b>t</b>=msg type
* - <b>pt</b>=payload type * - <b>pt</b>=payload type
* - <b>l</b>=length * - <b>l</b>=length
* - <b>sg</b>=signing flag * - <b>sg</b>=signing flag
* - <b>ft</b>=failed uplink transmission counter * - <b>ft</b>=failed uplink transmission counter
* - <b>st</b>=send status, OK=success, NACK=no radio ACK received * - <b>st</b>=send status, OK=success, NACK=no radio ACK received
* *
* @brief API declaration for MyTransport * @brief API declaration for MyTransport
* *
*/ */
#ifndef MyTransport_h #ifndef MyTransport_h
#define MyTransport_h #define MyTransport_h
#include "MySensorsCore.h" #include "MySensorsCore.h"
// debug // debug
#if defined(MY_DEBUG) #if defined(MY_DEBUG)
#define TRANSPORT_DEBUG(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug #define TRANSPORT_DEBUG(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug
extern char _convBuf[MAX_PAYLOAD * 2 + 1]; extern char _convBuf[MAX_PAYLOAD * 2 + 1];
#else #else
#define TRANSPORT_DEBUG(x,...) //!< debug NULL #define TRANSPORT_DEBUG(x,...) //!< debug NULL
#endif #endif
#if defined(MY_REPEATER_FEATURE) #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 #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 #endif
#define MY_TRANSPORT_MAX_TSM_FAILURES (7u) //!< Max. number of consecutive TSM failure state entries (3bits) #define MY_TRANSPORT_MAX_TSM_FAILURES (7u) //!< Max. number of consecutive TSM failure state entries (3bits)
#ifndef MY_TRANSPORT_TIMEOUT_FAILURE_STATE #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 #endif
#ifndef MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE #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 #endif
#ifndef MY_TRANSPORT_STATE_TIMEOUT_MS #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 #endif
#ifndef MY_TRANSPORT_CHKUPL_INTERVAL_MS #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 #endif
#ifndef MY_TRANSPORT_STATE_RETRIES #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 #endif
#define AUTO (255u) //!< ID 255 is reserved #define AUTO (255u) //!< ID 255 is reserved
@@ -188,7 +188,7 @@
// parent node check // parent node check
#if defined(MY_PARENT_NODE_IS_STATIC) && !defined(MY_PARENT_NODE_ID) #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 #endif
#define _autoFindParent (bool)(MY_PARENT_NODE_ID == AUTO) //!< returns true if static parent id is undefined #define _autoFindParent (bool)(MY_PARENT_NODE_ID == AUTO) //!< returns true if static parent id is undefined
@@ -197,14 +197,14 @@
// RX queue // RX queue
#if defined(MY_RX_MESSAGE_BUFFER_FEATURE) #if defined(MY_RX_MESSAGE_BUFFER_FEATURE)
#if defined(MY_RADIO_RFM69) #if defined(MY_RADIO_RFM69)
#error Receive message buffering not supported for RFM69! #error Receive message buffering not supported for RFM69!
#endif #endif
#if defined(MY_RS485) #if defined(MY_RS485)
#error Receive message buffering not supported for RS485! #error Receive message buffering not supported for RS485!
#endif #endif
#elif !defined(MY_RX_MESSAGE_BUFFER_FEATURE) && defined(MY_RX_MESSAGE_BUFFER_SIZE) #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 #endif
/** /**
+2 -1
View File
@@ -37,7 +37,8 @@ typedef struct _transportQueuedMessage {
/** Buffer to store queued messages in. */ /** Buffer to store queued messages in. */
static transportQueuedMessage transportRxQueueStorage[MY_RX_MESSAGE_BUFFER_SIZE]; static transportQueuedMessage transportRxQueueStorage[MY_RX_MESSAGE_BUFFER_SIZE];
/** Circular buffer, which uses the transportRxQueueStorage and administers stored messages. */ /** Circular buffer, which uses the transportRxQueueStorage and administers stored messages. */
static CircularBuffer<transportQueuedMessage> transportRxQueue(transportRxQueueStorage, MY_RX_MESSAGE_BUFFER_SIZE); static CircularBuffer<transportQueuedMessage> transportRxQueue(transportRxQueueStorage,
MY_RX_MESSAGE_BUFFER_SIZE);
static volatile uint8_t transportLostMessageCount = 0; static volatile uint8_t transportLostMessageCount = 0;
+18 -10
View File
@@ -26,43 +26,50 @@ RFM69 _radio(MY_RF69_SPI_CS, MY_RF69_IRQ_PIN, MY_RFM69HW, MY_RF69_IRQ_NUM);
uint8_t _address; uint8_t _address;
bool transportInit() { bool transportInit()
{
// Start up the radio library (_address will be set later by the MySensors library) // Start up the radio library (_address will be set later by the MySensors library)
if (_radio.initialize(MY_RFM69_FREQUENCY, _address, MY_RFM69_NETWORKID)) { if (_radio.initialize(MY_RFM69_FREQUENCY, _address, MY_RFM69_NETWORKID)) {
#ifdef MY_RFM69_ENABLE_ENCRYPTION #ifdef MY_RFM69_ENABLE_ENCRYPTION
uint8_t _psk[16]; uint8_t _psk[16];
hwReadConfigBlock((void*)_psk, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); hwReadConfigBlock((void*)_psk, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16);
_radio.encrypt((const char*)_psk); _radio.encrypt((const char*)_psk);
memset(_psk, 0, 16); // Make sure it is purged from memory when set memset(_psk, 0, 16); // Make sure it is purged from memory when set
#endif #endif
return true; return true;
} }
return false; return false;
} }
void transportSetAddress(uint8_t address) { void transportSetAddress(uint8_t address)
{
_address = address; _address = address;
_radio.setAddress(address); _radio.setAddress(address);
} }
uint8_t transportGetAddress() { uint8_t transportGetAddress()
{
return _address; return _address;
} }
bool transportSend(uint8_t to, const void* data, uint8_t len) { bool transportSend(uint8_t to, const void* data, uint8_t len)
{
return _radio.sendWithRetry(to,data,len); return _radio.sendWithRetry(to,data,len);
} }
bool transportAvailable() { bool transportAvailable()
{
return _radio.receiveDone(); return _radio.receiveDone();
} }
bool transportSanityCheck() { bool transportSanityCheck()
{
// not implemented yet // not implemented yet
return true; return true;
} }
uint8_t transportReceive(void* data) { uint8_t transportReceive(void* data)
{
memcpy(data,(const void *)_radio.DATA, _radio.DATALEN); memcpy(data,(const void *)_radio.DATA, _radio.DATALEN);
// save payload length // save payload length
const uint8_t dataLen = _radio.DATALEN; const uint8_t dataLen = _radio.DATALEN;
@@ -73,6 +80,7 @@ uint8_t transportReceive(void* data) {
return dataLen; return dataLen;
} }
void transportPowerDown() { void transportPowerDown()
{
_radio.sleep(); _radio.sleep();
} }
+20 -11
View File
@@ -22,43 +22,52 @@
#include "MyTransport.h" #include "MyTransport.h"
#include "drivers/RFM95/RFM95.h" #include "drivers/RFM95/RFM95.h"
bool transportInit(void) { bool transportInit(void)
{
const bool result = RFM95_initialise(MY_RFM95_FREQUENCY); const bool result = RFM95_initialise(MY_RFM95_FREQUENCY);
#if !defined(MY_GATEWAY_FEATURE) && !defined(MY_RFM95_ATC_MODE_DISABLED) #if !defined(MY_GATEWAY_FEATURE) && !defined(MY_RFM95_ATC_MODE_DISABLED)
// only enable ATC mode nodes // only enable ATC mode nodes
RFM95_ATCmode(true, MY_RFM95_ATC_TARGET_RSSI); RFM95_ATCmode(true, MY_RFM95_ATC_TARGET_RSSI);
#endif #endif
return result; return result;
} }
void transportSetAddress(uint8_t address) { void transportSetAddress(uint8_t address)
{
RFM95_setAddress(address); RFM95_setAddress(address);
} }
uint8_t transportGetAddress(void) { uint8_t transportGetAddress(void)
{
return RFM95_getAddress(); return RFM95_getAddress();
} }
bool transportSend(uint8_t to, const void* data, uint8_t len) { bool transportSend(uint8_t to, const void* data, uint8_t len)
{
return RFM95_sendWithRetry(to, data, len); return RFM95_sendWithRetry(to, data, len);
} }
bool transportAvailable(void) { bool transportAvailable(void)
{
return RFM95_available(); return RFM95_available();
} }
bool transportSanityCheck(void) { bool transportSanityCheck(void)
{
return RFM95_sanityCheck(); return RFM95_sanityCheck();
} }
uint8_t transportReceive(void* data) { uint8_t transportReceive(void* data)
{
return RFM95_recv((uint8_t*)data); return RFM95_recv((uint8_t*)data);
} }
void transportPowerDown(void) { void transportPowerDown(void)
{
(void)RFM95_sleep(); (void)RFM95_sleep();
} }
int16_t transportGetSignalStrength(void) { int16_t transportGetSignalStrength(void)
{
return RFM95_getRSSI(); return RFM95_getRSSI();
} }
+38 -31
View File
@@ -62,16 +62,16 @@
#include "MyTransport.h" #include "MyTransport.h"
#ifdef __linux__ #ifdef __linux__
#include "SerialPort.h" #include "SerialPort.h"
#endif #endif
#if defined(MY_RS485_DE_PIN) #if defined(MY_RS485_DE_PIN)
#define assertDE() hwDigitalWrite(MY_RS485_DE_PIN, HIGH); delayMicroseconds(5) #define assertDE() hwDigitalWrite(MY_RS485_DE_PIN, HIGH); delayMicroseconds(5)
#define deassertDE() hwDigitalWrite(MY_RS485_DE_PIN, LOW) #define deassertDE() hwDigitalWrite(MY_RS485_DE_PIN, LOW)
#else #else
#define assertDE() #define assertDE()
#define deassertDE() #define deassertDE()
#endif #endif
// We only use SYS_PACK in this application // We only use SYS_PACK in this application
@@ -114,7 +114,8 @@ bool _packet_received;
//Reset the state machine and release the data pointer //Reset the state machine and release the data pointer
void _serialReset(){ void _serialReset()
{
_recPhase = 0; _recPhase = 0;
_recPos = 0; _recPos = 0;
_recLen = 0; _recLen = 0;
@@ -264,13 +265,13 @@ bool transportSend(uint8_t to, const void* data, uint8_t len)
} }
} }
#if defined(MY_RS485_DE_PIN) #if defined(MY_RS485_DE_PIN)
hwDigitalWrite(MY_RS485_DE_PIN, HIGH); hwDigitalWrite(MY_RS485_DE_PIN, HIGH);
delayMicroseconds(5); delayMicroseconds(5);
#endif #endif
// Start of header by writing multiple SOH // Start of header by writing multiple SOH
for(byte w=0;w<1;w++) { for(byte w=0; w<1; w++) {
_dev.write(SOH); _dev.write(SOH);
} }
_dev.write(to); // Destination address _dev.write(to); // Destination address
@@ -290,75 +291,81 @@ bool transportSend(uint8_t to, const void* data, uint8_t len)
_dev.write(cs); _dev.write(cs);
_dev.write(EOT); _dev.write(EOT);
#if defined(MY_RS485_DE_PIN) #if defined(MY_RS485_DE_PIN)
#ifdef __PIC32MX__ #ifdef __PIC32MX__
// MPIDE has nothing yet for this. It uses the hardware buffer, which // 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 // could be up to 8 levels deep. For now, let's just delay for 8
// characters worth. // characters worth.
delayMicroseconds((F_CPU/9600)+1); delayMicroseconds((F_CPU/9600)+1);
#else #else
#if defined(ARDUINO) && ARDUINO >= 100 #if defined(ARDUINO) && ARDUINO >= 100
#if ARDUINO >= 104 #if ARDUINO >= 104
// Arduino 1.0.4 and upwards does it right // Arduino 1.0.4 and upwards does it right
_dev.flush(); _dev.flush();
#else #else
// Between 1.0.0 and 1.0.3 it almost does it - need to compensate // 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. // for the hardware buffer. Delay for 2 bytes worth of transmission.
_dev.flush(); _dev.flush();
delayMicroseconds((20000000UL/9600)+1); delayMicroseconds((20000000UL/9600)+1);
#endif #endif
#elif defined(__linux__) #elif defined(__linux__)
_dev.flush(); _dev.flush();
#endif #endif
#endif #endif
hwDigitalWrite(MY_RS485_DE_PIN, LOW); hwDigitalWrite(MY_RS485_DE_PIN, LOW);
#endif #endif
return true; return true;
} }
bool transportInit() { bool transportInit()
{
// Reset the state machine // Reset the state machine
_dev.begin(MY_RS485_BAUD_RATE); _dev.begin(MY_RS485_BAUD_RATE);
_serialReset(); _serialReset();
#if defined(MY_RS485_DE_PIN) #if defined(MY_RS485_DE_PIN)
hwPinMode(MY_RS485_DE_PIN, OUTPUT); hwPinMode(MY_RS485_DE_PIN, OUTPUT);
hwDigitalWrite(MY_RS485_DE_PIN, LOW); hwDigitalWrite(MY_RS485_DE_PIN, LOW);
#endif #endif
return true; return true;
} }
void transportSetAddress(uint8_t address) { void transportSetAddress(uint8_t address)
{
_nodeId = address; _nodeId = address;
} }
uint8_t transportGetAddress() { uint8_t transportGetAddress()
{
return _nodeId; return _nodeId;
} }
bool transportAvailable() { bool transportAvailable()
{
_serialProcess(); _serialProcess();
return _packet_received; return _packet_received;
} }
bool transportSanityCheck() { bool transportSanityCheck()
{
// not implemented yet // not implemented yet
return true; return true;
} }
uint8_t transportReceive(void* data) { uint8_t transportReceive(void* data)
{
if (_packet_received) { if (_packet_received) {
memcpy(data,_data,_packet_len); memcpy(data,_data,_packet_len);
_packet_received = false; _packet_received = false;
return _packet_len; return _packet_len;
} } else {
else {
return (0); return (0);
} }
} }
void transportPowerDown() { void transportPowerDown()
{
// Nothing to shut down here // Nothing to shut down here
} }
+114 -94
View File
@@ -65,8 +65,7 @@
#define WPOLY 0x011B #define WPOLY 0x011B
#define DPOLY 0x008D #define DPOLY 0x008D
const static byte s_fwd [0x100] PROGMEM = const static byte s_fwd [0x100] PROGMEM = {
{
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
@@ -85,8 +84,7 @@ const static byte s_fwd [0x100] PROGMEM =
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
} ; } ;
const static byte s_inv [0x100] PROGMEM = const static byte s_inv [0x100] PROGMEM = {
{
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
@@ -125,8 +123,7 @@ static byte is_box (byte x)
static void xor_block (byte * d, byte * s) static void xor_block (byte * d, byte * s)
{ {
for (byte i = 0 ; i < N_BLOCK ; i += 4) for (byte i = 0 ; i < N_BLOCK ; i += 4) {
{
*d++ ^= *s++ ; // some unrolling *d++ ^= *s++ ; // some unrolling
*d++ ^= *s++ ; *d++ ^= *s++ ;
*d++ ^= *s++ ; *d++ ^= *s++ ;
@@ -136,8 +133,7 @@ static void xor_block (byte * d, byte * s)
static void copy_and_key (byte * d, byte * s, byte * k) static void copy_and_key (byte * d, byte * s, byte * k)
{ {
for (byte i = 0 ; i < N_BLOCK ; i += 4) for (byte i = 0 ; i < N_BLOCK ; i += 4) {
{
*d++ = *s++ ^ *k++ ; // some unrolling *d++ = *s++ ^ *k++ ; // some unrolling
*d++ = *s++ ^ *k++ ; *d++ = *s++ ^ *k++ ;
*d++ = *s++ ^ *k++ ; *d++ = *s++ ^ *k++ ;
@@ -151,36 +147,56 @@ static void copy_and_key (byte * d, byte * s, byte * k)
static void shift_sub_rows (byte st [N_BLOCK]) static void shift_sub_rows (byte st [N_BLOCK])
{ {
st [0] = s_box (st [0]) ; st [4] = s_box (st [4]) ; st [0] = s_box (st [0]) ;
st [8] = s_box (st [8]) ; st [12] = s_box (st [12]) ; st [4] = s_box (st [4]) ;
st [8] = s_box (st [8]) ;
st [12] = s_box (st [12]) ;
byte tt = st [1] ; byte tt = st [1] ;
st [1] = s_box (st [5]) ; st [5] = s_box (st [9]) ; st [1] = s_box (st [5]) ;
st [9] = s_box (st [13]) ; st [13] = s_box (tt) ; st [5] = s_box (st [9]) ;
st [9] = s_box (st [13]) ;
st [13] = s_box (tt) ;
tt = st[2] ; st [2] = s_box (st [10]) ; st [10] = s_box (tt) ; tt = st[2] ;
tt = st[6] ; st [6] = s_box (st [14]) ; st [14] = s_box (tt) ; st [2] = s_box (st [10]) ;
st [10] = s_box (tt) ;
tt = st[6] ;
st [6] = s_box (st [14]) ;
st [14] = s_box (tt) ;
tt = st[15] ; tt = st[15] ;
st [15] = s_box (st [11]) ; st [11] = s_box (st [7]) ; st [15] = s_box (st [11]) ;
st [7] = s_box (st [3]) ; st [3] = s_box (tt) ; st [11] = s_box (st [7]) ;
st [7] = s_box (st [3]) ;
st [3] = s_box (tt) ;
} }
static void inv_shift_sub_rows (byte st[N_BLOCK]) static void inv_shift_sub_rows (byte st[N_BLOCK])
{ {
st [0] = is_box (st[0]) ; st [4] = is_box (st [4]); st [0] = is_box (st[0]) ;
st [8] = is_box (st[8]) ; st [12] = is_box (st [12]); st [4] = is_box (st [4]);
st [8] = is_box (st[8]) ;
st [12] = is_box (st [12]);
byte tt = st[13] ; byte tt = st[13] ;
st [13] = is_box (st [9]) ; st [9] = is_box (st [5]) ; st [13] = is_box (st [9]) ;
st [5] = is_box (st [1]) ; st [1] = is_box (tt) ; st [9] = is_box (st [5]) ;
st [5] = is_box (st [1]) ;
st [1] = is_box (tt) ;
tt = st [2] ; st [2] = is_box (st [10]) ; st [10] = is_box (tt) ; tt = st [2] ;
tt = st [6] ; st [6] = is_box (st [14]) ; st [14] = is_box (tt) ; st [2] = is_box (st [10]) ;
st [10] = is_box (tt) ;
tt = st [6] ;
st [6] = is_box (st [14]) ;
st [14] = is_box (tt) ;
tt = st [3] ; tt = st [3] ;
st [3] = is_box (st [7]) ; st [7] = is_box (st [11]) ; st [3] = is_box (st [7]) ;
st [11] = is_box (st [15]) ; st [15] = is_box (tt) ; st [7] = is_box (st [11]) ;
st [11] = is_box (st [15]) ;
st [15] = is_box (tt) ;
} }
/* SUB COLUMNS PHASE */ /* SUB COLUMNS PHASE */
@@ -190,12 +206,14 @@ static void mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
byte j = 5 ; byte j = 5 ;
byte k = 10 ; byte k = 10 ;
byte l = 15 ; byte l = 15 ;
for (byte i = 0 ; i < N_BLOCK ; i += N_COL) for (byte i = 0 ; i < N_BLOCK ; i += N_COL) {
{
byte a = st [i] ; byte a = st [i] ;
byte b = st [j] ; j = (j+N_COL) & 15 ; byte b = st [j] ;
byte c = st [k] ; k = (k+N_COL) & 15 ; j = (j+N_COL) & 15 ;
byte d = st [l] ; l = (l+N_COL) & 15 ; byte c = st [k] ;
k = (k+N_COL) & 15 ;
byte d = st [l] ;
l = (l+N_COL) & 15 ;
byte a1 = s_box (a), b1 = s_box (b), c1 = s_box (c), d1 = s_box (d) ; byte a1 = s_box (a), b1 = s_box (b), c1 = s_box (c), d1 = s_box (d) ;
byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ; byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ;
dt[i] = a2 ^ b2^b1 ^ c1 ^ d1 ; dt[i] = a2 ^ b2^b1 ^ c1 ^ d1 ;
@@ -207,8 +225,7 @@ static void mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
static void inv_mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK]) static void inv_mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
{ {
for (byte i = 0 ; i < N_BLOCK ; i += N_COL) for (byte i = 0 ; i < N_BLOCK ; i += N_COL) {
{
byte a1 = st [i] ; byte a1 = st [i] ;
byte b1 = st [i+1] ; byte b1 = st [i+1] ;
byte c1 = st [i+2] ; byte c1 = st [i+2] ;
@@ -228,7 +245,8 @@ static void inv_mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
/******************************************************************************/ /******************************************************************************/
AES::AES(){ AES::AES()
{
byte ar_iv[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 }; byte ar_iv[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 };
memcpy(iv,ar_iv,8); memcpy(iv,ar_iv,8);
memcpy(iv+8,ar_iv,8); memcpy(iv+8,ar_iv,8);
@@ -254,8 +272,7 @@ AES::AES(){
byte AES::set_key (byte key [], int keylen) byte AES::set_key (byte key [], int keylen)
{ {
byte hi ; byte hi ;
switch (keylen) switch (keylen) {
{
case 16: case 16:
case 128: case 128:
keylen = 16; // 10 rounds keylen = 16; // 10 rounds
@@ -279,13 +296,11 @@ byte AES::set_key (byte key [], int keylen)
copy_n_bytes (key_sched, key, keylen) ; copy_n_bytes (key_sched, key, keylen) ;
byte t[4] ; byte t[4] ;
byte next = keylen ; byte next = keylen ;
for (byte cc = keylen, rc = 1 ; cc < hi ; cc += N_COL) for (byte cc = keylen, rc = 1 ; cc < hi ; cc += N_COL) {
{
for (byte i = 0 ; i < N_COL ; i++) { for (byte i = 0 ; i < N_COL ; i++) {
t[i] = key_sched [cc-4+i] ; t[i] = key_sched [cc-4+i] ;
} }
if (cc == next) if (cc == next) {
{
next += keylen ; next += keylen ;
byte ttt = t[0] ; byte ttt = t[0] ;
t[0] = s_box (t[1]) ^ rc ; t[0] = s_box (t[1]) ^ rc ;
@@ -293,9 +308,7 @@ byte AES::set_key (byte key [], int keylen)
t[2] = s_box (t[3]) ; t[2] = s_box (t[3]) ;
t[3] = s_box (ttt) ; t[3] = s_box (ttt) ;
rc = f2 (rc) ; rc = f2 (rc) ;
} } else if (keylen == 32 && (cc & 31) == 16) {
else if (keylen == 32 && (cc & 31) == 16)
{
for (byte i = 0 ; i < 4 ; i++) { for (byte i = 0 ; i < 4 ; i++) {
t[i] = s_box (t[i]) ; t[i] = s_box (t[i]) ;
} }
@@ -322,38 +335,36 @@ void AES::clean ()
void AES::copy_n_bytes (byte * d, byte * s, byte nn) void AES::copy_n_bytes (byte * d, byte * s, byte nn)
{ {
while (nn >= 4) while (nn >= 4) {
{
*d++ = *s++ ; // some unrolling *d++ = *s++ ; // some unrolling
*d++ = *s++ ; *d++ = *s++ ;
*d++ = *s++ ; *d++ = *s++ ;
*d++ = *s++ ; *d++ = *s++ ;
nn -= 4 ; nn -= 4 ;
} }
while (nn--) while (nn--) {
*d++ = *s++ ; *d++ = *s++ ;
}
} }
/******************************************************************************/ /******************************************************************************/
byte AES::encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK]) byte AES::encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
{ {
if (round) if (round) {
{
byte s1 [N_BLOCK], r ; byte s1 [N_BLOCK], r ;
copy_and_key (s1, plain, (byte*) (key_sched)) ; copy_and_key (s1, plain, (byte*) (key_sched)) ;
for (r = 1 ; r < round ; r++) for (r = 1 ; r < round ; r++) {
{
byte s2 [N_BLOCK] ; byte s2 [N_BLOCK] ;
mix_sub_columns (s2, s1) ; mix_sub_columns (s2, s1) ;
copy_and_key (s1, s2, (byte*) (key_sched + r * N_BLOCK)) ; copy_and_key (s1, s2, (byte*) (key_sched + r * N_BLOCK)) ;
} }
shift_sub_rows (s1) ; shift_sub_rows (s1) ;
copy_and_key (cipher, s1, (byte*) (key_sched + r * N_BLOCK)) ; copy_and_key (cipher, s1, (byte*) (key_sched + r * N_BLOCK)) ;
} } else {
else
return AES_FAILURE ; return AES_FAILURE ;
}
return AES_SUCCESS ; return AES_SUCCESS ;
} }
@@ -361,8 +372,7 @@ byte AES::encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOCK]) byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOCK])
{ {
while (n_block--) while (n_block--) {
{
xor_block (iv, plain) ; xor_block (iv, plain) ;
if (encrypt (iv, iv) != AES_SUCCESS) { if (encrypt (iv, iv) != AES_SUCCESS) {
return AES_FAILURE ; return AES_FAILURE ;
@@ -378,8 +388,7 @@ byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOC
byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block) byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block)
{ {
while (n_block--) while (n_block--) {
{
xor_block (iv, plain) ; xor_block (iv, plain) ;
if (encrypt (iv, iv) != AES_SUCCESS) { if (encrypt (iv, iv) != AES_SUCCESS) {
return AES_FAILURE ; return AES_FAILURE ;
@@ -395,22 +404,20 @@ byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block)
byte AES::decrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK]) byte AES::decrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
{ {
if (round) if (round) {
{
byte s1 [N_BLOCK] ; byte s1 [N_BLOCK] ;
copy_and_key (s1, plain, (byte*) (key_sched + round * N_BLOCK)) ; copy_and_key (s1, plain, (byte*) (key_sched + round * N_BLOCK)) ;
inv_shift_sub_rows (s1) ; inv_shift_sub_rows (s1) ;
for (byte r = round ; --r ; ) for (byte r = round ; --r ; ) {
{
byte s2 [N_BLOCK] ; byte s2 [N_BLOCK] ;
copy_and_key (s2, s1, (byte*) (key_sched + r * N_BLOCK)) ; copy_and_key (s2, s1, (byte*) (key_sched + r * N_BLOCK)) ;
inv_mix_sub_columns (s1, s2) ; inv_mix_sub_columns (s1, s2) ;
} }
copy_and_key (cipher, s1, (byte*) (key_sched)) ; copy_and_key (cipher, s1, (byte*) (key_sched)) ;
} } else {
else
return AES_FAILURE ; return AES_FAILURE ;
}
return AES_SUCCESS ; return AES_SUCCESS ;
} }
@@ -418,8 +425,7 @@ byte AES::decrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK]) byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK])
{ {
while (n_block--) while (n_block--) {
{
byte tmp [N_BLOCK] ; byte tmp [N_BLOCK] ;
copy_n_bytes (tmp, cipher, N_BLOCK) ; copy_n_bytes (tmp, cipher, N_BLOCK) ;
if (decrypt (cipher, plain) != AES_SUCCESS) { if (decrypt (cipher, plain) != AES_SUCCESS) {
@@ -437,8 +443,7 @@ byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOC
byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block) byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block)
{ {
while (n_block--) while (n_block--) {
{
byte tmp [N_BLOCK] ; byte tmp [N_BLOCK] ;
copy_n_bytes (tmp, cipher, N_BLOCK) ; copy_n_bytes (tmp, cipher, N_BLOCK) ;
if (decrypt (cipher, plain) != AES_SUCCESS) { if (decrypt (cipher, plain) != AES_SUCCESS) {
@@ -454,7 +459,8 @@ byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block)
/*****************************************************************************/ /*****************************************************************************/
void AES::set_IV(unsigned long long int IVCl){ void AES::set_IV(unsigned long long int IVCl)
{
memcpy(iv,&IVCl,8); memcpy(iv,&IVCl,8);
memcpy(iv+8,&IVCl,8); memcpy(iv+8,&IVCl,8);
IVC = IVCl; IVC = IVCl;
@@ -462,7 +468,8 @@ void AES::set_IV(unsigned long long int IVCl){
/******************************************************************************/ /******************************************************************************/
void AES::iv_inc(){ void AES::iv_inc()
{
IVC += 1; IVC += 1;
memcpy(iv,&IVC,8); memcpy(iv,&IVC,8);
memcpy(iv+8,&IVC,8); memcpy(iv+8,&IVC,8);
@@ -470,31 +477,35 @@ void AES::iv_inc(){
/******************************************************************************/ /******************************************************************************/
int AES::get_size(){ int AES::get_size()
{
return size; return size;
} }
/******************************************************************************/ /******************************************************************************/
void AES::set_size(int sizel){ void AES::set_size(int sizel)
{
size = sizel; size = sizel;
} }
/******************************************************************************/ /******************************************************************************/
void AES::get_IV(byte *out){ void AES::get_IV(byte *out)
{
memcpy(out,&IVC,8); memcpy(out,&IVC,8);
memcpy(out+8,&IVC,8); memcpy(out+8,&IVC,8);
} }
/******************************************************************************/ /******************************************************************************/
void AES::calc_size_n_pad(int p_size){ void AES::calc_size_n_pad(int p_size)
{
int s_of_p = p_size - 1; int s_of_p = p_size - 1;
if ( s_of_p % N_BLOCK == 0){ if ( s_of_p % N_BLOCK == 0) {
size = s_of_p; size = s_of_p;
}else{ } else {
size = s_of_p + (N_BLOCK-(s_of_p % N_BLOCK)); size = s_of_p + (N_BLOCK-(s_of_p % N_BLOCK));
} }
pad = size - s_of_p; pad = size - s_of_p;
@@ -505,41 +516,44 @@ void AES::calc_size_n_pad(int p_size){
void AES::padPlaintext(void* in,byte* out) void AES::padPlaintext(void* in,byte* out)
{ {
memcpy(out,in,size); memcpy(out,in,size);
for (int i = size-pad; i < size; i++){; for (int i = size-pad; i < size; i++) {
;
out[i] = arr_pad[pad - 1]; out[i] = arr_pad[pad - 1];
} }
} }
/******************************************************************************/ /******************************************************************************/
bool AES::CheckPad(byte* in,int lsize){ bool AES::CheckPad(byte* in,int lsize)
if (in[lsize-1] <= 0x0f){ {
if (in[lsize-1] <= 0x0f) {
int lpad = (int)in[lsize-1]; int lpad = (int)in[lsize-1];
for (int i = lsize - 1; i >= lsize-lpad; i--){ for (int i = lsize - 1; i >= lsize-lpad; i--) {
if (arr_pad[lpad - 1] != in[i]){ if (arr_pad[lpad - 1] != in[i]) {
return false; return false;
} }
} }
}else{ } else {
return true; return true;
} }
return true; return true;
} }
/******************************************************************************/ /******************************************************************************/
void AES::printArray(byte output[],bool p_pad) void AES::printArray(byte output[],bool p_pad)
{ {
uint8_t i,j; uint8_t i,j;
uint8_t loops = size/N_BLOCK; uint8_t loops = size/N_BLOCK;
uint8_t outp = N_BLOCK; uint8_t outp = N_BLOCK;
for (j = 0; j < loops; j += 1){ for (j = 0; j < loops; j += 1) {
if (p_pad && (j == (loops - 1)) ) { outp = N_BLOCK - pad; } if (p_pad && (j == (loops - 1)) ) {
for (i = 0; i < outp; i++) outp = N_BLOCK - pad;
{ }
for (i = 0; i < outp; i++) {
printf_P(PSTR("%c"),output[j*N_BLOCK + i]); printf_P(PSTR("%c"),output[j*N_BLOCK + i]);
} }
} }
printf_P(PSTR("\n")); printf_P(PSTR("\n"));
} }
@@ -547,8 +561,7 @@ for (j = 0; j < loops; j += 1){
void AES::printArray(byte output[],int sizel) void AES::printArray(byte output[],int sizel)
{ {
for (int i = 0; i < sizel; i++) for (int i = 0; i < sizel; i++) {
{
printf_P(PSTR("%x"),output[i]); printf_P(PSTR("%x"),output[i]);
} }
printf_P(PSTR("\n")); printf_P(PSTR("\n"));
@@ -557,7 +570,9 @@ void AES::printArray(byte output[],int sizel)
/******************************************************************************/ /******************************************************************************/
void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits, byte ivl [N_BLOCK]){ void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits,
byte ivl [N_BLOCK])
{
calc_size_n_pad(size_p); calc_size_n_pad(size_p);
byte plain_p[get_size()]; byte plain_p[get_size()];
padPlaintext(plain,plain_p); padPlaintext(plain,plain_p);
@@ -568,7 +583,8 @@ void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits
/******************************************************************************/ /******************************************************************************/
void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits){ void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits)
{
calc_size_n_pad(size_p); calc_size_n_pad(size_p);
byte plain_p[get_size()]; byte plain_p[get_size()];
padPlaintext(plain,plain_p); padPlaintext(plain,plain_p);
@@ -579,7 +595,9 @@ void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits
/******************************************************************************/ /******************************************************************************/
void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits, byte ivl [N_BLOCK]){ void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits,
byte ivl [N_BLOCK])
{
set_size(size_c); set_size(size_c);
int blocks = size_c / N_BLOCK; int blocks = size_c / N_BLOCK;
set_key (key, bits); set_key (key, bits);
@@ -588,7 +606,8 @@ void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits
/******************************************************************************/ /******************************************************************************/
void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits){ void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits)
{
set_size(size_c); set_size(size_c);
int blocks = size_c / N_BLOCK; int blocks = size_c / N_BLOCK;
set_key (key, bits); set_key (key, bits);
@@ -599,7 +618,8 @@ void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits
/******************************************************************************/ /******************************************************************************/
#if defined(AES_LINUX) #if defined(AES_LINUX)
double AES::millis(){ double AES::millis()
{
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
return (tv.tv_sec + 0.000001 * tv.tv_usec); return (tv.tv_sec + 0.000001 * tv.tv_usec);
} }
+38 -37
View File
@@ -32,21 +32,21 @@
cipher state. cipher state.
*/ */
/* code was modified by george spanos <spaniakos@gmail.com> /* code was modified by george spanos <spaniakos@gmail.com>
* 16/12/14 * 16/12/14
*/ */
/** AES class */ /** AES class */
class AES 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 NOTE: If the length_type used for the key length is an
unsigned 8-bit character, a key length of 256 bits must unsigned 8-bit character, a key length of 256 bits must
be entered as a length in bytes (valid inputs are hence be entered as a length in bytes (valid inputs are hence
128, 192, 16, 24 and 32). 128, 192, 16, 24 and 32).
*/ */
/** \fn AES() /** \fn AES()
* \brief AES constructor * \brief AES constructor
* *
@@ -285,27 +285,28 @@ class AES
*/ */
void do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits); void do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits);
#if defined(AES_LINUX) #if defined(AES_LINUX)
/** /**
* used in linux in order to retrieve the time in milliseconds. * used in linux in order to retrieve the time in milliseconds.
* *
* @return returns the milliseconds in a double format. * @return returns the milliseconds in a double format.
*/ */
double millis(); double millis();
#endif #endif
private: private:
int round ;/**< holds the number of rounds to be used. */ int round ;/**< holds the number of rounds to be used. */
byte key_sched [KEY_SCHEDULE_BYTES] ;/**< holds the pre-computed key for the encryption/decrpytion. */ byte key_sched [KEY_SCHEDULE_BYTES]
;/**< holds the pre-computed key for the encryption/decrpytion. */
unsigned long long int IVC;/**< holds the initialization vector counter in numerical format. */ unsigned long long int IVC;/**< holds the initialization vector counter in numerical format. */
byte iv[16];/**< holds the initialization vector that will be used in the cipher. */ byte iv[16];/**< holds the initialization vector that will be used in the cipher. */
int pad;/**< holds the size of the padding. */ int pad;/**< holds the size of the padding. */
int size;/**< hold the size of the plaintext to be ciphered */ int size;/**< hold the size of the plaintext to be ciphered */
#if defined(AES_LINUX) #if defined(AES_LINUX)
timeval tv;/**< holds the time value on linux */ timeval tv;/**< holds the time value on linux */
byte arr_pad[15];/**< holds the hexadecimal padding values 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 */ 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
} ; } ;
@@ -320,32 +321,32 @@ class AES
* The text and keys can be either in HEX or String format.<br /> * The text and keys can be either in HEX or String format.<br />
*/ */
/** /**
* @example aes.cpp * @example aes.cpp
* <b>For Rasberry pi</b><br> * <b>For Rasberry pi</b><br>
* <b>Updated: spaniakos 2015 </b><br> * <b>Updated: spaniakos 2015 </b><br>
* *
* This is an example of how to use AES in CBC mode easily. * 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.<br /> * The text and keys can be either in HEX or String format.<br />
*/ */
/** /**
* @example test_vectors.pde * @example test_vectors.pde
* <b>For Arduino</b><br> * <b>For Arduino</b><br>
* <b>Updated: spaniakos 2015 </b><br> * <b>Updated: spaniakos 2015 </b><br>
* *
* This is an example of monte carlo test vectors, in order to justify the effectiveness of the algorithm.<br /> * This is an example of monte carlo test vectors, in order to justify the effectiveness of the algorithm.<br />
* plus is a classical approach to the AES encryption library with out the easy to use add-on modifications. * plus is a classical approach to the AES encryption library with out the easy to use add-on modifications.
*/ */
/** /**
* @example test_vectors.cpp * @example test_vectors.cpp
* <b>For Rasberry pi</b><br> * <b>For Rasberry pi</b><br>
* <b>Updated: spaniakos 2015 </b><br> * <b>Updated: spaniakos 2015 </b><br>
* *
* This is an example of monte carlo test vectors, in order to justify the effectiveness of the algorithm.<br /> * This is an example of monte carlo test vectors, in order to justify the effectiveness of the algorithm.<br />
* plus is a classical approach to the AES encryption library with out the easy to use add-on modifications. * 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 * @defgroup aeslib AES library for Arduino and Raspberry pi
+17 -17
View File
@@ -7,34 +7,34 @@
#if (defined(__linux) || defined(linux)) && !defined(__ARDUINO_X86__) #if (defined(__linux) || defined(linux)) && !defined(__ARDUINO_X86__)
#define AES_LINUX #define AES_LINUX
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/time.h> #include <sys/time.h>
#include <unistd.h> #include <unistd.h>
#else #else
#include <Arduino.h> #include <Arduino.h>
#endif #endif
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#if defined(__ARDUINO_X86__) || (defined (__linux) || defined (linux)) #if defined(__ARDUINO_X86__) || (defined (__linux) || defined (linux))
#undef PROGMEM #undef PROGMEM
#define PROGMEM __attribute__(( section(".progmem.data") )) #define PROGMEM __attribute__(( section(".progmem.data") ))
#define pgm_read_byte(p) (*(p)) #define pgm_read_byte(p) (*(p))
typedef unsigned char byte; typedef unsigned char byte;
#define printf_P printf #define printf_P printf
#define PSTR(x) (x) #define PSTR(x) (x)
#elif defined(ARDUINO_ARCH_ESP8266) #elif defined(ARDUINO_ARCH_ESP8266)
#include <pgmspace.h> #include <pgmspace.h>
#elif defined(ARDUINO_ARCH_SAMD) #elif defined(ARDUINO_ARCH_SAMD)
#define printf_P printf #define printf_P printf
#else #else
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#endif #endif
#define N_ROW 4 #define N_ROW 4
+1 -1
View File
@@ -17,7 +17,7 @@ int main(int argc, char** argv)
{ {
printf("\n===testng mode\n") ; printf("\n===testng mode\n") ;
for (int i=0;i<1;i++){ for (int i=0; i<1; i++) {
prekey_test () ; prekey_test () ;
} }
} }
+38 -39
View File
@@ -22,8 +22,7 @@ int main(int argc, char** argv)
monte_carlo (128) ; monte_carlo (128) ;
for (int keysize = 128 ; keysize <= 256 ; keysize += 64) for (int keysize = 128 ; keysize <= 256 ; keysize += 64) {
{
prekey_test_var_plaintext (keysize) ; prekey_test_var_plaintext (keysize) ;
prekey_test_var_key (keysize) ; prekey_test_var_key (keysize) ;
} }
@@ -37,12 +36,12 @@ void prekey_test_var_plaintext (int bits)
byte succ ; byte succ ;
set_bits (bits, key, 0) ; // all zero key set_bits (bits, key, 0) ; // all zero key
succ = aes.set_key (key, bits) ; succ = aes.set_key (key, bits) ;
if (succ != SUCCESS) if (succ != SUCCESS) {
printf("Failure set_key\n") ; printf("Failure set_key\n") ;
}
for (int bitcount = 1 ; bitcount <= 128 ; bitcount++) for (int bitcount = 1 ; bitcount <= 128 ; bitcount++) {
{
printf ("COUNT = %i \n",bitcount-1); printf ("COUNT = %i \n",bitcount-1);
print_value ("KEY = ", key, bits) ; print_value ("KEY = ", key, bits) ;
set_bits (128, plain, bitcount) ; set_bits (128, plain, bitcount) ;
@@ -50,14 +49,16 @@ void prekey_test_var_plaintext (int bits)
print_value ("PLAINTEXT = ", plain, 128) ; print_value ("PLAINTEXT = ", plain, 128) ;
succ = aes.encrypt (plain, cipher) ; succ = aes.encrypt (plain, cipher) ;
if (succ != SUCCESS) if (succ != SUCCESS) {
printf ("Failure encrypt\n") ; printf ("Failure encrypt\n") ;
}
print_value ("CIPHERTEXT = ", cipher, 128) ; print_value ("CIPHERTEXT = ", cipher, 128) ;
succ = aes.decrypt (cipher, check) ; succ = aes.decrypt (cipher, check) ;
if (succ != SUCCESS) if (succ != SUCCESS) {
printf ("Failure decrypt\n") ; printf ("Failure decrypt\n") ;
}
//print_value ("CHECK = ", check, 128) ; //print_value ("CHECK = ", check, 128) ;
check_same (plain, check, 128) ; check_same (plain, check, 128) ;
@@ -73,26 +74,28 @@ void prekey_test_var_key (int bits)
byte succ ; byte succ ;
set_bits (128, plain, 0) ; set_bits (128, plain, 0) ;
for (int bitcount = 1 ; bitcount <= bits ; bitcount++) for (int bitcount = 1 ; bitcount <= bits ; bitcount++) {
{
set_bits (bits, key, bitcount) ; // all zero key set_bits (bits, key, bitcount) ; // all zero key
succ = aes.set_key (key, bits) ; succ = aes.set_key (key, bits) ;
if (succ != SUCCESS) if (succ != SUCCESS) {
printf ("Failure set_key\n") ; printf ("Failure set_key\n") ;
}
printf ("COUNT = %i\n",bitcount-1); printf ("COUNT = %i\n",bitcount-1);
print_value ("KEY = ", key, bits) ; print_value ("KEY = ", key, bits) ;
print_value ("PLAINTEXT = ", plain, 128) ; print_value ("PLAINTEXT = ", plain, 128) ;
succ = aes.encrypt (plain, cipher) ; succ = aes.encrypt (plain, cipher) ;
if (succ != SUCCESS) if (succ != SUCCESS) {
printf ("Failure encrypt\n") ; printf ("Failure encrypt\n") ;
}
print_value ("CIPHERTEXT = ", cipher, 128) ; print_value ("CIPHERTEXT = ", cipher, 128) ;
succ = aes.decrypt (cipher, check) ; succ = aes.decrypt (cipher, check) ;
if (succ != SUCCESS) if (succ != SUCCESS) {
printf ("Failure decrypt\n") ; printf ("Failure decrypt\n") ;
}
check_same (plain, check, 128) ; check_same (plain, check, 128) ;
printf("\n"); printf("\n");
@@ -103,20 +106,22 @@ void set_bits (int bits, byte * a, int count)
{ {
bits >>= 3 ; bits >>= 3 ;
byte bcount = count >> 3 ; byte bcount = count >> 3 ;
for (byte i = 0 ; i < bcount ; i++) for (byte i = 0 ; i < bcount ; i++) {
a [i] = 0xFF ; a [i] = 0xFF ;
if ((count & 7) != 0) }
if ((count & 7) != 0) {
a [bcount++] = 0xFF & (0xFF00 >> (count & 7)) ; a [bcount++] = 0xFF & (0xFF00 >> (count & 7)) ;
for (byte i = bcount ; i < bits ; i++) }
for (byte i = bcount ; i < bits ; i++) {
a [i] = 0x00 ; a [i] = 0x00 ;
}
} }
void check_same (byte * a, byte * b, int bits) void check_same (byte * a, byte * b, int bits)
{ {
bits >>= 3 ; bits >>= 3 ;
for (byte i = 0 ; i < bits ; i++) for (byte i = 0 ; i < bits ; i++)
if (a[i] != b[i]) if (a[i] != b[i]) {
{
printf ("Failure plain != check\n") ; printf ("Failure plain != check\n") ;
return ; return ;
} }
@@ -129,8 +134,7 @@ void print_value (const char * str, byte * a, int bits)
{ {
printf ("%s",str) ; printf ("%s",str) ;
bits >>= 3 ; bits >>= 3 ;
for (int i = 0 ; i < bits ; i++) for (int i = 0 ; i < bits ; i++) {
{
byte b = a[i] ; byte b = a[i] ;
printf("%c%c",hex[b >> 4],hex [b & 15]); printf("%c%c",hex[b >> 4],hex [b & 15]);
//Serial.print (hex [b >> 4]) ; //Serial.print (hex [b >> 4]) ;
@@ -139,45 +143,40 @@ void print_value (const char * str, byte * a, int bits)
printf("\n") ; printf("\n") ;
} }
byte monteplain [] = byte monteplain [] = {
{ 0xb9, 0x14, 0x5a, 0x76, 0x8b, 0x7d, 0xc4, 0x89, 0xb9, 0x14, 0x5a, 0x76, 0x8b, 0x7d, 0xc4, 0x89,
0xa0, 0x96, 0xb5, 0x46, 0xf4, 0x3b, 0x23, 0x1f } ; 0xa0, 0x96, 0xb5, 0x46, 0xf4, 0x3b, 0x23, 0x1f
byte montekey [] = } ;
{ 0x13, 0x9a, 0x35, 0x42, 0x2f, 0x1d, 0x61, 0xde, byte montekey [] = {
0x3c, 0x91, 0x78, 0x7f, 0xe0, 0x50, 0x7a, 0xfd } ; 0x13, 0x9a, 0x35, 0x42, 0x2f, 0x1d, 0x61, 0xde,
0x3c, 0x91, 0x78, 0x7f, 0xe0, 0x50, 0x7a, 0xfd
} ;
void monte_carlo (int bits) void monte_carlo (int bits)
{ {
printf ("\nMonte Carlo %i bits\n",bits); printf ("\nMonte Carlo %i bits\n",bits);
byte succ; byte succ;
for (int i = 0 ; i < 16 ; i++) for (int i = 0 ; i < 16 ; i++) {
{
plain [i] = monteplain [i] ; plain [i] = monteplain [i] ;
key [i] = montekey [i] ; key [i] = montekey [i] ;
} }
for (int i = 0 ; i < 100 ; i++) for (int i = 0 ; i < 100 ; i++) {
{
printf ("COUNT = %i\n",i); printf ("COUNT = %i\n",i);
print_value ("KEY = ", key, bits) ; print_value ("KEY = ", key, bits) ;
print_value ("PLAINTEXT = ", plain, 128) ; print_value ("PLAINTEXT = ", plain, 128) ;
succ = aes.set_key (key, bits) ; succ = aes.set_key (key, bits) ;
for (int j = 0 ; j < 1000 ; j++) for (int j = 0 ; j < 1000 ; j++) {
{
succ = aes.encrypt (plain, cipher) ; succ = aes.encrypt (plain, cipher) ;
aes.copy_n_bytes (plain, cipher, 16) ; aes.copy_n_bytes (plain, cipher, 16) ;
} }
print_value ("CIPHERTEXT = ", cipher, 128) ; print_value ("CIPHERTEXT = ", cipher, 128) ;
printf("\n"); printf("\n");
if (bits == 128) if (bits == 128) {
{ for (byte k = 0 ; k < 16 ; k++) {
for (byte k = 0 ; k < 16 ; k++)
key [k] ^= cipher [k] ; key [k] ^= cipher [k] ;
} }
else if (bits == 192) } else if (bits == 192) {
{ } else {
}
else
{
} }
} }
} }
+2 -2
View File
@@ -5,7 +5,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation.
*/ */
/* Galileo support from spaniakos <spaniakos@gmail.com> */ /* Galileo support from spaniakos <spaniakos@gmail.com> */
/** /**
* @file printf.h * @file printf.h
@@ -33,7 +33,7 @@ void printf_begin(void)
#elif defined (__arm__) #elif defined (__arm__)
void printf_begin(void){} void printf_begin(void) {}
#elif defined(__ARDUINO_X86__) #elif defined(__ARDUINO_X86__)
int serial_putc( char c, FILE * ) int serial_putc( char c, FILE * )
+52 -89
View File
@@ -16,7 +16,8 @@ static uint8_t swi_send_byte(uint8_t value);
static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response); static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response);
static uint8_t sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, uint16_t address); static uint8_t sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, uint16_t address);
static uint8_t sha204c_resync(uint8_t size, uint8_t *response); static uint8_t sha204c_resync(uint8_t size, uint8_t *response);
static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, uint8_t execution_delay, uint8_t execution_timeout); static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer,
uint8_t execution_delay, uint8_t execution_timeout);
/* SWI bit bang functions */ /* SWI bit bang functions */
@@ -26,8 +27,7 @@ static void swi_set_signal_pin(uint8_t is_high)
if (is_high) { if (is_high) {
SHA204_POUT_HIGH(); SHA204_POUT_HIGH();
} } else {
else {
SHA204_POUT_LOW(); SHA204_POUT_LOW();
} }
} }
@@ -47,19 +47,14 @@ static uint8_t swi_send_bytes(uint8_t count, uint8_t *buffer)
// Wait turn around time. // Wait turn around time.
delayMicroseconds(RX_TX_DELAY); //RX_TX_DELAY; delayMicroseconds(RX_TX_DELAY); //RX_TX_DELAY;
for (i = 0; i < count; i++) for (i = 0; i < count; i++) {
{ for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) {
for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) if (bit_mask & buffer[i]) {
{
if (bit_mask & buffer[i])
{
SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin; SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin;
delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; delayMicroseconds(BIT_DELAY); //BIT_DELAY_1;
SHA204_POUT_HIGH(); //*device_port_OUT |= device_pin; SHA204_POUT_HIGH(); //*device_port_OUT |= device_pin;
delayMicroseconds(7*BIT_DELAY); //BIT_DELAY_7; delayMicroseconds(7*BIT_DELAY); //BIT_DELAY_7;
} } else {
else
{
// Send a zero bit. // Send a zero bit.
SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin; SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin;
delayMicroseconds(BIT_DELAY); //BIT_DELAY_1; delayMicroseconds(BIT_DELAY); //BIT_DELAY_1;
@@ -96,10 +91,8 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
SHA204_SET_INPUT(); SHA204_SET_INPUT();
// Receive bits and store in buffer. // Receive bits and store in buffer.
for (i = 0; i < count; i++) for (i = 0; i < count; i++) {
{ for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) {
for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1)
{
pulse_count = 0; pulse_count = 0;
// Make sure that the variable below is big enough. // Make sure that the variable below is big enough.
@@ -108,33 +101,28 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
timeout_count = START_PULSE_TIME_OUT; timeout_count = START_PULSE_TIME_OUT;
// Detect start bit. // Detect start bit.
while (--timeout_count > 0) while (--timeout_count > 0) {
{
// Wait for falling edge. // Wait for falling edge.
if (SHA204_PIN_READ() == 0) { if (SHA204_PIN_READ() == 0) {
break; break;
} }
} }
if (timeout_count == 0) if (timeout_count == 0) {
{
status = SWI_FUNCTION_RETCODE_TIMEOUT; status = SWI_FUNCTION_RETCODE_TIMEOUT;
break; break;
} }
do do {
{
// Wait for rising edge. // Wait for rising edge.
if (SHA204_PIN_READ() != 0) if (SHA204_PIN_READ() != 0) {
{
// For an Atmel microcontroller this might be faster than "pulse_count++". // For an Atmel microcontroller this might be faster than "pulse_count++".
pulse_count = 1; pulse_count = 1;
break; break;
} }
} while (--timeout_count > 0); } while (--timeout_count > 0);
if (pulse_count == 0) if (pulse_count == 0) {
{
status = SWI_FUNCTION_RETCODE_TIMEOUT; status = SWI_FUNCTION_RETCODE_TIMEOUT;
break; break;
} }
@@ -146,10 +134,8 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
timeout_count = ZERO_PULSE_TIME_OUT; timeout_count = ZERO_PULSE_TIME_OUT;
// Detect possible edge indicating zero bit. // Detect possible edge indicating zero bit.
do do {
{ if (SHA204_PIN_READ() == 0) {
if (SHA204_PIN_READ() == 0)
{
// For an Atmel microcontroller this might be faster than "pulse_count++". // For an Atmel microcontroller this might be faster than "pulse_count++".
pulse_count = 2; pulse_count = 2;
break; break;
@@ -158,10 +144,8 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
// Wait for rising edge of zero pulse before returning. Otherwise we might interpret // Wait for rising edge of zero pulse before returning. Otherwise we might interpret
// its rising edge as the next start pulse. // its rising edge as the next start pulse.
if (pulse_count == 2) if (pulse_count == 2) {
{ do {
do
{
if (SHA204_PIN_READ() != 0) { if (SHA204_PIN_READ() != 0) {
break; break;
} }
@@ -169,9 +153,10 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
} }
// Update byte at current buffer index. // Update byte at current buffer index.
else else {
buffer[i] |= bit_mask; // received "one" bit buffer[i] |= bit_mask; // received "one" bit
} }
}
if (status != SWI_FUNCTION_RETCODE_SUCCESS) { if (status != SWI_FUNCTION_RETCODE_SUCCESS) {
break; break;
@@ -179,8 +164,7 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
} }
interrupts(); //swi_enable_interrupts(); interrupts(); //swi_enable_interrupts();
if (status == SWI_FUNCTION_RETCODE_TIMEOUT) if (status == SWI_FUNCTION_RETCODE_TIMEOUT) {
{
if (i > 0) { if (i > 0) {
// Indicate that we timed out after having received at least one byte. // Indicate that we timed out after having received at least one byte.
status = SWI_FUNCTION_RETCODE_RX_FAIL; status = SWI_FUNCTION_RETCODE_RX_FAIL;
@@ -204,8 +188,7 @@ static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response)
(void) swi_send_byte(SHA204_SWI_FLAG_TX); (void) swi_send_byte(SHA204_SWI_FLAG_TX);
ret_code = swi_receive_bytes(size, response); ret_code = swi_receive_bytes(size, response);
if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) {
{
count_byte = response[SHA204_BUFFER_POS_COUNT]; count_byte = response[SHA204_BUFFER_POS_COUNT];
if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) { if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) {
return SHA204_INVALID_SIZE; return SHA204_INVALID_SIZE;
@@ -219,8 +202,7 @@ static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response)
// device being busy executing a command. // device being busy executing a command.
if (ret_code == SWI_FUNCTION_RETCODE_TIMEOUT) { if (ret_code == SWI_FUNCTION_RETCODE_TIMEOUT) {
return SHA204_RX_NO_RESPONSE; return SHA204_RX_NO_RESPONSE;
} } else {
else {
return SHA204_RX_FAIL; return SHA204_RX_FAIL;
} }
} }
@@ -249,7 +231,8 @@ static uint8_t sha204c_resync(uint8_t size, uint8_t *response)
return (ret_code == SHA204_SUCCESS ? SHA204_RESYNC_WITH_WAKEUP : ret_code); return (ret_code == SHA204_SUCCESS ? SHA204_RESYNC_WITH_WAKEUP : ret_code);
} }
static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, uint8_t execution_delay, uint8_t execution_timeout) static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer,
uint8_t execution_delay, uint8_t execution_timeout)
{ {
uint8_t ret_code = SHA204_FUNC_FAIL; uint8_t ret_code = SHA204_FUNC_FAIL;
uint8_t ret_code_resync; uint8_t ret_code_resync;
@@ -268,23 +251,19 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
// Retry loop for sending a command and receiving a response. // Retry loop for sending a command and receiving a response.
n_retries_send = SHA204_RETRY_COUNT + 1; n_retries_send = SHA204_RETRY_COUNT + 1;
while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS)) while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS)) {
{
// Send command. // Send command.
ret_code = swi_send_byte(SHA204_SWI_FLAG_CMD); ret_code = swi_send_byte(SHA204_SWI_FLAG_CMD);
if (ret_code != SWI_FUNCTION_RETCODE_SUCCESS) { if (ret_code != SWI_FUNCTION_RETCODE_SUCCESS) {
ret_code = SHA204_COMM_FAIL; ret_code = SHA204_COMM_FAIL;
} } else {
else {
ret_code = swi_send_bytes(count, tx_buffer); ret_code = swi_send_bytes(count, tx_buffer);
} }
if (ret_code != SHA204_SUCCESS) if (ret_code != SHA204_SUCCESS) {
{
if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) { if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) {
return ret_code; // The device seems to be dead in the water. return ret_code; // The device seems to be dead in the water.
} } else {
else {
continue; continue;
} }
} }
@@ -294,8 +273,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
// Retry loop for receiving a response. // Retry loop for receiving a response.
n_retries_receive = SHA204_RETRY_COUNT + 1; n_retries_receive = SHA204_RETRY_COUNT + 1;
while (n_retries_receive-- > 0) while (n_retries_receive-- > 0) {
{
// Reset response buffer. // Reset response buffer.
for (i = 0; i < rx_size; i++) { for (i = 0; i < rx_size; i++) {
rx_buffer[i] = 0; rx_buffer[i] = 0;
@@ -303,28 +281,23 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
// Poll for response. // Poll for response.
timeout_countdown = execution_timeout_us; timeout_countdown = execution_timeout_us;
do do {
{
ret_code = sha204p_receive_response(rx_size, rx_buffer); ret_code = sha204p_receive_response(rx_size, rx_buffer);
timeout_countdown -= SHA204_RESPONSE_TIMEOUT; timeout_countdown -= SHA204_RESPONSE_TIMEOUT;
} } while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (ret_code == SHA204_RX_NO_RESPONSE));
while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (ret_code == SHA204_RX_NO_RESPONSE));
if (ret_code == SHA204_RX_NO_RESPONSE) if (ret_code == SHA204_RX_NO_RESPONSE) {
{
// We did not receive a response. Re-synchronize and send command again. // We did not receive a response. Re-synchronize and send command again.
if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) { if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) {
// The device seems to be dead in the water. // The device seems to be dead in the water.
return ret_code; return ret_code;
} } else {
else {
break; break;
} }
} }
// Check whether we received a valid response. // Check whether we received a valid response.
if (ret_code == SHA204_INVALID_SIZE) if (ret_code == SHA204_INVALID_SIZE) {
{
// We see 0xFF for the count when communication got out of sync. // We see 0xFF for the count when communication got out of sync.
ret_code_resync = sha204c_resync(rx_size, rx_buffer); ret_code_resync = sha204c_resync(rx_size, rx_buffer);
if (ret_code_resync == SHA204_SUCCESS) { if (ret_code_resync == SHA204_SUCCESS) {
@@ -335,8 +308,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
// We could re-synchronize, but only after waking up the device. // We could re-synchronize, but only after waking up the device.
// Re-send command. // Re-send command.
break; break;
} } else {
else {
// We failed to re-synchronize. // We failed to re-synchronize.
return ret_code; return ret_code;
} }
@@ -345,8 +317,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
// We received a response of valid size. // We received a response of valid size.
// Check the consistency of the response. // Check the consistency of the response.
ret_code = sha204c_check_crc(rx_buffer); ret_code = sha204c_check_crc(rx_buffer);
if (ret_code == SHA204_SUCCESS) if (ret_code == SHA204_SUCCESS) {
{
// Received valid response. // Received valid response.
if (rx_buffer[SHA204_BUFFER_POS_COUNT] > SHA204_RSP_SIZE_MIN) { if (rx_buffer[SHA204_BUFFER_POS_COUNT] > SHA204_RSP_SIZE_MIN) {
// Received non-status response. We are done. // Received non-status response. We are done.
@@ -364,8 +335,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
if (status_byte == SHA204_STATUS_BYTE_EXEC) { if (status_byte == SHA204_STATUS_BYTE_EXEC) {
return SHA204_CMD_FAIL; return SHA204_CMD_FAIL;
} }
if (status_byte == SHA204_STATUS_BYTE_COMM) if (status_byte == SHA204_STATUS_BYTE_COMM) {
{
// In case of the device status byte indicating a communication // In case of the device status byte indicating a communication
// error this function exits the retry loop for receiving a response // error this function exits the retry loop for receiving a response
// and enters the overall retry loop // and enters the overall retry loop
@@ -379,8 +349,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
return ret_code; return ret_code;
} }
else else {
{
// Received response with incorrect CRC. // Received response with incorrect CRC.
ret_code_resync = sha204c_resync(rx_size, rx_buffer); ret_code_resync = sha204c_resync(rx_size, rx_buffer);
if (ret_code_resync == SHA204_SUCCESS) { if (ret_code_resync == SHA204_SUCCESS) {
@@ -391,8 +360,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
// We could re-synchronize, but only after waking up the device. // We could re-synchronize, but only after waking up the device.
// Re-send command. // Re-send command.
break; break;
} } else {
else {
// We failed to re-synchronize. // We failed to re-synchronize.
return ret_code; return ret_code;
} }
@@ -422,7 +390,8 @@ static uint8_t sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone
rx_size = (zone & SHA204_ZONE_COUNT_FLAG) ? READ_32_RSP_SIZE : READ_4_RSP_SIZE; rx_size = (zone & SHA204_ZONE_COUNT_FLAG) ? READ_32_RSP_SIZE : READ_4_RSP_SIZE;
return sha204c_send_and_receive(&tx_buffer[0], rx_size, &rx_buffer[0], READ_DELAY, READ_EXEC_MAX - READ_DELAY); return sha204c_send_and_receive(&tx_buffer[0], rx_size, &rx_buffer[0], READ_DELAY,
READ_EXEC_MAX - READ_DELAY);
} }
/* CRC Calculator and Checker */ /* CRC Calculator and Checker */
@@ -435,10 +404,8 @@ static void sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc)
uint8_t shift_register; uint8_t shift_register;
uint8_t data_bit, crc_bit; uint8_t data_bit, crc_bit;
for (counter = 0; counter < length; counter++) for (counter = 0; counter < length; counter++) {
{ for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) {
for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1)
{
data_bit = (data[counter] & shift_register) ? 1 : 0; data_bit = (data[counter] & shift_register) ? 1 : 0;
crc_bit = crc_register >> 15; crc_bit = crc_register >> 15;
@@ -510,12 +477,9 @@ uint8_t atsha204_wakeup(uint8_t *response)
// Verify status response. // Verify status response.
if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN) { if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN) {
ret_code = SHA204_INVALID_SIZE; ret_code = SHA204_INVALID_SIZE;
} } else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP) {
else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP) {
ret_code = SHA204_COMM_FAIL; ret_code = SHA204_COMM_FAIL;
} } else {
else
{
if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33) if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33)
|| (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43)) { || (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43)) {
ret_code = SHA204_BAD_CRC; ret_code = SHA204_BAD_CRC;
@@ -529,7 +493,8 @@ uint8_t atsha204_wakeup(uint8_t *response)
} }
uint8_t atsha204_execute(uint8_t op_code, uint8_t param1, uint16_t param2, uint8_t atsha204_execute(uint8_t op_code, uint8_t param1, uint16_t param2,
uint8_t datalen1, uint8_t *data1, uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer) uint8_t datalen1, uint8_t *data1, uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size,
uint8_t *rx_buffer)
{ {
uint8_t poll_delay, poll_timeout, response_size; uint8_t poll_delay, poll_timeout, response_size;
uint8_t *p_buffer; uint8_t *p_buffer;
@@ -537,8 +502,7 @@ uint8_t atsha204_execute(uint8_t op_code, uint8_t param1, uint16_t param2,
(void)tx_size; (void)tx_size;
// Supply delays and response size. // Supply delays and response size.
switch (op_code) switch (op_code) {
{
case SHA204_GENDIG: case SHA204_GENDIG:
poll_delay = GENDIG_DELAY; poll_delay = GENDIG_DELAY;
poll_timeout = GENDIG_EXEC_MAX - GENDIG_DELAY; poll_timeout = GENDIG_EXEC_MAX - GENDIG_DELAY;
@@ -611,8 +575,7 @@ uint8_t atsha204_getSerialNumber(uint8_t * response)
/* read from bytes 0->3 of config zone */ /* read from bytes 0->3 of config zone */
uint8_t returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN03); uint8_t returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN03);
if (!returnCode) if (!returnCode) {
{
for (int i=0; i<4; i++) {// store bytes 0-3 into respones array for (int i=0; i<4; i++) {// store bytes 0-3 into respones array
response[i] = readResponse[SHA204_BUFFER_POS_DATA+i]; response[i] = readResponse[SHA204_BUFFER_POS_DATA+i];
} }
@@ -624,8 +587,8 @@ uint8_t atsha204_getSerialNumber(uint8_t * response)
response[i] = readResponse[SHA204_BUFFER_POS_DATA+(i-4)]; response[i] = readResponse[SHA204_BUFFER_POS_DATA+(i-4)];
} }
if (!returnCode) if (!returnCode) {
{ /* Finally if last two reads were successful, read byte 8 of the SN */ /* Finally if last two reads were successful, read byte 8 of the SN */
returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN8); returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN8);
response[8] = readResponse[SHA204_BUFFER_POS_DATA]; // Byte 8 of SN should always be 0xEE response[8] = readResponse[SHA204_BUFFER_POS_DATA]; // Byte 8 of SN should always be 0xEE
} }
+29 -13
View File
@@ -1,7 +1,7 @@
#include <string.h> #include <string.h>
#if defined(__AVR__) #if defined(__AVR__)
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#define PRIPSTR "%S" #define PRIPSTR "%S"
#elif defined(ESP8266) #elif defined(ESP8266)
#include <pgmspace.h> #include <pgmspace.h>
#endif #endif
@@ -32,17 +32,20 @@ const uint8_t sha256InitState[] PROGMEM = {
0x19,0xcd,0xe0,0x5b // H7 0x19,0xcd,0xe0,0x5b // H7
}; };
void Sha256Class::init(void) { void Sha256Class::init(void)
{
memcpy_P(state.b,sha256InitState,32); memcpy_P(state.b,sha256InitState,32);
byteCount = 0; byteCount = 0;
bufferOffset = 0; bufferOffset = 0;
} }
uint32_t Sha256Class::ror32(uint32_t number, uint8_t bits) { uint32_t Sha256Class::ror32(uint32_t number, uint8_t bits)
{
return ((number << (32-bits)) | (number >> bits)); return ((number << (32-bits)) | (number >> bits));
} }
void Sha256Class::hashBlock() { void Sha256Class::hashBlock()
{
uint8_t i; uint8_t i;
uint32_t a,b,c,d,e,f,g,h,t1,t2; uint32_t a,b,c,d,e,f,g,h,t1,t2;
@@ -71,7 +74,14 @@ void Sha256Class::hashBlock() {
t1 += buffer.w[i&15]; // Wi t1 += buffer.w[i&15]; // Wi
t2 = ror32(a,2) ^ ror32(a,13) ^ ror32(a,22); // ∑0(a) t2 = ror32(a,2) ^ ror32(a,13) ^ ror32(a,22); // ∑0(a)
t2 += ((b & c) | (a & (b | c))); // Maj(a,b,c) t2 += ((b & c) | (a & (b | c))); // Maj(a,b,c)
h=g; g=f; f=e; e=d+t1; d=c; c=b; b=a; a=t1+t2; h=g;
g=f;
f=e;
e=d+t1;
d=c;
c=b;
b=a;
a=t1+t2;
} }
state.w[0] += a; state.w[0] += a;
state.w[1] += b; state.w[1] += b;
@@ -83,7 +93,8 @@ void Sha256Class::hashBlock() {
state.w[7] += h; state.w[7] += h;
} }
void Sha256Class::addUncounted(uint8_t data) { void Sha256Class::addUncounted(uint8_t data)
{
buffer.b[bufferOffset ^ 3] = data; buffer.b[bufferOffset ^ 3] = data;
bufferOffset++; bufferOffset++;
if (bufferOffset == BUFFER_SIZE) { if (bufferOffset == BUFFER_SIZE) {
@@ -92,12 +103,14 @@ void Sha256Class::addUncounted(uint8_t data) {
} }
} }
void Sha256Class::write(uint8_t data) { void Sha256Class::write(uint8_t data)
{
++byteCount; ++byteCount;
addUncounted(data); addUncounted(data);
} }
void Sha256Class::pad() { void Sha256Class::pad()
{
// Implement SHA-256 padding (fips180-2 §5.1.1) // Implement SHA-256 padding (fips180-2 §5.1.1)
// Pad with 0x80 followed by 0x00 until the end of the block // Pad with 0x80 followed by 0x00 until the end of the block
@@ -118,7 +131,8 @@ void Sha256Class::pad() {
} }
uint8_t* Sha256Class::result(void) { uint8_t* Sha256Class::result(void)
{
// Pad to complete the last block // Pad to complete the last block
pad(); pad();
@@ -143,13 +157,14 @@ uint8_t* Sha256Class::result(void) {
uint8_t keyBuffer[BLOCK_LENGTH]; // K0 in FIPS-198a uint8_t keyBuffer[BLOCK_LENGTH]; // K0 in FIPS-198a
uint8_t innerHash[HASH_LENGTH]; uint8_t innerHash[HASH_LENGTH];
void Sha256Class::initHmac(const uint8_t* key, int keyLength) { void Sha256Class::initHmac(const uint8_t* key, int keyLength)
{
uint8_t i; uint8_t i;
memset(keyBuffer,0,BLOCK_LENGTH); memset(keyBuffer,0,BLOCK_LENGTH);
if (keyLength > BLOCK_LENGTH) { if (keyLength > BLOCK_LENGTH) {
// Hash long keys // Hash long keys
init(); init();
for (;keyLength--;) { for (; keyLength--;) {
write(*key++); write(*key++);
} }
memcpy(keyBuffer,result(),HASH_LENGTH); memcpy(keyBuffer,result(),HASH_LENGTH);
@@ -164,7 +179,8 @@ void Sha256Class::initHmac(const uint8_t* key, int keyLength) {
} }
} }
uint8_t* Sha256Class::resultHmac(void) { uint8_t* Sha256Class::resultHmac(void)
{
uint8_t i; uint8_t i;
// Complete inner hash // Complete inner hash
memcpy(innerHash,result(),HASH_LENGTH); memcpy(innerHash,result(),HASH_LENGTH);
+2 -2
View File
@@ -18,13 +18,13 @@ union _state {
class Sha256Class class Sha256Class
{ {
public: public:
void init(void); void init(void);
void initHmac(const uint8_t* secret, int secretLength); void initHmac(const uint8_t* secret, int secretLength);
uint8_t* result(void); uint8_t* result(void);
uint8_t* resultHmac(void); uint8_t* resultHmac(void);
void write(uint8_t); void write(uint8_t);
private: private:
void pad(); void pad();
void addUncounted(uint8_t data); void addUncounted(uint8_t data);
void hashBlock(); void hashBlock();
+44 -21
View File
@@ -397,12 +397,13 @@ static const uint8_t digitalPinCount = sizeof(pinMap)/sizeof(pin_map_t);
//============================================================================== //==============================================================================
/** generate bad pin number error */ /** generate bad pin number error */
void badPinNumber(void) void badPinNumber(void)
__attribute__((error("Pin number is too large or not a constant"))); __attribute__((error("Pin number is too large or not a constant")));
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Check for valid pin number /** Check for valid pin number
* @param[in] pin Number of pin to be checked. * @param[in] pin Number of pin to be checked.
*/ */
static ALWAYS_INLINE void badPinCheck(uint8_t pin) { static ALWAYS_INLINE void badPinCheck(uint8_t pin)
{
if (!__builtin_constant_p(pin) || pin >= digitalPinCount) { if (!__builtin_constant_p(pin) || pin >= digitalPinCount) {
badPinNumber(); badPinNumber();
} }
@@ -413,7 +414,8 @@ static ALWAYS_INLINE void badPinCheck(uint8_t pin) {
* @param[in] bit bit number to write * @param[in] bit bit number to write
* @param[in] level value for bit * @param[in] level value for bit
*/ */
static ALWAYS_INLINE void fastBitWriteSafe(volatile uint8_t* address, uint8_t bit, bool level) { static ALWAYS_INLINE void fastBitWriteSafe(volatile uint8_t* address, uint8_t bit, bool level)
{
uint8_t oldSREG; uint8_t oldSREG;
if (address > (uint8_t*)0X5F) { if (address > (uint8_t*)0X5F) {
oldSREG = SREG; oldSREG = SREG;
@@ -433,7 +435,8 @@ static ALWAYS_INLINE void fastBitWriteSafe(volatile uint8_t* address, uint8_t bi
* @param[in] pin Arduino pin number * @param[in] pin Arduino pin number
* @return value read * @return value read
*/ */
static ALWAYS_INLINE bool fastDigitalRead(uint8_t pin) { static ALWAYS_INLINE bool fastDigitalRead(uint8_t pin)
{
badPinCheck(pin); badPinCheck(pin);
return (*pinMap[pin].pin >> pinMap[pin].bit) & 1; return (*pinMap[pin].pin >> pinMap[pin].bit) & 1;
} }
@@ -444,7 +447,8 @@ static ALWAYS_INLINE bool fastDigitalRead(uint8_t pin) {
* If the pin is in output mode toggle the pin level. * If the pin is in output mode toggle the pin level.
* If the pin is in input mode toggle the state of the 20K pullup. * If the pin is in input mode toggle the state of the 20K pullup.
*/ */
static ALWAYS_INLINE void fastDigitalToggle(uint8_t pin) { static ALWAYS_INLINE void fastDigitalToggle(uint8_t pin)
{
badPinCheck(pin); badPinCheck(pin);
if (pinMap[pin].pin > (uint8_t*)0X5F) { if (pinMap[pin].pin > (uint8_t*)0X5F) {
// must write bit to high address port // must write bit to high address port
@@ -459,7 +463,8 @@ static ALWAYS_INLINE void fastDigitalToggle(uint8_t pin) {
* @param[in] pin Arduino pin number * @param[in] pin Arduino pin number
* @param[in] level value to write * @param[in] level value to write
*/ */
static ALWAYS_INLINE void fastDigitalWrite(uint8_t pin, bool level) { static ALWAYS_INLINE void fastDigitalWrite(uint8_t pin, bool level)
{
badPinCheck(pin); badPinCheck(pin);
fastBitWriteSafe(pinMap[pin].port, pinMap[pin].bit, level); fastBitWriteSafe(pinMap[pin].port, pinMap[pin].bit, level);
} }
@@ -470,7 +475,8 @@ static ALWAYS_INLINE void fastDigitalWrite(uint8_t pin, bool level) {
* *
* fastPinMode does not enable or disable the 20K pullup for input mode. * fastPinMode does not enable or disable the 20K pullup for input mode.
*/ */
static ALWAYS_INLINE void fastPinMode(uint8_t pin, bool mode) { static ALWAYS_INLINE void fastPinMode(uint8_t pin, bool mode)
{
badPinCheck(pin); badPinCheck(pin);
fastBitWriteSafe(pinMap[pin].ddr, pinMap[pin].bit, mode); fastBitWriteSafe(pinMap[pin].ddr, pinMap[pin].bit, mode);
} }
@@ -481,7 +487,8 @@ static ALWAYS_INLINE void fastPinMode(uint8_t pin, bool mode) {
* @param[in] level If mode is output, set level high/low. * @param[in] level If mode is output, set level high/low.
* If mode is input, enable or disable the pin's 20K pullup. * If mode is input, enable or disable the pin's 20K pullup.
*/ */
static ALWAYS_INLINE void fastPinConfig(uint8_t pin, bool mode, bool level) { static ALWAYS_INLINE void fastPinConfig(uint8_t pin, bool mode, bool level)
{
fastPinMode(pin, mode); fastPinMode(pin, mode);
fastDigitalWrite(pin, level); fastDigitalWrite(pin, level);
} }
@@ -491,8 +498,9 @@ static ALWAYS_INLINE void fastPinConfig(uint8_t pin, bool mode, bool level) {
* @brief Fast AVR digital port I/O * @brief Fast AVR digital port I/O
*/ */
template<uint8_t PinNumber> template<uint8_t PinNumber>
class DigitalPin { class DigitalPin
public: {
public:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Constructor */ /** Constructor */
DigitalPin() {} DigitalPin() {}
@@ -500,7 +508,8 @@ class DigitalPin {
/** Constructor /** Constructor
* @param[in] pinMode if true set output mode else input mode. * @param[in] pinMode if true set output mode else input mode.
*/ */
explicit DigitalPin(bool pinMode) { explicit DigitalPin(bool pinMode)
{
mode(pinMode); mode(pinMode);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -509,7 +518,8 @@ class DigitalPin {
* @param[in] level If mode is output, set level high/low. * @param[in] level If mode is output, set level high/low.
* If mode is input, enable or disable the pin's 20K pullup. * If mode is input, enable or disable the pin's 20K pullup.
*/ */
DigitalPin(bool mode, bool level) { DigitalPin(bool mode, bool level)
{
config(mode, level); config(mode, level);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -519,7 +529,8 @@ class DigitalPin {
* *
* @return This DigitalPin instance. * @return This DigitalPin instance.
*/ */
inline DigitalPin & operator = (bool value) __attribute__((always_inline)) { inline DigitalPin & operator = (bool value) __attribute__((always_inline))
{
write(value); write(value);
return *this; return *this;
} }
@@ -527,7 +538,8 @@ class DigitalPin {
/** Parenthesis operator /** Parenthesis operator
* @return Pin's level * @return Pin's level
*/ */
inline operator bool () const __attribute__((always_inline)) { inline operator bool () const __attribute__((always_inline))
{
return read(); return read();
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -536,19 +548,26 @@ class DigitalPin {
* @param[in] level If mode is output, set level high/low. * @param[in] level If mode is output, set level high/low.
* If mode is input, enable or disable the pin's 20K pullup. * If mode is input, enable or disable the pin's 20K pullup.
*/ */
ALWAYS_INLINE void config(bool mode, bool level) { ALWAYS_INLINE void config(bool mode, bool level)
{
fastPinConfig(PinNumber, mode, level); fastPinConfig(PinNumber, mode, level);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** /**
* Set pin level high if output mode or enable 20K pullup if input mode. * Set pin level high if output mode or enable 20K pullup if input mode.
*/ */
ALWAYS_INLINE void high() {write(true);} ALWAYS_INLINE void high()
{
write(true);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** /**
* Set pin level low if output mode or disable 20K pullup if input mode. * Set pin level low if output mode or disable 20K pullup if input mode.
*/ */
ALWAYS_INLINE void low() {write(false);} ALWAYS_INLINE void low()
{
write(false);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** /**
* Set pin mode * Set pin mode
@@ -556,12 +575,14 @@ class DigitalPin {
* *
* mode() does not enable or disable the 20K pullup for input mode. * mode() does not enable or disable the 20K pullup for input mode.
*/ */
ALWAYS_INLINE void mode(bool pinMode) { ALWAYS_INLINE void mode(bool pinMode)
{
fastPinMode(PinNumber, pinMode); fastPinMode(PinNumber, pinMode);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** @return Pin's level */ /** @return Pin's level */
ALWAYS_INLINE bool read() const { ALWAYS_INLINE bool read() const
{
return fastDigitalRead(PinNumber); return fastDigitalRead(PinNumber);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -570,7 +591,8 @@ class DigitalPin {
* If the pin is in output mode toggle the pin's level. * If the pin is in output mode toggle the pin's level.
* If the pin is in input mode toggle the state of the 20K pullup. * If the pin is in input mode toggle the state of the 20K pullup.
*/ */
ALWAYS_INLINE void toggle() { ALWAYS_INLINE void toggle()
{
fastDigitalToggle(PinNumber); fastDigitalToggle(PinNumber);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -578,7 +600,8 @@ class DigitalPin {
* @param[in] value If true set the pin's level high else set the * @param[in] value If true set the pin's level high else set the
* pin's level low. * pin's level low.
*/ */
ALWAYS_INLINE void write(bool value) { ALWAYS_INLINE void write(bool value)
{
fastDigitalWrite(PinNumber, value); fastDigitalWrite(PinNumber, value);
} }
}; };
+9 -4
View File
@@ -32,7 +32,8 @@
/** Constructor /** Constructor
* @param[in] pin Pin assigned to this object. * @param[in] pin Pin assigned to this object.
*/ */
PinIO::PinIO(uint8_t pin) { PinIO::PinIO(uint8_t pin)
{
begin(pin); begin(pin);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -40,8 +41,11 @@ PinIO::PinIO(uint8_t pin) {
* @param[in] pin Arduino board pin number. * @param[in] pin Arduino board pin number.
* @return true for success or false if invalid pin number. * @return true for success or false if invalid pin number.
*/ */
bool PinIO::begin(uint8_t pin) { bool PinIO::begin(uint8_t pin)
if (pin >= NUM_DIGITAL_PINS) return false; {
if (pin >= NUM_DIGITAL_PINS) {
return false;
}
uint8_t port = digitalPinToPort(pin); uint8_t port = digitalPinToPort(pin);
pinReg_ = portInputRegister(port); pinReg_ = portInputRegister(port);
bit_ = digitalPinToBitMask(pin); bit_ = digitalPinToBitMask(pin);
@@ -59,7 +63,8 @@ bool PinIO::begin(uint8_t pin) {
* This function may be used with interrupts enabled or disabled. * This function may be used with interrupts enabled or disabled.
* The previous interrupt state will be restored. * The previous interrupt state will be restored.
*/ */
void PinIO::config(bool mode, bool data) { void PinIO::config(bool mode, bool data)
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
modeI(mode); modeI(mode);
writeI(data); writeI(data);
+48 -13
View File
@@ -37,8 +37,9 @@
* @class PinIO * @class PinIO
* @brief AVR port I/O with runtime pin numbers. * @brief AVR port I/O with runtime pin numbers.
*/ */
class PinIO { class PinIO
public: {
public:
/** Create a PinIO object with no assigned pin. */ /** Create a PinIO object with no assigned pin. */
PinIO() : bit_(0), mask_(0XFF) {} PinIO() : bit_(0), mask_(0XFF) {}
/** Constructor /** Constructor
@@ -62,14 +63,20 @@ class PinIO {
void config(bool mode, bool data); void config(bool mode, bool data);
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** @return Pin's level */ /** @return Pin's level */
ALWAYS_INLINE bool read() {return *pinReg_ & bit_;} ALWAYS_INLINE bool read()
{
return *pinReg_ & bit_;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** toggle a pin /** toggle a pin
* *
* If the pin is in output mode toggle the pin's level. * If the pin is in output mode toggle the pin's level.
* If the pin is in input mode toggle the state of the 20K pullup. * If the pin is in input mode toggle the state of the 20K pullup.
*/ */
ALWAYS_INLINE void toggle() {*pinReg_ = bit_;} ALWAYS_INLINE void toggle()
{
*pinReg_ = bit_;
}
//============================================================================ //============================================================================
/** /**
* Set pin high if output mode or enable 20K pullup if input mode. * Set pin high if output mode or enable 20K pullup if input mode.
@@ -77,14 +84,20 @@ class PinIO {
* This function must be called with interrupts disabled. * This function must be called with interrupts disabled.
* This function will not change the interrupt state. * This function will not change the interrupt state.
*/ */
ALWAYS_INLINE void highI() {writeI(1);} ALWAYS_INLINE void highI()
{
writeI(1);
}
/** /**
* Set pin low if output mode or disable 20K pullup if input mode. * Set pin low if output mode or disable 20K pullup if input mode.
* *
* This function must be called with interrupts disabled. * This function must be called with interrupts disabled.
* This function will not change the interrupt state. * This function will not change the interrupt state.
*/ */
ALWAYS_INLINE void lowI() {writeI(0);} ALWAYS_INLINE void lowI()
{
writeI(0);
}
/** /**
* Set pin mode * Set pin mode
* @param[in] mode if true set output mode else input mode. * @param[in] mode if true set output mode else input mode.
@@ -94,7 +107,8 @@ class PinIO {
* This function must be called with interrupts disabled. * This function must be called with interrupts disabled.
* This function will not change the interrupt state. * This function will not change the interrupt state.
*/ */
ALWAYS_INLINE void modeI(bool mode) { ALWAYS_INLINE void modeI(bool mode)
{
volatile uint8_t* ddrReg = pinReg_ + 1; volatile uint8_t* ddrReg = pinReg_ + 1;
*ddrReg = mode ? *ddrReg | bit_ : *ddrReg & mask_; *ddrReg = mode ? *ddrReg | bit_ : *ddrReg & mask_;
} }
@@ -106,7 +120,8 @@ class PinIO {
* This function must be called with interrupts disabled. * This function must be called with interrupts disabled.
* This function will not change the interrupt state. * This function will not change the interrupt state.
*/ */
ALWAYS_INLINE void writeI(bool level) { ALWAYS_INLINE void writeI(bool level)
{
*portReg_ = level ? *portReg_ | bit_ : *portReg_ & mask_; *portReg_ = level ? *portReg_ | bit_ : *portReg_ & mask_;
} }
//============================================================================ //============================================================================
@@ -116,14 +131,24 @@ class PinIO {
* This function will enable interrupts. This function should not be * This function will enable interrupts. This function should not be
* called in an ISR or where interrupts are disabled. * called in an ISR or where interrupts are disabled.
*/ */
ALWAYS_INLINE void high() {ATOMIC_BLOCK(ATOMIC_FORCEON) {highI();}} ALWAYS_INLINE void high()
{
ATOMIC_BLOCK(ATOMIC_FORCEON) {
highI();
}
}
/** /**
* Set pin level low if output mode or disable 20K pullup if input mode. * Set pin level low if output mode or disable 20K pullup if input mode.
* *
* This function will enable interrupts. This function should not be * This function will enable interrupts. This function should not be
* called in an ISR or where interrupts are disabled. * called in an ISR or where interrupts are disabled.
*/ */
ALWAYS_INLINE void low() {ATOMIC_BLOCK(ATOMIC_FORCEON) {lowI();}} ALWAYS_INLINE void low()
{
ATOMIC_BLOCK(ATOMIC_FORCEON) {
lowI();
}
}
/** /**
* Set pin mode * Set pin mode
* @param[in] pinMode if true set output mode else input mode. * @param[in] pinMode if true set output mode else input mode.
@@ -133,7 +158,12 @@ class PinIO {
* This function will enable interrupts. This function should not be * This function will enable interrupts. This function should not be
* called in an ISR or where interrupts are disabled. * called in an ISR or where interrupts are disabled.
*/ */
ALWAYS_INLINE void mode(bool pinMode) {ATOMIC_BLOCK(ATOMIC_FORCEON) {modeI(pinMode);}} ALWAYS_INLINE void mode(bool pinMode)
{
ATOMIC_BLOCK(ATOMIC_FORCEON) {
modeI(pinMode);
}
}
/** Write pin. /** Write pin.
* *
* @param[in] level If output mode set pin high if true else low. * @param[in] level If output mode set pin high if true else low.
@@ -142,9 +172,14 @@ class PinIO {
* This function will enable interrupts. This function should not be * This function will enable interrupts. This function should not be
* called in an ISR or where interrupts are disabled. * called in an ISR or where interrupts are disabled.
*/ */
ALWAYS_INLINE void write(bool level) {ATOMIC_BLOCK(ATOMIC_FORCEON) {writeI(level);}} ALWAYS_INLINE void write(bool level)
{
ATOMIC_BLOCK(ATOMIC_FORCEON) {
writeI(level);
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
private: private:
uint8_t bit_; uint8_t bit_;
uint8_t mask_; uint8_t mask_;
volatile uint8_t* pinReg_; volatile uint8_t* pinReg_;
+20 -10
View File
@@ -49,7 +49,8 @@
* @return true for success else false. * @return true for success else false.
*/ */
bool I2cMasterBase::transfer(uint8_t addrRW, bool I2cMasterBase::transfer(uint8_t addrRW,
void *buf, size_t nbytes, uint8_t option) { void *buf, size_t nbytes, uint8_t option)
{
if (_state != STATE_REP_START) { if (_state != STATE_REP_START) {
start(); start();
} }
@@ -76,7 +77,8 @@ bool I2cMasterBase::transfer(uint8_t addrRW,
* . * .
* @return true for success else false. * @return true for success else false.
*/ */
bool I2cMasterBase::transferContinue(void *buf, size_t nbytes, uint8_t option) { bool I2cMasterBase::transferContinue(void *buf, size_t nbytes, uint8_t option)
{
uint8_t* p = reinterpret_cast<uint8_t*>(buf); uint8_t* p = reinterpret_cast<uint8_t*>(buf);
if (_state == STATE_RX_DATA) { if (_state == STATE_RX_DATA) {
for (size_t i = 0; i < nbytes; i++) { for (size_t i = 0; i < nbytes; i++) {
@@ -111,7 +113,8 @@ bool I2cMasterBase::transferContinue(void *buf, size_t nbytes, uint8_t option) {
* *
* @param[in] sclPin The software SCL pin number. * @param[in] sclPin The software SCL pin number.
*/ */
SoftI2cMaster::SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin) { SoftI2cMaster::SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin)
{
begin(sclPin, sdaPin); begin(sclPin, sdaPin);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -122,7 +125,8 @@ SoftI2cMaster::SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin) {
* *
* @param[in] sclPin The software SCL pin number. * @param[in] sclPin The software SCL pin number.
*/ */
void SoftI2cMaster::begin(uint8_t sclPin, uint8_t sdaPin) { void SoftI2cMaster::begin(uint8_t sclPin, uint8_t sdaPin)
{
uint8_t port; uint8_t port;
// Get bit mask and address of scl registers. // Get bit mask and address of scl registers.
@@ -156,7 +160,8 @@ void SoftI2cMaster::begin(uint8_t sclPin, uint8_t sdaPin) {
* *
* @return The byte read from the I2C bus. * @return The byte read from the I2C bus.
*/ */
uint8_t SoftI2cMaster::read(uint8_t last) { uint8_t SoftI2cMaster::read(uint8_t last)
{
uint8_t b = 0; uint8_t b = 0;
// Set sda to high Z mode for read. // Set sda to high Z mode for read.
@@ -168,7 +173,9 @@ uint8_t SoftI2cMaster::read(uint8_t last) {
sclDelay(16); sclDelay(16);
writeScl(HIGH); writeScl(HIGH);
sclDelay(12); sclDelay(12);
if (readSda()) b |= 1; if (readSda()) {
b |= 1;
}
writeScl(LOW); writeScl(LOW);
} }
// send ACK or NACK // send ACK or NACK
@@ -182,7 +189,8 @@ uint8_t SoftI2cMaster::read(uint8_t last) {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/* Issue a start condition. */ /* Issue a start condition. */
void SoftI2cMaster::start() { void SoftI2cMaster::start()
{
if (!readSda()) { if (!readSda()) {
writeSda(HIGH); writeSda(HIGH);
writeScl(HIGH); writeScl(HIGH);
@@ -193,8 +201,9 @@ void SoftI2cMaster::start() {
writeScl(LOW); writeScl(LOW);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/* Issue a stop condition. */ /* Issue a stop condition. */
void SoftI2cMaster::stop(void) { void SoftI2cMaster::stop(void)
{
writeSda(LOW); writeSda(LOW);
sclDelay(20); sclDelay(20);
writeScl(HIGH); writeScl(HIGH);
@@ -210,7 +219,8 @@ void SoftI2cMaster::stop(void) {
* *
* @return The value true, 1, if the slave returned an ACK or false for NACK. * @return The value true, 1, if the slave returned an ACK or false for NACK.
*/ */
bool SoftI2cMaster::write(uint8_t data) { bool SoftI2cMaster::write(uint8_t data)
{
// write byte // write byte
for (uint8_t m = 0X80; m != 0; m >>= 1) { for (uint8_t m = 0X80; m != 0; m >>= 1) {
// don't change this loop unless you verify the change with a scope // don't change this loop unless you verify the change with a scope
+67 -35
View File
@@ -63,8 +63,9 @@ const uint8_t STATE_TX_DATA_NACK = 6;
* @class I2cMasterBase * @class I2cMasterBase
* @brief Base class for FastI2cMaster, SoftI2cMaster * @brief Base class for FastI2cMaster, SoftI2cMaster
*/ */
class I2cMasterBase { class I2cMasterBase
public: {
public:
I2cMasterBase() : _state(STATE_STOP) {} I2cMasterBase() : _state(STATE_STOP) {}
/** Read a byte /** Read a byte
* *
@@ -91,7 +92,7 @@ class I2cMasterBase {
*/ */
virtual void stop() = 0; virtual void stop() = 0;
/** /**
* Start an I2C transfer with possible continuation. * Start an I2C transfer with possible continuation.
* *
* @param[in] addressRW I2C slave address plus R/W bit. * @param[in] addressRW I2C slave address plus R/W bit.
@@ -115,7 +116,7 @@ class I2cMasterBase {
bool transfer(uint8_t addressRW, void *buf, bool transfer(uint8_t addressRW, void *buf,
size_t nbyte, uint8_t option = I2C_STOP); size_t nbyte, uint8_t option = I2C_STOP);
/** /**
* Continue an I2C transfer. * Continue an I2C transfer.
* *
* @param[in,out] buf Source or destination for transfer. * @param[in,out] buf Source or destination for transfer.
@@ -140,7 +141,7 @@ class I2cMasterBase {
* @return true for ACK or false for NACK */ * @return true for ACK or false for NACK */
virtual bool write(uint8_t data) = 0; virtual bool write(uint8_t data) = 0;
private: private:
uint8_t _state; uint8_t _state;
}; };
//============================================================================== //==============================================================================
@@ -148,8 +149,9 @@ class I2cMasterBase {
* @class SoftI2cMaster * @class SoftI2cMaster
* @brief Software I2C master class * @brief Software I2C master class
*/ */
class SoftI2cMaster : public I2cMasterBase { class SoftI2cMaster : public I2cMasterBase
public: {
public:
SoftI2cMaster() {} SoftI2cMaster() {}
/** /**
* Constructor, initialize SCL/SDA pins and set the bus high. * Constructor, initialize SCL/SDA pins and set the bus high.
@@ -172,18 +174,25 @@ class SoftI2cMaster : public I2cMasterBase {
void stop(void); void stop(void);
bool write(uint8_t b); bool write(uint8_t b);
private: private:
uint8_t _sclBit; uint8_t _sclBit;
uint8_t _sdaBit; uint8_t _sdaBit;
volatile uint8_t* _sclDDR; volatile uint8_t* _sclDDR;
volatile uint8_t* _sdaDDR; volatile uint8_t* _sdaDDR;
volatile uint8_t* _sdaInReg; volatile uint8_t* _sdaInReg;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool readSda() {return *_sdaInReg & _sdaBit;} bool readSda()
{
return *_sdaInReg & _sdaBit;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void sclDelay(uint8_t n) {_delay_loop_1(n);} void sclDelay(uint8_t n)
{
_delay_loop_1(n);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void writeScl(bool value) { void writeScl(bool value)
{
uint8_t s = SREG; uint8_t s = SREG;
noInterrupts(); noInterrupts();
if (value == LOW) { if (value == LOW) {
@@ -196,7 +205,8 @@ class SoftI2cMaster : public I2cMasterBase {
SREG = s; SREG = s;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void writeSda(bool value) { void writeSda(bool value)
{
uint8_t s = SREG; uint8_t s = SREG;
noInterrupts(); noInterrupts();
if (value == LOW) { if (value == LOW) {
@@ -217,15 +227,18 @@ class SoftI2cMaster : public I2cMasterBase {
* @brief Fast software I2C master class. * @brief Fast software I2C master class.
*/ */
template<uint8_t sclPin, uint8_t sdaPin> template<uint8_t sclPin, uint8_t sdaPin>
class FastI2cMaster : public I2cMasterBase { class FastI2cMaster : public I2cMasterBase
public: {
public:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
FastI2cMaster() { FastI2cMaster()
{
begin(); begin();
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Initialize I2C bus pins. */ /** Initialize I2C bus pins. */
void begin() { void begin()
{
fastDigitalWrite(sclPin, LOW); fastDigitalWrite(sclPin, LOW);
fastDigitalWrite(sdaPin, LOW); fastDigitalWrite(sdaPin, LOW);
@@ -233,7 +246,8 @@ class FastI2cMaster : public I2cMasterBase {
sdaWrite(HIGH); sdaWrite(HIGH);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
uint8_t read(uint8_t last) { uint8_t read(uint8_t last)
{
uint8_t data = 0; uint8_t data = 0;
sdaWrite(HIGH); sdaWrite(HIGH);
@@ -256,7 +270,8 @@ class FastI2cMaster : public I2cMasterBase {
return data; return data;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void start() { void start()
{
if (!fastDigitalRead(sdaPin)) { if (!fastDigitalRead(sdaPin)) {
// It's a repeat start. // It's a repeat start.
sdaWrite(HIGH); sdaWrite(HIGH);
@@ -270,7 +285,8 @@ class FastI2cMaster : public I2cMasterBase {
sclDelay(8); sclDelay(8);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void stop(void) { void stop(void)
{
sdaWrite(LOW); sdaWrite(LOW);
sclDelay(8); sclDelay(8);
sclWrite(HIGH); sclWrite(HIGH);
@@ -279,7 +295,8 @@ class FastI2cMaster : public I2cMasterBase {
sclDelay(8); sclDelay(8);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool write(uint8_t data) { bool write(uint8_t data)
{
// write byte // write byte
writeBit(7, data); writeBit(7, data);
writeBit(6, data); writeBit(6, data);
@@ -301,27 +318,42 @@ class FastI2cMaster : public I2cMasterBase {
return rtn == 0; return rtn == 0;
} }
private: private:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void sclWrite(bool value) {fastPinMode(sclPin, !value);} void sclWrite(bool value)
//---------------------------------------------------------------------------- {
inline __attribute__((always_inline)) fastPinMode(sclPin, !value);
void sdaWrite(bool value) {fastPinMode(sdaPin, !value);}
//----------------------------------------------------------------------------
inline __attribute__((always_inline))
void readBit(uint8_t bit, uint8_t* data) {
sclWrite(HIGH);
sclDelay(5);
if (fastDigitalRead(sdaPin)) *data |= 1 << bit;
sclWrite(LOW);
if (bit) sclDelay(6);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void sclDelay(uint8_t n) {_delay_loop_1(n);} inline __attribute__((always_inline))
void sdaWrite(bool value)
{
fastPinMode(sdaPin, !value);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void writeBit(uint8_t bit, uint8_t data) { void readBit(uint8_t bit, uint8_t* data)
{
sclWrite(HIGH);
sclDelay(5);
if (fastDigitalRead(sdaPin)) {
*data |= 1 << bit;
}
sclWrite(LOW);
if (bit) {
sclDelay(6);
}
}
//----------------------------------------------------------------------------
void sclDelay(uint8_t n)
{
_delay_loop_1(n);
}
//----------------------------------------------------------------------------
inline __attribute__((always_inline))
void writeBit(uint8_t bit, uint8_t data)
{
uint8_t mask = 1 << bit; uint8_t mask = 1 << bit;
sdaWrite(data & mask); sdaWrite(data & mask);
sclWrite(HIGH); sclWrite(HIGH);
+32 -14
View File
@@ -48,11 +48,13 @@ const bool SCK_MODE = true;
* @brief Fast software SPI. * @brief Fast software SPI.
*/ */
template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin, uint8_t Mode = 0> template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin, uint8_t Mode = 0>
class SoftSPI { class SoftSPI
public: {
public:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Initialize SoftSPI pins. */ /** Initialize SoftSPI pins. */
void begin() { void begin()
{
fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL); fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL);
fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode)); fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode));
fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode)); fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode));
@@ -61,7 +63,8 @@ class SoftSPI {
/** Soft SPI receive byte. /** Soft SPI receive byte.
* @return Data byte received. * @return Data byte received.
*/ */
ALWAYS_INLINE uint8_t receive() { ALWAYS_INLINE uint8_t receive()
{
uint8_t data = 0; uint8_t data = 0;
receiveBit(7, &data); receiveBit(7, &data);
receiveBit(6, &data); receiveBit(6, &data);
@@ -77,7 +80,8 @@ class SoftSPI {
/** Soft SPI send byte. /** Soft SPI send byte.
* @param[in] data Data byte to send. * @param[in] data Data byte to send.
*/ */
ALWAYS_INLINE void send(uint8_t data) { ALWAYS_INLINE void send(uint8_t data)
{
sendBit(7, data); sendBit(7, data);
sendBit(6, data); sendBit(6, data);
sendBit(5, data); sendBit(5, data);
@@ -92,7 +96,8 @@ class SoftSPI {
* @param[in] txData Data byte to send. * @param[in] txData Data byte to send.
* @return Data byte received. * @return Data byte received.
*/ */
ALWAYS_INLINE uint8_t transfer(uint8_t txData) { ALWAYS_INLINE uint8_t transfer(uint8_t txData)
{
uint8_t rxData = 0; uint8_t rxData = 0;
transferBit(7, &rxData, txData); transferBit(7, &rxData, txData);
transferBit(6, &rxData, txData); transferBit(6, &rxData, txData);
@@ -105,11 +110,18 @@ class SoftSPI {
return rxData; return rxData;
} }
private: private:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ALWAYS_INLINE bool MODE_CPHA(uint8_t mode) {return (mode & 1) != 0;} ALWAYS_INLINE bool MODE_CPHA(uint8_t mode)
ALWAYS_INLINE bool MODE_CPOL(uint8_t mode) {return (mode & 2) != 0;} {
ALWAYS_INLINE void receiveBit(uint8_t bit, uint8_t* data) { return (mode & 1) != 0;
}
ALWAYS_INLINE bool MODE_CPOL(uint8_t mode)
{
return (mode & 2) != 0;
}
ALWAYS_INLINE void receiveBit(uint8_t bit, uint8_t* data)
{
if (MODE_CPHA(Mode)) { if (MODE_CPHA(Mode)) {
fastDigitalWrite(SckPin, !MODE_CPOL(Mode)); fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
} }
@@ -117,13 +129,16 @@ class SoftSPI {
nop; nop;
fastDigitalWrite(SckPin, fastDigitalWrite(SckPin,
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode)); MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
if (fastDigitalRead(MisoPin)) *data |= 1 << bit; if (fastDigitalRead(MisoPin)) {
*data |= 1 << bit;
}
if (!MODE_CPHA(Mode)) { if (!MODE_CPHA(Mode)) {
fastDigitalWrite(SckPin, MODE_CPOL(Mode)); fastDigitalWrite(SckPin, MODE_CPOL(Mode));
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ALWAYS_INLINE void sendBit(uint8_t bit, uint8_t data) { ALWAYS_INLINE void sendBit(uint8_t bit, uint8_t data)
{
if (MODE_CPHA(Mode)) { if (MODE_CPHA(Mode)) {
fastDigitalWrite(SckPin, !MODE_CPOL(Mode)); fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
} }
@@ -137,14 +152,17 @@ class SoftSPI {
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ALWAYS_INLINE void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData) { ALWAYS_INLINE void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData)
{
if (MODE_CPHA(Mode)) { if (MODE_CPHA(Mode)) {
fastDigitalWrite(SckPin, !MODE_CPOL(Mode)); fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
} }
fastDigitalWrite(MosiPin, txData & (1 << bit)); fastDigitalWrite(MosiPin, txData & (1 << bit));
fastDigitalWrite(SckPin, fastDigitalWrite(SckPin,
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode)); MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
if (fastDigitalRead(MisoPin)) *rxData |= 1 << bit; if (fastDigitalRead(MisoPin)) {
*rxData |= 1 << bit;
}
if (!MODE_CPHA(Mode)) { if (!MODE_CPHA(Mode)) {
fastDigitalWrite(SckPin, MODE_CPOL(Mode)); fastDigitalWrite(SckPin, MODE_CPOL(Mode));
} }
+35 -21
View File
@@ -9,11 +9,13 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<uint8_t ClkPin, uint8_t ConvPin, uint8_t DataPin> template<uint8_t ClkPin, uint8_t ConvPin, uint8_t DataPin>
/** ADS7818 class */ /** ADS7818 class */
class ADS7818 { class ADS7818
public: {
public:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Set pin modes and initial levels. */ /** Set pin modes and initial levels. */
void begin() { void begin()
{
fastPinMode(ClkPin, 1); fastPinMode(ClkPin, 1);
fastDigitalWrite(ClkPin, 0); fastDigitalWrite(ClkPin, 0);
fastPinMode(ConvPin, 1); fastPinMode(ConvPin, 1);
@@ -25,7 +27,8 @@ class ADS7818 {
* \return 16-bit value read. * \return 16-bit value read.
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
uint16_t read() { uint16_t read()
{
uint16_t v = 0; uint16_t v = 0;
fastDigitalWrite(ConvPin, 0); fastDigitalWrite(ConvPin, 0);
fastDigitalWrite(ClkPin, 1); fastDigitalWrite(ClkPin, 1);
@@ -48,18 +51,22 @@ class ADS7818 {
readBitFast16(v, 0); readBitFast16(v, 0);
return v; return v;
} }
private: private:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void readBitFast16(uint16_t &v, uint8_t b) { void readBitFast16(uint16_t &v, uint8_t b)
{
fastDigitalWrite(ClkPin, 1); fastDigitalWrite(ClkPin, 1);
if (fastDigitalRead(DataPin)) v |= (1 << b); if (fastDigitalRead(DataPin)) {
v |= (1 << b);
}
fastDigitalWrite(ClkPin, 0); fastDigitalWrite(ClkPin, 0);
} }
}; };
#if 0 #if 0
/** initialize I/O ports */ /** initialize I/O ports */
STATIC_ALWAYS_INLINE void adcBegin() { STATIC_ALWAYS_INLINE void adcBegin()
{
fastPinMode(ADC_CLK_PIN, 1); fastPinMode(ADC_CLK_PIN, 1);
fastDigitalWrite(ADC_CLK_PIN, 0); fastDigitalWrite(ADC_CLK_PIN, 0);
fastPinMode(ADC_CONV_PIN, 1); fastPinMode(ADC_CONV_PIN, 1);
@@ -69,8 +76,11 @@ STATIC_ALWAYS_INLINE void adcBegin() {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** clock for don't care bits /** clock for don't care bits
*\param[in] delayBefore if true, delay before raising clock*/ *\param[in] delayBefore if true, delay before raising clock*/
STATIC_ALWAYS_INLINE void fastDummy(bool first) { STATIC_ALWAYS_INLINE void fastDummy(bool first)
if (!first) nop; {
if (!first) {
nop;
}
fastDigitalWrite(ADC_CLK_PIN, 1); fastDigitalWrite(ADC_CLK_PIN, 1);
nop; nop;
fastDigitalWrite(ADC_CLK_PIN, 0); fastDigitalWrite(ADC_CLK_PIN, 0);
@@ -80,16 +90,20 @@ STATIC_ALWAYS_INLINE void fastDummy(bool first) {
* \param[in] v word to receive bit * \param[in] v word to receive bit
* \param[in] b bit number to be set. v |= (1 << b) if next bit is high. * \param[in] b bit number to be set. v |= (1 << b) if next bit is high.
*/ */
STATIC_ALWAYS_INLINE void readBitFast16(uint16_t &v, uint8_t b) { STATIC_ALWAYS_INLINE void readBitFast16(uint16_t &v, uint8_t b)
{
fastDigitalWrite(ADC_CLK_PIN, 1); fastDigitalWrite(ADC_CLK_PIN, 1);
if (fastDigitalRead(ADC_DATA_PIN)) v |= (1 << b); if (fastDigitalRead(ADC_DATA_PIN)) {
v |= (1 << b);
}
fastDigitalWrite(ADC_CLK_PIN, 0); fastDigitalWrite(ADC_CLK_PIN, 0);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Read AD7680 16-bit ADC in less than 8 microseconds /** Read AD7680 16-bit ADC in less than 8 microseconds
* cs is chip select pin * cs is chip select pin
*/ */
STATIC_ALWAYS_INLINE uint16_t adcRead(bool centered = false) { STATIC_ALWAYS_INLINE uint16_t adcRead(bool centered = false)
{
uint16_t v = 0; uint16_t v = 0;
fastDigitalWrite(ADC_CONV_PIN, 0); fastDigitalWrite(ADC_CONV_PIN, 0);
fastDigitalWrite(ADC_CLK_PIN, 1); fastDigitalWrite(ADC_CLK_PIN, 1);
@@ -97,17 +111,17 @@ STATIC_ALWAYS_INLINE uint16_t adcRead(bool centered = false) {
fastDigitalWrite(ADC_CONV_PIN, 1); fastDigitalWrite(ADC_CONV_PIN, 1);
fastDigitalWrite(ADC_CLK_PIN, 1); fastDigitalWrite(ADC_CLK_PIN, 1);
fastDigitalWrite(ADC_CLK_PIN, 0); fastDigitalWrite(ADC_CLK_PIN, 0);
// uint16_t v = 0; // uint16_t v = 0;
// fastDummy(1); // fastDummy(1);
// fastDummy(0); // fastDummy(0);
// fastDummy(0); // fastDummy(0);
// fastDummy(0); // fastDummy(0);
// readBitFast16(v, 15); // readBitFast16(v, 15);
// readBitFast16(v, 14); // readBitFast16(v, 14);
// readBitFast16(v, 13); // readBitFast16(v, 13);
// readBitFast16(v, 12); // readBitFast16(v, 12);
readBitFast16(v, 11); readBitFast16(v, 11);
readBitFast16(v, 10); readBitFast16(v, 10);
readBitFast16(v, 9); readBitFast16(v, 9);
+83 -40
View File
@@ -4,11 +4,13 @@
//============================================================================== //==============================================================================
template<uint8_t CsPin, uint8_t ClkPin, uint8_t DoutPin, uint8_t UsecDelay = 0> template<uint8_t CsPin, uint8_t ClkPin, uint8_t DoutPin, uint8_t UsecDelay = 0>
/** MCP3201 class */ /** MCP3201 class */
class MCP3201 { class MCP3201
public: {
public:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Set pin modes and initial levels. */ /** Set pin modes and initial levels. */
void begin() { void begin()
{
fastPinMode(ClkPin, 1); fastPinMode(ClkPin, 1);
fastDigitalWrite(ClkPin, 0); fastDigitalWrite(ClkPin, 0);
fastPinMode(CsPin, 1); fastPinMode(CsPin, 1);
@@ -20,12 +22,13 @@ class MCP3201 {
* \return 16-bit value read. * \return 16-bit value read.
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
uint16_t read() { uint16_t read()
{
fastDigitalWrite(CsPin, 0); fastDigitalWrite(CsPin, 0);
// Start sample. // Start sample.
mcpAdcDummy(3); mcpAdcDummy(3);
// Extra sample time. // Extra sample time.
if (UsecDelay){ if (UsecDelay) {
delayMicroseconds(UsecDelay); delayMicroseconds(UsecDelay);
} }
// End sample. // End sample.
@@ -48,22 +51,30 @@ class MCP3201 {
fastDigitalWrite(CsPin, 1); fastDigitalWrite(CsPin, 1);
return v; return v;
} }
private: private:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** delay n nops /** delay n nops
* \param[in] n nops to delay, must be a constant so compiler optimizes if(). * \param[in] n nops to delay, must be a constant so compiler optimizes if().
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void delayCycles(uint8_t n) { void delayCycles(uint8_t n)
if (n & 1) asm volatile("nop\n\t"); {
if (n & 2) asm volatile("nop\n\t" "nop\n\t"); if (n & 1) {
if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); asm volatile("nop\n\t");
}
if (n & 2) {
asm volatile("nop\n\t" "nop\n\t");
}
if (n & 4) {
asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** clock for don't care bits /** clock for don't care bits
*\param[in] delayBefore if true, delay before raising clock*/ *\param[in] delayBefore if true, delay before raising clock*/
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void mcpAdcDummy(uint8_t delayBefore) { void mcpAdcDummy(uint8_t delayBefore)
{
delayCycles(delayBefore); delayCycles(delayBefore);
fastDigitalWrite(ClkPin, 1); fastDigitalWrite(ClkPin, 1);
delayCycles(3); delayCycles(3);
@@ -71,11 +82,14 @@ class MCP3201 {
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 2) { void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 2)
{
delayCycles(3); delayCycles(3);
fastDigitalWrite(ClkPin, 1); fastDigitalWrite(ClkPin, 1);
delayCycles(delayRead); delayCycles(delayRead);
if (fastDigitalRead(DoutPin)) v |= (1 << b); if (fastDigitalRead(DoutPin)) {
v |= (1 << b);
}
fastDigitalWrite(ClkPin, 0); fastDigitalWrite(ClkPin, 0);
} }
}; };
@@ -83,11 +97,13 @@ class MCP3201 {
template<uint8_t CsPin, uint8_t ClkPin, template<uint8_t CsPin, uint8_t ClkPin,
uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0> uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0>
/** MCP3202 class */ /** MCP3202 class */
class MCP3202 { class MCP3202
public: {
public:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Set pin modes and initial levels. */ /** Set pin modes and initial levels. */
void begin() { void begin()
{
fastPinMode(ClkPin, 1); fastPinMode(ClkPin, 1);
fastDigitalWrite(ClkPin, 0); fastDigitalWrite(ClkPin, 0);
fastPinMode(CsPin, 1); fastPinMode(CsPin, 1);
@@ -100,7 +116,8 @@ class MCP3202 {
* \return 16-bit value read. * \return 16-bit value read.
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
uint16_t read(uint8_t config) { uint16_t read(uint8_t config)
{
uint16_t v = 0; uint16_t v = 0;
fastDigitalWrite(CsPin, 0); fastDigitalWrite(CsPin, 0);
// Start bit. // Start bit.
@@ -110,7 +127,7 @@ class MCP3202 {
// Channel Selection and start sample. // Channel Selection and start sample.
writeBit(config & 1); writeBit(config & 1);
// Extra sample time. // Extra sample time.
if (UsecDelay){ if (UsecDelay) {
delayMicroseconds(UsecDelay); delayMicroseconds(UsecDelay);
} }
// MSB first format and end sample. // MSB first format and end sample.
@@ -133,22 +150,30 @@ class MCP3202 {
fastDigitalWrite(CsPin, 1); fastDigitalWrite(CsPin, 1);
return v; return v;
} }
private: private:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** delay n nops /** delay n nops
* \param[in] n nops to delay, must be a constant so compiler optimizes if(). * \param[in] n nops to delay, must be a constant so compiler optimizes if().
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void delayCycles(uint8_t n) { void delayCycles(uint8_t n)
if (n & 1) asm volatile("nop\n\t"); {
if (n & 2) asm volatile("nop\n\t" "nop\n\t"); if (n & 1) {
if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); asm volatile("nop\n\t");
}
if (n & 2) {
asm volatile("nop\n\t" "nop\n\t");
}
if (n & 4) {
asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** clock for don't care bits /** clock for don't care bits
*\param[in] delayBefore if true, delay before raising clock*/ *\param[in] delayBefore if true, delay before raising clock*/
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void writeBit(bool value) { void writeBit(bool value)
{
fastDigitalWrite(DinPin, value); fastDigitalWrite(DinPin, value);
fastDigitalWrite(ClkPin, 1); fastDigitalWrite(ClkPin, 1);
delayCycles(2); delayCycles(2);
@@ -156,11 +181,14 @@ class MCP3202 {
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1) { void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1)
{
delayCycles(2); delayCycles(2);
fastDigitalWrite(ClkPin, 1); fastDigitalWrite(ClkPin, 1);
delayCycles(delayRead); delayCycles(delayRead);
if (fastDigitalRead(DoutPin)) v |= (1 << b); if (fastDigitalRead(DoutPin)) {
v |= (1 << b);
}
fastDigitalWrite(ClkPin, 0); fastDigitalWrite(ClkPin, 0);
} }
}; };
@@ -168,11 +196,13 @@ class MCP3202 {
template<uint8_t CsPin, uint8_t ClkPin, template<uint8_t CsPin, uint8_t ClkPin,
uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0> uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0>
/** MCP3204 class */ /** MCP3204 class */
class MCP3204 { class MCP3204
public: {
public:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Set pin modes and initial levels. */ /** Set pin modes and initial levels. */
void begin() { void begin()
{
fastPinMode(ClkPin, 1); fastPinMode(ClkPin, 1);
fastDigitalWrite(ClkPin, 0); fastDigitalWrite(ClkPin, 0);
fastPinMode(CsPin, 1); fastPinMode(CsPin, 1);
@@ -185,7 +215,8 @@ class MCP3204 {
* \return 16-bit value read. * \return 16-bit value read.
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
uint16_t read(uint8_t config) { uint16_t read(uint8_t config)
{
uint16_t v = 0; uint16_t v = 0;
fastDigitalWrite(CsPin, 0); fastDigitalWrite(CsPin, 0);
// Start bit. // Start bit.
@@ -199,7 +230,7 @@ class MCP3204 {
// D0 channel bit and start sample. // D0 channel bit and start sample.
writeBit(config & 1); writeBit(config & 1);
// Extra sample time. // Extra sample time.
if (UsecDelay){ if (UsecDelay) {
delayMicroseconds(UsecDelay); delayMicroseconds(UsecDelay);
} }
// End sample cycle. // End sample cycle.
@@ -222,22 +253,30 @@ class MCP3204 {
fastDigitalWrite(CsPin, 1); fastDigitalWrite(CsPin, 1);
return v; return v;
} }
private: private:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** delay n nops /** delay n nops
* \param[in] n nops to delay, must be a constant so compiler optimizes if(). * \param[in] n nops to delay, must be a constant so compiler optimizes if().
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void delayCycles(uint8_t n) { void delayCycles(uint8_t n)
if (n & 1) asm volatile("nop\n\t"); {
if (n & 2) asm volatile("nop\n\t" "nop\n\t"); if (n & 1) {
if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); asm volatile("nop\n\t");
}
if (n & 2) {
asm volatile("nop\n\t" "nop\n\t");
}
if (n & 4) {
asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** clock for don't care bits /** clock for don't care bits
*\param[in] delayBefore if true, delay before raising clock*/ *\param[in] delayBefore if true, delay before raising clock*/
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void writeBit(bool value) { void writeBit(bool value)
{
fastDigitalWrite(DinPin, value); fastDigitalWrite(DinPin, value);
fastDigitalWrite(ClkPin, 1); fastDigitalWrite(ClkPin, 1);
delayCycles(2); delayCycles(2);
@@ -245,11 +284,14 @@ class MCP3204 {
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1) { void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1)
{
delayCycles(2); delayCycles(2);
fastDigitalWrite(ClkPin, 1); fastDigitalWrite(ClkPin, 1);
delayCycles(delayRead); delayCycles(delayRead);
if (fastDigitalRead(DoutPin)) v |= (1 << b); if (fastDigitalRead(DoutPin)) {
v |= (1 << b);
}
fastDigitalWrite(ClkPin, 0); fastDigitalWrite(ClkPin, 0);
} }
}; };
@@ -257,6 +299,7 @@ class MCP3204 {
// MCP3204 and MCP3208 use the same code. // MCP3204 and MCP3208 use the same code.
template<uint8_t CsPin, uint8_t ClkPin, template<uint8_t CsPin, uint8_t ClkPin,
uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0> uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0>
class MCP3208 : public MCP3204<CsPin, ClkPin, DoutPin, DinPin, UsecDelay> { class MCP3208 : public MCP3204<CsPin, ClkPin, DoutPin, DinPin, UsecDelay>
{
}; };
#endif // MCP320X_h #endif // MCP320X_h
+44 -18
View File
@@ -9,11 +9,13 @@ const uint8_t MCP355X_TO_MS = 100;
//============================================================================== //==============================================================================
template<uint8_t CsPin, uint8_t SckPin, uint8_t SdoPin> template<uint8_t CsPin, uint8_t SckPin, uint8_t SdoPin>
/** MCP355X class */ /** MCP355X class */
class MCP355X { class MCP355X
public: {
public:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** Set pin modes and initial levels. */ /** Set pin modes and initial levels. */
void begin(bool singleMode = true) { void begin(bool singleMode = true)
{
m_singleMode = singleMode; m_singleMode = singleMode;
fastPinMode(SdoPin, 0); fastPinMode(SdoPin, 0);
fastPinMode(SckPin, 1); fastPinMode(SckPin, 1);
@@ -32,7 +34,8 @@ class MCP355X {
* \return 22-bit value. * \return 22-bit value.
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
int32_t read() { int32_t read()
{
uint8_t t = 0; uint8_t t = 0;
uint8_t v3 = 0; uint8_t v3 = 0;
if (m_singleMode) { if (m_singleMode) {
@@ -48,15 +51,23 @@ class MCP355X {
fastDigitalWrite(CsPin, 0); fastDigitalWrite(CsPin, 0);
// Delay while RDY settles. // Delay while RDY settles.
delayCycles(4); delayCycles(4);
if (!fastDigitalRead(SdoPin)) break; if (!fastDigitalRead(SdoPin)) {
break;
}
fastDigitalWrite(CsPin, 1); fastDigitalWrite(CsPin, 1);
if (t++ > MCP355X_TO_MS) return MCP355X_ERR; if (t++ > MCP355X_TO_MS) {
return MCP355X_ERR;
}
} }
} else { } else {
while (1) { while (1) {
if (!fastDigitalRead(SdoPin)) break; if (!fastDigitalRead(SdoPin)) {
break;
}
delay(1); delay(1);
if (t++ > MCP355X_TO_MS) return MCP355X_ERR; if (t++ > MCP355X_TO_MS) {
return MCP355X_ERR;
}
} }
} }
uint8_t v2 = readByte(); uint8_t v2 = readByte();
@@ -76,40 +87,55 @@ class MCP355X {
v3 = 0XFF; v3 = 0XFF;
} else if (v2 & 0X40) { } else if (v2 & 0X40) {
// Overflow high. Cause value to be >= MCP355X_OVH. // Overflow high. Cause value to be >= MCP355X_OVH.
if (v2 & 0X20) v2 &= 0X3F; if (v2 & 0X20) {
v2 &= 0X3F;
}
} else if (v2 & 0X80) { } else if (v2 & 0X80) {
// Overflow low. Cause value to be <= MCP355X_OVH. // Overflow low. Cause value to be <= MCP355X_OVH.
if ((v2 & 0X20) == 0) v2 |= 0X40; if ((v2 & 0X20) == 0) {
v2 |= 0X40;
}
v3 = 0XFF; v3 = 0XFF;
} }
uint16_t v_high = (v3 << 8) | v2; uint16_t v_high = (v3 << 8) | v2;
uint16_t v_low = (v1 << 8) | v0; uint16_t v_low = (v1 << 8) | v0;
return ((uint32_t)v_high << 16) | v_low; return ((uint32_t)v_high << 16) | v_low;
} }
private: private:
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** delay n nops /** delay n nops
* \param[in] n nops to delay, must be a constant so compiler optimizes if(). * \param[in] n nops to delay, must be a constant so compiler optimizes if().
*/ */
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void delayCycles(uint8_t n) { void delayCycles(uint8_t n)
if (n & 1) asm volatile("nop\n\t"); {
if (n & 2) asm volatile("nop\n\t" "nop\n\t"); if (n & 1) {
if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); asm volatile("nop\n\t");
}
if (n & 2) {
asm volatile("nop\n\t" "nop\n\t");
}
if (n & 4) {
asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Default delay yields about 2 MHz clock. // Default delay yields about 2 MHz clock.
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void readBit(uint8_t &v, uint8_t b, uint8_t delayRead = 0) { void readBit(uint8_t &v, uint8_t b, uint8_t delayRead = 0)
{
fastDigitalWrite(SckPin, 0); fastDigitalWrite(SckPin, 0);
delayCycles(2 + delayRead); delayCycles(2 + delayRead);
fastDigitalWrite(SckPin, 1); fastDigitalWrite(SckPin, 1);
if (fastDigitalRead(SdoPin)) v |= (1 << b); if (fastDigitalRead(SdoPin)) {
v |= (1 << b);
}
delayCycles(delayRead); delayCycles(delayRead);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline __attribute__((always_inline)) inline __attribute__((always_inline))
uint8_t readByte() { uint8_t readByte()
{
uint8_t v = 0; uint8_t v = 0;
readBit(v, 7); readBit(v, 7);
readBit(v, 6); readBit(v, 6);
@@ -4,7 +4,8 @@ DigitalPin<13> pin13(OUTPUT);
void setup() {} void setup() {}
void loop() { void loop()
{
// toggle is a two byte instruction that executes // toggle is a two byte instruction that executes
// in two cycles or 125 ns on a 16 MHz CPU // in two cycles or 125 ns on a 16 MHz CPU
pin13.toggle(); pin13.toggle();
@@ -4,11 +4,13 @@
// Class with compile time pin number. // Class with compile time pin number.
DigitalPin<13> pin13; DigitalPin<13> pin13;
void setup() { void setup()
{
// Set mode to OUTPUT and level LOW. // Set mode to OUTPUT and level LOW.
pin13.config(OUTPUT, LOW); pin13.config(OUTPUT, LOW);
} }
void loop() { void loop()
{
// toggle is a two byte instruction that executes // toggle is a two byte instruction that executes
// in two cycles or 125 ns on a 16 MHz CPU // in two cycles or 125 ns on a 16 MHz CPU
pin13.toggle(); pin13.toggle();
@@ -6,6 +6,7 @@ DigitalPin<13> pin13(OUTPUT);
void setup() {} void setup() {}
void loop() { void loop()
{
pin13 = pin12; pin13 = pin12;
} }
@@ -10,7 +10,8 @@ DigitalPin<13> dataPin(OUTPUT, HIGH);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Time to send one bit is ten cycles or 625 ns for 16 MHz CPU. // Time to send one bit is ten cycles or 625 ns for 16 MHz CPU.
inline __attribute__((always_inline)) inline __attribute__((always_inline))
void sendBit(uint8_t bit, uint8_t data) { void sendBit(uint8_t bit, uint8_t data)
{
dataPin = data & (1 << bit); dataPin = data & (1 << bit);
clockPin = 1; clockPin = 1;
// may want a nop here - clock pulse is 125 ns wide // may want a nop here - clock pulse is 125 ns wide
@@ -18,7 +19,8 @@ void sendBit(uint8_t bit, uint8_t data) {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Time to send one byte is 5 usec. // Time to send one byte is 5 usec.
void shiftOut(uint8_t bits) { void shiftOut(uint8_t bits)
{
sendBit(7, bits); sendBit(7, bits);
sendBit(6, bits); sendBit(6, bits);
sendBit(5, bits); sendBit(5, bits);
@@ -29,11 +31,13 @@ void shiftOut(uint8_t bits) {
sendBit(0, bits); sendBit(0, bits);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void setup() { void setup()
{
// Not used. // Not used.
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void loop() { void loop()
{
shiftOut(0X55); shiftOut(0X55);
delay(2); delay(2);
} }
@@ -6,7 +6,8 @@
PinIO readPin; PinIO readPin;
PinIO writePin; PinIO writePin;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void setup() { void setup()
{
// Assign pin 12 to readPin. // Assign pin 12 to readPin.
readPin.begin(12); readPin.begin(12);
@@ -18,7 +19,8 @@ void setup() {
writePin.mode(OUTPUT); writePin.mode(OUTPUT);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void loop() { void loop()
{
// Copy the value read from readPin to writePin. // Copy the value read from readPin to writePin.
writePin.write(readPin.read()); writePin.write(readPin.read());
} }
@@ -4,11 +4,13 @@
// Set runtime pin number. // Set runtime pin number.
PinIO pin13(13); PinIO pin13(13);
void setup() { void setup()
{
// set mode to OUTPUT and level LOW // set mode to OUTPUT and level LOW
pin13.config(OUTPUT, LOW); pin13.config(OUTPUT, LOW);
} }
void loop() { void loop()
{
pin13.toggle(); pin13.toggle();
delay(100); delay(100);
pin13.toggle(); pin13.toggle();
@@ -4,13 +4,15 @@
PinIO readPin(12); PinIO readPin(12);
PinIO writePin(13); PinIO writePin(13);
void setup() { void setup()
{
// Set input mode and disable pull-up. // Set input mode and disable pull-up.
readPin.config(INPUT, LOW); readPin.config(INPUT, LOW);
// set output mode // set output mode
writePin.mode(OUTPUT); writePin.mode(OUTPUT);
} }
void loop() { void loop()
{
writePin.write(readPin.read()); writePin.write(readPin.read());
} }
@@ -26,7 +26,8 @@ const uint8_t SCL_PIN = A5;
SoftI2cMaster i2c(SCL_PIN, SDA_PIN); SoftI2cMaster i2c(SCL_PIN, SDA_PIN);
//FastI2cMaster<SCL_PIN, SDA_PIN> i2c; //FastI2cMaster<SCL_PIN, SDA_PIN> i2c;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void setup() { void setup()
{
Serial.begin(9600); Serial.begin(9600);
while (!Serial); while (!Serial);
@@ -55,14 +56,19 @@ void setup() {
Serial.print("Device at address: 0X"); Serial.print("Device at address: 0X");
Serial.print(add, HEX); Serial.print(add, HEX);
Serial.print(" responds to "); Serial.print(" responds to ");
if (rd) Serial.print("Read"); if (rd) {
if (rd && wr) Serial.print(" and "); Serial.print("Read");
if (wr) Serial.print("Write"); }
if (rd && wr) {
Serial.print(" and ");
}
if (wr) {
Serial.print("Write");
}
Serial.println('.'); Serial.println('.');
} }
add += 2; add += 2;
} } while (add);
while (add);
if (!found) { if (!found) {
Serial.println("No devices found."); Serial.println("No devices found.");
@@ -70,7 +76,8 @@ void setup() {
Serial.println("Done"); Serial.println("Done");
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void loop() { void loop()
{
// Not used. // Not used.
} }
@@ -16,10 +16,13 @@ FastI2cMaster<SCL_PIN, SDA_PIN> rtc;
/* /*
* Read 'count' bytes from the DS1307 starting at 'address'. * Read 'count' bytes from the DS1307 starting at 'address'.
*/ */
uint8_t readDS1307(uint8_t address, uint8_t *buf, uint8_t count) { uint8_t readDS1307(uint8_t address, uint8_t *buf, uint8_t count)
{
// Send address of data. // Send address of data.
if (!rtc.transfer(DS1307ADDR | I2C_WRITE, &address, 1)) return false; if (!rtc.transfer(DS1307ADDR | I2C_WRITE, &address, 1)) {
return false;
}
// Read data. // Read data.
return rtc.transfer(DS1307ADDR | I2C_READ, buf, count); return rtc.transfer(DS1307ADDR | I2C_READ, buf, count);
@@ -28,7 +31,8 @@ uint8_t readDS1307(uint8_t address, uint8_t *buf, uint8_t count) {
/* /*
* write 'count' bytes to DS1307 starting at 'address'. * write 'count' bytes to DS1307 starting at 'address'.
*/ */
uint8_t writeDS1307(uint8_t address, uint8_t *buf, uint8_t count) { uint8_t writeDS1307(uint8_t address, uint8_t *buf, uint8_t count)
{
// Write address and continue transfer for write of data. // Write address and continue transfer for write of data.
if (!rtc.transfer(DS1307ADDR | I2C_WRITE, &address, 1, I2C_CONTINUE)) { if (!rtc.transfer(DS1307ADDR | I2C_WRITE, &address, 1, I2C_CONTINUE)) {
@@ -38,7 +42,8 @@ uint8_t writeDS1307(uint8_t address, uint8_t *buf, uint8_t count) {
return rtc.transferContinue(buf, count); return rtc.transferContinue(buf, count);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void setup(void) { void setup(void)
{
Serial.begin(9600); Serial.begin(9600);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -50,18 +55,21 @@ void setup(void) {
// Day of week U.S. convention. // Day of week U.S. convention.
char *Ddd[] = {"Bad", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; char *Ddd[] = {"Bad", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void hexPrint(uint8_t v) { void hexPrint(uint8_t v)
{
Serial.print(v >> 4, HEX); Serial.print(v >> 4, HEX);
Serial.print(v & 0XF, HEX); Serial.print(v & 0XF, HEX);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void hexPrintln(uint8_t v) { void hexPrintln(uint8_t v)
{
hexPrint(v); hexPrint(v);
Serial.println(); Serial.println();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// read hex input // read hex input
uint8_t hexRead(uint16_t* v) { uint8_t hexRead(uint16_t* v)
{
bool valid = false; bool valid = false;
uint16_t n = 0; uint16_t n = 0;
while (!Serial.available()); while (!Serial.available());
@@ -77,14 +85,11 @@ uint8_t hexRead(uint16_t* v) {
n <<= 4; n <<= 4;
if ('a' <= c && c <= 'f') { if ('a' <= c && c <= 'f') {
n += c - ('a' - 10); n += c - ('a' - 10);
} } else if ('A' <= c && c <= 'F') {
else if ('A' <= c && c <= 'F') {
n += c - ('A' - 10); n += c - ('A' - 10);
} } else if ('0' <= c && c <= '9') {
else if ('0' <= c && c <= '9') {
n += c - '0'; n += c - '0';
} } else {
else {
valid = false; valid = false;
break; break;
} }
@@ -99,9 +104,12 @@ uint8_t hexRead(uint16_t* v) {
return true; return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
uint8_t bcdRead(uint8_t min, uint8_t max, uint8_t* n) { uint8_t bcdRead(uint8_t min, uint8_t max, uint8_t* n)
{
uint16_t v; uint16_t v;
if (!hexRead(&v)) return false; if (!hexRead(&v)) {
return false;
}
uint8_t d = 10 * (v >> 4) + (v & 0XF); uint8_t d = 10 * (v >> 4) + (v & 0XF);
if ((v >> 4) > 9 || (v & 0XF) > 9 || d < min || d > max) { if ((v >> 4) > 9 || (v & 0XF) > 9 || d < min || d > max) {
PgmPrintln("Invalid"); PgmPrintln("Invalid");
@@ -111,7 +119,8 @@ uint8_t bcdRead(uint8_t min, uint8_t max, uint8_t* n) {
return true; return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void displayTime(void) { void displayTime(void)
{
uint8_t r[8]; uint8_t r[8];
if (!readDS1307(0, r, 8)) { if (!readDS1307(0, r, 8)) {
PgmPrintln("Read Failed for display time"); PgmPrintln("Read Failed for display time");
@@ -150,7 +159,8 @@ void displayTime(void) {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// dump registers and 56 bytes of RAM // dump registers and 56 bytes of RAM
void dumpAll(void) { void dumpAll(void)
{
uint8_t buf[8]; uint8_t buf[8];
for (uint8_t a = 0; a < 64; a += 8) { for (uint8_t a = 0; a < 64; a += 8) {
hexPrint(a); hexPrint(a);
@@ -167,11 +177,14 @@ void dumpAll(void) {
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void fillNvRam(void) { void fillNvRam(void)
{
uint8_t buf[8]; uint8_t buf[8];
PgmPrint("Enter HEX value for all NV RAM locations (00-FF): "); PgmPrint("Enter HEX value for all NV RAM locations (00-FF): ");
uint16_t v; uint16_t v;
if (!hexRead(&v)) return; if (!hexRead(&v)) {
return;
}
hexPrint(v); hexPrint(v);
for (uint8_t a = 8; a < 64; a ++) { for (uint8_t a = 8; a < 64; a ++) {
if (!writeDS1307(a, (uint8_t *)&v, 1)) { if (!writeDS1307(a, (uint8_t *)&v, 1)) {
@@ -205,7 +218,8 @@ RS1 RS0 FREQUENCY
1 0 8.192kHz 1 0 8.192kHz
1 1 32.768kHz 1 1 32.768kHz
*/ */
void setControl(void) { void setControl(void)
{
PgmPrintln("SQW/OUT pin: "); PgmPrintln("SQW/OUT pin: ");
PgmPrintln("(00) Low"); PgmPrintln("(00) Low");
PgmPrintln("(10) 1Hz"); PgmPrintln("(10) 1Hz");
@@ -215,26 +229,37 @@ void setControl(void) {
PgmPrintln("(80) High"); PgmPrintln("(80) High");
PgmPrint("Enter control: "); PgmPrint("Enter control: ");
uint16_t r; uint16_t r;
if (!hexRead(&r)) return; if (!hexRead(&r)) {
return;
}
hexPrintln(r); hexPrintln(r);
if (!writeDS1307(7, (uint8_t *)&r, 1)) { if (!writeDS1307(7, (uint8_t *)&r, 1)) {
PgmPrint("Write Failed for setControl"); PgmPrint("Write Failed for setControl");
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void setDate(void) { void setDate(void)
{
uint8_t r[4]; uint8_t r[4];
PgmPrint("Enter year (00-99): "); PgmPrint("Enter year (00-99): ");
if (!bcdRead(0, 99, &r[3])) return; if (!bcdRead(0, 99, &r[3])) {
return;
}
hexPrintln(r[3]); hexPrintln(r[3]);
PgmPrint("Enter month (01-12): "); PgmPrint("Enter month (01-12): ");
if (!bcdRead(1, 12, &r[2])) return; if (!bcdRead(1, 12, &r[2])) {
return;
}
hexPrintln(r[2]); hexPrintln(r[2]);
PgmPrint("Enter day (01-31): "); PgmPrint("Enter day (01-31): ");
if (!bcdRead(1, 31, &r[1])) return; if (!bcdRead(1, 31, &r[1])) {
return;
}
hexPrintln(r[1]); hexPrintln(r[1]);
PgmPrint("Enter day of week (01-07, Sun-Sat): "); PgmPrint("Enter day of week (01-07, Sun-Sat): ");
if (!bcdRead(1, 7, &r[0])) return; if (!bcdRead(1, 7, &r[0])) {
return;
}
hexPrintln(r[0]); hexPrintln(r[0]);
if (!writeDS1307(3, r, 4)) { if (!writeDS1307(3, r, 4)) {
@@ -242,12 +267,15 @@ void setDate(void) {
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void setNvRam() { void setNvRam()
{
uint8_t u; uint8_t u;
uint16_t a, v; uint16_t a, v;
while (true) { while (true) {
PgmPrint("Enter zero to quit or Hex address (8-3F):"); PgmPrint("Enter zero to quit or Hex address (8-3F):");
if (!hexRead(&a) || a == 0) return; if (!hexRead(&a) || a == 0) {
return;
}
if (a < 8 || a > 0X3F) { if (a < 8 || a > 0X3F) {
PgmPrintln("Invalid address"); PgmPrintln("Invalid address");
return; return;
@@ -260,7 +288,9 @@ void setNvRam() {
PgmPrint("Current value: "); PgmPrint("Current value: ");
hexPrintln(u); hexPrintln(u);
PgmPrint("Enter new HEX value (00-FF): "); PgmPrint("Enter new HEX value (00-FF): ");
if (!hexRead(&v)) return; if (!hexRead(&v)) {
return;
}
hexPrintln(v); hexPrintln(v);
if (!writeDS1307(a, (uint8_t *)&v, 1)) { if (!writeDS1307(a, (uint8_t *)&v, 1)) {
PgmPrint("Write Failed"); PgmPrint("Write Failed");
@@ -269,16 +299,23 @@ void setNvRam() {
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void setTime(void) { void setTime(void)
{
uint8_t r[3]; uint8_t r[3];
PgmPrint("Enter hours (00-23): "); PgmPrint("Enter hours (00-23): ");
if (!bcdRead(0, 23, &r[2])) return; if (!bcdRead(0, 23, &r[2])) {
return;
}
hexPrintln(r[2]); hexPrintln(r[2]);
PgmPrint("Enter minutes (00-59): "); PgmPrint("Enter minutes (00-59): ");
if (!bcdRead(0, 59, &r[1])) return; if (!bcdRead(0, 59, &r[1])) {
return;
}
hexPrintln(r[1]); hexPrintln(r[1]);
PgmPrint("Enter seconds (00-59): "); PgmPrint("Enter seconds (00-59): ");
if (!bcdRead(0, 59, &r[0])) return; if (!bcdRead(0, 59, &r[0])) {
return;
}
hexPrintln(r[0]); hexPrintln(r[0]);
if (!writeDS1307(0, r, 3)) { if (!writeDS1307(0, r, 3)) {
@@ -287,7 +324,8 @@ void setTime(void) {
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void loop(void) { void loop(void)
{
Serial.println(); Serial.println();
displayTime(); displayTime();
while (Serial.read() >= 0) {} while (Serial.read() >= 0) {}
@@ -302,9 +340,13 @@ void loop(void) {
PgmPrint("Enter option: "); PgmPrint("Enter option: ");
uint16_t n; uint16_t n;
if (!hexRead(&n)) return; if (!hexRead(&n)) {
return;
}
Serial.println(n, DEC); Serial.println(n, DEC);
if (n == 0) return; if (n == 0) {
return;
}
Serial.println(); Serial.println();
if (n == 1) { if (n == 1) {
setTime(); setTime();
@@ -1,11 +1,13 @@
// Scope test for write timing with Arduino digitaWrite(). // Scope test for write timing with Arduino digitaWrite().
const uint8_t PIN13 = 13; const uint8_t PIN13 = 13;
void setup() { void setup()
{
// Set mode to OUTPUT. // Set mode to OUTPUT.
pinMode(PIN13, OUTPUT); pinMode(PIN13, OUTPUT);
} }
void loop() { void loop()
{
digitalWrite(PIN13, HIGH); digitalWrite(PIN13, HIGH);
digitalWrite(PIN13, LOW); digitalWrite(PIN13, LOW);
digitalWrite(PIN13, HIGH); digitalWrite(PIN13, HIGH);
@@ -4,11 +4,13 @@
// Class with compile time pin number. // Class with compile time pin number.
DigitalPin<13> pin13; DigitalPin<13> pin13;
void setup() { void setup()
{
// set mode to OUTPUT // set mode to OUTPUT
pin13.mode(OUTPUT); pin13.mode(OUTPUT);
} }
void loop() { void loop()
{
pin13.high(); pin13.high();
pin13.low(); pin13.low();
pin13.write(1); pin13.write(1);
@@ -1,10 +1,12 @@
// Test fastDigital function timing with a scope. // Test fastDigital function timing with a scope.
#include <DigitalIO.h> #include <DigitalIO.h>
const uint8_t PIN = 13; const uint8_t PIN = 13;
void setup() { void setup()
{
fastPinMode(PIN, OUTPUT); fastPinMode(PIN, OUTPUT);
} }
void loop() { void loop()
{
fastDigitalWrite(PIN, HIGH); fastDigitalWrite(PIN, HIGH);
fastDigitalWrite(PIN, LOW); fastDigitalWrite(PIN, LOW);
fastDigitalToggle(PIN); fastDigitalToggle(PIN);
@@ -4,11 +4,13 @@
// Class with runtime pin numbers. // Class with runtime pin numbers.
PinIO pin(13); PinIO pin(13);
void setup() { void setup()
{
// Set mode to OUTPUT. // Set mode to OUTPUT.
pin.mode(OUTPUT); pin.mode(OUTPUT);
} }
void loop() { void loop()
{
pin.high(); pin.high();
pin.low(); pin.low();
pin.write(1); pin.write(1);
@@ -9,7 +9,8 @@ const uint8_t SPI_MODE = 0;
SoftSPI<SOFT_SPI_MISO_PIN, SOFT_SPI_MOSI_PIN, SOFT_SPI_SCK_PIN, SPI_MODE> spi; SoftSPI<SOFT_SPI_MISO_PIN, SOFT_SPI_MOSI_PIN, SOFT_SPI_SCK_PIN, SPI_MODE> spi;
int test; int test;
void setup() { void setup()
{
Serial.begin(9600); Serial.begin(9600);
spi.begin(); spi.begin();
while(1) { while(1) {
@@ -19,14 +20,19 @@ void setup() {
Serial.println("T - Transfer"); Serial.println("T - Transfer");
while ((test = Serial.read()) <= 0) {} while ((test = Serial.read()) <= 0) {}
test = toupper(test); test = toupper(test);
if (strchr("RST", test)) break; if (strchr("RST", test)) {
break;
}
Serial.println("Invalid entry"); Serial.println("Invalid entry");
}; };
Serial.print("Starting test "); Serial.print("Starting test ");
Serial.println((char)test); Serial.println((char)test);
} }
void loop() { void loop()
if (test == 'S') spi.send(0X55); {
if (test == 'S') {
spi.send(0X55);
}
if (test == 'R') { if (test == 'R') {
Serial.println(spi.receive(), HEX); Serial.println(spi.receive(), HEX);
} }
+35 -35
View File
@@ -7,7 +7,7 @@
#define __digitalWriteFast_h_ #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__) #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) \ #define __digitalPinToPortReg(__pin) \
(((__pin) >= 22 && (__pin) <= 29) ? &PORTA : \ (((__pin) >= 22 && (__pin) <= 29) ? &PORTA : \
((((__pin) >= 10 && (__pin) <= 13) || ((__pin) >= 50 && (__pin) <= 53)) ? &PORTB : \ ((((__pin) >= 10 && (__pin) <= 13) || ((__pin) >= 50 && (__pin) <= 53)) ? &PORTB : \
(((__pin) >= 30 && (__pin) <= 37) ? &PORTC : \ (((__pin) >= 30 && (__pin) <= 37) ? &PORTC : \
@@ -18,7 +18,7 @@
((((__pin) >= 6 && (__pin) <= 9) || (__pin) == 16 || (__pin) == 17) ? &PORTH : \ ((((__pin) >= 6 && (__pin) <= 9) || (__pin) == 16 || (__pin) == 17) ? &PORTH : \
(((__pin) == 14 || (__pin) == 15) ? &PORTJ : \ (((__pin) == 14 || (__pin) == 15) ? &PORTJ : \
(((__pin) >= 62 && (__pin) <= 69) ? &PORTK : &PORTL)))))))))) (((__pin) >= 62 && (__pin) <= 69) ? &PORTK : &PORTL))))))))))
#define __digitalPinToDDRReg(__pin) \ #define __digitalPinToDDRReg(__pin) \
(((__pin) >= 22 && (__pin) <= 29) ? &DDRA : \ (((__pin) >= 22 && (__pin) <= 29) ? &DDRA : \
((((__pin) >= 10 && (__pin) <= 13) || ((__pin) >= 50 && (__pin) <= 53)) ? &DDRB : \ ((((__pin) >= 10 && (__pin) <= 13) || ((__pin) >= 50 && (__pin) <= 53)) ? &DDRB : \
(((__pin) >= 30 && (__pin) <= 37) ? &DDRC : \ (((__pin) >= 30 && (__pin) <= 37) ? &DDRC : \
@@ -29,7 +29,7 @@
((((__pin) >= 6 && (__pin) <= 9) || (__pin) == 16 || (__pin) == 17) ? &DDRH : \ ((((__pin) >= 6 && (__pin) <= 9) || (__pin) == 16 || (__pin) == 17) ? &DDRH : \
(((__pin) == 14 || (__pin) == 15) ? &DDRJ : \ (((__pin) == 14 || (__pin) == 15) ? &DDRJ : \
(((__pin) >= 62 && (__pin) <= 69) ? &DDRK : &DDRL)))))))))) (((__pin) >= 62 && (__pin) <= 69) ? &DDRK : &DDRL))))))))))
#define __digitalPinToPINReg(__pin) \ #define __digitalPinToPINReg(__pin) \
(((__pin) >= 22 && (__pin) <= 29) ? &PINA : \ (((__pin) >= 22 && (__pin) <= 29) ? &PINA : \
((((__pin) >= 10 && (__pin) <= 13) || ((__pin) >= 50 && (__pin) <= 53)) ? &PINB : \ ((((__pin) >= 10 && (__pin) <= 13) || ((__pin) >= 50 && (__pin) <= 53)) ? &PINB : \
(((__pin) >= 30 && (__pin) <= 37) ? &PINC : \ (((__pin) >= 30 && (__pin) <= 37) ? &PINC : \
@@ -40,7 +40,7 @@
((((__pin) >= 6 && (__pin) <= 9) || (__pin) == 16 || (__pin) == 17) ? &PINH : \ ((((__pin) >= 6 && (__pin) <= 9) || (__pin) == 16 || (__pin) == 17) ? &PINH : \
(((__pin) == 14 || (__pin) == 15) ? &PINJ : \ (((__pin) == 14 || (__pin) == 15) ? &PINJ : \
(((__pin) >= 62 && (__pin) <= 69) ? &PINK : &PINL)))))))))) (((__pin) >= 62 && (__pin) <= 69) ? &PINK : &PINL))))))))))
#define __digitalPinToBit(__pin) \ #define __digitalPinToBit(__pin) \
(((__pin) >= 7 && (__pin) <= 9) ? (__pin) - 3 : \ (((__pin) >= 7 && (__pin) <= 9) ? (__pin) - 3 : \
(((__pin) >= 10 && (__pin) <= 13) ? (__pin) - 6 : \ (((__pin) >= 10 && (__pin) <= 13) ? (__pin) - 6 : \
(((__pin) >= 22 && (__pin) <= 29) ? (__pin) - 22 : \ (((__pin) >= 22 && (__pin) <= 29) ? (__pin) - 22 : \
@@ -57,42 +57,42 @@
(((__pin) == 2) ? 4 : \ (((__pin) == 2) ? 4 : \
(((__pin) == 3 || (__pin) == 4) ? 5 : 7))))))))))))))) (((__pin) == 3 || (__pin) == 4) ? 5 : 7)))))))))))))))
#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) #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 __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 __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 __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 __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__) #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 __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 __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 __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 __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__) #elif defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_DUEMILANOVE) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__)
#if 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 __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 __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 __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)))) #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 #else
#define __digitalPinToPortReg(__pin) (((__pin) <= 7) ? &PORTD : (((__pin) >= 8 && (__pin) <= 13) ? &PORTB : &PORTC)) #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 __digitalPinToDDRReg(__pin) (((__pin) <= 7) ? &DDRD : (((__pin) >= 8 && (__pin) <= 13) ? &DDRB : &DDRC))
#define __digitalPinToPINReg(__pin) (((__pin) <= 7) ? &PIND : (((__pin) >= 8 && (__pin) <= 13) ? &PINB : &PINC)) #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)) #define __digitalPinToBit(__pin) (((__pin) <= 7) ? (__pin) : (((__pin) >= 8 && (__pin) <= 13) ? (__pin) - 8 : (__pin) - 14))
#endif #endif
#endif #endif
#if defined(ARDUINO_ARCH_AVR) #if defined(ARDUINO_ARCH_AVR)
#if !defined(__atomicWrite) #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) #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 #endif
#if !defined(digitalWriteFast) #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) #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 #endif
#if !defined(pinModeFast) #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) #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 #endif
#if !defined(digitalReadFast) #if !defined(digitalReadFast)
#define digitalReadFast(__pin) ( (bool) (__builtin_constant_p(__pin) ) ? (( bitRead(*__digitalPinToPINReg(__pin), __digitalPinToBit(__pin))) ) : digitalRead((__pin)) ) #define digitalReadFast(__pin) ( (bool) (__builtin_constant_p(__pin) ) ? (( bitRead(*__digitalPinToPINReg(__pin), __digitalPinToBit(__pin))) ) : digitalRead((__pin)) )
#endif #endif
#endif #endif
#endif #endif
+43 -10
View File
@@ -44,28 +44,61 @@ class AltSoftSerial : public Stream
{ {
public: public:
AltSoftSerial() { } //!< Constructor AltSoftSerial() { } //!< Constructor
~AltSoftSerial() { end(); } //!< Destructor ~AltSoftSerial()
static void begin(uint32_t baud) { init((ALTSS_BASE_FREQ + baud / 2) / baud); } //!< begin {
end(); //!< Destructor
}
static void begin(uint32_t baud)
{
init((ALTSS_BASE_FREQ + baud / 2) / baud); //!< begin
}
static void end(); //!< end static void end(); //!< end
int peek(); //!< peek int peek(); //!< peek
int read(); //!< read int read(); //!< read
int available(); //!< available int available(); //!< available
#if ARDUINO >= 100 #if ARDUINO >= 100
size_t write(uint8_t byte) { writeByte(byte); return 1; } //!< write size_t write(uint8_t byte)
void flush() { flushOutput(); } //!< flush {
writeByte(byte); //!< write
return 1;
}
void flush()
{
flushOutput(); //!< flush
}
#else #else
void write(uint8_t byte) { writeByte(byte); } //!< write void write(uint8_t byte)
void flush() { flushInput(); } //!< flush {
writeByte(byte); //!< write
}
void flush()
{
flushInput(); //!< flush
}
#endif #endif
using Print::write; using Print::write;
static void flushInput(); //!< flushInput static void flushInput(); //!< flushInput
static void flushOutput(); //!< flushOutput static void flushOutput(); //!< flushOutput
// for drop-in compatibility with NewSoftSerial, rxPin & txPin ignored // for drop-in compatibility with NewSoftSerial, rxPin & txPin ignored
//AltSoftSerial(uint8_t rxPin, uint8_t txPin, bool inverse = false) { } //AltSoftSerial(uint8_t rxPin, uint8_t txPin, bool inverse = false) { }
bool listen() { return false; } //!< listen bool listen()
bool isListening() { return true; } //!< isListening {
bool overflow() { bool r = timing_error; timing_error = false; return r; } //!< overflow return false; //!< listen
static int library_version() { return 1; } //!< library_version }
bool isListening()
{
return true; //!< isListening
}
bool overflow()
{
bool r = timing_error; //!< overflow
timing_error = false;
return r;
}
static int library_version()
{
return 1; //!< library_version
}
static void enable_timer0(bool) { } //!< enable_timer0 static void enable_timer0(bool) { } //!< enable_timer0
static bool timing_error; //!< timing_error static bool timing_error; //!< timing_error
private: private:
@@ -26,15 +26,15 @@
// //
#if defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY) #if defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY)
//#define ALTSS_USE_TIMER1 //#define ALTSS_USE_TIMER1
//#define INPUT_CAPTURE_PIN 22 // receive //#define INPUT_CAPTURE_PIN 22 // receive
//#define OUTPUT_COMPARE_A_PIN 14 // transmit //#define OUTPUT_COMPARE_A_PIN 14 // transmit
//#define OUTPUT_COMPARE_B_PIN 15 // unusable PWM //#define OUTPUT_COMPARE_B_PIN 15 // unusable PWM
//#define OUTPUT_COMPARE_C_PIN 4 // unusable PWM //#define OUTPUT_COMPARE_C_PIN 4 // unusable PWM
#define ALTSS_USE_TIMER3 #define ALTSS_USE_TIMER3
#define INPUT_CAPTURE_PIN 10 // receive #define INPUT_CAPTURE_PIN 10 // receive
#define OUTPUT_COMPARE_A_PIN 9 // transmit #define OUTPUT_COMPARE_A_PIN 9 // transmit
@@ -42,41 +42,41 @@
// //
#elif defined(__AVR_AT90USB1286__) && defined(CORE_TEENSY) #elif defined(__AVR_AT90USB1286__) && defined(CORE_TEENSY)
#define ALTSS_USE_TIMER1 #define ALTSS_USE_TIMER1
#define INPUT_CAPTURE_PIN 4 // receive #define INPUT_CAPTURE_PIN 4 // receive
#define OUTPUT_COMPARE_A_PIN 25 // transmit #define OUTPUT_COMPARE_A_PIN 25 // transmit
#define OUTPUT_COMPARE_B_PIN 26 // unusable PWM #define OUTPUT_COMPARE_B_PIN 26 // unusable PWM
#define OUTPUT_COMPARE_C_PIN 27 // unusable PWM #define OUTPUT_COMPARE_C_PIN 27 // unusable PWM
//#define ALTSS_USE_TIMER3 //#define ALTSS_USE_TIMER3
//#define INPUT_CAPTURE_PIN 17 // receive //#define INPUT_CAPTURE_PIN 17 // receive
//#define OUTPUT_COMPARE_A_PIN 16 // transmit //#define OUTPUT_COMPARE_A_PIN 16 // transmit
//#define OUTPUT_COMPARE_B_PIN 15 // unusable PWM //#define OUTPUT_COMPARE_B_PIN 15 // unusable PWM
//#define OUTPUT_COMPARE_C_PIN 14 // unusable PWM //#define OUTPUT_COMPARE_C_PIN 14 // unusable PWM
// Teensy 3.0 & 3.1 // Teensy 3.0 & 3.1
// //
#elif defined(__MK20DX128__) || defined(__MK20DX256__) #elif defined(__MK20DX128__) || defined(__MK20DX256__)
#define ALTSS_USE_FTM0 #define ALTSS_USE_FTM0
#define INPUT_CAPTURE_PIN 20 // receive (FTM0_CH5) #define INPUT_CAPTURE_PIN 20 // receive (FTM0_CH5)
#define OUTPUT_COMPARE_A_PIN 21 // transmit (FTM0_CH6) #define OUTPUT_COMPARE_A_PIN 21 // transmit (FTM0_CH6)
#define OUTPUT_COMPARE_B_PIN 22 // unusable PWM (FTM0_CH0) #define OUTPUT_COMPARE_B_PIN 22 // unusable PWM (FTM0_CH0)
#define OUTPUT_COMPARE_C_PIN 23 // PWM usable fixed freq #define OUTPUT_COMPARE_C_PIN 23 // PWM usable fixed freq
#define OUTPUT_COMPARE_D_PIN 5 // 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_E_PIN 6 // PWM usable fixed freq
#define OUTPUT_COMPARE_F_PIN 9 // 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 OUTPUT_COMPARE_G_PIN 10 // PWM usable fixed freq
// Wiring-S // Wiring-S
// //
#elif defined(__AVR_ATmega644P__) && defined(WIRING) #elif defined(__AVR_ATmega644P__) && defined(WIRING)
#define ALTSS_USE_TIMER1 #define ALTSS_USE_TIMER1
#define INPUT_CAPTURE_PIN 6 // receive #define INPUT_CAPTURE_PIN 6 // receive
#define OUTPUT_COMPARE_A_PIN 5 // transmit #define OUTPUT_COMPARE_A_PIN 5 // transmit
#define OUTPUT_COMPARE_B_PIN 4 // unusable PWM #define OUTPUT_COMPARE_B_PIN 4 // unusable PWM
@@ -84,51 +84,51 @@
// //
#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
#define ALTSS_USE_TIMER1 #define ALTSS_USE_TIMER1
#define INPUT_CAPTURE_PIN 8 // receive #define INPUT_CAPTURE_PIN 8 // receive
#define OUTPUT_COMPARE_A_PIN 9 // transmit #define OUTPUT_COMPARE_A_PIN 9 // transmit
#define OUTPUT_COMPARE_B_PIN 10 // unusable PWM #define OUTPUT_COMPARE_B_PIN 10 // unusable PWM
// Arduino Leonardo & Yun (from Cristian Maglie) // Arduino Leonardo & Yun (from Cristian Maglie)
// //
#elif defined(ARDUINO_AVR_YUN) || defined(ARDUINO_AVR_LEONARDO) || defined(__AVR_ATmega32U4__) #elif defined(ARDUINO_AVR_YUN) || defined(ARDUINO_AVR_LEONARDO) || defined(__AVR_ATmega32U4__)
//#define ALTSS_USE_TIMER1 //#define ALTSS_USE_TIMER1
//#define INPUT_CAPTURE_PIN 4 // receive //#define INPUT_CAPTURE_PIN 4 // receive
//#define OUTPUT_COMPARE_A_PIN 9 // transmit //#define OUTPUT_COMPARE_A_PIN 9 // transmit
//#define OUTPUT_COMPARE_B_PIN 10 // unusable PWM //#define OUTPUT_COMPARE_B_PIN 10 // unusable PWM
//#define OUTPUT_COMPARE_C_PIN 11 // unusable PWM //#define OUTPUT_COMPARE_C_PIN 11 // unusable PWM
#define ALTSS_USE_TIMER3 #define ALTSS_USE_TIMER3
#define INPUT_CAPTURE_PIN 13 // receive #define INPUT_CAPTURE_PIN 13 // receive
#define OUTPUT_COMPARE_A_PIN 5 // transmit #define OUTPUT_COMPARE_A_PIN 5 // transmit
// Arduino Mega // Arduino Mega
// //
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
//#define ALTSS_USE_TIMER4 //#define ALTSS_USE_TIMER4
//#define INPUT_CAPTURE_PIN 49 // receive //#define INPUT_CAPTURE_PIN 49 // receive
//#define OUTPUT_COMPARE_A_PIN 6 // transmit //#define OUTPUT_COMPARE_A_PIN 6 // transmit
//#define OUTPUT_COMPARE_B_PIN 7 // unusable PWM //#define OUTPUT_COMPARE_B_PIN 7 // unusable PWM
//#define OUTPUT_COMPARE_C_PIN 8 // unusable PWM //#define OUTPUT_COMPARE_C_PIN 8 // unusable PWM
#define ALTSS_USE_TIMER5 #define ALTSS_USE_TIMER5
#define INPUT_CAPTURE_PIN 48 // receive #define INPUT_CAPTURE_PIN 48 // receive
#define OUTPUT_COMPARE_A_PIN 46 // transmit #define OUTPUT_COMPARE_A_PIN 46 // transmit
#define OUTPUT_COMPARE_B_PIN 45 // unusable PWM #define OUTPUT_COMPARE_B_PIN 45 // unusable PWM
#define OUTPUT_COMPARE_C_PIN 44 // unusable PWM #define OUTPUT_COMPARE_C_PIN 44 // unusable PWM
// Sanguino // Sanguino
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
#define ALTSS_USE_TIMER1 #define ALTSS_USE_TIMER1
#define INPUT_CAPTURE_PIN 14 // receive #define INPUT_CAPTURE_PIN 14 // receive
#define OUTPUT_COMPARE_A_PIN 13 // transmit #define OUTPUT_COMPARE_A_PIN 13 // transmit
#define OUTPUT_COMPARE_B_PIN 12 // unusable PWM #define OUTPUT_COMPARE_B_PIN 12 // unusable PWM
// Unknown board // Unknown board
@@ -22,153 +22,153 @@
*/ */
#if defined(ALTSS_USE_TIMER1) #if defined(ALTSS_USE_TIMER1)
#define CONFIG_TIMER_NOPRESCALE() (TIMSK1 = 0, TCCR1A = 0, TCCR1B = (1<<ICNC1) | (1<<CS10)) #define CONFIG_TIMER_NOPRESCALE() (TIMSK1 = 0, TCCR1A = 0, TCCR1B = (1<<ICNC1) | (1<<CS10))
#define CONFIG_TIMER_PRESCALE_8() (TIMSK1 = 0, TCCR1A = 0, TCCR1B = (1<<ICNC1) | (1<<CS11)) #define CONFIG_TIMER_PRESCALE_8() (TIMSK1 = 0, TCCR1A = 0, TCCR1B = (1<<ICNC1) | (1<<CS11))
#define CONFIG_MATCH_NORMAL() (TCCR1A = TCCR1A & ~((1<<COM1A1) | (1<<COM1A0))) #define CONFIG_MATCH_NORMAL() (TCCR1A = TCCR1A & ~((1<<COM1A1) | (1<<COM1A0)))
#define CONFIG_MATCH_TOGGLE() (TCCR1A = (TCCR1A & ~(1<<COM1A1)) | (1<<COM1A0)) #define CONFIG_MATCH_TOGGLE() (TCCR1A = (TCCR1A & ~(1<<COM1A1)) | (1<<COM1A0))
#define CONFIG_MATCH_CLEAR() (TCCR1A = (TCCR1A | (1<<COM1A1)) & ~(1<<COM1A0)) #define CONFIG_MATCH_CLEAR() (TCCR1A = (TCCR1A | (1<<COM1A1)) & ~(1<<COM1A0))
#define CONFIG_MATCH_SET() (TCCR1A = TCCR1A | ((1<<COM1A1) | (1<<COM1A0))) #define CONFIG_MATCH_SET() (TCCR1A = TCCR1A | ((1<<COM1A1) | (1<<COM1A0)))
#define CONFIG_CAPTURE_FALLING_EDGE() (TCCR1B &= ~(1<<ICES1)) #define CONFIG_CAPTURE_FALLING_EDGE() (TCCR1B &= ~(1<<ICES1))
#define CONFIG_CAPTURE_RISING_EDGE() (TCCR1B |= (1<<ICES1)) #define CONFIG_CAPTURE_RISING_EDGE() (TCCR1B |= (1<<ICES1))
#define ENABLE_INT_INPUT_CAPTURE() (TIFR1 = (1<<ICF1), TIMSK1 = (1<<ICIE1)) #define ENABLE_INT_INPUT_CAPTURE() (TIFR1 = (1<<ICF1), TIMSK1 = (1<<ICIE1))
#define ENABLE_INT_COMPARE_A() (TIFR1 = (1<<OCF1A), TIMSK1 |= (1<<OCIE1A)) #define ENABLE_INT_COMPARE_A() (TIFR1 = (1<<OCF1A), TIMSK1 |= (1<<OCIE1A))
#define ENABLE_INT_COMPARE_B() (TIFR1 = (1<<OCF1B), TIMSK1 |= (1<<OCIE1B)) #define ENABLE_INT_COMPARE_B() (TIFR1 = (1<<OCF1B), TIMSK1 |= (1<<OCIE1B))
#define DISABLE_INT_INPUT_CAPTURE() (TIMSK1 &= ~(1<<ICIE1)) #define DISABLE_INT_INPUT_CAPTURE() (TIMSK1 &= ~(1<<ICIE1))
#define DISABLE_INT_COMPARE_A() (TIMSK1 &= ~(1<<OCIE1A)) #define DISABLE_INT_COMPARE_A() (TIMSK1 &= ~(1<<OCIE1A))
#define DISABLE_INT_COMPARE_B() (TIMSK1 &= ~(1<<OCIE1B)) #define DISABLE_INT_COMPARE_B() (TIMSK1 &= ~(1<<OCIE1B))
#define GET_TIMER_COUNT() (TCNT1) #define GET_TIMER_COUNT() (TCNT1)
#define GET_INPUT_CAPTURE() (ICR1) #define GET_INPUT_CAPTURE() (ICR1)
#define GET_COMPARE_A() (OCR1A) #define GET_COMPARE_A() (OCR1A)
#define GET_COMPARE_B() (OCR1B) #define GET_COMPARE_B() (OCR1B)
#define SET_COMPARE_A(val) (OCR1A = (val)) #define SET_COMPARE_A(val) (OCR1A = (val))
#define SET_COMPARE_B(val) (OCR1B = (val)) #define SET_COMPARE_B(val) (OCR1B = (val))
#define CAPTURE_INTERRUPT TIMER1_CAPT_vect #define CAPTURE_INTERRUPT TIMER1_CAPT_vect
#define COMPARE_A_INTERRUPT TIMER1_COMPA_vect #define COMPARE_A_INTERRUPT TIMER1_COMPA_vect
#define COMPARE_B_INTERRUPT TIMER1_COMPB_vect #define COMPARE_B_INTERRUPT TIMER1_COMPB_vect
#elif defined(ALTSS_USE_TIMER3) #elif defined(ALTSS_USE_TIMER3)
#define CONFIG_TIMER_NOPRESCALE() (TIMSK3 = 0, TCCR3A = 0, TCCR3B = (1<<ICNC3) | (1<<CS30)) #define CONFIG_TIMER_NOPRESCALE() (TIMSK3 = 0, TCCR3A = 0, TCCR3B = (1<<ICNC3) | (1<<CS30))
#define CONFIG_TIMER_PRESCALE_8() (TIMSK3 = 0, TCCR3A = 0, TCCR3B = (1<<ICNC3) | (1<<CS31)) #define CONFIG_TIMER_PRESCALE_8() (TIMSK3 = 0, TCCR3A = 0, TCCR3B = (1<<ICNC3) | (1<<CS31))
#define CONFIG_MATCH_NORMAL() (TCCR3A = TCCR3A & ~((1<<COM3A1) | (1<<COM3A0))) #define CONFIG_MATCH_NORMAL() (TCCR3A = TCCR3A & ~((1<<COM3A1) | (1<<COM3A0)))
#define CONFIG_MATCH_TOGGLE() (TCCR3A = (TCCR3A & ~(1<<COM3A1)) | (1<<COM3A0)) #define CONFIG_MATCH_TOGGLE() (TCCR3A = (TCCR3A & ~(1<<COM3A1)) | (1<<COM3A0))
#define CONFIG_MATCH_CLEAR() (TCCR3A = (TCCR3A | (1<<COM3A1)) & ~(1<<COM3A0)) #define CONFIG_MATCH_CLEAR() (TCCR3A = (TCCR3A | (1<<COM3A1)) & ~(1<<COM3A0))
#define CONFIG_MATCH_SET() (TCCR3A = TCCR3A | ((1<<COM3A1) | (1<<COM3A0))) #define CONFIG_MATCH_SET() (TCCR3A = TCCR3A | ((1<<COM3A1) | (1<<COM3A0)))
#define CONFIG_CAPTURE_FALLING_EDGE() (TCCR3B &= ~(1<<ICES3)) #define CONFIG_CAPTURE_FALLING_EDGE() (TCCR3B &= ~(1<<ICES3))
#define CONFIG_CAPTURE_RISING_EDGE() (TCCR3B |= (1<<ICES3)) #define CONFIG_CAPTURE_RISING_EDGE() (TCCR3B |= (1<<ICES3))
#define ENABLE_INT_INPUT_CAPTURE() (TIFR3 = (1<<ICF3), TIMSK3 = (1<<ICIE3)) #define ENABLE_INT_INPUT_CAPTURE() (TIFR3 = (1<<ICF3), TIMSK3 = (1<<ICIE3))
#define ENABLE_INT_COMPARE_A() (TIFR3 = (1<<OCF3A), TIMSK3 |= (1<<OCIE3A)) #define ENABLE_INT_COMPARE_A() (TIFR3 = (1<<OCF3A), TIMSK3 |= (1<<OCIE3A))
#define ENABLE_INT_COMPARE_B() (TIFR3 = (1<<OCF3B), TIMSK3 |= (1<<OCIE3B)) #define ENABLE_INT_COMPARE_B() (TIFR3 = (1<<OCF3B), TIMSK3 |= (1<<OCIE3B))
#define DISABLE_INT_INPUT_CAPTURE() (TIMSK3 &= ~(1<<ICIE3)) #define DISABLE_INT_INPUT_CAPTURE() (TIMSK3 &= ~(1<<ICIE3))
#define DISABLE_INT_COMPARE_A() (TIMSK3 &= ~(1<<OCIE3A)) #define DISABLE_INT_COMPARE_A() (TIMSK3 &= ~(1<<OCIE3A))
#define DISABLE_INT_COMPARE_B() (TIMSK3 &= ~(1<<OCIE3B)) #define DISABLE_INT_COMPARE_B() (TIMSK3 &= ~(1<<OCIE3B))
#define GET_TIMER_COUNT() (TCNT3) #define GET_TIMER_COUNT() (TCNT3)
#define GET_INPUT_CAPTURE() (ICR3) #define GET_INPUT_CAPTURE() (ICR3)
#define GET_COMPARE_A() (OCR3A) #define GET_COMPARE_A() (OCR3A)
#define GET_COMPARE_B() (OCR3B) #define GET_COMPARE_B() (OCR3B)
#define SET_COMPARE_A(val) (OCR3A = (val)) #define SET_COMPARE_A(val) (OCR3A = (val))
#define SET_COMPARE_B(val) (OCR3B = (val)) #define SET_COMPARE_B(val) (OCR3B = (val))
#define CAPTURE_INTERRUPT TIMER3_CAPT_vect #define CAPTURE_INTERRUPT TIMER3_CAPT_vect
#define COMPARE_A_INTERRUPT TIMER3_COMPA_vect #define COMPARE_A_INTERRUPT TIMER3_COMPA_vect
#define COMPARE_B_INTERRUPT TIMER3_COMPB_vect #define COMPARE_B_INTERRUPT TIMER3_COMPB_vect
#elif defined(ALTSS_USE_TIMER4) #elif defined(ALTSS_USE_TIMER4)
#define CONFIG_TIMER_NOPRESCALE() (TIMSK4 = 0, TCCR4A = 0, TCCR4B = (1<<ICNC4) | (1<<CS40)) #define CONFIG_TIMER_NOPRESCALE() (TIMSK4 = 0, TCCR4A = 0, TCCR4B = (1<<ICNC4) | (1<<CS40))
#define CONFIG_TIMER_PRESCALE_8() (TIMSK4 = 0, TCCR4A = 0, TCCR4B = (1<<ICNC4) | (1<<CS41)) #define CONFIG_TIMER_PRESCALE_8() (TIMSK4 = 0, TCCR4A = 0, TCCR4B = (1<<ICNC4) | (1<<CS41))
#define CONFIG_MATCH_NORMAL() (TCCR4A = TCCR4A & ~((1<<COM4A1) | (1<<COM4A0))) #define CONFIG_MATCH_NORMAL() (TCCR4A = TCCR4A & ~((1<<COM4A1) | (1<<COM4A0)))
#define CONFIG_MATCH_TOGGLE() (TCCR4A = (TCCR4A & ~(1<<COM4A1)) | (1<<COM4A0)) #define CONFIG_MATCH_TOGGLE() (TCCR4A = (TCCR4A & ~(1<<COM4A1)) | (1<<COM4A0))
#define CONFIG_MATCH_CLEAR() (TCCR4A = (TCCR4A | (1<<COM4A1)) & ~(1<<COM4A0)) #define CONFIG_MATCH_CLEAR() (TCCR4A = (TCCR4A | (1<<COM4A1)) & ~(1<<COM4A0))
#define CONFIG_MATCH_SET() (TCCR4A = TCCR4A | ((1<<COM4A1) | (1<<COM4A0))) #define CONFIG_MATCH_SET() (TCCR4A = TCCR4A | ((1<<COM4A1) | (1<<COM4A0)))
#define CONFIG_CAPTURE_FALLING_EDGE() (TCCR4B &= ~(1<<ICES4)) #define CONFIG_CAPTURE_FALLING_EDGE() (TCCR4B &= ~(1<<ICES4))
#define CONFIG_CAPTURE_RISING_EDGE() (TCCR4B |= (1<<ICES4)) #define CONFIG_CAPTURE_RISING_EDGE() (TCCR4B |= (1<<ICES4))
#define ENABLE_INT_INPUT_CAPTURE() (TIFR4 = (1<<ICF4), TIMSK4 = (1<<ICIE4)) #define ENABLE_INT_INPUT_CAPTURE() (TIFR4 = (1<<ICF4), TIMSK4 = (1<<ICIE4))
#define ENABLE_INT_COMPARE_A() (TIFR4 = (1<<OCF4A), TIMSK4 |= (1<<OCIE4A)) #define ENABLE_INT_COMPARE_A() (TIFR4 = (1<<OCF4A), TIMSK4 |= (1<<OCIE4A))
#define ENABLE_INT_COMPARE_B() (TIFR4 = (1<<OCF4B), TIMSK4 |= (1<<OCIE4B)) #define ENABLE_INT_COMPARE_B() (TIFR4 = (1<<OCF4B), TIMSK4 |= (1<<OCIE4B))
#define DISABLE_INT_INPUT_CAPTURE() (TIMSK4 &= ~(1<<ICIE4)) #define DISABLE_INT_INPUT_CAPTURE() (TIMSK4 &= ~(1<<ICIE4))
#define DISABLE_INT_COMPARE_A() (TIMSK4 &= ~(1<<OCIE4A)) #define DISABLE_INT_COMPARE_A() (TIMSK4 &= ~(1<<OCIE4A))
#define DISABLE_INT_COMPARE_B() (TIMSK4 &= ~(1<<OCIE4B)) #define DISABLE_INT_COMPARE_B() (TIMSK4 &= ~(1<<OCIE4B))
#define GET_TIMER_COUNT() (TCNT4) #define GET_TIMER_COUNT() (TCNT4)
#define GET_INPUT_CAPTURE() (ICR4) #define GET_INPUT_CAPTURE() (ICR4)
#define GET_COMPARE_A() (OCR4A) #define GET_COMPARE_A() (OCR4A)
#define GET_COMPARE_B() (OCR4B) #define GET_COMPARE_B() (OCR4B)
#define SET_COMPARE_A(val) (OCR4A = (val)) #define SET_COMPARE_A(val) (OCR4A = (val))
#define SET_COMPARE_B(val) (OCR4B = (val)) #define SET_COMPARE_B(val) (OCR4B = (val))
#define CAPTURE_INTERRUPT TIMER4_CAPT_vect #define CAPTURE_INTERRUPT TIMER4_CAPT_vect
#define COMPARE_A_INTERRUPT TIMER4_COMPA_vect #define COMPARE_A_INTERRUPT TIMER4_COMPA_vect
#define COMPARE_B_INTERRUPT TIMER4_COMPB_vect #define COMPARE_B_INTERRUPT TIMER4_COMPB_vect
#elif defined(ALTSS_USE_TIMER5) #elif defined(ALTSS_USE_TIMER5)
#define CONFIG_TIMER_NOPRESCALE() (TIMSK5 = 0, TCCR5A = 0, TCCR5B = (1<<ICNC5) | (1<<CS50)) #define CONFIG_TIMER_NOPRESCALE() (TIMSK5 = 0, TCCR5A = 0, TCCR5B = (1<<ICNC5) | (1<<CS50))
#define CONFIG_TIMER_PRESCALE_8() (TIMSK5 = 0, TCCR5A = 0, TCCR5B = (1<<ICNC5) | (1<<CS51)) #define CONFIG_TIMER_PRESCALE_8() (TIMSK5 = 0, TCCR5A = 0, TCCR5B = (1<<ICNC5) | (1<<CS51))
#define CONFIG_MATCH_NORMAL() (TCCR5A = TCCR5A & ~((1<<COM5A1) | (1<<COM5A0))) #define CONFIG_MATCH_NORMAL() (TCCR5A = TCCR5A & ~((1<<COM5A1) | (1<<COM5A0)))
#define CONFIG_MATCH_TOGGLE() (TCCR5A = (TCCR5A & ~(1<<COM5A1)) | (1<<COM5A0)) #define CONFIG_MATCH_TOGGLE() (TCCR5A = (TCCR5A & ~(1<<COM5A1)) | (1<<COM5A0))
#define CONFIG_MATCH_CLEAR() (TCCR5A = (TCCR5A | (1<<COM5A1)) & ~(1<<COM5A0)) #define CONFIG_MATCH_CLEAR() (TCCR5A = (TCCR5A | (1<<COM5A1)) & ~(1<<COM5A0))
#define CONFIG_MATCH_SET() (TCCR5A = TCCR5A | ((1<<COM5A1) | (1<<COM5A0))) #define CONFIG_MATCH_SET() (TCCR5A = TCCR5A | ((1<<COM5A1) | (1<<COM5A0)))
#define CONFIG_CAPTURE_FALLING_EDGE() (TCCR5B &= ~(1<<ICES5)) #define CONFIG_CAPTURE_FALLING_EDGE() (TCCR5B &= ~(1<<ICES5))
#define CONFIG_CAPTURE_RISING_EDGE() (TCCR5B |= (1<<ICES5)) #define CONFIG_CAPTURE_RISING_EDGE() (TCCR5B |= (1<<ICES5))
#define ENABLE_INT_INPUT_CAPTURE() (TIFR5 = (1<<ICF5), TIMSK5 = (1<<ICIE5)) #define ENABLE_INT_INPUT_CAPTURE() (TIFR5 = (1<<ICF5), TIMSK5 = (1<<ICIE5))
#define ENABLE_INT_COMPARE_A() (TIFR5 = (1<<OCF5A), TIMSK5 |= (1<<OCIE5A)) #define ENABLE_INT_COMPARE_A() (TIFR5 = (1<<OCF5A), TIMSK5 |= (1<<OCIE5A))
#define ENABLE_INT_COMPARE_B() (TIFR5 = (1<<OCF5B), TIMSK5 |= (1<<OCIE5B)) #define ENABLE_INT_COMPARE_B() (TIFR5 = (1<<OCF5B), TIMSK5 |= (1<<OCIE5B))
#define DISABLE_INT_INPUT_CAPTURE() (TIMSK5 &= ~(1<<ICIE5)) #define DISABLE_INT_INPUT_CAPTURE() (TIMSK5 &= ~(1<<ICIE5))
#define DISABLE_INT_COMPARE_A() (TIMSK5 &= ~(1<<OCIE5A)) #define DISABLE_INT_COMPARE_A() (TIMSK5 &= ~(1<<OCIE5A))
#define DISABLE_INT_COMPARE_B() (TIMSK5 &= ~(1<<OCIE5B)) #define DISABLE_INT_COMPARE_B() (TIMSK5 &= ~(1<<OCIE5B))
#define GET_TIMER_COUNT() (TCNT5) #define GET_TIMER_COUNT() (TCNT5)
#define GET_INPUT_CAPTURE() (ICR5) #define GET_INPUT_CAPTURE() (ICR5)
#define GET_COMPARE_A() (OCR5A) #define GET_COMPARE_A() (OCR5A)
#define GET_COMPARE_B() (OCR5B) #define GET_COMPARE_B() (OCR5B)
#define SET_COMPARE_A(val) (OCR5A = (val)) #define SET_COMPARE_A(val) (OCR5A = (val))
#define SET_COMPARE_B(val) (OCR5B = (val)) #define SET_COMPARE_B(val) (OCR5B = (val))
#define CAPTURE_INTERRUPT TIMER5_CAPT_vect #define CAPTURE_INTERRUPT TIMER5_CAPT_vect
#define COMPARE_A_INTERRUPT TIMER5_COMPA_vect #define COMPARE_A_INTERRUPT TIMER5_COMPA_vect
#define COMPARE_B_INTERRUPT TIMER5_COMPB_vect #define COMPARE_B_INTERRUPT TIMER5_COMPB_vect
#elif defined(ALTSS_USE_FTM0) #elif defined(ALTSS_USE_FTM0)
// CH5 = input capture (input, pin 20) // CH5 = input capture (input, pin 20)
// CH6 = compare a (output, pin 21) // CH6 = compare a (output, pin 21)
// CH0 = compare b (input timeout) // CH0 = compare b (input timeout)
#define CONFIG_TIMER_NOPRESCALE() FTM0_SC = 0; FTM0_CNT = 0; FTM0_MOD = 0xFFFF; \ #define CONFIG_TIMER_NOPRESCALE() FTM0_SC = 0; FTM0_CNT = 0; FTM0_MOD = 0xFFFF; \
FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0); \ FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0); \
digitalWriteFast(21, HIGH); \ digitalWriteFast(21, HIGH); \
NVIC_SET_PRIORITY(IRQ_FTM0, 48); \ NVIC_SET_PRIORITY(IRQ_FTM0, 48); \
NVIC_ENABLE_IRQ(IRQ_FTM0); NVIC_ENABLE_IRQ(IRQ_FTM0);
#define CONFIG_TIMER_PRESCALE_8() FTM0_SC = 0; FTM0_CNT = 0; FTM0_MOD = 0xFFFF; \ #define CONFIG_TIMER_PRESCALE_8() FTM0_SC = 0; FTM0_CNT = 0; FTM0_MOD = 0xFFFF; \
FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(3); \ FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(3); \
digitalWriteFast(21, HIGH); \ digitalWriteFast(21, HIGH); \
NVIC_SET_PRIORITY(IRQ_FTM0, 48); \ NVIC_SET_PRIORITY(IRQ_FTM0, 48); \
NVIC_ENABLE_IRQ(IRQ_FTM0); NVIC_ENABLE_IRQ(IRQ_FTM0);
#define CONFIG_MATCH_NORMAL() (FTM0_C6SC = 0) #define CONFIG_MATCH_NORMAL() (FTM0_C6SC = 0)
#define CONFIG_MATCH_TOGGLE() (FTM0_C6SC = (FTM0_C6SC & 0xC3) | 0x14) #define CONFIG_MATCH_TOGGLE() (FTM0_C6SC = (FTM0_C6SC & 0xC3) | 0x14)
#define CONFIG_MATCH_CLEAR() (FTM0_C6SC = (FTM0_C6SC & 0xC3) | 0x18) #define CONFIG_MATCH_CLEAR() (FTM0_C6SC = (FTM0_C6SC & 0xC3) | 0x18)
#define CONFIG_MATCH_SET() (FTM0_C6SC = (FTM0_C6SC & 0xC3) | 0x1C) #define CONFIG_MATCH_SET() (FTM0_C6SC = (FTM0_C6SC & 0xC3) | 0x1C)
#define CONFIG_CAPTURE_FALLING_EDGE() (FTM0_C5SC = (FTM0_C5SC & 0xC3) | 0x08) #define CONFIG_CAPTURE_FALLING_EDGE() (FTM0_C5SC = (FTM0_C5SC & 0xC3) | 0x08)
#define CONFIG_CAPTURE_RISING_EDGE() (FTM0_C5SC = (FTM0_C5SC & 0xC3) | 0x04) #define CONFIG_CAPTURE_RISING_EDGE() (FTM0_C5SC = (FTM0_C5SC & 0xC3) | 0x04)
#define ENABLE_INT_INPUT_CAPTURE() FTM0_C5SC = 0x48; \ #define ENABLE_INT_INPUT_CAPTURE() FTM0_C5SC = 0x48; \
CORE_PIN20_CONFIG = PORT_PCR_MUX(4)|PORT_PCR_PE|PORT_PCR_PS CORE_PIN20_CONFIG = PORT_PCR_MUX(4)|PORT_PCR_PE|PORT_PCR_PS
#define ENABLE_INT_COMPARE_A() FTM0_C6SC |= 0x40; \ #define ENABLE_INT_COMPARE_A() FTM0_C6SC |= 0x40; \
CORE_PIN21_CONFIG = PORT_PCR_MUX(4)|PORT_PCR_DSE|PORT_PCR_SRE CORE_PIN21_CONFIG = PORT_PCR_MUX(4)|PORT_PCR_DSE|PORT_PCR_SRE
#define ENABLE_INT_COMPARE_B() (FTM0_C0SC |= 0x40) #define ENABLE_INT_COMPARE_B() (FTM0_C0SC |= 0x40)
#define DISABLE_INT_INPUT_CAPTURE() FTM0_C5SC &= ~0x40; \ #define DISABLE_INT_INPUT_CAPTURE() FTM0_C5SC &= ~0x40; \
CORE_PIN20_CONFIG = PORT_PCR_MUX(1)|PORT_PCR_PE|PORT_PCR_PS CORE_PIN20_CONFIG = PORT_PCR_MUX(1)|PORT_PCR_PE|PORT_PCR_PS
#define DISABLE_INT_COMPARE_A() FTM0_C6SC &= ~0x40; \ #define DISABLE_INT_COMPARE_A() FTM0_C6SC &= ~0x40; \
CORE_PIN21_CONFIG = PORT_PCR_MUX(1)|PORT_PCR_DSE|PORT_PCR_SRE; \ CORE_PIN21_CONFIG = PORT_PCR_MUX(1)|PORT_PCR_DSE|PORT_PCR_SRE; \
digitalWriteFast(21, HIGH) digitalWriteFast(21, HIGH)
#define DISABLE_INT_COMPARE_B() (FTM0_C0SC &= ~0x40) #define DISABLE_INT_COMPARE_B() (FTM0_C0SC &= ~0x40)
#define GET_TIMER_COUNT() (FTM0_CNT) #define GET_TIMER_COUNT() (FTM0_CNT)
#define GET_INPUT_CAPTURE() (FTM0_C5V) #define GET_INPUT_CAPTURE() (FTM0_C5V)
#define GET_COMPARE_A() (FTM0_C6V) #define GET_COMPARE_A() (FTM0_C6V)
#define GET_COMPARE_B() (FTM0_C0V) #define GET_COMPARE_B() (FTM0_C0V)
#define SET_COMPARE_A(val) (FTM0_C6V = val) #define SET_COMPARE_A(val) (FTM0_C6V = val)
#define SET_COMPARE_B(val) (FTM0_C0V = val) #define SET_COMPARE_B(val) (FTM0_C0V = val)
#define CAPTURE_INTERRUPT altss_capture_interrupt #define CAPTURE_INTERRUPT altss_capture_interrupt
#define COMPARE_A_INTERRUPT altss_compare_a_interrupt #define COMPARE_A_INTERRUPT altss_compare_a_interrupt
#define COMPARE_B_INTERRUPT altss_compare_b_interrupt #define COMPARE_B_INTERRUPT altss_compare_b_interrupt
#ifdef ISR #ifdef ISR
#undef ISR #undef ISR
#endif #endif
#define ISR(f) static void f (void) #define ISR(f) static void f (void)
#endif #endif
+48 -48
View File
@@ -4,15 +4,15 @@
// //
#if defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY) #if defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY)
//#define ALTSS_USE_TIMER1 //#define ALTSS_USE_TIMER1
//#define INPUT_CAPTURE_PIN 22 // receive //#define INPUT_CAPTURE_PIN 22 // receive
//#define OUTPUT_COMPARE_A_PIN 14 // transmit //#define OUTPUT_COMPARE_A_PIN 14 // transmit
//#define OUTPUT_COMPARE_B_PIN 15 // unusable PWM //#define OUTPUT_COMPARE_B_PIN 15 // unusable PWM
//#define OUTPUT_COMPARE_C_PIN 4 // unusable PWM //#define OUTPUT_COMPARE_C_PIN 4 // unusable PWM
#define ALTSS_USE_TIMER3 #define ALTSS_USE_TIMER3
#define INPUT_CAPTURE_PIN 10 // receive #define INPUT_CAPTURE_PIN 10 // receive
#define OUTPUT_COMPARE_A_PIN 9 // transmit #define OUTPUT_COMPARE_A_PIN 9 // transmit
@@ -20,17 +20,17 @@
// //
#elif defined(__AVR_AT90USB1286__) && defined(CORE_TEENSY) #elif defined(__AVR_AT90USB1286__) && defined(CORE_TEENSY)
#define ALTSS_USE_TIMER1 #define ALTSS_USE_TIMER1
#define INPUT_CAPTURE_PIN 4 // receive #define INPUT_CAPTURE_PIN 4 // receive
#define OUTPUT_COMPARE_A_PIN 25 // transmit #define OUTPUT_COMPARE_A_PIN 25 // transmit
#define OUTPUT_COMPARE_B_PIN 26 // unusable PWM #define OUTPUT_COMPARE_B_PIN 26 // unusable PWM
#define OUTPUT_COMPARE_C_PIN 27 // unusable PWM #define OUTPUT_COMPARE_C_PIN 27 // unusable PWM
//#define ALTSS_USE_TIMER3 //#define ALTSS_USE_TIMER3
//#define INPUT_CAPTURE_PIN 17 // receive //#define INPUT_CAPTURE_PIN 17 // receive
//#define OUTPUT_COMPARE_A_PIN 16 // transmit //#define OUTPUT_COMPARE_A_PIN 16 // transmit
//#define OUTPUT_COMPARE_B_PIN 15 // unusable PWM //#define OUTPUT_COMPARE_B_PIN 15 // unusable PWM
//#define OUTPUT_COMPARE_C_PIN 14 // unusable PWM //#define OUTPUT_COMPARE_C_PIN 14 // unusable PWM
@@ -38,10 +38,10 @@
// //
#elif defined(__AVR_ATmega644P__) && defined(WIRING) #elif defined(__AVR_ATmega644P__) && defined(WIRING)
#define ALTSS_USE_TIMER1 #define ALTSS_USE_TIMER1
#define INPUT_CAPTURE_PIN 6 // receive #define INPUT_CAPTURE_PIN 6 // receive
#define OUTPUT_COMPARE_A_PIN 5 // transmit #define OUTPUT_COMPARE_A_PIN 5 // transmit
#define OUTPUT_COMPARE_B_PIN 4 // unusable PWM #define OUTPUT_COMPARE_B_PIN 4 // unusable PWM
@@ -49,51 +49,51 @@
// //
#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
#define ALTSS_USE_TIMER1 #define ALTSS_USE_TIMER1
#define INPUT_CAPTURE_PIN 8 // receive #define INPUT_CAPTURE_PIN 8 // receive
#define OUTPUT_COMPARE_A_PIN 9 // transmit #define OUTPUT_COMPARE_A_PIN 9 // transmit
#define OUTPUT_COMPARE_B_PIN 10 // unusable PWM #define OUTPUT_COMPARE_B_PIN 10 // unusable PWM
// Arduino Leonardo & Yun (from Cristian Maglie) // Arduino Leonardo & Yun (from Cristian Maglie)
// //
#elif defined(ARDUINO_AVR_YUN) || defined(ARDUINO_AVR_LEONARDO) #elif defined(ARDUINO_AVR_YUN) || defined(ARDUINO_AVR_LEONARDO)
//#define ALTSS_USE_TIMER1 //#define ALTSS_USE_TIMER1
//#define INPUT_CAPTURE_PIN 4 // receive //#define INPUT_CAPTURE_PIN 4 // receive
//#define OUTPUT_COMPARE_A_PIN 9 // transmit //#define OUTPUT_COMPARE_A_PIN 9 // transmit
//#define OUTPUT_COMPARE_B_PIN 10 // unusable PWM //#define OUTPUT_COMPARE_B_PIN 10 // unusable PWM
//#define OUTPUT_COMPARE_C_PIN 11 // unusable PWM //#define OUTPUT_COMPARE_C_PIN 11 // unusable PWM
#define ALTSS_USE_TIMER3 #define ALTSS_USE_TIMER3
#define INPUT_CAPTURE_PIN 13 // receive #define INPUT_CAPTURE_PIN 13 // receive
#define OUTPUT_COMPARE_A_PIN 5 // transmit #define OUTPUT_COMPARE_A_PIN 5 // transmit
// Arduino Mega // Arduino Mega
// //
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
//#define ALTSS_USE_TIMER4 //#define ALTSS_USE_TIMER4
//#define INPUT_CAPTURE_PIN 49 // receive //#define INPUT_CAPTURE_PIN 49 // receive
//#define OUTPUT_COMPARE_A_PIN 6 // transmit //#define OUTPUT_COMPARE_A_PIN 6 // transmit
//#define OUTPUT_COMPARE_B_PIN 7 // unusable PWM //#define OUTPUT_COMPARE_B_PIN 7 // unusable PWM
//#define OUTPUT_COMPARE_C_PIN 8 // unusable PWM //#define OUTPUT_COMPARE_C_PIN 8 // unusable PWM
#define ALTSS_USE_TIMER5 #define ALTSS_USE_TIMER5
#define INPUT_CAPTURE_PIN 48 // receive #define INPUT_CAPTURE_PIN 48 // receive
#define OUTPUT_COMPARE_A_PIN 46 // transmit #define OUTPUT_COMPARE_A_PIN 46 // transmit
#define OUTPUT_COMPARE_B_PIN 45 // unusable PWM #define OUTPUT_COMPARE_B_PIN 45 // unusable PWM
#define OUTPUT_COMPARE_C_PIN 44 // unusable PWM #define OUTPUT_COMPARE_C_PIN 44 // unusable PWM
// Sanguino // Sanguino
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
#define ALTSS_USE_TIMER1 #define ALTSS_USE_TIMER1
#define INPUT_CAPTURE_PIN 14 // receive #define INPUT_CAPTURE_PIN 14 // receive
#define OUTPUT_COMPARE_A_PIN 13 // transmit #define OUTPUT_COMPARE_A_PIN 13 // transmit
#define OUTPUT_COMPARE_B_PIN 12 // unusable PWM #define OUTPUT_COMPARE_B_PIN 12 // unusable PWM
// Unknown board // Unknown board
+92 -92
View File
@@ -1,106 +1,106 @@
#if defined(ALTSS_USE_TIMER1) #if defined(ALTSS_USE_TIMER1)
#define CONFIG_TIMER_NOPRESCALE() (TIMSK1 = 0, TCCR1A = 0, TCCR1B = (1<<ICNC1) | (1<<CS10)) #define CONFIG_TIMER_NOPRESCALE() (TIMSK1 = 0, TCCR1A = 0, TCCR1B = (1<<ICNC1) | (1<<CS10))
#define CONFIG_TIMER_PRESCALE_8() (TIMSK1 = 0, TCCR1A = 0, TCCR1B = (1<<ICNC1) | (1<<CS11)) #define CONFIG_TIMER_PRESCALE_8() (TIMSK1 = 0, TCCR1A = 0, TCCR1B = (1<<ICNC1) | (1<<CS11))
#define CONFIG_MATCH_NORMAL() (TCCR1A = TCCR1A & ~((1<<COM1A1) | (1<<COM1A0))) #define CONFIG_MATCH_NORMAL() (TCCR1A = TCCR1A & ~((1<<COM1A1) | (1<<COM1A0)))
#define CONFIG_MATCH_TOGGLE() (TCCR1A = (TCCR1A & ~(1<<COM1A1)) | (1<<COM1A0)) #define CONFIG_MATCH_TOGGLE() (TCCR1A = (TCCR1A & ~(1<<COM1A1)) | (1<<COM1A0))
#define CONFIG_MATCH_CLEAR() (TCCR1A = (TCCR1A | (1<<COM1A1)) & ~(1<<COM1A0)) #define CONFIG_MATCH_CLEAR() (TCCR1A = (TCCR1A | (1<<COM1A1)) & ~(1<<COM1A0))
#define CONFIG_MATCH_SET() (TCCR1A = TCCR1A | ((1<<COM1A1) | (1<<COM1A0))) #define CONFIG_MATCH_SET() (TCCR1A = TCCR1A | ((1<<COM1A1) | (1<<COM1A0)))
#define CONFIG_CAPTURE_FALLING_EDGE() (TCCR1B &= ~(1<<ICES1)) #define CONFIG_CAPTURE_FALLING_EDGE() (TCCR1B &= ~(1<<ICES1))
#define CONFIG_CAPTURE_RISING_EDGE() (TCCR1B |= (1<<ICES1)) #define CONFIG_CAPTURE_RISING_EDGE() (TCCR1B |= (1<<ICES1))
#define ENABLE_INT_INPUT_CAPTURE() (TIFR1 = (1<<ICF1), TIMSK1 = (1<<ICIE1)) #define ENABLE_INT_INPUT_CAPTURE() (TIFR1 = (1<<ICF1), TIMSK1 = (1<<ICIE1))
#define ENABLE_INT_COMPARE_A() (TIFR1 = (1<<OCF1A), TIMSK1 |= (1<<OCIE1A)) #define ENABLE_INT_COMPARE_A() (TIFR1 = (1<<OCF1A), TIMSK1 |= (1<<OCIE1A))
#define ENABLE_INT_COMPARE_B() (TIFR1 = (1<<OCF1B), TIMSK1 |= (1<<OCIE1B)) #define ENABLE_INT_COMPARE_B() (TIFR1 = (1<<OCF1B), TIMSK1 |= (1<<OCIE1B))
#define DISABLE_INT_INPUT_CAPTURE() (TIMSK1 &= ~(1<<ICIE1)) #define DISABLE_INT_INPUT_CAPTURE() (TIMSK1 &= ~(1<<ICIE1))
#define DISABLE_INT_COMPARE_A() (TIMSK1 &= ~(1<<OCIE1A)) #define DISABLE_INT_COMPARE_A() (TIMSK1 &= ~(1<<OCIE1A))
#define DISABLE_INT_COMPARE_B() (TIMSK1 &= ~(1<<OCIE1B)) #define DISABLE_INT_COMPARE_B() (TIMSK1 &= ~(1<<OCIE1B))
#define GET_TIMER_COUNT() (TCNT1) #define GET_TIMER_COUNT() (TCNT1)
#define GET_INPUT_CAPTURE() (ICR1) #define GET_INPUT_CAPTURE() (ICR1)
#define GET_COMPARE_A() (OCR1A) #define GET_COMPARE_A() (OCR1A)
#define GET_COMPARE_B() (OCR1B) #define GET_COMPARE_B() (OCR1B)
#define SET_COMPARE_A(val) (OCR1A = (val)) #define SET_COMPARE_A(val) (OCR1A = (val))
#define SET_COMPARE_B(val) (OCR1B = (val)) #define SET_COMPARE_B(val) (OCR1B = (val))
#define CAPTURE_INTERRUPT TIMER1_CAPT_vect #define CAPTURE_INTERRUPT TIMER1_CAPT_vect
#define COMPARE_A_INTERRUPT TIMER1_COMPA_vect #define COMPARE_A_INTERRUPT TIMER1_COMPA_vect
#define COMPARE_B_INTERRUPT TIMER1_COMPB_vect #define COMPARE_B_INTERRUPT TIMER1_COMPB_vect
#elif defined(ALTSS_USE_TIMER3) #elif defined(ALTSS_USE_TIMER3)
#define CONFIG_TIMER_NOPRESCALE() (TIMSK3 = 0, TCCR3A = 0, TCCR3B = (1<<ICNC3) | (1<<CS30)) #define CONFIG_TIMER_NOPRESCALE() (TIMSK3 = 0, TCCR3A = 0, TCCR3B = (1<<ICNC3) | (1<<CS30))
#define CONFIG_TIMER_PRESCALE_8() (TIMSK3 = 0, TCCR3A = 0, TCCR3B = (1<<ICNC3) | (1<<CS31)) #define CONFIG_TIMER_PRESCALE_8() (TIMSK3 = 0, TCCR3A = 0, TCCR3B = (1<<ICNC3) | (1<<CS31))
#define CONFIG_MATCH_NORMAL() (TCCR3A = TCCR3A & ~((1<<COM3A1) | (1<<COM3A0))) #define CONFIG_MATCH_NORMAL() (TCCR3A = TCCR3A & ~((1<<COM3A1) | (1<<COM3A0)))
#define CONFIG_MATCH_TOGGLE() (TCCR3A = (TCCR3A & ~(1<<COM3A1)) | (1<<COM3A0)) #define CONFIG_MATCH_TOGGLE() (TCCR3A = (TCCR3A & ~(1<<COM3A1)) | (1<<COM3A0))
#define CONFIG_MATCH_CLEAR() (TCCR3A = (TCCR3A | (1<<COM3A1)) & ~(1<<COM3A0)) #define CONFIG_MATCH_CLEAR() (TCCR3A = (TCCR3A | (1<<COM3A1)) & ~(1<<COM3A0))
#define CONFIG_MATCH_SET() (TCCR3A = TCCR3A | ((1<<COM3A1) | (1<<COM3A0))) #define CONFIG_MATCH_SET() (TCCR3A = TCCR3A | ((1<<COM3A1) | (1<<COM3A0)))
#define CONFIG_CAPTURE_FALLING_EDGE() (TCCR3B &= ~(1<<ICES3)) #define CONFIG_CAPTURE_FALLING_EDGE() (TCCR3B &= ~(1<<ICES3))
#define CONFIG_CAPTURE_RISING_EDGE() (TCCR3B |= (1<<ICES3)) #define CONFIG_CAPTURE_RISING_EDGE() (TCCR3B |= (1<<ICES3))
#define ENABLE_INT_INPUT_CAPTURE() (TIFR3 = (1<<ICF3), TIMSK3 = (1<<ICIE3)) #define ENABLE_INT_INPUT_CAPTURE() (TIFR3 = (1<<ICF3), TIMSK3 = (1<<ICIE3))
#define ENABLE_INT_COMPARE_A() (TIFR3 = (1<<OCF3A), TIMSK3 |= (1<<OCIE3A)) #define ENABLE_INT_COMPARE_A() (TIFR3 = (1<<OCF3A), TIMSK3 |= (1<<OCIE3A))
#define ENABLE_INT_COMPARE_B() (TIFR3 = (1<<OCF3B), TIMSK3 |= (1<<OCIE3B)) #define ENABLE_INT_COMPARE_B() (TIFR3 = (1<<OCF3B), TIMSK3 |= (1<<OCIE3B))
#define DISABLE_INT_INPUT_CAPTURE() (TIMSK3 &= ~(1<<ICIE3)) #define DISABLE_INT_INPUT_CAPTURE() (TIMSK3 &= ~(1<<ICIE3))
#define DISABLE_INT_COMPARE_A() (TIMSK3 &= ~(1<<OCIE3A)) #define DISABLE_INT_COMPARE_A() (TIMSK3 &= ~(1<<OCIE3A))
#define DISABLE_INT_COMPARE_B() (TIMSK3 &= ~(1<<OCIE3B)) #define DISABLE_INT_COMPARE_B() (TIMSK3 &= ~(1<<OCIE3B))
#define GET_TIMER_COUNT() (TCNT3) #define GET_TIMER_COUNT() (TCNT3)
#define GET_INPUT_CAPTURE() (ICR3) #define GET_INPUT_CAPTURE() (ICR3)
#define GET_COMPARE_A() (OCR3A) #define GET_COMPARE_A() (OCR3A)
#define GET_COMPARE_B() (OCR3B) #define GET_COMPARE_B() (OCR3B)
#define SET_COMPARE_A(val) (OCR3A = (val)) #define SET_COMPARE_A(val) (OCR3A = (val))
#define SET_COMPARE_B(val) (OCR3B = (val)) #define SET_COMPARE_B(val) (OCR3B = (val))
#define CAPTURE_INTERRUPT TIMER3_CAPT_vect #define CAPTURE_INTERRUPT TIMER3_CAPT_vect
#define COMPARE_A_INTERRUPT TIMER3_COMPA_vect #define COMPARE_A_INTERRUPT TIMER3_COMPA_vect
#define COMPARE_B_INTERRUPT TIMER3_COMPB_vect #define COMPARE_B_INTERRUPT TIMER3_COMPB_vect
#elif defined(ALTSS_USE_TIMER4) #elif defined(ALTSS_USE_TIMER4)
#define CONFIG_TIMER_NOPRESCALE() (TIMSK4 = 0, TCCR4A = 0, TCCR4B = (1<<ICNC4) | (1<<CS40)) #define CONFIG_TIMER_NOPRESCALE() (TIMSK4 = 0, TCCR4A = 0, TCCR4B = (1<<ICNC4) | (1<<CS40))
#define CONFIG_TIMER_PRESCALE_8() (TIMSK4 = 0, TCCR4A = 0, TCCR4B = (1<<ICNC4) | (1<<CS41)) #define CONFIG_TIMER_PRESCALE_8() (TIMSK4 = 0, TCCR4A = 0, TCCR4B = (1<<ICNC4) | (1<<CS41))
#define CONFIG_MATCH_NORMAL() (TCCR4A = TCCR4A & ~((1<<COM4A1) | (1<<COM4A0))) #define CONFIG_MATCH_NORMAL() (TCCR4A = TCCR4A & ~((1<<COM4A1) | (1<<COM4A0)))
#define CONFIG_MATCH_TOGGLE() (TCCR4A = (TCCR4A & ~(1<<COM4A1)) | (1<<COM4A0)) #define CONFIG_MATCH_TOGGLE() (TCCR4A = (TCCR4A & ~(1<<COM4A1)) | (1<<COM4A0))
#define CONFIG_MATCH_CLEAR() (TCCR4A = (TCCR4A | (1<<COM4A1)) & ~(1<<COM4A0)) #define CONFIG_MATCH_CLEAR() (TCCR4A = (TCCR4A | (1<<COM4A1)) & ~(1<<COM4A0))
#define CONFIG_MATCH_SET() (TCCR4A = TCCR4A | ((1<<COM4A1) | (1<<COM4A0))) #define CONFIG_MATCH_SET() (TCCR4A = TCCR4A | ((1<<COM4A1) | (1<<COM4A0)))
#define CONFIG_CAPTURE_FALLING_EDGE() (TCCR4B &= ~(1<<ICES4)) #define CONFIG_CAPTURE_FALLING_EDGE() (TCCR4B &= ~(1<<ICES4))
#define CONFIG_CAPTURE_RISING_EDGE() (TCCR4B |= (1<<ICES4)) #define CONFIG_CAPTURE_RISING_EDGE() (TCCR4B |= (1<<ICES4))
#define ENABLE_INT_INPUT_CAPTURE() (TIFR4 = (1<<ICF4), TIMSK4 = (1<<ICIE4)) #define ENABLE_INT_INPUT_CAPTURE() (TIFR4 = (1<<ICF4), TIMSK4 = (1<<ICIE4))
#define ENABLE_INT_COMPARE_A() (TIFR4 = (1<<OCF4A), TIMSK4 |= (1<<OCIE4A)) #define ENABLE_INT_COMPARE_A() (TIFR4 = (1<<OCF4A), TIMSK4 |= (1<<OCIE4A))
#define ENABLE_INT_COMPARE_B() (TIFR4 = (1<<OCF4B), TIMSK4 |= (1<<OCIE4B)) #define ENABLE_INT_COMPARE_B() (TIFR4 = (1<<OCF4B), TIMSK4 |= (1<<OCIE4B))
#define DISABLE_INT_INPUT_CAPTURE() (TIMSK4 &= ~(1<<ICIE4)) #define DISABLE_INT_INPUT_CAPTURE() (TIMSK4 &= ~(1<<ICIE4))
#define DISABLE_INT_COMPARE_A() (TIMSK4 &= ~(1<<OCIE4A)) #define DISABLE_INT_COMPARE_A() (TIMSK4 &= ~(1<<OCIE4A))
#define DISABLE_INT_COMPARE_B() (TIMSK4 &= ~(1<<OCIE4B)) #define DISABLE_INT_COMPARE_B() (TIMSK4 &= ~(1<<OCIE4B))
#define GET_TIMER_COUNT() (TCNT4) #define GET_TIMER_COUNT() (TCNT4)
#define GET_INPUT_CAPTURE() (ICR4) #define GET_INPUT_CAPTURE() (ICR4)
#define GET_COMPARE_A() (OCR4A) #define GET_COMPARE_A() (OCR4A)
#define GET_COMPARE_B() (OCR4B) #define GET_COMPARE_B() (OCR4B)
#define SET_COMPARE_A(val) (OCR4A = (val)) #define SET_COMPARE_A(val) (OCR4A = (val))
#define SET_COMPARE_B(val) (OCR4B = (val)) #define SET_COMPARE_B(val) (OCR4B = (val))
#define CAPTURE_INTERRUPT TIMER4_CAPT_vect #define CAPTURE_INTERRUPT TIMER4_CAPT_vect
#define COMPARE_A_INTERRUPT TIMER4_COMPA_vect #define COMPARE_A_INTERRUPT TIMER4_COMPA_vect
#define COMPARE_B_INTERRUPT TIMER4_COMPB_vect #define COMPARE_B_INTERRUPT TIMER4_COMPB_vect
#elif defined(ALTSS_USE_TIMER5) #elif defined(ALTSS_USE_TIMER5)
#define CONFIG_TIMER_NOPRESCALE() (TIMSK5 = 0, TCCR5A = 0, TCCR5B = (1<<ICNC5) | (1<<CS50)) #define CONFIG_TIMER_NOPRESCALE() (TIMSK5 = 0, TCCR5A = 0, TCCR5B = (1<<ICNC5) | (1<<CS50))
#define CONFIG_TIMER_PRESCALE_8() (TIMSK5 = 0, TCCR5A = 0, TCCR5B = (1<<ICNC5) | (1<<CS51)) #define CONFIG_TIMER_PRESCALE_8() (TIMSK5 = 0, TCCR5A = 0, TCCR5B = (1<<ICNC5) | (1<<CS51))
#define CONFIG_MATCH_NORMAL() (TCCR5A = TCCR5A & ~((1<<COM5A1) | (1<<COM5A0))) #define CONFIG_MATCH_NORMAL() (TCCR5A = TCCR5A & ~((1<<COM5A1) | (1<<COM5A0)))
#define CONFIG_MATCH_TOGGLE() (TCCR5A = (TCCR5A & ~(1<<COM5A1)) | (1<<COM5A0)) #define CONFIG_MATCH_TOGGLE() (TCCR5A = (TCCR5A & ~(1<<COM5A1)) | (1<<COM5A0))
#define CONFIG_MATCH_CLEAR() (TCCR5A = (TCCR5A | (1<<COM5A1)) & ~(1<<COM5A0)) #define CONFIG_MATCH_CLEAR() (TCCR5A = (TCCR5A | (1<<COM5A1)) & ~(1<<COM5A0))
#define CONFIG_MATCH_SET() (TCCR5A = TCCR5A | ((1<<COM5A1) | (1<<COM5A0))) #define CONFIG_MATCH_SET() (TCCR5A = TCCR5A | ((1<<COM5A1) | (1<<COM5A0)))
#define CONFIG_CAPTURE_FALLING_EDGE() (TCCR5B &= ~(1<<ICES5)) #define CONFIG_CAPTURE_FALLING_EDGE() (TCCR5B &= ~(1<<ICES5))
#define CONFIG_CAPTURE_RISING_EDGE() (TCCR5B |= (1<<ICES5)) #define CONFIG_CAPTURE_RISING_EDGE() (TCCR5B |= (1<<ICES5))
#define ENABLE_INT_INPUT_CAPTURE() (TIFR5 = (1<<ICF5), TIMSK5 = (1<<ICIE5)) #define ENABLE_INT_INPUT_CAPTURE() (TIFR5 = (1<<ICF5), TIMSK5 = (1<<ICIE5))
#define ENABLE_INT_COMPARE_A() (TIFR5 = (1<<OCF5A), TIMSK5 |= (1<<OCIE5A)) #define ENABLE_INT_COMPARE_A() (TIFR5 = (1<<OCF5A), TIMSK5 |= (1<<OCIE5A))
#define ENABLE_INT_COMPARE_B() (TIFR5 = (1<<OCF5B), TIMSK5 |= (1<<OCIE5B)) #define ENABLE_INT_COMPARE_B() (TIFR5 = (1<<OCF5B), TIMSK5 |= (1<<OCIE5B))
#define DISABLE_INT_INPUT_CAPTURE() (TIMSK5 &= ~(1<<ICIE5)) #define DISABLE_INT_INPUT_CAPTURE() (TIMSK5 &= ~(1<<ICIE5))
#define DISABLE_INT_COMPARE_A() (TIMSK5 &= ~(1<<OCIE5A)) #define DISABLE_INT_COMPARE_A() (TIMSK5 &= ~(1<<OCIE5A))
#define DISABLE_INT_COMPARE_B() (TIMSK5 &= ~(1<<OCIE5B)) #define DISABLE_INT_COMPARE_B() (TIMSK5 &= ~(1<<OCIE5B))
#define GET_TIMER_COUNT() (TCNT5) #define GET_TIMER_COUNT() (TCNT5)
#define GET_INPUT_CAPTURE() (ICR5) #define GET_INPUT_CAPTURE() (ICR5)
#define GET_COMPARE_A() (OCR5A) #define GET_COMPARE_A() (OCR5A)
#define GET_COMPARE_B() (OCR5B) #define GET_COMPARE_B() (OCR5B)
#define SET_COMPARE_A(val) (OCR5A = (val)) #define SET_COMPARE_A(val) (OCR5A = (val))
#define SET_COMPARE_B(val) (OCR5B = (val)) #define SET_COMPARE_B(val) (OCR5B = (val))
#define CAPTURE_INTERRUPT TIMER5_CAPT_vect #define CAPTURE_INTERRUPT TIMER5_CAPT_vect
#define COMPARE_A_INTERRUPT TIMER5_COMPA_vect #define COMPARE_A_INTERRUPT TIMER5_COMPA_vect
#define COMPARE_B_INTERRUPT TIMER5_COMPB_vect #define COMPARE_B_INTERRUPT TIMER5_COMPB_vect
#endif #endif
+23 -24
View File
@@ -18,11 +18,11 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
/** /**
* @file CircularBuffer.h * @file CircularBuffer.h
* *
* Circular buffering for arbitrary types. * Circular buffering for arbitrary types.
*/ */
#ifndef CircularBuffer_h #ifndef CircularBuffer_h
#define CircularBuffer_h #define CircularBuffer_h
@@ -33,7 +33,7 @@
*/ */
template <class T> class CircularBuffer template <class T> class CircularBuffer
{ {
public: public:
/** /**
* Constructor * Constructor
* @param buffer Preallocated buffer of at least size records. * @param buffer Preallocated buffer of at least size records.
@@ -50,8 +50,7 @@ template <class T> class CircularBuffer
*/ */
void clear(void) void clear(void)
{ {
MY_CRITICAL_SECTION MY_CRITICAL_SECTION {
{
m_front = 0; m_front = 0;
m_fill = 0; m_fill = 0;
} }
@@ -64,8 +63,7 @@ template <class T> class CircularBuffer
inline bool empty(void) const inline bool empty(void) const
{ {
bool empty; bool empty;
MY_CRITICAL_SECTION MY_CRITICAL_SECTION {
{
empty = !m_fill; empty = !m_fill;
} }
return empty; return empty;
@@ -78,8 +76,7 @@ template <class T> class CircularBuffer
inline bool full(void) const inline bool full(void) const
{ {
bool full; bool full;
MY_CRITICAL_SECTION MY_CRITICAL_SECTION {
{
full = m_fill == m_size; full = m_fill == m_size;
} }
return full; return full;
@@ -91,8 +88,7 @@ template <class T> class CircularBuffer
*/ */
inline uint8_t available(void) const inline uint8_t available(void) const
{ {
MY_CRITICAL_SECTION MY_CRITICAL_SECTION {
{
return m_fill; return m_fill;
} }
} }
@@ -105,9 +101,11 @@ template <class T> class CircularBuffer
*/ */
T* getFront(void) const T* getFront(void) const
{ {
MY_CRITICAL_SECTION MY_CRITICAL_SECTION {
if (!full())
{ {
if (!full()) return get(m_front); return get(m_front);
}
} }
return static_cast<T*>(NULL); return static_cast<T*>(NULL);
} }
@@ -120,13 +118,13 @@ template <class T> class CircularBuffer
*/ */
bool pushFront(T* record) bool pushFront(T* record)
{ {
MY_CRITICAL_SECTION MY_CRITICAL_SECTION {
{
if (!full()) if (!full())
{ {
T* f = get(m_front); T* f = get(m_front);
if (f != record) if (f != record) {
*f = *record; *f = *record;
}
m_front = (m_front+1) % m_size; m_front = (m_front+1) % m_size;
m_fill++; m_fill++;
return true; return true;
@@ -143,9 +141,11 @@ template <class T> class CircularBuffer
*/ */
T* getBack(void) const T* getBack(void) const
{ {
MY_CRITICAL_SECTION MY_CRITICAL_SECTION {
if (!empty())
{ {
if (!empty()) return get(back()); return get(back());
}
} }
return static_cast<T*>(NULL); return static_cast<T*>(NULL);
} }
@@ -156,8 +156,7 @@ template <class T> class CircularBuffer
*/ */
bool popBack(void) bool popBack(void)
{ {
MY_CRITICAL_SECTION MY_CRITICAL_SECTION {
{
if (!empty()) if (!empty())
{ {
m_fill--; m_fill--;
@@ -167,7 +166,7 @@ template <class T> class CircularBuffer
return false; return false;
} }
protected: protected:
/** /**
* Internal getter for records. * Internal getter for records.
* @param idx Record index in buffer. * @param idx Record index in buffer.
+3 -3
View File
@@ -14,8 +14,8 @@
#include "stdlib_noniso.h" #include "stdlib_noniso.h"
#ifdef LINUX_ARCH_RASPBERRYPI #ifdef LINUX_ARCH_RASPBERRYPI
#include "rpi_util.h" #include "rpi_util.h"
using namespace rpi_util; using namespace rpi_util;
#endif #endif
#undef PSTR #undef PSTR
@@ -57,7 +57,7 @@
#define random(...) GET_MACRO(_0, ##__VA_ARGS__, randMinMax, randMax, rand)(__VA_ARGS__) #define random(...) GET_MACRO(_0, ##__VA_ARGS__, randMinMax, randMax, rand)(__VA_ARGS__)
#ifndef delay #ifndef delay
#define delay _delay_ms #define delay _delay_ms
#endif #endif
using std::string; using std::string;
+6 -2
View File
@@ -26,7 +26,8 @@
#include "IPAddress.h" #include "IPAddress.h"
#if !DOXYGEN #if !DOXYGEN
class Client : public Stream { class Client : public Stream
{
public: public:
virtual int connect(IPAddress ip, uint16_t port) = 0; virtual int connect(IPAddress ip, uint16_t port) = 0;
@@ -43,7 +44,10 @@ public:
virtual operator bool() = 0; virtual operator bool() = 0;
protected: protected:
uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; uint8_t* rawIPAddress(IPAddress& addr)
{
return addr.raw_address();
};
}; };
#endif #endif
+43 -23
View File
@@ -32,13 +32,16 @@
#include "log.h" #include "log.h"
#include "EthernetClient.h" #include "EthernetClient.h"
EthernetClient::EthernetClient() : _sock(-1) { EthernetClient::EthernetClient() : _sock(-1)
{
} }
EthernetClient::EthernetClient(int sock) : _sock(sock) { EthernetClient::EthernetClient(int sock) : _sock(sock)
{
} }
int EthernetClient::connect(const char* host, uint16_t port) { int EthernetClient::connect(const char* host, uint16_t port)
{
int sockfd; int sockfd;
struct addrinfo hints, *servinfo, *p; struct addrinfo hints, *servinfo, *p;
int rv; int rv;
@@ -88,15 +91,18 @@ int EthernetClient::connect(const char* host, uint16_t port) {
return 1; return 1;
} }
int EthernetClient::connect(IPAddress ip, uint16_t port) { int EthernetClient::connect(IPAddress ip, uint16_t port)
{
return connect(ip.toString().c_str(), port); return connect(ip.toString().c_str(), port);
} }
size_t EthernetClient::write(uint8_t b) { size_t EthernetClient::write(uint8_t b)
{
return write(&b, 1); return write(&b, 1);
} }
size_t EthernetClient::write(const uint8_t *buf, size_t size) { size_t EthernetClient::write(const uint8_t *buf, size_t size)
{
int rc = 0; int rc = 0;
int bytes = 0; int bytes = 0;
@@ -119,17 +125,20 @@ size_t EthernetClient::write(const uint8_t *buf, size_t size) {
return bytes; return bytes;
} }
size_t EthernetClient::write(const char *str) { size_t EthernetClient::write(const char *str)
{
if (str == NULL) { if (str == NULL) {
return 0; return 0;
} }
return write((const uint8_t *)str, strlen(str)); return write((const uint8_t *)str, strlen(str));
} }
size_t EthernetClient::write(const char *buffer, size_t size) { size_t EthernetClient::write(const char *buffer, size_t size)
{
return write((const uint8_t *)buffer, size); return write((const uint8_t *)buffer, size);
} }
int EthernetClient::available() { int EthernetClient::available()
{
int count = 0; int count = 0;
if (_sock != -1) { if (_sock != -1) {
@@ -139,10 +148,10 @@ int EthernetClient::available() {
return 0; return 0;
} }
int EthernetClient::read() { int EthernetClient::read()
{
uint8_t b; uint8_t b;
if ( recv(_sock, &b, 1, 0) > 0 ) if ( recv(_sock, &b, 1, 0) > 0 ) {
{
// recv worked // recv worked
return b; return b;
} else { } else {
@@ -151,22 +160,26 @@ int EthernetClient::read() {
} }
} }
int EthernetClient::read(uint8_t *buf, size_t size) { int EthernetClient::read(uint8_t *buf, size_t size)
{
return recv(_sock, buf, size, 0); return recv(_sock, buf, size, 0);
} }
int EthernetClient::peek() { int EthernetClient::peek()
{
uint8_t b; uint8_t b;
return recv(_sock, &b, 1, MSG_PEEK | MSG_DONTWAIT); return recv(_sock, &b, 1, MSG_PEEK | MSG_DONTWAIT);
} }
void EthernetClient::flush() { void EthernetClient::flush()
{
// There isn't much we can do here // There isn't much we can do here
return; return;
} }
void EthernetClient::stop() { void EthernetClient::stop()
{
if (_sock == -1) { if (_sock == -1) {
return; return;
} }
@@ -186,7 +199,8 @@ void EthernetClient::stop() {
} }
usleep(1000); usleep(1000);
gettimeofday(&curTime, NULL); gettimeofday(&curTime, NULL);
} while (((curTime.tv_sec - startTime.tv_sec) * 1000000) + (curTime.tv_usec - startTime.tv_usec) < 1000000); } while (((curTime.tv_sec - startTime.tv_sec) * 1000000) + (curTime.tv_usec - startTime.tv_usec) <
1000000);
// if it hasn't closed, close it forcefully // if it hasn't closed, close it forcefully
if (s != ETHERNETCLIENT_W5100_CLOSED) { if (s != ETHERNETCLIENT_W5100_CLOSED) {
@@ -195,7 +209,8 @@ void EthernetClient::stop() {
_sock = -1; _sock = -1;
} }
uint8_t EthernetClient::status() { uint8_t EthernetClient::status()
{
if (_sock == -1) { if (_sock == -1) {
return ETHERNETCLIENT_W5100_CLOSED; return ETHERNETCLIENT_W5100_CLOSED;
} }
@@ -203,7 +218,8 @@ uint8_t EthernetClient::status() {
struct tcp_info tcp_info; struct tcp_info tcp_info;
int tcp_info_length = sizeof(tcp_info); int tcp_info_length = sizeof(tcp_info);
if ( getsockopt( _sock, SOL_TCP, TCP_INFO, (void *)&tcp_info, (socklen_t *)&tcp_info_length ) == 0 ) { if ( getsockopt( _sock, SOL_TCP, TCP_INFO, (void *)&tcp_info,
(socklen_t *)&tcp_info_length ) == 0 ) {
switch (tcp_info.tcpi_state) { switch (tcp_info.tcpi_state) {
case TCP_ESTABLISHED: case TCP_ESTABLISHED:
return ETHERNETCLIENT_W5100_ESTABLISHED; return ETHERNETCLIENT_W5100_ESTABLISHED;
@@ -232,7 +248,8 @@ uint8_t EthernetClient::status() {
return ETHERNETCLIENT_W5100_CLOSED; return ETHERNETCLIENT_W5100_CLOSED;
} }
uint8_t EthernetClient::connected() { uint8_t EthernetClient::connected()
{
if (_sock == -1) { if (_sock == -1) {
return 0; return 0;
} }
@@ -246,17 +263,20 @@ uint8_t EthernetClient::connected() {
return 1; return 1;
} }
int EthernetClient::getSocketNumber() { int EthernetClient::getSocketNumber()
{
return _sock; return _sock;
} }
// the next function allows us to use the client returned by // the next function allows us to use the client returned by
// EthernetServer::available() as the condition in an if-statement. // EthernetServer::available() as the condition in an if-statement.
EthernetClient::operator bool() { EthernetClient::operator bool()
{
return _sock != -1; return _sock != -1;
} }
bool EthernetClient::operator==(const EthernetClient& rhs) { bool EthernetClient::operator==(const EthernetClient& rhs)
{
return _sock == rhs._sock && _sock != -1 && rhs._sock != -1; return _sock == rhs._sock && _sock != -1 && rhs._sock != -1;
} }
+14 -4
View File
@@ -40,7 +40,8 @@
/** /**
* EthernetClient class * EthernetClient class
*/ */
class EthernetClient : public Client { class EthernetClient : public Client
{
private: private:
int _sock; //!< @brief Network socket. int _sock; //!< @brief Network socket.
@@ -168,12 +169,18 @@ public:
* @brief Overloaded cast operators. * @brief Overloaded cast operators.
* *
*/ */
virtual bool operator==(const bool value) { return bool() == value; } virtual bool operator==(const bool value)
{
return bool() == value;
}
/** /**
* @brief Overloaded cast operators. * @brief Overloaded cast operators.
* *
*/ */
virtual bool operator!=(const bool value) { return bool() != value; } virtual bool operator!=(const bool value)
{
return bool() != value;
}
/** /**
* @brief Overloaded cast operators. * @brief Overloaded cast operators.
* *
@@ -183,7 +190,10 @@ public:
* @brief Overloaded cast operators. * @brief Overloaded cast operators.
* *
*/ */
virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); }; virtual bool operator!=(const EthernetClient& rhs)
{
return !this->operator==(rhs);
};
friend class EthernetServer; friend class EthernetServer;
}; };
+2 -1
View File
@@ -32,7 +32,8 @@
#include "EthernetClient.h" #include "EthernetClient.h"
#include "EthernetServer.h" #include "EthernetServer.h"
EthernetServer::EthernetServer(uint16_t port, uint16_t max_clients) : port(port), max_clients(max_clients) EthernetServer::EthernetServer(uint16_t port, uint16_t max_clients) : port(port),
max_clients(max_clients)
{ {
clients.reserve(max_clients); clients.reserve(max_clients);
} }
+5 -4
View File
@@ -28,10 +28,10 @@
#include "IPAddress.h" #include "IPAddress.h"
#ifdef ETHERNETSERVER_MAX_CLIENTS #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 #else
#define ETHERNETSERVER_MAX_CLIENTS 10 //!< Default value for max_clients. #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_BACKLOG 10 //!< Maximum length to which the queue of pending connections may grow.
#endif #endif
class EthernetClient; class EthernetClient;
@@ -39,7 +39,8 @@ class EthernetClient;
/** /**
* @brief EthernetServer class * @brief EthernetServer class
*/ */
class EthernetServer : public Server { class EthernetServer : public Server
{
private: private:
uint16_t port; //!< @brief Port number for the network socket. uint16_t port; //!< @brief Port number for the network socket.
+23 -19
View File
@@ -24,53 +24,53 @@
#include <cstring> #include <cstring>
#include "IPAddress.h" #include "IPAddress.h"
IPAddress::IPAddress() { IPAddress::IPAddress()
{
_address.dword = 0; _address.dword = 0;
} }
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) { IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet,
uint8_t fourth_octet)
{
_address.bytes[0] = first_octet; _address.bytes[0] = first_octet;
_address.bytes[1] = second_octet; _address.bytes[1] = second_octet;
_address.bytes[2] = third_octet; _address.bytes[2] = third_octet;
_address.bytes[3] = fourth_octet; _address.bytes[3] = fourth_octet;
} }
IPAddress::IPAddress(uint32_t address) { IPAddress::IPAddress(uint32_t address)
{
_address.dword = address; _address.dword = address;
} }
IPAddress::IPAddress(const uint8_t *address) { IPAddress::IPAddress(const uint8_t *address)
{
memcpy(_address.bytes, address, sizeof(_address.bytes)); memcpy(_address.bytes, address, sizeof(_address.bytes));
} }
bool IPAddress::fromString(const char *address) { bool IPAddress::fromString(const char *address)
{
// TODO: add support for "a", "a.b", "a.b.c" formats // TODO: add support for "a", "a.b", "a.b.c" formats
uint16_t acc = 0; // Accumulator uint16_t acc = 0; // Accumulator
uint8_t dots = 0; uint8_t dots = 0;
while (*address) while (*address) {
{
char c = *address++; char c = *address++;
if (c >= '0' && c <= '9') if (c >= '0' && c <= '9') {
{
acc = acc * 10 + (c - '0'); acc = acc * 10 + (c - '0');
if (acc > 255) { if (acc > 255) {
// Value out of [0..255] range // Value out of [0..255] range
return false; return false;
} }
} } else if (c == '.') {
else if (c == '.')
{
if (dots == 3) { if (dots == 3) {
// Too much dots (there must be 3 dots) // Too much dots (there must be 3 dots)
return false; return false;
} }
_address.bytes[dots++] = acc; _address.bytes[dots++] = acc;
acc = 0; acc = 0;
} } else {
else
{
// Invalid char // Invalid char
return false; return false;
} }
@@ -84,23 +84,27 @@ bool IPAddress::fromString(const char *address) {
return true; return true;
} }
IPAddress& IPAddress::operator=(const uint8_t *address) { IPAddress& IPAddress::operator=(const uint8_t *address)
{
memcpy(_address.bytes, address, sizeof(_address.bytes)); memcpy(_address.bytes, address, sizeof(_address.bytes));
return *this; return *this;
} }
IPAddress& IPAddress::operator=(uint32_t address) { IPAddress& IPAddress::operator=(uint32_t address)
{
_address.dword = address; _address.dword = address;
return *this; return *this;
} }
bool IPAddress::operator==(const uint8_t* addr) const { bool IPAddress::operator==(const uint8_t* addr) const
{
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0; return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
} }
std::string IPAddress::toString() std::string IPAddress::toString()
{ {
char szRet[16]; char szRet[16];
sprintf(szRet,"%u.%u.%u.%u", _address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3]); sprintf(szRet,"%u.%u.%u.%u", _address.bytes[0], _address.bytes[1], _address.bytes[2],
_address.bytes[3]);
return std::string(szRet); return std::string(szRet);
} }
+20 -10
View File
@@ -29,8 +29,9 @@
/** /**
* @brief A class to make it easier to handle and pass around IP addresses * @brief A class to make it easier to handle and pass around IP addresses
*/ */
class IPAddress { class IPAddress
private: {
private:
union { union {
uint8_t bytes[4]; //!< IPv4 address as an array uint8_t bytes[4]; //!< IPv4 address as an array
uint32_t dword; //!< IPv4 address in 32 bits format uint32_t dword; //!< IPv4 address in 32 bits format
@@ -45,11 +46,12 @@ class IPAddress {
* *
* @return pointer to the internal structure. * @return pointer to the internal structure.
*/ */
uint8_t* raw_address() { uint8_t* raw_address()
{
return _address.bytes; return _address.bytes;
} }
public: public:
/** /**
* @brief IPAddress constructor. * @brief IPAddress constructor.
*/ */
@@ -86,27 +88,33 @@ class IPAddress {
* *
* @param address to be set. * @param address to be set.
*/ */
bool fromString(const std::string &address) { return fromString(address.c_str()); } bool fromString(const std::string &address)
{
return fromString(address.c_str());
}
/** /**
* @brief Overloaded cast operator * @brief Overloaded cast operator
* *
* Allow IPAddress objects to be used where a pointer to a four-byte uint8_t array is expected * Allow IPAddress objects to be used where a pointer to a four-byte uint8_t array is expected
*/ */
operator uint32_t() const { operator uint32_t() const
{
return _address.dword; return _address.dword;
} }
/** /**
* @brief Overloaded cast operator * @brief Overloaded cast operator
* *
*/ */
bool operator==(const IPAddress& addr) const { bool operator==(const IPAddress& addr) const
{
return _address.dword == addr._address.dword; return _address.dword == addr._address.dword;
} }
/** /**
* @brief Overloaded cast operator * @brief Overloaded cast operator
* *
*/ */
bool operator==(uint32_t addr) const { bool operator==(uint32_t addr) const
{
return _address.dword == addr; return _address.dword == addr;
} }
/** /**
@@ -120,14 +128,16 @@ class IPAddress {
* Allow getting and setting individual octets of the address. * Allow getting and setting individual octets of the address.
* *
*/ */
uint8_t operator[](int index) const { uint8_t operator[](int index) const
{
return _address.bytes[index]; return _address.bytes[index];
} }
/** /**
* @brief Overloaded index operator * @brief Overloaded index operator
* *
*/ */
uint8_t& operator[](int index) { uint8_t& operator[](int index)
{
return _address.bytes[index]; return _address.bytes[index];
} }
/** /**
+47 -25
View File
@@ -30,7 +30,8 @@
// Public Methods ////////////////////////////////////////////////////////////// // Public Methods //////////////////////////////////////////////////////////////
size_t Print::write(const uint8_t *buffer, size_t size) { size_t Print::write(const uint8_t *buffer, size_t size)
{
size_t n = 0; size_t n = 0;
while(size--) { while(size--) {
n += write(*buffer++); n += write(*buffer++);
@@ -42,7 +43,8 @@ size_t
#ifdef __GNUC__ #ifdef __GNUC__
__attribute__((format(printf, 2, 3))) __attribute__((format(printf, 2, 3)))
#endif #endif
Print::printf(const char *format, ...) { Print::printf(const char *format, ...)
{
va_list arg; va_list arg;
va_start(arg, format); va_start(arg, format);
char temp[64]; char temp[64];
@@ -65,31 +67,38 @@ Print::printf(const char *format, ...) {
return len; return len;
} }
size_t Print::print(const std::string &s) { size_t Print::print(const std::string &s)
{
return write(s.c_str(), s.length()); return write(s.c_str(), s.length());
} }
size_t Print::print(const char str[]) { size_t Print::print(const char str[])
{
return write(str); return write(str);
} }
size_t Print::print(char c) { size_t Print::print(char c)
{
return write(c); return write(c);
} }
size_t Print::print(unsigned char b, int base) { size_t Print::print(unsigned char b, int base)
{
return print((unsigned long) b, base); return print((unsigned long) b, base);
} }
size_t Print::print(int n, int base) { size_t Print::print(int n, int base)
{
return print((long) n, base); return print((long) n, base);
} }
size_t Print::print(unsigned int n, int base) { size_t Print::print(unsigned int n, int base)
{
return print((unsigned long) n, base); return print((unsigned long) n, base);
} }
size_t Print::print(long n, int base) { size_t Print::print(long n, int base)
{
if(base == 0) { if(base == 0) {
return write(n); return write(n);
} else if(base == 10) { } else if(base == 10) {
@@ -104,72 +113,83 @@ size_t Print::print(long n, int base) {
} }
} }
size_t Print::print(unsigned long n, int base) { size_t Print::print(unsigned long n, int base)
{
if(base == 0) { if(base == 0) {
return write(n); return write(n);
} } else {
else {
return printNumber(n, base); return printNumber(n, base);
} }
} }
size_t Print::print(double n, int digits) { size_t Print::print(double n, int digits)
{
return printFloat(n, digits); return printFloat(n, digits);
} }
size_t Print::println(void) { size_t Print::println(void)
{
return print("\r\n"); return print("\r\n");
} }
size_t Print::println(const std::string &s) { size_t Print::println(const std::string &s)
{
size_t n = print(s); size_t n = print(s);
n += println(); n += println();
return n; return n;
} }
size_t Print::println(const char c[]) { size_t Print::println(const char c[])
{
size_t n = print(c); size_t n = print(c);
n += println(); n += println();
return n; return n;
} }
size_t Print::println(char c) { size_t Print::println(char c)
{
size_t n = print(c); size_t n = print(c);
n += println(); n += println();
return n; return n;
} }
size_t Print::println(unsigned char b, int base) { size_t Print::println(unsigned char b, int base)
{
size_t n = print(b, base); size_t n = print(b, base);
n += println(); n += println();
return n; return n;
} }
size_t Print::println(int num, int base) { size_t Print::println(int num, int base)
{
size_t n = print(num, base); size_t n = print(num, base);
n += println(); n += println();
return n; return n;
} }
size_t Print::println(unsigned int num, int base) { size_t Print::println(unsigned int num, int base)
{
size_t n = print(num, base); size_t n = print(num, base);
n += println(); n += println();
return n; return n;
} }
size_t Print::println(long num, int base) { size_t Print::println(long num, int base)
{
size_t n = print(num, base); size_t n = print(num, base);
n += println(); n += println();
return n; return n;
} }
size_t Print::println(unsigned long num, int base) { size_t Print::println(unsigned long num, int base)
{
size_t n = print(num, base); size_t n = print(num, base);
n += println(); n += println();
return n; return n;
} }
size_t Print::println(double num, int digits) { size_t Print::println(double num, int digits)
{
size_t n = print(num, digits); size_t n = print(num, digits);
n += println(); n += println();
return n; return n;
@@ -177,7 +197,8 @@ size_t Print::println(double num, int digits) {
// Private Methods ///////////////////////////////////////////////////////////// // Private Methods /////////////////////////////////////////////////////////////
size_t Print::printNumber(unsigned long n, uint8_t base) { size_t Print::printNumber(unsigned long n, uint8_t base)
{
char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
char *str = &buf[sizeof(buf) - 1]; char *str = &buf[sizeof(buf) - 1];
@@ -198,7 +219,8 @@ size_t Print::printNumber(unsigned long n, uint8_t base) {
return write(str); return write(str);
} }
size_t Print::printFloat(double number, uint8_t digits) { size_t Print::printFloat(double number, uint8_t digits)
{
size_t n = 0; size_t n = 0;
if(std::isnan(number)) { if(std::isnan(number)) {
+24 -11
View File
@@ -32,29 +32,42 @@
#define OCT 8 #define OCT 8
#define BIN 2 #define BIN 2
class Print { class Print
private: {
private:
int write_error; int write_error;
size_t printNumber(unsigned long n, uint8_t base); size_t printNumber(unsigned long n, uint8_t base);
size_t printFloat(double number, uint8_t digits); size_t printFloat(double number, uint8_t digits);
protected: protected:
void setWriteError(int err = 1) { write_error = err; } void setWriteError(int err = 1)
{
write_error = err;
}
public: public:
Print() : write_error(0) {} Print() : write_error(0) {}
int getWriteError() { return write_error; } int getWriteError()
void clearWriteError() { setWriteError(0); } {
return write_error;
}
void clearWriteError()
{
setWriteError(0);
}
virtual size_t write(uint8_t) = 0; virtual size_t write(uint8_t) = 0;
size_t write(const char *str) { size_t write(const char *str)
if (str == NULL) {
if (str == NULL) {
return 0; return 0;
}
return write((const uint8_t *) str, strlen(str)); return write((const uint8_t *) str, strlen(str));
} }
virtual size_t write(const uint8_t *buffer, size_t size); virtual size_t write(const uint8_t *buffer, size_t size);
size_t write(const char *buffer, size_t size) { size_t write(const char *buffer, size_t size)
{
return write((const uint8_t *) buffer, size); return write((const uint8_t *) buffer, size);
} }
@@ -79,7 +92,7 @@ class Print {
size_t println(unsigned long, int = DEC); size_t println(unsigned long, int = DEC);
size_t println(double, int = 2); size_t println(double, int = 2);
size_t println(void); size_t println(void);
}; };
#endif #endif
#endif #endif
+53 -18
View File
@@ -69,7 +69,8 @@ bool SerialPort::open(int bauds)
/* create a symlink with predictable name to the PTY device */ /* create a symlink with predictable name to the PTY device */
unlink(serialPort.c_str()); // remove the symlink if it already exists unlink(serialPort.c_str()); // remove the symlink if it already exists
if (symlink(ptsname(sd), serialPort.c_str()) != 0) { if (symlink(ptsname(sd), serialPort.c_str()) != 0) {
logError("Couldn't create a symlink '%s' to PTY! (%d) %s\n", serialPort.c_str(), errno, strerror(errno)); logError("Couldn't create a symlink '%s' to PTY! (%d) %s\n", serialPort.c_str(), errno,
strerror(errno));
return false; return false;
} }
} else { } else {
@@ -83,23 +84,57 @@ bool SerialPort::open(int bauds)
} }
switch (bauds) { switch (bauds) {
case 50: speed = B50 ; break ; case 50:
case 75: speed = B75 ; break ; speed = B50 ;
case 110: speed = B110 ; break ; break ;
case 134: speed = B134 ; break ; case 75:
case 150: speed = B150 ; break ; speed = B75 ;
case 200: speed = B200 ; break ; break ;
case 300: speed = B300 ; break ; case 110:
case 600: speed = B600 ; break ; speed = B110 ;
case 1200: speed = B1200 ; break ; break ;
case 1800: speed = B1800 ; break ; case 134:
case 2400: speed = B2400 ; break ; speed = B134 ;
case 9600: speed = B9600 ; break ; break ;
case 19200: speed = B19200 ; break ; case 150:
case 38400: speed = B38400 ; break ; speed = B150 ;
case 57600: speed = B57600 ; break ; break ;
case 115200: speed = B115200 ; break ; case 200:
default: speed = B115200 ; break ; speed = B200 ;
break ;
case 300:
speed = B300 ;
break ;
case 600:
speed = B600 ;
break ;
case 1200:
speed = B1200 ;
break ;
case 1800:
speed = B1800 ;
break ;
case 2400:
speed = B2400 ;
break ;
case 9600:
speed = B9600 ;
break ;
case 19200:
speed = B19200 ;
break ;
case 38400:
speed = B38400 ;
break ;
case 57600:
speed = B57600 ;
break ;
case 115200:
speed = B115200 ;
break ;
default:
speed = B115200 ;
break ;
} }
// Get the current options of the port // Get the current options of the port
+2 -1
View File
@@ -28,7 +28,8 @@
* SerialPort Class * SerialPort Class
* Class that provides the functionality of arduino Serial library * Class that provides the functionality of arduino Serial library
*/ */
class SerialPort : public Stream { class SerialPort : public Stream
{
private: private:
int sd; //!< @brief file descriptor number. int sd; //!< @brief file descriptor number.
+3 -2
View File
@@ -23,8 +23,9 @@
#include "Print.h" #include "Print.h"
#if !DOXYGEN #if !DOXYGEN
class Server : public Print { class Server : public Print
public: {
public:
virtual void begin() =0; virtual void begin() =0;
}; };
#endif #endif
+2 -1
View File
@@ -52,7 +52,8 @@ SoftEeprom::SoftEeprom(const char *fileName, size_t length)
myFile.write((const char*)_values, _length); myFile.write((const char*)_values, _length);
myFile.close(); myFile.close();
} else if (fileInfo.st_size < 0 || (size_t)fileInfo.st_size != _length) { } else if (fileInfo.st_size < 0 || (size_t)fileInfo.st_size != _length) {
logError("Config file %s is not the correct size of %zu. Please remove the file and a new one will be created.\n", _fileName, _length); logError("Config file %s is not the correct size of %zu. Please remove the file and a new one will be created.\n",
_fileName, _length);
exit(1); exit(1);
} else { } else {
//Read config into local memory. //Read config into local memory.
+2 -1
View File
@@ -30,7 +30,8 @@
/** /**
* SoftEeprom class * SoftEeprom class
*/ */
class SoftEeprom { class SoftEeprom
{
private: private:
size_t _length; //!< @brief Eeprom max size. size_t _length; //!< @brief Eeprom max size.
+37 -27
View File
@@ -28,7 +28,8 @@
#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field #define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
// private method to read stream with timeout // private method to read stream with timeout
int Stream::timedRead() { int Stream::timedRead()
{
int c; int c;
_startMillis = millis(); _startMillis = millis();
do { do {
@@ -42,7 +43,8 @@ int Stream::timedRead() {
} }
// private method to peek stream with timeout // private method to peek stream with timeout
int Stream::timedPeek() { int Stream::timedPeek()
{
int c; int c;
_startMillis = millis(); _startMillis = millis();
do { do {
@@ -57,7 +59,8 @@ int Stream::timedPeek() {
// returns peek of the next digit in the stream or -1 if timeout // returns peek of the next digit in the stream or -1 if timeout
// discards non-numeric characters // discards non-numeric characters
int Stream::peekNextDigit() { int Stream::peekNextDigit()
{
int c; int c;
while(1) { while(1) {
c = timedPeek(); c = timedPeek();
@@ -83,25 +86,30 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi
} }
// find returns true if the target string is found // find returns true if the target string is found
bool Stream::find(const char *target) { bool Stream::find(const char *target)
{
return findUntil(target, (char*) ""); return findUntil(target, (char*) "");
} }
// reads data from the stream until the target string of given length is found // reads data from the stream until the target string of given length is found
// returns true if target string is found, false if timed out // returns true if target string is found, false if timed out
bool Stream::find(const char *target, size_t length) { bool Stream::find(const char *target, size_t length)
{
return findUntil(target, length, NULL, 0); return findUntil(target, length, NULL, 0);
} }
// as find but search ends if the terminator string is found // as find but search ends if the terminator string is found
bool Stream::findUntil(const char *target, const char *terminator) { bool Stream::findUntil(const char *target, const char *terminator)
{
return findUntil(target, strlen(target), terminator, strlen(terminator)); return findUntil(target, strlen(target), terminator, strlen(terminator));
} }
// reads data from the stream until the target string of the given length is found // reads data from the stream until the target string of the given length is found
// search terminated if the terminator string is found // search terminated if the terminator string is found
// returns true if target string is found, false if terminated or timed out // returns true if target string is found, false if terminated or timed out
bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen) { bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator,
size_t termLen)
{
size_t index = 0; // maximum target string length is 64k bytes! size_t index = 0; // maximum target string length is 64k bytes!
size_t termIndex = 0; size_t termIndex = 0;
int c; int c;
@@ -135,13 +143,15 @@ bool Stream::findUntil(const char *target, size_t targetLen, const char *termina
// returns the first valid (long) integer value from the current position. // returns the first valid (long) integer value from the current position.
// initial characters that are not digits (or the minus sign) are skipped // initial characters that are not digits (or the minus sign) are skipped
// function is terminated by the first character that is not a digit. // function is terminated by the first character that is not a digit.
long Stream::parseInt() { long Stream::parseInt()
{
return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout) return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
} }
// as above but a given skipChar is ignored // as above but a given skipChar is ignored
// this allows format characters (typically commas) in values to be ignored // this allows format characters (typically commas) in values to be ignored
long Stream::parseInt(char skipChar) { long Stream::parseInt(char skipChar)
{
boolean isNegative = false; boolean isNegative = false;
long value = 0; long value = 0;
int c; int c;
@@ -155,11 +165,9 @@ long Stream::parseInt(char skipChar) {
do { do {
if(c == skipChar) { if(c == skipChar) {
// ignore this charactor // ignore this charactor
} } else if(c == '-') {
else if(c == '-') {
isNegative = true; isNegative = true;
} } else if(c >= '0' && c <= '9') { // is c a digit?
else if(c >= '0' && c <= '9') { // is c a digit?
value = value * 10 + c - '0'; value = value * 10 + c - '0';
} }
read(); // consume the character we got with peek read(); // consume the character we got with peek
@@ -173,13 +181,15 @@ long Stream::parseInt(char skipChar) {
} }
// as parseInt but returns a floating point value // as parseInt but returns a floating point value
float Stream::parseFloat() { float Stream::parseFloat()
{
return parseFloat(NO_SKIP_CHAR); return parseFloat(NO_SKIP_CHAR);
} }
// as above but the given skipChar is ignored // as above but the given skipChar is ignored
// this allows format characters (typically commas) in values to be ignored // this allows format characters (typically commas) in values to be ignored
float Stream::parseFloat(char skipChar) { float Stream::parseFloat(char skipChar)
{
boolean isNegative = false; boolean isNegative = false;
boolean isFraction = false; boolean isFraction = false;
long value = 0; long value = 0;
@@ -195,14 +205,11 @@ float Stream::parseFloat(char skipChar) {
do { do {
if(c == skipChar) { if(c == skipChar) {
// ignore // ignore
} } else if(c == '-') {
else if(c == '-') {
isNegative = true; isNegative = true;
} } else if(c == '.') {
else if(c == '.') {
isFraction = true; isFraction = true;
} } else if(c >= '0' && c <= '9') { // is c a digit?
else if(c >= '0' && c <= '9') { // is c a digit?
value = value * 10 + c - '0'; value = value * 10 + c - '0';
if(isFraction) { if(isFraction) {
fraction *= 0.1; fraction *= 0.1;
@@ -217,8 +224,7 @@ float Stream::parseFloat(char skipChar) {
} }
if(isFraction) { if(isFraction) {
return value * fraction; return value * fraction;
} } else {
else {
return value; return value;
} }
} }
@@ -228,7 +234,8 @@ float Stream::parseFloat(char skipChar) {
// returns the number of characters placed in the buffer // returns the number of characters placed in the buffer
// the buffer is NOT null terminated. // the buffer is NOT null terminated.
// //
size_t Stream::readBytes(char *buffer, size_t length) { size_t Stream::readBytes(char *buffer, size_t length)
{
size_t count = 0; size_t count = 0;
while(count < length) { while(count < length) {
int c = timedRead(); int c = timedRead();
@@ -245,7 +252,8 @@ size_t Stream::readBytes(char *buffer, size_t length) {
// terminates if length characters have been read, timeout, or if the terminator character detected // terminates if length characters have been read, timeout, or if the terminator character detected
// returns the number of characters placed in the buffer (0 means no valid data found) // returns the number of characters placed in the buffer (0 means no valid data found)
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) { size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
{
if(length < 1) { if(length < 1) {
return 0; return 0;
} }
@@ -261,7 +269,8 @@ size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) {
return index; // return number of characters, not including null terminator return index; // return number of characters, not including null terminator
} }
std::string Stream::readString() { std::string Stream::readString()
{
std::string ret; std::string ret;
int c = timedRead(); int c = timedRead();
while(c >= 0) { while(c >= 0) {
@@ -271,7 +280,8 @@ std::string Stream::readString() {
return ret; return ret;
} }
std::string Stream::readStringUntil(char terminator) { std::string Stream::readStringUntil(char terminator)
{
std::string ret; std::string ret;
int c = timedRead(); int c = timedRead();
while(c >= 0 && c != terminator) { while(c >= 0 && c != terminator) {
+36 -19
View File
@@ -38,49 +38,63 @@
*/ */
#if !DOXYGEN #if !DOXYGEN
class Stream: public Print { class Stream: public Print
protected: {
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read protected:
unsigned long
_timeout; // number of milliseconds to wait for the next char before aborting timed read
unsigned long _startMillis; // used for timeout measurement unsigned long _startMillis; // used for timeout measurement
int timedRead(); // private method to read stream with timeout int timedRead(); // private method to read stream with timeout
int timedPeek(); // private method to peek stream with timeout int timedPeek(); // private method to peek stream with timeout
int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout
public: public:
virtual int available() = 0; virtual int available() = 0;
virtual int read() = 0; virtual int read() = 0;
virtual int peek() = 0; virtual int peek() = 0;
virtual void flush() = 0; virtual void flush() = 0;
Stream() { Stream()
{
_timeout = 1000; _timeout = 1000;
} }
// parsing methods // parsing methods
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second void setTimeout(unsigned long
timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
bool find(const char *target); // reads data from the stream until the target string is found bool find(const char *target); // reads data from the stream until the target string is found
bool find(uint8_t *target) { bool find(uint8_t *target)
{
return find((char *) target); return find((char *) target);
} }
// returns true if target string is found, false if timed out (see setTimeout) // returns true if target string is found, false if timed out (see setTimeout)
bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found bool find(const char *target, size_t
bool find(const uint8_t *target, size_t length) { length); // reads data from the stream until the target string of given length is found
bool find(const uint8_t *target, size_t length)
{
return find((char *) target, length); return find((char *) target, length);
} }
// returns true if target string is found, false if timed out // returns true if target string is found, false if timed out
bool find(char target) { return find (&target, 1); } bool find(char target)
{
return find (&target, 1);
}
bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found bool findUntil(const char *target,
bool findUntil(const uint8_t *target, const char *terminator) { const char *terminator); // as find but search ends if the terminator string is found
bool findUntil(const uint8_t *target, const char *terminator)
{
return findUntil((char *) target, terminator); return findUntil((char *) target, terminator);
} }
bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found bool findUntil(const char *target, size_t targetLen, const char *terminate,
bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) { size_t termLen); // as above but search ends if the terminate string is found
bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen)
{
return findUntil((char *) target, targetLen, terminate, termLen); return findUntil((char *) target, targetLen, terminate, termLen);
} }
@@ -91,14 +105,17 @@ class Stream: public Print {
float parseFloat(); // float version of parseInt float parseFloat(); // float version of parseInt
virtual size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer virtual size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer
virtual size_t readBytes(uint8_t *buffer, size_t length) { virtual size_t readBytes(uint8_t *buffer, size_t length)
{
return readBytes((char *) buffer, length); return readBytes((char *) buffer, length);
} }
// terminates if length characters have been read or timeout (see setTimeout) // terminates if length characters have been read or timeout (see setTimeout)
// returns the number of characters placed in the buffer (0 means no valid data found) // returns the number of characters placed in the buffer (0 means no valid data found)
size_t readBytesUntil(char terminator, char *buffer, size_t length); // as readBytes with terminator character size_t readBytesUntil(char terminator, char *buffer,
size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) { size_t length); // as readBytes with terminator character
size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length)
{
return readBytesUntil(terminator, (char *) buffer, length); return readBytesUntil(terminator, (char *) buffer, length);
} }
// terminates if length characters have been read, timeout, or if the terminator character detected // terminates if length characters have been read, timeout, or if the terminator character detected
@@ -108,7 +125,7 @@ class Stream: public Print {
std::string readString(); std::string readString();
std::string readStringUntil(char terminator); std::string readStringUntil(char terminator);
protected: protected:
long parseInt(char skipChar); // as above but the given skipChar is ignored long parseInt(char skipChar); // as above but the given skipChar is ignored
// as above but the given skipChar is ignored // as above but the given skipChar is ignored
// this allows format characters (typically commas) in values to be ignored // this allows format characters (typically commas) in values to be ignored
+18 -9
View File
@@ -23,7 +23,8 @@
#include <math.h> #include <math.h>
#include "stdlib_noniso.h" #include "stdlib_noniso.h"
char* utoa(unsigned value, char* result, int base) { char* utoa(unsigned value, char* result, int base)
{
if(base < 2 || base > 16) { if(base < 2 || base > 16) {
*result = 0; *result = 0;
return result; return result;
@@ -44,7 +45,8 @@ char* utoa(unsigned value, char* result, int base) {
return result; return result;
} }
char* itoa(int value, char* result, int base) { char* itoa(int value, char* result, int base)
{
if(base < 2 || base > 16) { if(base < 2 || base > 16) {
*result = 0; *result = 0;
return result; return result;
@@ -70,21 +72,25 @@ char* itoa(int value, char* result, int base) {
return result; return result;
} }
int atoi(const char* s) { int atoi(const char* s)
{
return (int) atol(s); return (int) atol(s);
} }
long atol(const char* s) { long atol(const char* s)
{
char * tmp; char * tmp;
return strtol(s, &tmp, 10); return strtol(s, &tmp, 10);
} }
double atof(const char* s) { double atof(const char* s)
{
char * tmp; char * tmp;
return strtod(s, &tmp); return strtod(s, &tmp);
} }
void reverse(char* begin, char* end) { void reverse(char* begin, char* end)
{
char *is = begin; char *is = begin;
char *ie = end - 1; char *ie = end - 1;
while(is < ie) { while(is < ie) {
@@ -96,7 +102,8 @@ void reverse(char* begin, char* end) {
} }
} }
char* ltoa(long value, char* result, int base) { char* ltoa(long value, char* result, int base)
{
if(base < 2 || base > 16) { if(base < 2 || base > 16) {
*result = 0; *result = 0;
return result; return result;
@@ -122,7 +129,8 @@ char* ltoa(long value, char* result, int base) {
return result; return result;
} }
char* ultoa(unsigned long value, char* result, int base) { char* ultoa(unsigned long value, char* result, int base)
{
if(base < 2 || base > 16) { if(base < 2 || base > 16) {
*result = 0; *result = 0;
return result; return result;
@@ -143,7 +151,8 @@ char* ultoa(unsigned long value, char* result, int base) {
return result; return result;
} }
char* dtostrf (double val, signed char width, unsigned char prec, char *s) { char* dtostrf (double val, signed char width, unsigned char prec, char *s)
{
sprintf(s,"%*.*f", width, prec, val); sprintf(s,"%*.*f", width, prec, val);
return s; return s;
} }

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