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:
@@ -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
@@ -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
@@ -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
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+303
-308
@@ -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,137 +35,133 @@ 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 {
|
||||||
}
|
// Ground pin
|
||||||
else
|
hwPinMode(MY_W5100_SPI_EN, OUTPUT);
|
||||||
{
|
hwDigitalWrite(MY_W5100_SPI_EN, LOW);
|
||||||
// Ground pin
|
|
||||||
hwPinMode(MY_W5100_SPI_EN, OUTPUT);
|
|
||||||
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."));
|
||||||
_w5100_spi_en(true);
|
_w5100_spi_en(true);
|
||||||
presentNode();
|
presentNode();
|
||||||
} else {
|
} else {
|
||||||
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,240 +174,239 @@ 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."));
|
||||||
_w5100_spi_en(true);
|
_w5100_spi_en(true);
|
||||||
presentNode();
|
presentNode();
|
||||||
} else {
|
} else {
|
||||||
// connecting to the server failed!
|
// connecting to the server failed!
|
||||||
debug(PSTR("Eth: Failed to connect\n"));
|
debug(PSTR("Eth: Failed to connect\n"));
|
||||||
_w5100_spi_en(false);
|
_w5100_spi_en(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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
|
||||||
}
|
nbytes = _ethernetServer.write(_ethernetMsg);
|
||||||
#else
|
#endif
|
||||||
nbytes = _ethernetServer.write(_ethernetMsg);
|
#endif /* MY_GATEWAY_CLIENT_MODE */
|
||||||
#endif
|
|
||||||
#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()) {
|
{
|
||||||
char inChar = clients[i].read();
|
while (clients[i].connected() && clients[i].available()) {
|
||||||
if (inputString[i].idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) {
|
char inChar = clients[i].read();
|
||||||
// if newline then command is complete
|
if (inputString[i].idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) {
|
||||||
if (inChar == '\n' || inChar == '\r') {
|
// if newline then command is complete
|
||||||
// Add string terminator and prepare for the next message
|
if (inChar == '\n' || inChar == '\r') {
|
||||||
inputString[i].string[inputString[i].idx] = 0;
|
// Add string terminator and prepare for the next message
|
||||||
debug(PSTR("Client %d: %s\n"), i, inputString[i].string);
|
inputString[i].string[inputString[i].idx] = 0;
|
||||||
inputString[i].idx = 0;
|
debug(PSTR("Client %d: %s\n"), i, inputString[i].string);
|
||||||
if (protocolParse(_ethernetMsg, inputString[i].string)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// add it to the inputString:
|
|
||||||
inputString[i].string[inputString[i].idx++] = inChar;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Incoming message too long. Throw away
|
|
||||||
debug(PSTR("Client %d: Message too long\n"), i);
|
|
||||||
inputString[i].idx = 0;
|
inputString[i].idx = 0;
|
||||||
// Finished with this client's message. Next loop() we'll see if there's more to read.
|
if (protocolParse(_ethernetMsg, inputString[i].string)) {
|
||||||
break;
|
return true;
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
bool _readFromClient() {
|
|
||||||
while (client.connected() && client.available()) {
|
|
||||||
char inChar = client.read();
|
|
||||||
if (inputString.idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) {
|
|
||||||
// if newline then command is complete
|
|
||||||
if (inChar == '\n' || inChar == '\r') {
|
|
||||||
// Add string terminator and prepare for the next message
|
|
||||||
inputString.string[inputString.idx] = 0;
|
|
||||||
debug(PSTR("Eth: %s\n"), inputString.string);
|
|
||||||
inputString.idx = 0;
|
|
||||||
if (protocolParse(_ethernetMsg, inputString.string)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// add it to the inputString:
|
|
||||||
inputString.string[inputString.idx++] = inChar;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Incoming message too long. Throw away
|
// add it to the inputString:
|
||||||
debug(PSTR("Eth: Message too long\n"));
|
inputString[i].string[inputString[i].idx++] = inChar;
|
||||||
inputString.idx = 0;
|
|
||||||
// Finished with this client's message. Next loop() we'll see if there's more to read.
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Incoming message too long. Throw away
|
||||||
|
debug(PSTR("Client %d: Message too long\n"), i);
|
||||||
|
inputString[i].idx = 0;
|
||||||
|
// Finished with this client's message. Next loop() we'll see if there's more to read.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
bool _readFromClient()
|
||||||
|
{
|
||||||
|
while (client.connected() && client.available()) {
|
||||||
|
char inChar = client.read();
|
||||||
|
if (inputString.idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) {
|
||||||
|
// if newline then command is complete
|
||||||
|
if (inChar == '\n' || inChar == '\r') {
|
||||||
|
// Add string terminator and prepare for the next message
|
||||||
|
inputString.string[inputString.idx] = 0;
|
||||||
|
debug(PSTR("Eth: %s\n"), inputString.string);
|
||||||
|
inputString.idx = 0;
|
||||||
|
if (protocolParse(_ethernetMsg, inputString.string)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// add it to the inputString:
|
||||||
|
inputString.string[inputString.idx++] = inChar;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Incoming message too long. Throw away
|
||||||
|
debug(PSTR("Eth: Message too long\n"));
|
||||||
|
inputString.idx = 0;
|
||||||
|
// Finished with this client's message. Next loop() we'll see if there's more to read.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#endif
|
#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;
|
|
||||||
}
|
}
|
||||||
#elif defined(MY_GATEWAY_CLIENT_MODE)
|
return ok;
|
||||||
if (!client.connected()) {
|
}
|
||||||
client.stop();
|
#elif defined(MY_GATEWAY_CLIENT_MODE)
|
||||||
#if defined(MY_CONTROLLER_URL_ADDRESS)
|
if (!client.connected()) {
|
||||||
if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) {
|
client.stop();
|
||||||
#else
|
#if defined(MY_CONTROLLER_URL_ADDRESS)
|
||||||
if (client.connect(_ethernetControllerIP, MY_PORT)) {
|
if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) {
|
||||||
#endif
|
#else
|
||||||
debug(PSTR("Eth: connect\n"));
|
if (client.connect(_ethernetControllerIP, MY_PORT)) {
|
||||||
_w5100_spi_en(false);
|
#endif
|
||||||
|
debug(PSTR("Eth: connect\n"));
|
||||||
|
_w5100_spi_en(false);
|
||||||
|
gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete."));
|
||||||
|
_w5100_spi_en(true);
|
||||||
|
presentNode();
|
||||||
|
} else {
|
||||||
|
debug(PSTR("Eth: Failed to connect\n"));
|
||||||
|
_w5100_spi_en(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_readFromClient()) {
|
||||||
|
setIndication(INDICATION_GW_RX);
|
||||||
|
_w5100_spi_en(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_LINUX)
|
||||||
|
// ESP8266: Go over list of clients and stop any that are no longer connected.
|
||||||
|
// If the server has a new client connection it will be assigned to a free slot.
|
||||||
|
bool allSlotsOccupied = true;
|
||||||
|
for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) {
|
||||||
|
if (!clients[i].connected()) {
|
||||||
|
if (clientsConnected[i]) {
|
||||||
|
debug(PSTR("Client %d disconnected\n"), i);
|
||||||
|
clients[i].stop();
|
||||||
|
}
|
||||||
|
//check if there are any new clients
|
||||||
|
if (_ethernetServer.hasClient()) {
|
||||||
|
clients[i] = _ethernetServer.available();
|
||||||
|
inputString[i].idx = 0;
|
||||||
|
debug(PSTR("Client %d connected\n"), i);
|
||||||
gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete."));
|
gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete."));
|
||||||
_w5100_spi_en(true);
|
// Send presentation of locally attached sensors (and node if applicable)
|
||||||
presentNode();
|
presentNode();
|
||||||
} else {
|
|
||||||
debug(PSTR("Eth: Failed to connect\n"));
|
|
||||||
_w5100_spi_en(false);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_readFromClient()) {
|
bool connected = clients[i].connected();
|
||||||
|
clientsConnected[i] = connected;
|
||||||
|
allSlotsOccupied &= connected;
|
||||||
|
}
|
||||||
|
if (allSlotsOccupied && _ethernetServer.hasClient()) {
|
||||||
|
//no free/disconnected spot so reject
|
||||||
|
debug(PSTR("No free slot available\n"));
|
||||||
|
EthernetClient c = _ethernetServer.available();
|
||||||
|
c.stop();
|
||||||
|
}
|
||||||
|
// Loop over clients connect and read available data
|
||||||
|
for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) {
|
||||||
|
if (_readFromClient(i)) {
|
||||||
setIndication(INDICATION_GW_RX);
|
setIndication(INDICATION_GW_RX);
|
||||||
_w5100_spi_en(false);
|
_w5100_spi_en(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#else
|
}
|
||||||
#if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_LINUX)
|
#else
|
||||||
// ESP8266: Go over list of clients and stop any that are no longer connected.
|
// W5100/ENC module does not have hasClient-method. We can only serve one client at the time.
|
||||||
// If the server has a new client connection it will be assigned to a free slot.
|
EthernetClient newclient = _ethernetServer.available();
|
||||||
bool allSlotsOccupied = true;
|
// if a new client connects make sure to dispose any previous existing sockets
|
||||||
for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) {
|
if (newclient) {
|
||||||
if (!clients[i].connected()) {
|
if (client != newclient) {
|
||||||
if (clientsConnected[i]) {
|
client.stop();
|
||||||
debug(PSTR("Client %d disconnected\n"), i);
|
client = newclient;
|
||||||
clients[i].stop();
|
debug(PSTR("Eth: connect\n"));
|
||||||
}
|
_w5100_spi_en(false);
|
||||||
//check if there are any new clients
|
gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete."));
|
||||||
if (_ethernetServer.hasClient()) {
|
_w5100_spi_en(true);
|
||||||
clients[i] = _ethernetServer.available();
|
presentNode();
|
||||||
inputString[i].idx = 0;
|
}
|
||||||
debug(PSTR("Client %d connected\n"), i);
|
}
|
||||||
gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete."));
|
if (client) {
|
||||||
// Send presentation of locally attached sensors (and node if applicable)
|
if (!client.connected()) {
|
||||||
presentNode();
|
debug(PSTR("Eth: disconnect\n"));
|
||||||
}
|
client.stop();
|
||||||
}
|
} else {
|
||||||
bool connected = clients[i].connected();
|
if (_readFromClient()) {
|
||||||
clientsConnected[i] = connected;
|
setIndication(INDICATION_GW_RX);
|
||||||
allSlotsOccupied &= connected;
|
_w5100_spi_en(false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (allSlotsOccupied && _ethernetServer.hasClient()) {
|
}
|
||||||
//no free/disconnected spot so reject
|
}
|
||||||
debug(PSTR("No free slot available\n"));
|
#endif /* MY_GATEWAY_ESP8266 */
|
||||||
EthernetClient c = _ethernetServer.available();
|
#endif
|
||||||
c.stop();
|
|
||||||
}
|
|
||||||
// Loop over clients connect and read available data
|
|
||||||
for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) {
|
|
||||||
if (_readFromClient(i)) {
|
|
||||||
setIndication(INDICATION_GW_RX);
|
|
||||||
_w5100_spi_en(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// W5100/ENC module does not have hasClient-method. We can only serve one client at the time.
|
|
||||||
EthernetClient newclient = _ethernetServer.available();
|
|
||||||
// if a new client connects make sure to dispose any previous existing sockets
|
|
||||||
if (newclient) {
|
|
||||||
if (client != newclient) {
|
|
||||||
client.stop();
|
|
||||||
client = newclient;
|
|
||||||
debug(PSTR("Eth: connect\n"));
|
|
||||||
_w5100_spi_en(false);
|
|
||||||
gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete."));
|
|
||||||
_w5100_spi_en(true);
|
|
||||||
presentNode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (client) {
|
|
||||||
if (!client.connected()) {
|
|
||||||
debug(PSTR("Eth: disconnect\n"));
|
|
||||||
client.stop();
|
|
||||||
} else {
|
|
||||||
if (_readFromClient()) {
|
|
||||||
setIndication(INDICATION_GW_RX);
|
|
||||||
_w5100_spi_en(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* MY_GATEWAY_ESP8266 */
|
|
||||||
#endif
|
|
||||||
_w5100_spi_en(false);
|
_w5100_spi_en(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,19 +59,21 @@ 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
|
||||||
#if defined(MY_MQTT_USER) && defined(MY_MQTT_PASSWORD)
|
#if defined(MY_MQTT_USER) && defined(MY_MQTT_PASSWORD)
|
||||||
, MY_MQTT_USER, MY_MQTT_PASSWORD
|
, MY_MQTT_USER, MY_MQTT_PASSWORD
|
||||||
#endif
|
#endif
|
||||||
)) {
|
)) {
|
||||||
debug(PSTR("MQTT connected\n"));
|
debug(PSTR("MQTT connected\n"));
|
||||||
|
|
||||||
// Send presentation of locally attached sensors (and node if applicable)
|
// Send presentation of locally attached sensors (and node if applicable)
|
||||||
@@ -85,58 +88,60 @@ bool reconnectMQTT() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gatewayTransportConnect() {
|
bool gatewayTransportConnect()
|
||||||
#if defined(MY_GATEWAY_ESP8266)
|
{
|
||||||
while (WiFi.status() != WL_CONNECTED) {
|
#if defined(MY_GATEWAY_ESP8266)
|
||||||
wait(500);
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
MY_SERIALDEVICE.print(".");
|
wait(500);
|
||||||
}
|
MY_SERIALDEVICE.print(".");
|
||||||
MY_SERIALDEVICE.print("IP: ");
|
}
|
||||||
MY_SERIALDEVICE.println(WiFi.localIP());
|
MY_SERIALDEVICE.print("IP: ");
|
||||||
#elif defined(MY_GATEWAY_LINUX)
|
MY_SERIALDEVICE.println(WiFi.localIP());
|
||||||
#if defined(MY_IP_ADDRESS)
|
#elif defined(MY_GATEWAY_LINUX)
|
||||||
//TODO
|
#if defined(MY_IP_ADDRESS)
|
||||||
#endif
|
//TODO
|
||||||
#else
|
#endif
|
||||||
#ifdef MY_IP_ADDRESS
|
#else
|
||||||
Ethernet.begin(_MQTT_clientMAC, _MQTT_clientIp);
|
#ifdef MY_IP_ADDRESS
|
||||||
#else
|
Ethernet.begin(_MQTT_clientMAC, _MQTT_clientIp);
|
||||||
// Get IP address from DHCP
|
#else
|
||||||
if (!Ethernet.begin(_MQTT_clientMAC)) {
|
// Get IP address from DHCP
|
||||||
MY_SERIALDEVICE.print("DHCP FAILURE...");
|
if (!Ethernet.begin(_MQTT_clientMAC)) {
|
||||||
_MQTT_connecting = false;
|
MY_SERIALDEVICE.print("DHCP FAILURE...");
|
||||||
return false;
|
_MQTT_connecting = false;
|
||||||
}
|
return false;
|
||||||
#endif
|
}
|
||||||
MY_SERIALDEVICE.print("IP: ");
|
#endif
|
||||||
MY_SERIALDEVICE.println(Ethernet.localIP());
|
MY_SERIALDEVICE.print("IP: ");
|
||||||
// give the Ethernet interface a second to initialize
|
MY_SERIALDEVICE.println(Ethernet.localIP());
|
||||||
delay(1000);
|
// give the Ethernet interface a second to initialize
|
||||||
#endif
|
delay(1000);
|
||||||
|
#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,10 +149,11 @@ bool gatewayTransportInit() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gatewayTransportAvailable() {
|
bool gatewayTransportAvailable()
|
||||||
|
{
|
||||||
if (_MQTT_connecting) {
|
if (_MQTT_connecting) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//keep lease on dhcp address
|
//keep lease on dhcp address
|
||||||
//Ethernet.maintain();
|
//Ethernet.maintain();
|
||||||
if (!_MQTT_client.connected()) {
|
if (!_MQTT_client.connected()) {
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,11 +58,10 @@ 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;
|
|
||||||
return ok;
|
return ok;
|
||||||
} else {
|
} else {
|
||||||
// add it to the inputString:
|
// add it to the inputString:
|
||||||
@@ -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
@@ -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
|
||||||
|
|||||||
+126
-86
@@ -23,32 +23,33 @@
|
|||||||
|
|
||||||
#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;
|
||||||
}
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool interruptWakeUp()
|
bool interruptWakeUp()
|
||||||
{
|
{
|
||||||
return _wokeUpByInterrupt != INVALID_INTERRUPT_NUM;
|
return _wokeUpByInterrupt != INVALID_INTERRUPT_NUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Watchdog Timer interrupt service routine. This routine is required
|
// Watchdog Timer interrupt service routine. This routine is required
|
||||||
@@ -57,13 +58,13 @@ ISR (WDT_vect)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void hwPowerDown(period_t period) {
|
void hwPowerDown(period_t period)
|
||||||
|
{
|
||||||
// disable ADC for power saving
|
// 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,14 +75,14 @@ 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)
|
||||||
sleep_cpu();
|
sleep_cpu();
|
||||||
sleep_disable();
|
sleep_disable();
|
||||||
// restore previous WDT settings
|
// restore previous WDT settings
|
||||||
cli();
|
cli();
|
||||||
wdt_reset();
|
wdt_reset();
|
||||||
@@ -94,42 +95,77 @@ 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,
|
||||||
// Disable interrupts until going to sleep, otherwise interrupts occurring between attachInterrupt()
|
unsigned long ms)
|
||||||
// and sleep might cause the ATMega to not wakeup from sleep as interrupt has already be handled!
|
{
|
||||||
|
// Disable interrupts until going to sleep, otherwise interrupts occurring between attachInterrupt()
|
||||||
|
// and sleep might cause the ATMega to not wakeup from sleep as interrupt has already be handled!
|
||||||
cli();
|
cli();
|
||||||
// attach interrupts
|
// attach interrupts
|
||||||
_wakeUp1Interrupt = interrupt1;
|
_wakeUp1Interrupt = interrupt1;
|
||||||
_wakeUp2Interrupt = interrupt2;
|
_wakeUp2Interrupt = interrupt2;
|
||||||
if (interrupt1 != INVALID_INTERRUPT_NUM) {
|
if (interrupt1 != INVALID_INTERRUPT_NUM) {
|
||||||
attachInterrupt(interrupt1, wakeUp1, mode1);
|
attachInterrupt(interrupt1, wakeUp1, mode1);
|
||||||
}
|
}
|
||||||
if (interrupt2 != INVALID_INTERRUPT_NUM) {
|
if (interrupt2 != INVALID_INTERRUPT_NUM) {
|
||||||
attachInterrupt(interrupt2, wakeUp2, mode2);
|
attachInterrupt(interrupt2, wakeUp2, mode2);
|
||||||
}
|
}
|
||||||
@@ -139,40 +175,41 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo
|
|||||||
hwInternalSleep(ms);
|
hwInternalSleep(ms);
|
||||||
} else {
|
} else {
|
||||||
// sleep until ext interrupt triggered
|
// sleep until ext interrupt triggered
|
||||||
hwPowerDown(SLEEP_FOREVER);
|
hwPowerDown(SLEEP_FOREVER);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assure any interrupts attached, will get detached when they did not occur.
|
// Assure any interrupts attached, will get detached when they did not occur.
|
||||||
if (interrupt1 != INVALID_INTERRUPT_NUM) {
|
if (interrupt1 != INVALID_INTERRUPT_NUM) {
|
||||||
detachInterrupt(interrupt1);
|
detachInterrupt(interrupt1);
|
||||||
}
|
}
|
||||||
if (interrupt2 != INVALID_INTERRUPT_NUM) {
|
if (interrupt2 != INVALID_INTERRUPT_NUM) {
|
||||||
detachInterrupt(interrupt2);
|
detachInterrupt(interrupt2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return what woke the mcu.
|
// Return what woke the mcu.
|
||||||
int8_t ret = MY_WAKE_UP_BY_TIMER; // default: no interrupt triggered, timer wake up
|
int8_t ret = MY_WAKE_UP_BY_TIMER; // default: no interrupt triggered, timer wake up
|
||||||
if (interruptWakeUp()) {
|
if (interruptWakeUp()) {
|
||||||
ret = static_cast<int8_t>(_wokeUpByInterrupt);
|
ret = static_cast<int8_t>(_wokeUpByInterrupt);
|
||||||
}
|
}
|
||||||
// Clear woke-up-by-interrupt flag, so next sleeps won't return immediately.
|
// Clear woke-up-by-interrupt flag, so next sleeps won't return immediately.
|
||||||
_wokeUpByInterrupt = INVALID_INTERRUPT_NUM;
|
_wokeUpByInterrupt = INVALID_INTERRUPT_NUM;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#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();
|
||||||
|
|||||||
+15
-15
@@ -39,18 +39,18 @@
|
|||||||
#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" \
|
||||||
"out %[mcucr], %[tempreg]" "\n\t" \
|
"out %[mcucr], %[tempreg]" "\n\t" \
|
||||||
"andi %[tempreg], %[not_bodse]" "\n\t" \
|
"andi %[tempreg], %[not_bodse]" "\n\t" \
|
||||||
"out %[mcucr], %[tempreg]" \
|
"out %[mcucr], %[tempreg]" \
|
||||||
: [tempreg] "=&d" (tempreg) \
|
: [tempreg] "=&d" (tempreg) \
|
||||||
: [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
|
||||||
|
|||||||
+36
-29
@@ -31,12 +31,11 @@ void hwInit(void)
|
|||||||
|
|
||||||
void hwReadConfigBlock(void* buf, void* addr, size_t length)
|
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++);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hwWriteConfigBlock(void* buf, void* addr, size_t length)
|
void hwWriteConfigBlock(void* buf, void* addr, size_t length)
|
||||||
@@ -52,9 +51,9 @@ void hwWriteConfigBlock(void* buf, void* addr, size_t length)
|
|||||||
|
|
||||||
uint8_t hwReadConfig(const int addr)
|
uint8_t hwReadConfig(const int addr)
|
||||||
{
|
{
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
hwReadConfigBlock(&value, reinterpret_cast<void*>(addr), 1);
|
hwReadConfigBlock(&value, reinterpret_cast<void*>(addr), 1);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hwWriteConfig(const int addr, uint8_t value)
|
void hwWriteConfig(const int addr, uint8_t value)
|
||||||
@@ -63,13 +62,15 @@ void hwWriteConfig(const int addr, uint8_t value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int8_t hwSleep(unsigned long ms) {
|
int8_t hwSleep(unsigned long ms)
|
||||||
|
{
|
||||||
// TODO: Not supported!
|
// 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();
|
||||||
|
|||||||
+2
-2
@@ -54,11 +54,11 @@ uint8_t hwReadConfig(const int addr);
|
|||||||
*/
|
*/
|
||||||
static __inline__ void __psRestore(const uint32_t *__s)
|
static __inline__ void __psRestore(const uint32_t *__s)
|
||||||
{
|
{
|
||||||
xt_wsr_ps( *__s );
|
xt_wsr_ps( *__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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
+21
-19
@@ -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);
|
{
|
||||||
(void)__s;
|
pthread_mutex_unlock(&hw_mutex);
|
||||||
}
|
(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
|
||||||
|
|||||||
+30
-29
@@ -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
@@ -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();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+93
-83
@@ -42,107 +42,114 @@ 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;
|
{
|
||||||
Wire.beginTransmission(I2C_EEP_ADDRESS);
|
int rdata = data;
|
||||||
Wire.write((int)(eeaddress >> 8)); // MSB
|
Wire.beginTransmission(I2C_EEP_ADDRESS);
|
||||||
Wire.write((int)(eeaddress & 0xFF)); // LSB
|
Wire.write((int)(eeaddress >> 8)); // MSB
|
||||||
Wire.write(rdata);
|
Wire.write((int)(eeaddress & 0xFF)); // LSB
|
||||||
Wire.endTransmission();
|
Wire.write(rdata);
|
||||||
|
Wire.endTransmission();
|
||||||
}
|
}
|
||||||
|
|
||||||
byte i2c_eeprom_read_byte(unsigned int eeaddress ) {
|
byte i2c_eeprom_read_byte(unsigned int eeaddress )
|
||||||
byte rdata = 0xFF;
|
{
|
||||||
Wire.beginTransmission(I2C_EEP_ADDRESS);
|
byte rdata = 0xFF;
|
||||||
Wire.write((int)(eeaddress >> 8)); // MSB
|
Wire.beginTransmission(I2C_EEP_ADDRESS);
|
||||||
Wire.write((int)(eeaddress & 0xFF)); // LSB
|
Wire.write((int)(eeaddress >> 8)); // MSB
|
||||||
Wire.endTransmission();
|
Wire.write((int)(eeaddress & 0xFF)); // LSB
|
||||||
Wire.requestFrom(I2C_EEP_ADDRESS,1);
|
Wire.endTransmission();
|
||||||
if (Wire.available()) {
|
Wire.requestFrom(I2C_EEP_ADDRESS,1);
|
||||||
rdata = Wire.read();
|
if (Wire.available()) {
|
||||||
}
|
rdata = Wire.read();
|
||||||
return rdata;
|
}
|
||||||
|
return rdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hwReadConfigBlock(void* buf, void* adr, size_t length)
|
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++);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hwWriteConfigBlock(void* buf, void* adr, size_t length)
|
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++);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t hwReadConfig(int adr)
|
uint8_t hwReadConfig(int adr)
|
||||||
{
|
{
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
hwReadConfigBlock(&value, reinterpret_cast<void*>(adr), 1);
|
hwReadConfigBlock(&value, reinterpret_cast<void*>(adr), 1);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
{
|
||||||
#if defined(MY_GATEWAY_SERIAL)
|
MY_SERIALDEVICE.begin(MY_BAUD_RATE);
|
||||||
while (!MY_SERIALDEVICE) {}
|
#if defined(MY_GATEWAY_SERIAL)
|
||||||
#endif
|
while (!MY_SERIALDEVICE) {}
|
||||||
Wire.begin();
|
#endif
|
||||||
|
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!
|
{
|
||||||
(void)ms;
|
// TODO: Not supported!
|
||||||
return MY_SLEEP_NOT_POSSIBLE;
|
(void)ms;
|
||||||
|
return MY_SLEEP_NOT_POSSIBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) {
|
int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
|
||||||
// TODO: Not supported!
|
{
|
||||||
(void)interrupt;
|
// TODO: Not supported!
|
||||||
(void)mode;
|
(void)interrupt;
|
||||||
(void)ms;
|
(void)mode;
|
||||||
return MY_SLEEP_NOT_POSSIBLE;
|
(void)ms;
|
||||||
|
return MY_SLEEP_NOT_POSSIBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) {
|
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
|
||||||
// TODO: Not supported!
|
unsigned long ms)
|
||||||
(void)interrupt1;
|
{
|
||||||
(void)mode1;
|
// TODO: Not supported!
|
||||||
(void)interrupt2;
|
(void)interrupt1;
|
||||||
(void)mode2;
|
(void)mode1;
|
||||||
(void)ms;
|
(void)interrupt2;
|
||||||
return MY_SLEEP_NOT_POSSIBLE;
|
(void)mode2;
|
||||||
|
(void)ms;
|
||||||
|
return MY_SLEEP_NOT_POSSIBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#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,41 +185,44 @@ 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) {
|
{
|
||||||
char fmtBuffer[MY_SERIAL_OUTPUT_SIZE];
|
if (MY_SERIALDEVICE) {
|
||||||
#ifdef MY_GATEWAY_FEATURE
|
char fmtBuffer[MY_SERIAL_OUTPUT_SIZE];
|
||||||
|
#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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+4
-4
@@ -59,8 +59,8 @@ uint8_t hwReadConfig(int adr);
|
|||||||
*/
|
*/
|
||||||
static __inline__ uint8_t __disableIntsRetVal(void)
|
static __inline__ uint8_t __disableIntsRetVal(void)
|
||||||
{
|
{
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,11 +69,11 @@ static __inline__ uint8_t __disableIntsRetVal(void)
|
|||||||
*/
|
*/
|
||||||
static __inline__ void __priMaskRestore(const uint32_t *priMask)
|
static __inline__ void __priMaskRestore(const uint32_t *priMask)
|
||||||
{
|
{
|
||||||
__set_PRIMASK(*priMask);
|
__set_PRIMASK(*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
|
||||||
|
|||||||
+22
-19
@@ -19,41 +19,44 @@
|
|||||||
|
|
||||||
#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) {
|
{
|
||||||
_inclusionMode = newMode;
|
if (newMode != _inclusionMode) {
|
||||||
// Send back mode change to controller
|
_inclusionMode = newMode;
|
||||||
gatewayTransportSend(buildGw(_msgTmp, I_INCLUSION_MODE).set((uint8_t)(_inclusionMode?1:0)));
|
// Send back mode change to controller
|
||||||
if (_inclusionMode) {
|
gatewayTransportSend(buildGw(_msgTmp, I_INCLUSION_MODE).set((uint8_t)(_inclusionMode?1:0)));
|
||||||
_inclusionStartTime = hwMillis();
|
if (_inclusionMode) {
|
||||||
}
|
_inclusionStartTime = hwMillis();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
+13
-16
@@ -25,25 +25,22 @@
|
|||||||
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);
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
if (indication) {
|
if (indication) {
|
||||||
indication(ind);
|
indication(ind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-31
@@ -24,44 +24,44 @@
|
|||||||
* Indication type
|
* Indication type
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
INDICATION_TX = 0, //!< Sent a message.
|
INDICATION_TX = 0, //!< Sent a message.
|
||||||
INDICATION_RX, //!< Received a message.
|
INDICATION_RX, //!< Received a message.
|
||||||
|
|
||||||
INDICATION_GW_TX, //!< Gateway transmit message.
|
INDICATION_GW_TX, //!< Gateway transmit message.
|
||||||
INDICATION_GW_RX, //!< Gateway receive message.
|
INDICATION_GW_RX, //!< Gateway receive message.
|
||||||
|
|
||||||
INDICATION_FIND_PARENT, //!< Start finding parent node.
|
INDICATION_FIND_PARENT, //!< Start finding parent node.
|
||||||
INDICATION_GOT_PARENT, //!< Found parent node.
|
INDICATION_GOT_PARENT, //!< Found parent node.
|
||||||
INDICATION_REQ_NODEID, //!< Request node ID.
|
INDICATION_REQ_NODEID, //!< Request node ID.
|
||||||
INDICATION_GOT_NODEID, //!< Got a node ID.
|
INDICATION_GOT_NODEID, //!< Got a node ID.
|
||||||
INDICATION_CHECK_UPLINK, //!< Check uplink
|
INDICATION_CHECK_UPLINK, //!< Check uplink
|
||||||
INDICATION_REQ_REGISTRATION, //!< Request node registration.
|
INDICATION_REQ_REGISTRATION, //!< Request node registration.
|
||||||
INDICATION_GOT_REGISTRATION, //!< Got registration reponse.
|
INDICATION_GOT_REGISTRATION, //!< Got registration reponse.
|
||||||
INDICATION_REBOOT, //!< Rebooting node.
|
INDICATION_REBOOT, //!< Rebooting node.
|
||||||
INDICATION_PRESENT, //!< Presenting node to gateway.
|
INDICATION_PRESENT, //!< Presenting node to gateway.
|
||||||
INDICATION_CLEAR_ROUTING, //!< Clear routing table requested.
|
INDICATION_CLEAR_ROUTING, //!< Clear routing table requested.
|
||||||
INDICATION_SLEEP, //!< Node goes to sleep.
|
INDICATION_SLEEP, //!< Node goes to sleep.
|
||||||
INDICATION_WAKEUP, //!< Node just woke from sleep.
|
INDICATION_WAKEUP, //!< Node just woke from sleep.
|
||||||
INDICATION_FW_UPDATE_START, //!< Start of OTA firmware update process.
|
INDICATION_FW_UPDATE_START, //!< Start of OTA firmware update process.
|
||||||
INDICATION_FW_UPDATE_RX, //!< Received a piece of firmware data.
|
INDICATION_FW_UPDATE_RX, //!< Received a piece of firmware data.
|
||||||
|
|
||||||
INDICATION_ERR_START = 100,
|
INDICATION_ERR_START = 100,
|
||||||
INDICATION_ERR_TX, //!< Failed to transmit message.
|
INDICATION_ERR_TX, //!< Failed to transmit message.
|
||||||
INDICATION_ERR_TRANSPORT_FAILURE, //!< Transport failure.
|
INDICATION_ERR_TRANSPORT_FAILURE, //!< Transport failure.
|
||||||
INDICATION_ERR_INIT_TRANSPORT, //!< MySensors transport hardware (radio) init failure.
|
INDICATION_ERR_INIT_TRANSPORT, //!< MySensors transport hardware (radio) init failure.
|
||||||
INDICATION_ERR_FIND_PARENT, //!< Failed to find parent node.
|
INDICATION_ERR_FIND_PARENT, //!< Failed to find parent node.
|
||||||
INDICATION_ERR_GET_NODEID, //!< Failed to receive node ID.
|
INDICATION_ERR_GET_NODEID, //!< Failed to receive node ID.
|
||||||
INDICATION_ERR_CHECK_UPLINK, //!< Failed to check uplink
|
INDICATION_ERR_CHECK_UPLINK, //!< Failed to check uplink
|
||||||
INDICATION_ERR_SIGN, //!< Error signing.
|
INDICATION_ERR_SIGN, //!< Error signing.
|
||||||
INDICATION_ERR_LENGTH, //!< Invalid message length.
|
INDICATION_ERR_LENGTH, //!< Invalid message length.
|
||||||
INDICATION_ERR_VERSION, //!< Protocol version mismatch.
|
INDICATION_ERR_VERSION, //!< Protocol version mismatch.
|
||||||
INDICATION_ERR_NET_FULL, //!< Network full. All node ID's are taken.
|
INDICATION_ERR_NET_FULL, //!< Network full. All node ID's are taken.
|
||||||
INDICATION_ERR_INIT_GWTRANSPORT, //!< Gateway transport hardware init failure.
|
INDICATION_ERR_INIT_GWTRANSPORT, //!< Gateway transport hardware init failure.
|
||||||
INDICATION_ERR_LOCKED, //!< Node is locked.
|
INDICATION_ERR_LOCKED, //!< Node is locked.
|
||||||
INDICATION_ERR_FW_FLASH_INIT, //!< Firmware update flash initialisation failure.
|
INDICATION_ERR_FW_FLASH_INIT, //!< Firmware update flash initialisation failure.
|
||||||
INDICATION_ERR_FW_TIMEOUT, //!< Firmware update timeout.
|
INDICATION_ERR_FW_TIMEOUT, //!< Firmware update timeout.
|
||||||
INDICATION_ERR_FW_CHECKSUM, //!< Firmware update checksum mismatch.
|
INDICATION_ERR_FW_CHECKSUM, //!< Firmware update checksum mismatch.
|
||||||
INDICATION_ERR_END
|
INDICATION_ERR_END
|
||||||
} indication_t;
|
} indication_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+42
-36
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-21
@@ -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
|
||||||
|
|||||||
@@ -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(;;) {
|
||||||
|
|||||||
+32
-21
@@ -38,27 +38,31 @@ 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;
|
||||||
#else
|
#else
|
||||||
NULL;
|
NULL;
|
||||||
#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));
|
||||||
|
|
||||||
@@ -159,8 +170,8 @@ extern "C" void user_init(void) {
|
|||||||
cont_init(&g_cont);
|
cont_init(&g_cont);
|
||||||
|
|
||||||
ets_task(loop_task,
|
ets_task(loop_task,
|
||||||
LOOP_TASK_PRIORITY, g_loop_queue,
|
LOOP_TASK_PRIORITY, g_loop_queue,
|
||||||
LOOP_QUEUE_SIZE);
|
LOOP_QUEUE_SIZE);
|
||||||
|
|
||||||
system_init_done_cb(&init_done);
|
system_init_done_cb(&init_done);
|
||||||
}
|
}
|
||||||
|
|||||||
+86
-77
@@ -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();
|
||||||
|
|
||||||
@@ -103,19 +103,19 @@ static int daemonize(void)
|
|||||||
void print_usage()
|
void print_usage()
|
||||||
{
|
{
|
||||||
printf("Usage: mysgw [options]\n\n" \
|
printf("Usage: mysgw [options]\n\n" \
|
||||||
"Options:\n" \
|
"Options:\n" \
|
||||||
" -h, --help Display a short summary of all program options.\n" \
|
" -h, --help Display a short summary of all program options.\n" \
|
||||||
" -d, --debug Enable debug.\n" \
|
" -d, --debug Enable debug.\n" \
|
||||||
" -b, --background Run as a background process.\n"
|
" -b, --background Run as a background process.\n"
|
||||||
" --gen-soft-hmac-key Generate and print a soft hmac key.\n"
|
" --gen-soft-hmac-key Generate and print a soft hmac key.\n"
|
||||||
" --gen-soft-serial-key Generate and print a soft serial key.\n"
|
" --gen-soft-serial-key Generate and print a soft serial key.\n"
|
||||||
" --gen-aes-key Generate and print an aes encryption key.\n"
|
" --gen-aes-key Generate and print an aes encryption key.\n"
|
||||||
" --print-soft-hmac-key Print the soft hmac key from the config file.\n"
|
" --print-soft-hmac-key Print the soft hmac key from the config file.\n"
|
||||||
" --print-soft-serial-key Print the soft serial key from the config file.\n"
|
" --print-soft-serial-key Print the soft serial key from the config file.\n"
|
||||||
" --print-aes-key Print the aes encryption key from the config file.\n"
|
" --print-aes-key Print the aes encryption key from the config file.\n"
|
||||||
" --set-soft-hmac-key Write a soft hmac key to the config file.\n"
|
" --set-soft-hmac-key Write a soft hmac key to the config file.\n"
|
||||||
" --set-soft-serial-key Write a soft serial key to the config file.\n"
|
" --set-soft-serial-key Write a soft serial key to the config file.\n"
|
||||||
" --set-aes-key Write an aes encryption key to the config file.\n");
|
" --set-aes-key Write an aes encryption key to the config file.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_soft_sign_hmac_key(uint8_t *key_ptr = NULL)
|
void print_soft_sign_hmac_key(uint8_t *key_ptr = NULL)
|
||||||
@@ -137,7 +137,9 @@ void print_soft_sign_hmac_key(uint8_t *key_ptr = NULL)
|
|||||||
printf("#define MY_SOFT_HMAC_KEY ");
|
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");
|
||||||
}
|
}
|
||||||
@@ -155,7 +157,7 @@ void generate_soft_sign_hmac_key()
|
|||||||
print_soft_sign_hmac_key(key);
|
print_soft_sign_hmac_key(key);
|
||||||
|
|
||||||
printf("To use this key, run mysgw with:\n"
|
printf("To use this key, run mysgw with:\n"
|
||||||
" --set-soft-hmac-key=");
|
" --set-soft-hmac-key=");
|
||||||
for (int i = 0; i < 32; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
printf("%02X", key[i]);
|
printf("%02X", key[i]);
|
||||||
}
|
}
|
||||||
@@ -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");
|
||||||
}
|
}
|
||||||
@@ -227,7 +232,7 @@ void generate_soft_sign_serial_key()
|
|||||||
print_soft_sign_serial_key(key);
|
print_soft_sign_serial_key(key);
|
||||||
|
|
||||||
printf("To use this key, run mysgw with:\n"
|
printf("To use this key, run mysgw with:\n"
|
||||||
" --set-soft-serial-key=");
|
" --set-soft-serial-key=");
|
||||||
for (int i = 0; i < 9; i++) {
|
for (int i = 0; i < 9; i++) {
|
||||||
printf("%02X", key[i]);
|
printf("%02X", key[i]);
|
||||||
}
|
}
|
||||||
@@ -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");
|
||||||
}
|
}
|
||||||
@@ -299,7 +307,7 @@ void generate_aes_key()
|
|||||||
print_aes_key(key);
|
print_aes_key(key);
|
||||||
|
|
||||||
printf("To use this key, run mysgw with:\n"
|
printf("To use this key, run mysgw with:\n"
|
||||||
" --set-aes-key=");
|
" --set-aes-key=");
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
printf("%02X", key[i]);
|
printf("%02X", key[i]);
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
@@ -364,48 +373,48 @@ int main(int argc, char *argv[])
|
|||||||
int long_index = 0;
|
int long_index = 0;
|
||||||
while ((opt = getopt_long(argc, argv,"hdbABCDEFGHI", long_options, &long_index )) != -1) {
|
while ((opt = getopt_long(argc, argv,"hdbABCDEFGHI", long_options, &long_index )) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'h':
|
case 'h':
|
||||||
print_usage();
|
print_usage();
|
||||||
exit(0);
|
exit(0);
|
||||||
case 'd':
|
case 'd':
|
||||||
debug = 1;
|
debug = 1;
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
foreground = 0;
|
foreground = 0;
|
||||||
break;
|
break;
|
||||||
case 'A':
|
case 'A':
|
||||||
generate_soft_sign_hmac_key();
|
generate_soft_sign_hmac_key();
|
||||||
exit(0);
|
exit(0);
|
||||||
case 'B':
|
case 'B':
|
||||||
generate_soft_sign_serial_key();
|
generate_soft_sign_serial_key();
|
||||||
exit(0);
|
exit(0);
|
||||||
case 'C':
|
case 'C':
|
||||||
generate_aes_key();
|
generate_aes_key();
|
||||||
exit(0);
|
exit(0);
|
||||||
case 'D':
|
case 'D':
|
||||||
print_soft_sign_hmac_key();
|
print_soft_sign_hmac_key();
|
||||||
exit(0);
|
exit(0);
|
||||||
case 'E':
|
case 'E':
|
||||||
print_soft_sign_serial_key();
|
print_soft_sign_serial_key();
|
||||||
exit(0);
|
exit(0);
|
||||||
case 'F':
|
case 'F':
|
||||||
print_aes_key();
|
print_aes_key();
|
||||||
exit(0);
|
exit(0);
|
||||||
case 'G':
|
case 'G':
|
||||||
key = strdup(optarg);
|
key = strdup(optarg);
|
||||||
set_soft_sign_hmac_key(key);
|
set_soft_sign_hmac_key(key);
|
||||||
exit(0);
|
exit(0);
|
||||||
case 'H':
|
case 'H':
|
||||||
key = strdup(optarg);
|
key = strdup(optarg);
|
||||||
set_soft_sign_serial_key(key);
|
set_soft_sign_serial_key(key);
|
||||||
exit(0);
|
exit(0);
|
||||||
case 'I':
|
case 'I':
|
||||||
key = strdup(optarg);
|
key = strdup(optarg);
|
||||||
set_aes_key(key);
|
set_aes_key(key);
|
||||||
exit(0);
|
exit(0);
|
||||||
default:
|
default:
|
||||||
print_usage();
|
print_usage();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+66
-41
@@ -25,45 +25,49 @@
|
|||||||
|
|
||||||
MyMessage::MyMessage()
|
MyMessage::MyMessage()
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
MyMessage::MyMessage(uint8_t _sensor, uint8_t _type)
|
MyMessage::MyMessage(uint8_t _sensor, uint8_t _type)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
sensor = _sensor;
|
sensor = _sensor;
|
||||||
type = _type;
|
type = _type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyMessage::clear()
|
void MyMessage::clear()
|
||||||
{
|
{
|
||||||
last = 0u;
|
last = 0u;
|
||||||
sender = 0u;
|
sender = 0u;
|
||||||
destination = 0u; // Gateway is default destination
|
destination = 0u; // Gateway is default destination
|
||||||
version_length = 0u;
|
version_length = 0u;
|
||||||
command_ack_payload = 0u;
|
command_ack_payload = 0u;
|
||||||
type = 0u;
|
type = 0u;
|
||||||
sensor = 0u;
|
sensor = 0u;
|
||||||
(void)memset(data, 0u, sizeof(data));
|
(void)memset(data, 0u, sizeof(data));
|
||||||
|
|
||||||
// set message protocol version
|
// set message protocol version
|
||||||
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;
|
||||||
|
|||||||
+16
-17
@@ -151,11 +151,11 @@ typedef enum {
|
|||||||
V_POSITION = 49, //!< GPS position and altitude. Payload: latitude;longitude;altitude(m). E.g. "55.722526;13.017972;18"
|
V_POSITION = 49, //!< GPS position and altitude. Payload: latitude;longitude;altitude(m). E.g. "55.722526;13.017972;18"
|
||||||
V_IR_RECORD = 50, //!< Record IR codes S_IR for playback
|
V_IR_RECORD = 50, //!< Record IR codes S_IR for playback
|
||||||
V_PH = 51, //!< S_WATER_QUALITY, water PH
|
V_PH = 51, //!< S_WATER_QUALITY, water PH
|
||||||
V_ORP = 52, //!< S_WATER_QUALITY, water ORP : redox potential in mV
|
V_ORP = 52, //!< S_WATER_QUALITY, water ORP : redox potential in mV
|
||||||
V_EC = 53, //!< S_WATER_QUALITY, water electric conductivity μS/cm (microSiemens/cm)
|
V_EC = 53, //!< S_WATER_QUALITY, water electric conductivity μS/cm (microSiemens/cm)
|
||||||
V_VAR = 54, //!< S_POWER, Reactive power: volt-ampere reactive (var)
|
V_VAR = 54, //!< S_POWER, Reactive power: volt-ampere reactive (var)
|
||||||
V_VA = 55, //!< S_POWER, Apparent power: volt-ampere (VA)
|
V_VA = 55, //!< S_POWER, Apparent power: volt-ampere (VA)
|
||||||
V_POWER_FACTOR = 56, //!< S_POWER, Ratio of real power to apparent power: floating point value in the range [-1,..,1]
|
V_POWER_FACTOR = 56, //!< S_POWER, Ratio of real power to apparent power: floating point value in the range [-1,..,1]
|
||||||
} mysensor_data;
|
} mysensor_data;
|
||||||
|
|
||||||
|
|
||||||
@@ -284,10 +284,10 @@ public:
|
|||||||
|
|
||||||
char i2h(uint8_t i) const;
|
char i2h(uint8_t i) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear message contents.
|
* Clear message contents.
|
||||||
*/
|
*/
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If payload is something else than P_STRING you can have the payload value converted
|
* If payload is something else than P_STRING you can have the payload value converted
|
||||||
@@ -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
|
||||||
@@ -340,12 +339,12 @@ struct
|
|||||||
uint8_t destination; // 8 bit - Id of destination node
|
uint8_t destination; // 8 bit - Id of destination node
|
||||||
|
|
||||||
uint8_t version_length; // 2 bit - Protocol version
|
uint8_t version_length; // 2 bit - Protocol version
|
||||||
// 1 bit - Signed flag
|
// 1 bit - Signed flag
|
||||||
// 5 bit - Length of payload
|
// 5 bit - Length of payload
|
||||||
uint8_t command_ack_payload; // 3 bit - Command type
|
uint8_t command_ack_payload; // 3 bit - Command type
|
||||||
// 1 bit - Request an ack - Indicator that receiver should send an ack back.
|
// 1 bit - Request an ack - Indicator that receiver should send an ack back.
|
||||||
// 1 bit - Is ack messsage - Indicator that this is the actual ack message.
|
// 1 bit - Is ack messsage - Indicator that this is the actual ack message.
|
||||||
// 3 bit - Payload data type
|
// 3 bit - Payload data type
|
||||||
uint8_t type; // 8 bit - Type varies depending on command
|
uint8_t type; // 8 bit - Type varies depending on command
|
||||||
uint8_t sensor; // 8 bit - Id of sensor that this message concerns.
|
uint8_t sensor; // 8 bit - Id of sensor that this message concerns.
|
||||||
|
|
||||||
@@ -364,7 +363,7 @@ struct
|
|||||||
};
|
};
|
||||||
struct { // Presentation messages
|
struct { // Presentation messages
|
||||||
uint8_t version; // Library version
|
uint8_t version; // Library version
|
||||||
uint8_t sensorType; // Sensor type hint for controller, see table above
|
uint8_t sensorType; // Sensor type hint for controller, see table above
|
||||||
};
|
};
|
||||||
char data[MAX_PAYLOAD + 1];
|
char data[MAX_PAYLOAD + 1];
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -41,7 +42,7 @@ void firmwareOTAUpdateRequest(void)
|
|||||||
const uint32_t enterMS = hwMillis();
|
const uint32_t enterMS = hwMillis();
|
||||||
if (_firmwareUpdateOngoing && (enterMS - _firmwareLastRequest > MY_OTA_RETRY_DELAY)) {
|
if (_firmwareUpdateOngoing && (enterMS - _firmwareLastRequest > MY_OTA_RETRY_DELAY)) {
|
||||||
if (!_firmwareRetry) {
|
if (!_firmwareRetry) {
|
||||||
setIndication(INDICATION_ERR_FW_TIMEOUT);
|
setIndication(INDICATION_ERR_FW_TIMEOUT);
|
||||||
OTA_DEBUG(PSTR("!OTA:FRQ:FW UPD FAIL\n")); // fw update failed
|
OTA_DEBUG(PSTR("!OTA:FRQ:FW UPD FAIL\n")); // fw update failed
|
||||||
// Give up. We have requested MY_OTA_RETRY times without any packet in return.
|
// Give up. We have requested MY_OTA_RETRY times without any packet in return.
|
||||||
_firmwareUpdateOngoing = false;
|
_firmwareUpdateOngoing = false;
|
||||||
@@ -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)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,13 +68,13 @@ bool firmwareOTAUpdateProcess(void)
|
|||||||
nodeFirmwareConfig_t *firmwareConfigResponse = (nodeFirmwareConfig_t *)_msg.data;
|
nodeFirmwareConfig_t *firmwareConfigResponse = (nodeFirmwareConfig_t *)_msg.data;
|
||||||
// compare with current node configuration, if they differ, start FW fetch process
|
// compare with current node configuration, if they differ, start FW fetch process
|
||||||
if (memcmp(&_nodeFirmwareConfig, firmwareConfigResponse, sizeof(nodeFirmwareConfig_t))) {
|
if (memcmp(&_nodeFirmwareConfig, firmwareConfigResponse, sizeof(nodeFirmwareConfig_t))) {
|
||||||
setIndication(INDICATION_FW_UPDATE_START);
|
setIndication(INDICATION_FW_UPDATE_START);
|
||||||
OTA_DEBUG(PSTR("OTA:FWP:UPDATE\n")); // FW update initiated
|
OTA_DEBUG(PSTR("OTA:FWP:UPDATE\n")); // FW update initiated
|
||||||
// copy new FW config
|
// copy new FW config
|
||||||
(void)memcpy(&_nodeFirmwareConfig, firmwareConfigResponse, sizeof(nodeFirmwareConfig_t));
|
(void)memcpy(&_nodeFirmwareConfig, firmwareConfigResponse, sizeof(nodeFirmwareConfig_t));
|
||||||
// Init flash
|
// Init flash
|
||||||
if (!_flash.initialize()) {
|
if (!_flash.initialize()) {
|
||||||
setIndication(INDICATION_ERR_FW_FLASH_INIT);
|
setIndication(INDICATION_ERR_FW_FLASH_INIT);
|
||||||
OTA_DEBUG(PSTR("!OTA:FWP:FLASH INIT FAIL\n")); // failed to initialise flash
|
OTA_DEBUG(PSTR("!OTA:FWP:FLASH INIT FAIL\n")); // failed to initialise flash
|
||||||
_firmwareUpdateOngoing = false;
|
_firmwareUpdateOngoing = false;
|
||||||
} else {
|
} else {
|
||||||
@@ -91,12 +94,13 @@ bool firmwareOTAUpdateProcess(void)
|
|||||||
} else if (_msg.type == ST_FIRMWARE_RESPONSE) {
|
} else if (_msg.type == ST_FIRMWARE_RESPONSE) {
|
||||||
if (_firmwareUpdateOngoing) {
|
if (_firmwareUpdateOngoing) {
|
||||||
// Save block to flash
|
// Save block to flash
|
||||||
setIndication(INDICATION_FW_UPDATE_RX);
|
setIndication(INDICATION_FW_UPDATE_RX);
|
||||||
OTA_DEBUG(PSTR("OTA:FWP:RECV B=%04X\n"), _firmwareBlock); // received FW block
|
OTA_DEBUG(PSTR("OTA:FWP:RECV B=%04X\n"), _firmwareBlock); // received FW block
|
||||||
// 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),':'};
|
||||||
@@ -116,7 +121,7 @@ bool firmwareOTAUpdateProcess(void)
|
|||||||
while (_flash.busy()) {}
|
while (_flash.busy()) {}
|
||||||
hwReboot();
|
hwReboot();
|
||||||
} else {
|
} else {
|
||||||
setIndication(INDICATION_ERR_FW_CHECKSUM);
|
setIndication(INDICATION_ERR_FW_CHECKSUM);
|
||||||
OTA_DEBUG(PSTR("!OTA:FWP:CRC FAIL\n"));
|
OTA_DEBUG(PSTR("!OTA:FWP:CRC FAIL\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -36,48 +37,48 @@ bool protocolParse(MyMessage &message, char *inputString) {
|
|||||||
|
|
||||||
// Extract command data coming on serial line
|
// Extract command data coming on serial line
|
||||||
for (str = strtok_r(inputString, ";", &p); // split using semicolon
|
for (str = strtok_r(inputString, ";", &p); // split using semicolon
|
||||||
str && i < 6; // loop while str is not null an max 5 times
|
str && i < 6; // loop while str is not null an max 5 times
|
||||||
str = strtok_r(NULL, ";", &p) // get subsequent tokens
|
str = strtok_r(NULL, ";", &p) // get subsequent tokens
|
||||||
) {
|
) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0: // Radioid (destination)
|
case 0: // Radioid (destination)
|
||||||
message.destination = atoi(str);
|
message.destination = atoi(str);
|
||||||
break;
|
break;
|
||||||
case 1: // Childid
|
case 1: // Childid
|
||||||
message.sensor = atoi(str);
|
message.sensor = atoi(str);
|
||||||
break;
|
break;
|
||||||
case 2: // Message type
|
case 2: // Message type
|
||||||
command = atoi(str);
|
command = atoi(str);
|
||||||
mSetCommand(message, command);
|
mSetCommand(message, command);
|
||||||
break;
|
break;
|
||||||
case 3: // Should we request ack from destination?
|
case 3: // Should we request ack from destination?
|
||||||
mSetRequestAck(message, atoi(str)?1:0);
|
mSetRequestAck(message, atoi(str)?1:0);
|
||||||
break;
|
break;
|
||||||
case 4: // Data type
|
case 4: // Data type
|
||||||
message.type = atoi(str);
|
message.type = atoi(str);
|
||||||
break;
|
break;
|
||||||
case 5: // Variable value
|
case 5: // Variable value
|
||||||
if (command == C_STREAM) {
|
if (command == C_STREAM) {
|
||||||
blen = 0;
|
blen = 0;
|
||||||
uint8_t val;
|
uint8_t val;
|
||||||
while (*str) {
|
while (*str) {
|
||||||
val = protocolH2i(*str++) << 4;
|
val = protocolH2i(*str++) << 4;
|
||||||
val += protocolH2i(*str++);
|
val += protocolH2i(*str++);
|
||||||
bvalue[blen] = val;
|
bvalue[blen] = val;
|
||||||
blen++;
|
blen++;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
value = str;
|
|
||||||
// Remove trailing carriage return and newline character (if it exists)
|
|
||||||
uint8_t lastCharacter = strlen(value)-1;
|
|
||||||
if (value[lastCharacter] == '\r') {
|
|
||||||
value[lastCharacter] = 0;
|
|
||||||
}
|
|
||||||
if (value[lastCharacter] == '\n') {
|
|
||||||
value[lastCharacter] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
|
value = str;
|
||||||
|
// Remove trailing carriage return and newline character (if it exists)
|
||||||
|
uint8_t lastCharacter = strlen(value)-1;
|
||||||
|
if (value[lastCharacter] == '\r') {
|
||||||
|
value[lastCharacter] = 0;
|
||||||
|
}
|
||||||
|
if (value[lastCharacter] == '\n') {
|
||||||
|
value[lastCharacter] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -91,68 +92,74 @@ 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];
|
||||||
uint8_t blen = 0;
|
uint8_t blen = 0;
|
||||||
uint8_t command = 0;
|
uint8_t command = 0;
|
||||||
if (topic != strstr(topic, MY_MQTT_SUBSCRIBE_TOPIC_PREFIX)) {
|
if (topic != strstr(topic, MY_MQTT_SUBSCRIBE_TOPIC_PREFIX)) {
|
||||||
// Prefix doesn't match incoming topic
|
// Prefix doesn't match incoming topic
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (str = strtok_r(topic + strlen(MY_MQTT_SUBSCRIBE_TOPIC_PREFIX) + 1, "/", &p); str && i <= 5;
|
for (str = strtok_r(topic + strlen(MY_MQTT_SUBSCRIBE_TOPIC_PREFIX) + 1, "/", &p); str && i <= 5;
|
||||||
str = strtok_r(NULL, "/", &p)) {
|
str = strtok_r(NULL, "/", &p)) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0: {
|
case 0: {
|
||||||
// Node id
|
// Node id
|
||||||
message.destination = atoi(str);
|
message.destination = atoi(str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
// Sensor id
|
// Sensor id
|
||||||
message.sensor = atoi(str);
|
message.sensor = atoi(str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2: {
|
case 2: {
|
||||||
// Command type
|
// Command type
|
||||||
command = atoi(str);
|
command = atoi(str);
|
||||||
mSetCommand(message, command);
|
mSetCommand(message, command);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3: {
|
case 3: {
|
||||||
// Ack flag
|
// Ack flag
|
||||||
mSetRequestAck(message, atoi(str)?1:0);
|
mSetRequestAck(message, atoi(str)?1:0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4: {
|
case 4: {
|
||||||
// Sub type
|
// Sub type
|
||||||
message.type = atoi(str);
|
message.type = atoi(str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
+346
-313
@@ -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,47 +102,48 @@ 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
|
||||||
transportInitialise();
|
transportInitialise();
|
||||||
// Register transport=ready callback
|
// Register transport=ready callback
|
||||||
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()) {
|
||||||
setIndication(INDICATION_ERR_INIT_GWTRANSPORT);
|
setIndication(INDICATION_ERR_INIT_GWTRANSPORT);
|
||||||
CORE_DEBUG(PSTR("!MCO:BGN:TSP FAIL\n"));
|
CORE_DEBUG(PSTR("!MCO:BGN:TSP FAIL\n"));
|
||||||
// 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,213 +248,229 @@ 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)
|
{
|
||||||
(void)message;
|
#if defined(MY_CORE_ONLY)
|
||||||
#endif
|
(void)message;
|
||||||
#if defined(MY_GATEWAY_FEATURE)
|
#endif
|
||||||
if (message.destination == getNodeId()) {
|
#if defined(MY_GATEWAY_FEATURE)
|
||||||
// This is a message sent from a sensor attached on the gateway node.
|
if (message.destination == getNodeId()) {
|
||||||
// Pass it directly to the gateway transport layer.
|
// This is a message sent from a sensor attached on the gateway node.
|
||||||
return gatewayTransportSend(message);
|
// Pass it directly to the gateway transport layer.
|
||||||
}
|
return gatewayTransportSend(message);
|
||||||
#endif
|
}
|
||||||
#if defined(MY_SENSOR_NETWORK)
|
#endif
|
||||||
return transportSendRoute(message);
|
#if defined(MY_SENSOR_NETWORK)
|
||||||
#else
|
return transportSendRoute(message);
|
||||||
return false;
|
#else
|
||||||
#endif
|
return false;
|
||||||
|
#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);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
CORE_DEBUG(PSTR("!MCO:SND:NODE NOT REG\n")); // node not registered
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return _sendRoute(message);
|
return _sendRoute(message);
|
||||||
#endif
|
} else {
|
||||||
}
|
CORE_DEBUG(PSTR("!MCO:SND:NODE NOT REG\n")); // node not registered
|
||||||
|
|
||||||
bool sendBatteryLevel(const uint8_t value, const bool ack) {
|
|
||||||
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_BATTERY_LEVEL, ack).set(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sendHeartbeat(const bool ack) {
|
|
||||||
#if defined(MY_SENSOR_NETWORK)
|
|
||||||
const uint32_t heartbeat = transportGetHeartbeat();
|
|
||||||
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT_RESPONSE, ack).set(heartbeat));
|
|
||||||
#else
|
|
||||||
(void)ack;
|
|
||||||
return false;
|
return false;
|
||||||
#endif
|
}
|
||||||
|
#else
|
||||||
|
return _sendRoute(message);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool present(const uint8_t childSensorId, const uint8_t sensorType, const char *description, const bool ack) {
|
bool sendBatteryLevel(const uint8_t value, const bool ack)
|
||||||
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType, ack).set(childSensorId==NODE_SENSOR_ID?MYSENSORS_LIBRARY_VERSION:description));
|
{
|
||||||
|
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_BATTERY_LEVEL,
|
||||||
|
ack).set(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sendSketchInfo(const char *name, const char *version, const bool ack) {
|
bool sendHeartbeat(const bool ack)
|
||||||
|
{
|
||||||
|
#if defined(MY_SENSOR_NETWORK)
|
||||||
|
const uint32_t heartbeat = transportGetHeartbeat();
|
||||||
|
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT_RESPONSE,
|
||||||
|
ack).set(heartbeat));
|
||||||
|
#else
|
||||||
|
(void)ack;
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool present(const uint8_t childSensorId, const uint8_t sensorType, const char *description,
|
||||||
|
const bool ack)
|
||||||
|
{
|
||||||
|
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType,
|
||||||
|
ack).set(childSensorId==NODE_SENSOR_ID?MYSENSORS_LIBRARY_VERSION:description));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sendSketchInfo(const char *name, const char *version, const bool ack)
|
||||||
|
{
|
||||||
bool result = true;
|
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) {
|
||||||
}
|
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
|
||||||
else if (type == I_DEBUG) {
|
const char debug_msg = _msg.data[0];
|
||||||
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
|
if (debug_msg == 'R') { // routing table
|
||||||
const char debug_msg = _msg.data[0];
|
#if defined(MY_REPEATER_FEATURE)
|
||||||
if (debug_msg == 'R') { // routing table
|
for (uint16_t cnt = 0; cnt < SIZE_ROUTES; cnt++) {
|
||||||
#if defined(MY_REPEATER_FEATURE)
|
const uint8_t route = transportGetRoute(cnt);
|
||||||
for (uint16_t cnt = 0; cnt < SIZE_ROUTES; cnt++) {
|
if (route != BROADCAST_ADDRESS) {
|
||||||
const uint8_t route = transportGetRoute(cnt);
|
CORE_DEBUG(PSTR("MCO:PIM:ROUTE N=%d,R=%d\n"), cnt, route);
|
||||||
if (route != BROADCAST_ADDRESS) {
|
uint8_t outBuf[2] = { (uint8_t)cnt,route };
|
||||||
CORE_DEBUG(PSTR("MCO:PIM:ROUTE N=%d,R=%d\n"), cnt, route);
|
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(outBuf,
|
||||||
uint8_t outBuf[2] = { (uint8_t)cnt,route };
|
2));
|
||||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(outBuf, 2));
|
wait(200);
|
||||||
wait(200);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else if (debug_msg == 'V') { // CPU voltage
|
#endif
|
||||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(hwCPUVoltage()));
|
} else if (debug_msg == 'V') { // CPU voltage
|
||||||
|
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
|
||||||
|
I_DEBUG).set(hwCPUVoltage()));
|
||||||
|
} else if (debug_msg == 'F') { // CPU frequency in 1/10Mhz
|
||||||
|
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
|
||||||
|
I_DEBUG).set(hwCPUFrequency()));
|
||||||
|
} else if (debug_msg == 'M') { // free memory
|
||||||
|
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
|
||||||
|
I_DEBUG).set(hwFreeMem()));
|
||||||
|
} else if (debug_msg == 'E') { // clear MySensors eeprom area and reboot
|
||||||
|
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set("OK"));
|
||||||
|
for (int i = EEPROM_START; i<EEPROM_LOCAL_CONFIG_ADDRESS; i++) {
|
||||||
|
hwWriteConfig(i, 0xFF);
|
||||||
}
|
}
|
||||||
else if (debug_msg == 'F') { // CPU frequency in 1/10Mhz
|
setIndication(INDICATION_REBOOT);
|
||||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(hwCPUFrequency()));
|
hwReboot();
|
||||||
}
|
}
|
||||||
else if (debug_msg == 'M') { // free memory
|
#endif
|
||||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(hwFreeMem()));
|
} else {
|
||||||
}
|
return false;
|
||||||
else if (debug_msg == 'E') { // clear MySensors eeprom area and reboot
|
|
||||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set("OK"));
|
|
||||||
for (int i = EEPROM_START; i<EEPROM_LOCAL_CONFIG_ADDRESS; i++) {
|
|
||||||
hwWriteConfig(i, 0xFF);
|
|
||||||
}
|
|
||||||
setIndication(INDICATION_REBOOT);
|
|
||||||
hwReboot();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
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));
|
||||||
return false; // processing of this request via controller
|
#else
|
||||||
#endif
|
return false; // processing of this request via controller
|
||||||
#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,127 +482,138 @@ 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);
|
|
||||||
return MY_SLEEP_NOT_POSSIBLE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// repeater feature: sleeping not possible
|
|
||||||
#if defined(MY_REPEATER_FEATURE)
|
|
||||||
(void)smartSleep;
|
|
||||||
(void)interrupt1;
|
|
||||||
(void)mode1;
|
|
||||||
(void)interrupt2;
|
|
||||||
(void)mode2;
|
|
||||||
|
|
||||||
CORE_DEBUG(PSTR("!MCO:SLP:REP\n")); // sleeping not possible, repeater feature enabled
|
|
||||||
wait(sleepingMS);
|
wait(sleepingMS);
|
||||||
return MY_SLEEP_NOT_POSSIBLE;
|
return MY_SLEEP_NOT_POSSIBLE;
|
||||||
#else
|
}
|
||||||
uint32_t sleepingTimeMS = sleepingMS;
|
#endif
|
||||||
#if defined(MY_SENSOR_NETWORK)
|
// repeater feature: sleeping not possible
|
||||||
// Do not sleep if transport not ready
|
#if defined(MY_REPEATER_FEATURE)
|
||||||
if (!isTransportReady()) {
|
(void)smartSleep;
|
||||||
CORE_DEBUG(PSTR("!MCO:SLP:TNR\n")); // sleeping not possible, transport not ready
|
(void)interrupt1;
|
||||||
const uint32_t sleepEnterMS = hwMillis();
|
(void)mode1;
|
||||||
uint32_t sleepDeltaMS = 0;
|
(void)interrupt2;
|
||||||
while (!isTransportReady() && (sleepDeltaMS < sleepingTimeMS) && (sleepDeltaMS < MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS)) {
|
(void)mode2;
|
||||||
_process();
|
|
||||||
sleepDeltaMS = hwMillis() - sleepEnterMS;
|
|
||||||
}
|
|
||||||
// sleep remainder
|
|
||||||
if (sleepDeltaMS < sleepingTimeMS) {
|
|
||||||
sleepingTimeMS -= sleepDeltaMS; // calculate remaining sleeping time
|
|
||||||
CORE_DEBUG(PSTR("MCO:SLP:MS=%lu\n"), sleepingTimeMS);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// no sleeping time left
|
|
||||||
return MY_SLEEP_NOT_POSSIBLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (smartSleep) {
|
CORE_DEBUG(PSTR("!MCO:SLP:REP\n")); // sleeping not possible, repeater feature enabled
|
||||||
// notify controller about going to sleep
|
wait(sleepingMS);
|
||||||
(void)sendHeartbeat();
|
return MY_SLEEP_NOT_POSSIBLE;
|
||||||
wait(MY_SMART_SLEEP_WAIT_DURATION_MS); // listen for incoming messages
|
#else
|
||||||
|
uint32_t sleepingTimeMS = sleepingMS;
|
||||||
|
#if defined(MY_SENSOR_NETWORK)
|
||||||
|
// Do not sleep if transport not ready
|
||||||
|
if (!isTransportReady()) {
|
||||||
|
CORE_DEBUG(PSTR("!MCO:SLP:TNR\n")); // sleeping not possible, transport not ready
|
||||||
|
const uint32_t sleepEnterMS = hwMillis();
|
||||||
|
uint32_t sleepDeltaMS = 0;
|
||||||
|
while (!isTransportReady() && (sleepDeltaMS < sleepingTimeMS) &&
|
||||||
|
(sleepDeltaMS < MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS)) {
|
||||||
|
_process();
|
||||||
|
sleepDeltaMS = hwMillis() - sleepEnterMS;
|
||||||
}
|
}
|
||||||
|
// sleep remainder
|
||||||
#if defined(MY_SENSOR_NETWORK)
|
if (sleepDeltaMS < sleepingTimeMS) {
|
||||||
CORE_DEBUG(PSTR("MCO:SLP:TPD\n")); // sleep, power down transport
|
sleepingTimeMS -= sleepDeltaMS; // calculate remaining sleeping time
|
||||||
transportPowerDown();
|
CORE_DEBUG(PSTR("MCO:SLP:MS=%lu\n"), sleepingTimeMS);
|
||||||
#endif
|
} else {
|
||||||
|
// no sleeping time left
|
||||||
#if defined (MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN)
|
return MY_SLEEP_NOT_POSSIBLE;
|
||||||
// Wait until leds finish their blinking pattern
|
|
||||||
while (ledsBlinking()) {
|
|
||||||
doYield();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
setIndication(INDICATION_SLEEP);
|
|
||||||
|
|
||||||
int8_t result = MY_SLEEP_NOT_POSSIBLE; // default
|
|
||||||
|
|
||||||
if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 != INTERRUPT_NOT_DEFINED) {
|
|
||||||
// both IRQs
|
|
||||||
result = hwSleep(interrupt1, mode1, interrupt2, mode2, sleepingTimeMS);
|
|
||||||
}
|
|
||||||
else if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) {
|
|
||||||
// one IRQ
|
|
||||||
result = hwSleep(interrupt1, mode1, sleepingTimeMS);
|
|
||||||
}
|
|
||||||
else if (interrupt1 == INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) {
|
|
||||||
// no IRQ
|
|
||||||
result = hwSleep(sleepingTimeMS);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
setIndication(INDICATION_WAKEUP);
|
if (smartSleep) {
|
||||||
CORE_DEBUG(PSTR("MCO:SLP:WUP=%d\n"), result); // sleep wake-up
|
// notify controller about going to sleep
|
||||||
return result;
|
(void)sendHeartbeat();
|
||||||
#endif
|
wait(MY_SMART_SLEEP_WAIT_DURATION_MS); // listen for incoming messages
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(MY_SENSOR_NETWORK)
|
||||||
|
CORE_DEBUG(PSTR("MCO:SLP:TPD\n")); // sleep, power down transport
|
||||||
|
transportPowerDown();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined (MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN)
|
||||||
|
// Wait until leds finish their blinking pattern
|
||||||
|
while (ledsBlinking()) {
|
||||||
|
doYield();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
setIndication(INDICATION_SLEEP);
|
||||||
|
|
||||||
|
int8_t result = MY_SLEEP_NOT_POSSIBLE; // default
|
||||||
|
|
||||||
|
if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 != INTERRUPT_NOT_DEFINED) {
|
||||||
|
// both IRQs
|
||||||
|
result = hwSleep(interrupt1, mode1, interrupt2, mode2, sleepingTimeMS);
|
||||||
|
} else if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) {
|
||||||
|
// one IRQ
|
||||||
|
result = hwSleep(interrupt1, mode1, sleepingTimeMS);
|
||||||
|
} else if (interrupt1 == INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) {
|
||||||
|
// no IRQ
|
||||||
|
result = hwSleep(sleepingTimeMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
setIndication(INDICATION_WAKEUP);
|
||||||
|
CORE_DEBUG(PSTR("MCO:SLP:WUP=%d\n"), result); // sleep wake-up
|
||||||
|
return result;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// sleep functions
|
// 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
@@ -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;
|
||||||
|
|||||||
+115
-105
@@ -82,22 +82,24 @@ 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_ID_REQUEST || msg.type == I_ID_RESPONSE ||
|
msg.type == I_SIGNING_PRESENTATION ||
|
||||||
msg.type == I_FIND_PARENT_REQUEST || msg.type == I_FIND_PARENT_RESPONSE ||
|
msg.type == I_ID_REQUEST || msg.type == I_ID_RESPONSE ||
|
||||||
msg.type == I_HEARTBEAT_REQUEST || msg.type == I_HEARTBEAT_RESPONSE ||
|
msg.type == I_FIND_PARENT_REQUEST || msg.type == I_FIND_PARENT_RESPONSE ||
|
||||||
msg.type == I_PING || msg.type == I_PONG ||
|
msg.type == I_HEARTBEAT_REQUEST || msg.type == I_HEARTBEAT_RESPONSE ||
|
||||||
msg.type == I_REGISTRATION_REQUEST )) {
|
msg.type == I_PING || msg.type == I_PONG ||
|
||||||
|
msg.type == I_REGISTRATION_REQUEST )) {
|
||||||
SIGN_DEBUG(PSTR("Skipping security for command %d type %d\n"), mGetCommand(msg), msg.type);
|
SIGN_DEBUG(PSTR("Skipping security for command %d type %d\n"), mGetCommand(msg), msg.type);
|
||||||
return true;
|
return true;
|
||||||
} else if (mGetCommand(msg) == C_STREAM &&
|
} else if (mGetCommand(msg) == C_STREAM &&
|
||||||
(msg.type == ST_FIRMWARE_REQUEST || msg.type == ST_FIRMWARE_RESPONSE ||
|
(msg.type == ST_FIRMWARE_REQUEST || msg.type == ST_FIRMWARE_RESPONSE ||
|
||||||
msg.type == ST_SOUND || msg.type == ST_IMAGE)) {
|
msg.type == ST_SOUND || msg.type == ST_IMAGE)) {
|
||||||
SIGN_DEBUG(PSTR("Skipping security for command %d type %d\n"), mGetCommand(msg), msg.type);
|
SIGN_DEBUG(PSTR("Skipping security for command %d type %d\n"), mGetCommand(msg), msg.type);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -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,15 +119,16 @@ 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,
|
||||||
sizeof(_doSign));
|
sizeof(_doSign));
|
||||||
|
|
||||||
// Read out the whitelist requirements from EEPROM
|
// Read out the whitelist requirements from EEPROM
|
||||||
hwReadConfigBlock((void*)_doWhitelist, (void*)EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS,
|
hwReadConfigBlock((void*)_doWhitelist, (void*)EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS,
|
||||||
sizeof(_doWhitelist));
|
sizeof(_doWhitelist));
|
||||||
|
|
||||||
#if defined(MY_SIGNING_SOFT)
|
#if defined(MY_SIGNING_SOFT)
|
||||||
signerAtsha204SoftInit();
|
signerAtsha204SoftInit();
|
||||||
@@ -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,8 +172,9 @@ bool signerProcessInternal(MyMessage &msg) {
|
|||||||
// If we act as gateway and do not have the signing feature and receive a signing request we still
|
// 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(
|
||||||
sender);
|
PSTR("Informing node %d that we do not require signatures because we do not support it\n"),
|
||||||
|
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
|
||||||
}
|
}
|
||||||
@@ -192,113 +200,113 @@ bool signerProcessInternal(MyMessage &msg) {
|
|||||||
if (signerAtsha204SoftGetNonce(msg)) {
|
if (signerAtsha204SoftGetNonce(msg)) {
|
||||||
#endif
|
#endif
|
||||||
#if defined(MY_SIGNING_ATSHA204)
|
#if defined(MY_SIGNING_ATSHA204)
|
||||||
if (signerAtsha204GetNonce(msg)) {
|
if (signerAtsha204GetNonce(msg)) {
|
||||||
#endif
|
#endif
|
||||||
if (!_sendRoute(build(msg, msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_NONCE_RESPONSE))) {
|
if (!_sendRoute(build(msg, msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_NONCE_RESPONSE))) {
|
||||||
SIGN_DEBUG(PSTR("Failed to transmit nonce!\n"));
|
SIGN_DEBUG(PSTR("Failed to transmit nonce!\n"));
|
||||||
|
} else {
|
||||||
|
SIGN_DEBUG(PSTR("Transmitted nonce\n"));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
SIGN_DEBUG(PSTR("Transmitted nonce\n"));
|
SIGN_DEBUG(PSTR("Failed to generate nonce!\n"));
|
||||||
|
}
|
||||||
|
return true; // No need to further process I_NONCE_REQUEST
|
||||||
|
} else if (msg.type == I_SIGNING_PRESENTATION) {
|
||||||
|
if (msg.data[0] != SIGNING_PRESENTATION_VERSION_1) {
|
||||||
|
SIGN_DEBUG(PSTR("Unsupported signing presentation version (%d)!\n"), msg.data[0]);
|
||||||
|
return true; // Just drop this presentation message
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
SIGN_DEBUG(PSTR("Failed to generate nonce!\n"));
|
|
||||||
}
|
|
||||||
return true; // No need to further process I_NONCE_REQUEST
|
|
||||||
} else if (msg.type == I_SIGNING_PRESENTATION) {
|
|
||||||
if (msg.data[0] != SIGNING_PRESENTATION_VERSION_1) {
|
|
||||||
SIGN_DEBUG(PSTR("Unsupported signing presentation version (%d)!\n"), msg.data[0]);
|
|
||||||
return true; // Just drop this presentation message
|
|
||||||
}
|
|
||||||
// We only handle version 1 here...
|
// We only handle version 1 here...
|
||||||
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) {
|
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) {
|
||||||
// We received an indicator that the sender require us to sign all messages we send to it
|
// We received an indicator that the sender require us to sign all messages we send to it
|
||||||
SIGN_DEBUG(PSTR("Mark node %d as one that require signed messages\n"), msg.sender);
|
SIGN_DEBUG(PSTR("Mark node %d as one that require signed messages\n"), msg.sender);
|
||||||
SET_SIGN(msg.sender);
|
SET_SIGN(msg.sender);
|
||||||
} else {
|
} else {
|
||||||
// We received an indicator that the sender does not require us to sign all messages we send to it
|
// We received an indicator that the sender does not require us to sign all messages we send to it
|
||||||
SIGN_DEBUG(PSTR("Mark node %d as one that do not require signed messages\n"), msg.sender);
|
SIGN_DEBUG(PSTR("Mark node %d as one that do not require signed messages\n"), msg.sender);
|
||||||
CLEAR_SIGN(msg.sender);
|
CLEAR_SIGN(msg.sender);
|
||||||
}
|
}
|
||||||
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) {
|
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) {
|
||||||
// We received an indicator that the sender require us to salt signatures with serial
|
// We received an indicator that the sender require us to salt signatures with serial
|
||||||
SIGN_DEBUG(PSTR("Mark node %d as one that require whitelisting\n"), msg.sender);
|
SIGN_DEBUG(PSTR("Mark node %d as one that require whitelisting\n"), msg.sender);
|
||||||
SET_WHITELIST(msg.sender);
|
SET_WHITELIST(msg.sender);
|
||||||
} else {
|
} else {
|
||||||
// We received an indicator that the sender does not require us to sign all messages we send to it
|
// We received an indicator that the sender does not require us to sign all messages we send to it
|
||||||
SIGN_DEBUG(PSTR("Mark node %d as one that do not require whitelisting\n"), msg.sender);
|
SIGN_DEBUG(PSTR("Mark node %d as one that do not require whitelisting\n"), msg.sender);
|
||||||
CLEAR_WHITELIST(msg.sender);
|
CLEAR_WHITELIST(msg.sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save updated tables
|
// Save updated tables
|
||||||
hwWriteConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS,
|
hwWriteConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS,
|
||||||
sizeof(_doSign));
|
sizeof(_doSign));
|
||||||
hwWriteConfigBlock((void*)_doWhitelist, (void*)EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS,
|
hwWriteConfigBlock((void*)_doWhitelist, (void*)EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS,
|
||||||
sizeof(_doWhitelist));
|
sizeof(_doWhitelist));
|
||||||
|
|
||||||
// Inform sender about our preference if we are a gateway, but only require signing if the sender
|
// Inform sender about our preference if we are a gateway, but only require signing if the sender
|
||||||
// required signing unless we explicitly configure it to
|
// required signing unless we explicitly configure it to
|
||||||
// We do not want a gateway to require signing from all nodes in a network just because it wants one node
|
// We do not want a gateway to require signing from all nodes in a network just because it wants one node
|
||||||
// to sign it's messages unless we explicitly configure it to
|
// to sign it's messages unless we explicitly configure it to
|
||||||
#if defined(MY_GATEWAY_FEATURE)
|
#if defined(MY_GATEWAY_FEATURE)
|
||||||
prepareSigningPresentation(msg, sender);
|
prepareSigningPresentation(msg, sender);
|
||||||
#if defined(MY_SIGNING_REQUEST_SIGNATURES)
|
#if defined(MY_SIGNING_REQUEST_SIGNATURES)
|
||||||
if (DO_SIGN(sender)) {
|
if (DO_SIGN(sender)) {
|
||||||
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
|
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
|
||||||
}
|
}
|
||||||
#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL)
|
#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL)
|
||||||
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
|
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if defined(MY_SIGNING_NODE_WHITELISTING)
|
#if defined(MY_SIGNING_NODE_WHITELISTING)
|
||||||
if (DO_WHITELIST(sender)) {
|
if (DO_WHITELIST(sender)) {
|
||||||
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING;
|
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING;
|
||||||
}
|
}
|
||||||
#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL)
|
#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL)
|
||||||
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING;
|
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) {
|
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) {
|
||||||
SIGN_DEBUG(PSTR("Informing node %d that we require signatures\n"), sender);
|
SIGN_DEBUG(PSTR("Informing node %d that we require signatures\n"), sender);
|
||||||
} else {
|
} else {
|
||||||
SIGN_DEBUG(PSTR("Informing node %d that we do not require signatures\n"), sender);
|
SIGN_DEBUG(PSTR("Informing node %d that we do not require signatures\n"), sender);
|
||||||
}
|
}
|
||||||
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) {
|
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) {
|
||||||
SIGN_DEBUG(PSTR("Informing node %d that we require whitelisting\n"), sender);
|
SIGN_DEBUG(PSTR("Informing node %d that we require whitelisting\n"), sender);
|
||||||
} else {
|
} else {
|
||||||
SIGN_DEBUG(PSTR("Informing node %d that we do not require whitelisting\n"), sender);
|
SIGN_DEBUG(PSTR("Informing node %d that we do not require whitelisting\n"), 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"));
|
||||||
}
|
}
|
||||||
#endif // MY_GATEWAY_FEATURE
|
#endif // MY_GATEWAY_FEATURE
|
||||||
return true; // No need to further process I_SIGNING_PRESENTATION
|
return true; // No need to further process I_SIGNING_PRESENTATION
|
||||||
} else if (msg.type == I_NONCE_RESPONSE) {
|
} else if (msg.type == I_NONCE_RESPONSE) {
|
||||||
// Proceed with signing if nonce has been received
|
// Proceed with signing if nonce has been received
|
||||||
SIGN_DEBUG(PSTR("Nonce received from %d. Proceeding with signing...\n"), sender);
|
SIGN_DEBUG(PSTR("Nonce received from %d. Proceeding with signing...\n"), sender);
|
||||||
if (sender != _msgSign.destination) {
|
if (sender != _msgSign.destination) {
|
||||||
SIGN_DEBUG(PSTR("Nonce did not come from the destination (%d) of the message to be signed! "
|
SIGN_DEBUG(PSTR("Nonce did not come from the destination (%d) of the message to be signed! "
|
||||||
"It came from %d.\n"), _msgSign.destination, sender);
|
"It came from %d.\n"), _msgSign.destination, sender);
|
||||||
SIGN_DEBUG(PSTR("Silently discarding this nonce\n"));
|
SIGN_DEBUG(PSTR("Silently discarding this nonce\n"));
|
||||||
return true; // No need to further process I_NONCE_RESPONSE
|
return true; // No need to further process I_NONCE_RESPONSE
|
||||||
}
|
}
|
||||||
#if defined(MY_SIGNING_SOFT)
|
#if defined(MY_SIGNING_SOFT)
|
||||||
signerAtsha204SoftPutNonce(msg);
|
signerAtsha204SoftPutNonce(msg);
|
||||||
#endif
|
#endif
|
||||||
#if defined(MY_SIGNING_ATSHA204)
|
#if defined(MY_SIGNING_ATSHA204)
|
||||||
signerAtsha204PutNonce(msg);
|
signerAtsha204PutNonce(msg);
|
||||||
#endif
|
#endif
|
||||||
#if defined(MY_SIGNING_SOFT)
|
#if defined(MY_SIGNING_SOFT)
|
||||||
if (!signerAtsha204SoftSignMsg(_msgSign)) {
|
if (!signerAtsha204SoftSignMsg(_msgSign)) {
|
||||||
#endif
|
#endif
|
||||||
#if defined(MY_SIGNING_ATSHA204)
|
#if defined(MY_SIGNING_ATSHA204)
|
||||||
if (!signerAtsha204SignMsg(_msgSign)) {
|
if (!signerAtsha204SignMsg(_msgSign)) {
|
||||||
#endif
|
#endif
|
||||||
SIGN_DEBUG(PSTR("Failed to sign message!\n"));
|
SIGN_DEBUG(PSTR("Failed to sign message!\n"));
|
||||||
} else {
|
} else {
|
||||||
SIGN_DEBUG(PSTR("Message signed\n"));
|
SIGN_DEBUG(PSTR("Message signed\n"));
|
||||||
_signingNonceStatus = SIGN_OK; // _msgSign now contains the signed message pending transmission
|
_signingNonceStatus = SIGN_OK; // _msgSign now contains the signed message pending transmission
|
||||||
}
|
}
|
||||||
return true; // No need to further process I_NONCE_RESPONSE
|
return true; // No need to further process I_NONCE_RESPONSE
|
||||||
}
|
}
|
||||||
#endif // MY_SIGNING_FEATURE
|
#endif // MY_SIGNING_FEATURE
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
+60
-39
@@ -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,14 +107,15 @@ 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
|
||||||
// This 32-byte random value is then hashed (SHA256) to produce the resulting nonce
|
// This 32-byte random value is then hashed (SHA256) to produce the resulting nonce
|
||||||
(void)atsha204_wakeup(_signing_temp_message);
|
(void)atsha204_wakeup(_signing_temp_message);
|
||||||
if (atsha204_execute(SHA204_RANDOM, RANDOM_SEED_UPDATE, 0, 0, NULL,
|
if (atsha204_execute(SHA204_RANDOM, RANDOM_SEED_UPDATE, 0, 0, NULL,
|
||||||
RANDOM_COUNT, _signing_tx_buffer, RANDOM_RSP_SIZE, _signing_rx_buffer) != SHA204_SUCCESS) {
|
RANDOM_COUNT, _signing_tx_buffer, RANDOM_RSP_SIZE, _signing_rx_buffer) != SHA204_SUCCESS) {
|
||||||
DEBUG_SIGNING_PRINTBUF(F("Failed to generate nonce"), NULL, 0);
|
DEBUG_SIGNING_PRINTBUF(F("Failed to generate nonce"), NULL, 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -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,42 +257,49 @@ 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: "),
|
||||||
WRITE_COUNT_LONG, _signing_tx_buffer, WRITE_RSP_SIZE, _signing_rx_buffer);
|
signing ? _signing_signing_nonce : _signing_verifying_nonce, 32);
|
||||||
|
(void)atsha204_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, 8 << 3, 32,
|
||||||
|
_signing_temp_message,
|
||||||
|
WRITE_COUNT_LONG, _signing_tx_buffer, WRITE_RSP_SIZE, _signing_rx_buffer);
|
||||||
|
|
||||||
// Program the nonce to use for the signature (has to be done just before GENDIG due to chip limitations)
|
// Program the nonce to use for the signature (has to be done just before GENDIG due to chip limitations)
|
||||||
(void)atsha204_execute(SHA204_NONCE, NONCE_MODE_PASSTHROUGH, 0, NONCE_NUMIN_SIZE_PASSTHROUGH,
|
(void)atsha204_execute(SHA204_NONCE, NONCE_MODE_PASSTHROUGH, 0, NONCE_NUMIN_SIZE_PASSTHROUGH,
|
||||||
signing ? _signing_signing_nonce : _signing_verifying_nonce,
|
signing ? _signing_signing_nonce : _signing_verifying_nonce,
|
||||||
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,
|
||||||
GENDIG_COUNT_DATA, _signing_tx_buffer, GENDIG_RSP_SIZE, _signing_rx_buffer);
|
GENDIG_COUNT_DATA, _signing_tx_buffer, GENDIG_RSP_SIZE, _signing_rx_buffer);
|
||||||
|
|
||||||
// Calculate HMAC of message+nonce digest and secret key
|
// Calculate HMAC of message+nonce digest and secret key
|
||||||
(void)atsha204_execute(SHA204_HMAC, HMAC_MODE_SOURCE_FLAG_MATCH, 0, 0, NULL,
|
(void)atsha204_execute(SHA204_HMAC, HMAC_MODE_SOURCE_FLAG_MATCH, 0, 0, NULL,
|
||||||
HMAC_COUNT, _signing_tx_buffer, HMAC_RSP_SIZE, _signing_rx_buffer);
|
HMAC_COUNT, _signing_tx_buffer, HMAC_RSP_SIZE, _signing_rx_buffer);
|
||||||
|
|
||||||
DEBUG_SIGNING_PRINTBUF(F("HMAC: "), &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], 32);
|
DEBUG_SIGNING_PRINTBUF(F("HMAC: "), &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper to calculate a generic SHA256 digest of provided buffer (only supports one block)
|
// 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);
|
||||||
|
|
||||||
// Calculate a hash
|
// Calculate a hash
|
||||||
memset(_signing_temp_message, 0x00, SHA_MSG_SIZE);
|
memset(_signing_temp_message, 0x00, SHA_MSG_SIZE);
|
||||||
@@ -288,7 +309,7 @@ static uint8_t* signerSha256(const uint8_t* data, size_t sz) {
|
|||||||
_signing_temp_message[SHA_MSG_SIZE-2] = (sz >> 5);
|
_signing_temp_message[SHA_MSG_SIZE-2] = (sz >> 5);
|
||||||
_signing_temp_message[SHA_MSG_SIZE-1] = (sz << 3);
|
_signing_temp_message[SHA_MSG_SIZE-1] = (sz << 3);
|
||||||
(void)atsha204_execute(SHA204_SHA, SHA_CALC, 0, SHA_MSG_SIZE, _signing_temp_message,
|
(void)atsha204_execute(SHA204_SHA, SHA_CALC, 0, SHA_MSG_SIZE, _signing_temp_message,
|
||||||
SHA_COUNT_LONG, _signing_tx_buffer, SHA_RSP_SIZE_LONG, _signing_rx_buffer);
|
SHA_COUNT_LONG, _signing_tx_buffer, SHA_RSP_SIZE_LONG, _signing_rx_buffer);
|
||||||
|
|
||||||
DEBUG_SIGNING_PRINTBUF(F("SHA256: "), &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], 32);
|
DEBUG_SIGNING_PRINTBUF(F("SHA256: "), &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], 32);
|
||||||
return &_signing_rx_buffer[SHA204_BUFFER_POS_DATA];
|
return &_signing_rx_buffer[SHA204_BUFFER_POS_DATA];
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
+429
-389
File diff suppressed because it is too large
Load Diff
+141
-141
@@ -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
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+54
-53
@@ -30,33 +30,34 @@
|
|||||||
|
|
||||||
#if defined(MY_RX_MESSAGE_BUFFER_FEATURE)
|
#if defined(MY_RX_MESSAGE_BUFFER_FEATURE)
|
||||||
typedef struct _transportQueuedMessage {
|
typedef struct _transportQueuedMessage {
|
||||||
uint8_t m_len; // Length of the data
|
uint8_t m_len; // Length of the data
|
||||||
uint8_t m_data[MAX_MESSAGE_LENGTH]; // The raw data
|
uint8_t m_data[MAX_MESSAGE_LENGTH]; // The raw data
|
||||||
} transportQueuedMessage;
|
} 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;
|
||||||
|
|
||||||
static void transportRxCallback(void)
|
static void transportRxCallback(void)
|
||||||
{
|
{
|
||||||
// Called for each message received by radio, from interrupt context.
|
// Called for each message received by radio, from interrupt context.
|
||||||
// This function _must_ call RF24_readMessage() to de-assert interrupt line!
|
// This function _must_ call RF24_readMessage() to de-assert interrupt line!
|
||||||
if (!transportRxQueue.full()) {
|
if (!transportRxQueue.full()) {
|
||||||
transportQueuedMessage* msg = transportRxQueue.getFront();
|
transportQueuedMessage* msg = transportRxQueue.getFront();
|
||||||
msg->m_len = RF24_readMessage(msg->m_data); // Read payload & clear RX_DR
|
msg->m_len = RF24_readMessage(msg->m_data); // Read payload & clear RX_DR
|
||||||
(void)transportRxQueue.pushFront(msg);
|
(void)transportRxQueue.pushFront(msg);
|
||||||
} else {
|
} else {
|
||||||
// Queue is full. Discard message.
|
// Queue is full. Discard message.
|
||||||
(void)RF24_readMessage(NULL); // Read payload & clear RX_DR
|
(void)RF24_readMessage(NULL); // Read payload & clear RX_DR
|
||||||
// Keep track of messages lost. Max 255, prevent wrapping.
|
// Keep track of messages lost. Max 255, prevent wrapping.
|
||||||
if (transportLostMessageCount < 255) {
|
if (transportLostMessageCount < 255) {
|
||||||
++transportLostMessageCount;
|
++transportLostMessageCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -69,86 +70,86 @@ uint8_t _psk[16];
|
|||||||
bool transportInit(void)
|
bool transportInit(void)
|
||||||
{
|
{
|
||||||
#if defined(MY_RF24_ENABLE_ENCRYPTION)
|
#if defined(MY_RF24_ENABLE_ENCRYPTION)
|
||||||
hwReadConfigBlock((void*)_psk, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16);
|
hwReadConfigBlock((void*)_psk, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16);
|
||||||
//set up AES-key
|
//set up AES-key
|
||||||
_aes.set_key(_psk, 16);
|
_aes.set_key(_psk, 16);
|
||||||
// Make sure it is purged from memory when set
|
// Make sure it is purged from memory when set
|
||||||
memset(_psk, 0, 16);
|
memset(_psk, 0, 16);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MY_RX_MESSAGE_BUFFER_FEATURE)
|
#if defined(MY_RX_MESSAGE_BUFFER_FEATURE)
|
||||||
RF24_registerReceiveCallback( transportRxCallback );
|
RF24_registerReceiveCallback( transportRxCallback );
|
||||||
#endif
|
#endif
|
||||||
return RF24_initialize();
|
return RF24_initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void transportSetAddress(const uint8_t address)
|
void transportSetAddress(const uint8_t address)
|
||||||
{
|
{
|
||||||
RF24_setNodeAddress(address);
|
RF24_setNodeAddress(address);
|
||||||
RF24_startListening();
|
RF24_startListening();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t transportGetAddress(void)
|
uint8_t transportGetAddress(void)
|
||||||
{
|
{
|
||||||
return RF24_getNodeID();
|
return RF24_getNodeID();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool transportSend(const uint8_t recipient, const void* data, uint8_t len)
|
bool transportSend(const uint8_t recipient, const void* data, uint8_t len)
|
||||||
{
|
{
|
||||||
#if defined(MY_RF24_ENABLE_ENCRYPTION)
|
#if defined(MY_RF24_ENABLE_ENCRYPTION)
|
||||||
// copy input data because it is read-only
|
// copy input data because it is read-only
|
||||||
(void)memcpy(_dataenc,data,len);
|
(void)memcpy(_dataenc,data,len);
|
||||||
// has to be adjusted, WIP!
|
// has to be adjusted, WIP!
|
||||||
_aes.set_IV(0);
|
_aes.set_IV(0);
|
||||||
len = len > 16 ? 32 : 16;
|
len = len > 16 ? 32 : 16;
|
||||||
//encrypt data
|
//encrypt data
|
||||||
_aes.cbc_encrypt(_dataenc, _dataenc, len/16);
|
_aes.cbc_encrypt(_dataenc, _dataenc, len/16);
|
||||||
return RF24_sendMessage(recipient, _dataenc, len);
|
return RF24_sendMessage(recipient, _dataenc, len);
|
||||||
#else
|
#else
|
||||||
return RF24_sendMessage(recipient, data, len);
|
return RF24_sendMessage(recipient, data, len);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool transportAvailable(void)
|
bool transportAvailable(void)
|
||||||
{
|
{
|
||||||
#if defined(MY_RX_MESSAGE_BUFFER_FEATURE)
|
#if defined(MY_RX_MESSAGE_BUFFER_FEATURE)
|
||||||
(void)RF24_isDataAvailable; // Prevent 'defined but not used' warning
|
(void)RF24_isDataAvailable; // Prevent 'defined but not used' warning
|
||||||
return !transportRxQueue.empty();
|
return !transportRxQueue.empty();
|
||||||
#else
|
#else
|
||||||
return RF24_isDataAvailable();
|
return RF24_isDataAvailable();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool transportSanityCheck(void)
|
bool transportSanityCheck(void)
|
||||||
{
|
{
|
||||||
return RF24_sanityCheck();
|
return RF24_sanityCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t transportReceive(void* data)
|
uint8_t transportReceive(void* data)
|
||||||
{
|
{
|
||||||
uint8_t len = 0;
|
uint8_t len = 0;
|
||||||
#if defined(MY_RX_MESSAGE_BUFFER_FEATURE)
|
#if defined(MY_RX_MESSAGE_BUFFER_FEATURE)
|
||||||
transportQueuedMessage* msg = transportRxQueue.getBack();
|
transportQueuedMessage* msg = transportRxQueue.getBack();
|
||||||
if (msg) {
|
if (msg) {
|
||||||
len = msg->m_len;
|
len = msg->m_len;
|
||||||
(void)memcpy(data, msg->m_data, len);
|
(void)memcpy(data, msg->m_data, len);
|
||||||
(void)transportRxQueue.popBack();
|
(void)transportRxQueue.popBack();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
len = RF24_readMessage(data);
|
len = RF24_readMessage(data);
|
||||||
#endif
|
#endif
|
||||||
#if defined(MY_RF24_ENABLE_ENCRYPTION)
|
#if defined(MY_RF24_ENABLE_ENCRYPTION)
|
||||||
// has to be adjusted, WIP!
|
// has to be adjusted, WIP!
|
||||||
_aes.set_IV(0);
|
_aes.set_IV(0);
|
||||||
// decrypt data
|
// decrypt data
|
||||||
if (_aes.cbc_decrypt((uint8_t*)(data), (uint8_t*)(data), len > 16 ? 2 : 1) != AES_SUCCESS) {
|
if (_aes.cbc_decrypt((uint8_t*)(data), (uint8_t*)(data), len > 16 ? 2 : 1) != AES_SUCCESS) {
|
||||||
len = 0;
|
len = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void transportPowerDown(void)
|
void transportPowerDown(void)
|
||||||
{
|
{
|
||||||
RF24_powerDown();
|
RF24_powerDown();
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-14
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-13
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
+189
-182
@@ -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,13 +114,14 @@ 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;
|
{
|
||||||
_recPos = 0;
|
_recPhase = 0;
|
||||||
_recLen = 0;
|
_recPos = 0;
|
||||||
_recCommand = 0;
|
_recLen = 0;
|
||||||
_recCS = 0;
|
_recCommand = 0;
|
||||||
_recCalcCS = 0;
|
_recCS = 0;
|
||||||
|
_recCalcCS = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the main reception state machine. Progress through the states
|
// This is the main reception state machine. Progress through the states
|
||||||
@@ -132,118 +133,118 @@ void _serialReset(){
|
|||||||
// function.
|
// function.
|
||||||
bool _serialProcess()
|
bool _serialProcess()
|
||||||
{
|
{
|
||||||
char inch;
|
char inch;
|
||||||
unsigned char i;
|
unsigned char i;
|
||||||
if (!_dev.available()) {
|
if (!_dev.available()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(_dev.available()) {
|
||||||
|
inch = _dev.read();
|
||||||
|
|
||||||
|
switch(_recPhase) {
|
||||||
|
|
||||||
|
// Case 0 looks for the header. Bytes arrive in the serial interface and get
|
||||||
|
// shifted through a header buffer. When the start and end characters in
|
||||||
|
// the buffer match the SOH/STX pair, and the destination station ID matches
|
||||||
|
// our ID, save the header information and progress to the next state.
|
||||||
|
case 0:
|
||||||
|
memcpy(&_header[0],&_header[1],5);
|
||||||
|
_header[5] = inch;
|
||||||
|
if ((_header[0] == SOH) && (_header[5] == STX) && (_header[1] != _header[2])) {
|
||||||
|
_recCalcCS = 0;
|
||||||
|
_recStation = _header[1];
|
||||||
|
_recSender = _header[2];
|
||||||
|
_recCommand = _header[3];
|
||||||
|
_recLen = _header[4];
|
||||||
|
|
||||||
|
for (i=1; i<=4; i++) {
|
||||||
|
_recCalcCS += _header[i];
|
||||||
|
}
|
||||||
|
_recPhase = 1;
|
||||||
|
_recPos = 0;
|
||||||
|
|
||||||
|
//Check if we should process this message
|
||||||
|
//We reject the message if we are the sender
|
||||||
|
//We reject if we are not the receiver and message is not a broadcast
|
||||||
|
if ((_recSender == _nodeId) ||
|
||||||
|
(_recStation != _nodeId &&
|
||||||
|
_recStation != BROADCAST_ADDRESS)) {
|
||||||
|
_serialReset();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_recLen == 0) {
|
||||||
|
_recPhase = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Case 1 receives the data portion of the packet. Read in "_recLen" number
|
||||||
|
// of bytes and store them in the _data array.
|
||||||
|
case 1:
|
||||||
|
_data[_recPos++] = inch;
|
||||||
|
_recCalcCS += inch;
|
||||||
|
if (_recPos == _recLen) {
|
||||||
|
_recPhase = 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// After the data comes a single ETX character. Do we have it? If not,
|
||||||
|
// reset the state machine to default and start looking for a new header.
|
||||||
|
case 2:
|
||||||
|
// Packet properly terminated?
|
||||||
|
if (inch == ETX) {
|
||||||
|
_recPhase = 3;
|
||||||
|
} else {
|
||||||
|
_serialReset();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Next comes the checksum. We have already calculated it from the incoming
|
||||||
|
// data, so just store the incoming checksum byte for later.
|
||||||
|
case 3:
|
||||||
|
_recCS = inch;
|
||||||
|
_recPhase = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// The final state - check the last character is EOT and that the checksum matches.
|
||||||
|
// If that test passes, then look for a valid command callback to execute.
|
||||||
|
// Execute it if found.
|
||||||
|
case 4:
|
||||||
|
if (inch == EOT) {
|
||||||
|
if (_recCS == _recCalcCS) {
|
||||||
|
// First, check for system level commands. It is possible
|
||||||
|
// to register your own callback as well for system level
|
||||||
|
// commands which will be called after the system default
|
||||||
|
// hook.
|
||||||
|
|
||||||
|
switch (_recCommand) {
|
||||||
|
case ICSC_SYS_PACK:
|
||||||
|
_packet_from = _recSender;
|
||||||
|
_packet_len = _recLen;
|
||||||
|
_packet_received = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Clear the data
|
||||||
|
_serialReset();
|
||||||
|
//Return true, we have processed one command
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
while(_dev.available()) {
|
return true;
|
||||||
inch = _dev.read();
|
|
||||||
|
|
||||||
switch(_recPhase) {
|
|
||||||
|
|
||||||
// Case 0 looks for the header. Bytes arrive in the serial interface and get
|
|
||||||
// shifted through a header buffer. When the start and end characters in
|
|
||||||
// the buffer match the SOH/STX pair, and the destination station ID matches
|
|
||||||
// our ID, save the header information and progress to the next state.
|
|
||||||
case 0:
|
|
||||||
memcpy(&_header[0],&_header[1],5);
|
|
||||||
_header[5] = inch;
|
|
||||||
if ((_header[0] == SOH) && (_header[5] == STX) && (_header[1] != _header[2])) {
|
|
||||||
_recCalcCS = 0;
|
|
||||||
_recStation = _header[1];
|
|
||||||
_recSender = _header[2];
|
|
||||||
_recCommand = _header[3];
|
|
||||||
_recLen = _header[4];
|
|
||||||
|
|
||||||
for (i=1; i<=4; i++) {
|
|
||||||
_recCalcCS += _header[i];
|
|
||||||
}
|
|
||||||
_recPhase = 1;
|
|
||||||
_recPos = 0;
|
|
||||||
|
|
||||||
//Check if we should process this message
|
|
||||||
//We reject the message if we are the sender
|
|
||||||
//We reject if we are not the receiver and message is not a broadcast
|
|
||||||
if ((_recSender == _nodeId) ||
|
|
||||||
(_recStation != _nodeId &&
|
|
||||||
_recStation != BROADCAST_ADDRESS)) {
|
|
||||||
_serialReset();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_recLen == 0) {
|
|
||||||
_recPhase = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Case 1 receives the data portion of the packet. Read in "_recLen" number
|
|
||||||
// of bytes and store them in the _data array.
|
|
||||||
case 1:
|
|
||||||
_data[_recPos++] = inch;
|
|
||||||
_recCalcCS += inch;
|
|
||||||
if (_recPos == _recLen) {
|
|
||||||
_recPhase = 2;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// After the data comes a single ETX character. Do we have it? If not,
|
|
||||||
// reset the state machine to default and start looking for a new header.
|
|
||||||
case 2:
|
|
||||||
// Packet properly terminated?
|
|
||||||
if (inch == ETX) {
|
|
||||||
_recPhase = 3;
|
|
||||||
} else {
|
|
||||||
_serialReset();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Next comes the checksum. We have already calculated it from the incoming
|
|
||||||
// data, so just store the incoming checksum byte for later.
|
|
||||||
case 3:
|
|
||||||
_recCS = inch;
|
|
||||||
_recPhase = 4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// The final state - check the last character is EOT and that the checksum matches.
|
|
||||||
// If that test passes, then look for a valid command callback to execute.
|
|
||||||
// Execute it if found.
|
|
||||||
case 4:
|
|
||||||
if (inch == EOT) {
|
|
||||||
if (_recCS == _recCalcCS) {
|
|
||||||
// First, check for system level commands. It is possible
|
|
||||||
// to register your own callback as well for system level
|
|
||||||
// commands which will be called after the system default
|
|
||||||
// hook.
|
|
||||||
|
|
||||||
switch (_recCommand) {
|
|
||||||
case ICSC_SYS_PACK:
|
|
||||||
_packet_from = _recSender;
|
|
||||||
_packet_len = _recLen;
|
|
||||||
_packet_received = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Clear the data
|
|
||||||
_serialReset();
|
|
||||||
//Return true, we have processed one command
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool transportSend(uint8_t to, const void* data, uint8_t len)
|
bool transportSend(uint8_t to, const void* data, uint8_t len)
|
||||||
{
|
{
|
||||||
const char *datap = static_cast<char const *>(data);
|
const char *datap = static_cast<char const *>(data);
|
||||||
unsigned char i;
|
unsigned char i;
|
||||||
unsigned char cs = 0;
|
unsigned char cs = 0;
|
||||||
unsigned char del;
|
unsigned char del;
|
||||||
|
|
||||||
// This is how many times to try and transmit before failing.
|
// This is how many times to try and transmit before failing.
|
||||||
unsigned char timeout = 10;
|
unsigned char timeout = 10;
|
||||||
@@ -264,101 +265,107 @@ bool transportSend(uint8_t to, const void* data, uint8_t len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MY_RS485_DE_PIN)
|
#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
|
||||||
cs += to;
|
cs += to;
|
||||||
_dev.write(_nodeId); // Source address
|
_dev.write(_nodeId); // Source address
|
||||||
cs += _nodeId;
|
cs += _nodeId;
|
||||||
_dev.write(ICSC_SYS_PACK); // Command code
|
_dev.write(ICSC_SYS_PACK); // Command code
|
||||||
cs += ICSC_SYS_PACK;
|
cs += ICSC_SYS_PACK;
|
||||||
_dev.write(len); // Length of text
|
_dev.write(len); // Length of text
|
||||||
cs += len;
|
cs += len;
|
||||||
_dev.write(STX); // Start of text
|
_dev.write(STX); // Start of text
|
||||||
for(i=0; i<len; i++) {
|
for(i=0; i<len; i++) {
|
||||||
_dev.write(datap[i]); // Text bytes
|
_dev.write(datap[i]); // Text bytes
|
||||||
cs += datap[i];
|
cs += datap[i];
|
||||||
}
|
}
|
||||||
_dev.write(ETX); // End of text
|
_dev.write(ETX); // End of text
|
||||||
_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
|
||||||
}
|
}
|
||||||
|
|||||||
+312
-292
@@ -65,44 +65,42 @@
|
|||||||
#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,
|
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
|
||||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
|
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
|
||||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
|
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
|
||||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
|
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
|
||||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
|
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
|
||||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
|
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
||||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
|
||||||
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,
|
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
|
||||||
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
|
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
|
||||||
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
|
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
||||||
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
|
||||||
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
|
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
|
||||||
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
|
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
||||||
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
|
||||||
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
|
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
|
||||||
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
|
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
||||||
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
||||||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
||||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||||
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
|
||||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
|
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
// times 2 in the GF(2^8)
|
// times 2 in the GF(2^8)
|
||||||
@@ -111,38 +109,36 @@ const static byte s_inv [0x100] PROGMEM =
|
|||||||
|
|
||||||
static byte s_box (byte x)
|
static byte s_box (byte x)
|
||||||
{
|
{
|
||||||
// return fwd_affine (pgm_read_byte (&inv [x])) ;
|
// return fwd_affine (pgm_read_byte (&inv [x])) ;
|
||||||
return pgm_read_byte (& s_fwd [x]) ;
|
return pgm_read_byte (& s_fwd [x]) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inverse Sbox
|
// Inverse Sbox
|
||||||
static byte is_box (byte x)
|
static byte is_box (byte x)
|
||||||
{
|
{
|
||||||
// return pgm_read_byte (&inv [inv_affine (x)]) ;
|
// return pgm_read_byte (&inv [inv_affine (x)]) ;
|
||||||
return pgm_read_byte (& s_inv [x]) ;
|
return pgm_read_byte (& s_inv [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++ ;
|
*d++ ^= *s++ ;
|
||||||
*d++ ^= *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++ ;
|
*d++ = *s++ ^ *k++ ;
|
||||||
*d++ = *s++ ^ *k++ ;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// #define add_round_key(d, k) xor_block (d, k)
|
// #define add_round_key(d, k) xor_block (d, k)
|
||||||
@@ -151,88 +147,110 @@ static void copy_and_key (byte * d, byte * s, byte * k)
|
|||||||
|
|
||||||
static void shift_sub_rows (byte st [N_BLOCK])
|
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 */
|
||||||
|
|
||||||
static void mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
|
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] ;
|
||||||
byte b = st [j] ; j = (j+N_COL) & 15 ;
|
j = (j+N_COL) & 15 ;
|
||||||
byte c = st [k] ; k = (k+N_COL) & 15 ;
|
byte c = st [k] ;
|
||||||
byte d = st [l] ; l = (l+N_COL) & 15 ;
|
k = (k+N_COL) & 15 ;
|
||||||
byte a1 = s_box (a), b1 = s_box (b), c1 = s_box (c), d1 = s_box (d) ;
|
byte d = st [l] ;
|
||||||
byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ;
|
l = (l+N_COL) & 15 ;
|
||||||
dt[i] = a2 ^ b2^b1 ^ c1 ^ d1 ;
|
byte a1 = s_box (a), b1 = s_box (b), c1 = s_box (c), d1 = s_box (d) ;
|
||||||
dt[i+1] = a1 ^ b2 ^ c2^c1 ^ d1 ;
|
byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ;
|
||||||
dt[i+2] = a1 ^ b1 ^ c2 ^ d2^d1 ;
|
dt[i] = a2 ^ b2^b1 ^ c1 ^ d1 ;
|
||||||
dt[i+3] = a2^a1 ^ b1 ^ c1 ^ d2 ;
|
dt[i+1] = a1 ^ b2 ^ c2^c1 ^ d1 ;
|
||||||
}
|
dt[i+2] = a1 ^ b1 ^ c2 ^ d2^d1 ;
|
||||||
|
dt[i+3] = a2^a1 ^ b1 ^ c1 ^ d2 ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inv_mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
|
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] ;
|
byte d1 = st [i+3] ;
|
||||||
byte d1 = st [i+3] ;
|
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) ;
|
byte a4 = f2(a2), b4 = f2(b2), c4 = f2(c2), d4 = f2(d2) ;
|
||||||
byte a4 = f2(a2), b4 = f2(b2), c4 = f2(c2), d4 = f2(d2) ;
|
byte a8 = f2(a4), b8 = f2(b4), c8 = f2(c4), d8 = f2(d4) ;
|
||||||
byte a8 = f2(a4), b8 = f2(b4), c8 = f2(c4), d8 = f2(d4) ;
|
byte a9 = a8 ^ a1,b9 = b8 ^ b1,c9 = c8 ^ c1,d9 = d8 ^ d1 ;
|
||||||
byte a9 = a8 ^ a1,b9 = b8 ^ b1,c9 = c8 ^ c1,d9 = d8 ^ d1 ;
|
byte ac = a8 ^ a4,bc = b8 ^ b4,cc = c8 ^ c4,dc = d8 ^ d4 ;
|
||||||
byte ac = a8 ^ a4,bc = b8 ^ b4,cc = c8 ^ c4,dc = d8 ^ d4 ;
|
|
||||||
|
|
||||||
dt[i] = is_box (ac^a2 ^ b9^b2 ^ cc^c1 ^ d9) ;
|
dt[i] = is_box (ac^a2 ^ b9^b2 ^ cc^c1 ^ d9) ;
|
||||||
dt[(i+5)&15] = is_box (a9 ^ bc^b2 ^ c9^c2 ^ dc^d1) ;
|
dt[(i+5)&15] = is_box (a9 ^ bc^b2 ^ c9^c2 ^ dc^d1) ;
|
||||||
dt[(i+10)&15] = is_box (ac^a1 ^ b9 ^ cc^c2 ^ d9^d2) ;
|
dt[(i+10)&15] = is_box (ac^a1 ^ b9 ^ cc^c2 ^ d9^d2) ;
|
||||||
dt[(i+15)&15] = is_box (a9^a2 ^ bc^b1 ^ c9 ^ dc^d2) ;
|
dt[(i+15)&15] = is_box (a9^a2 ^ bc^b1 ^ c9 ^ dc^d2) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
AES::AES(){
|
AES::AES()
|
||||||
|
{
|
||||||
byte ar_iv[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 };
|
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);
|
||||||
arr_pad[0] = 0x01;
|
arr_pad[0] = 0x01;
|
||||||
arr_pad[1] = 0x02;
|
arr_pad[1] = 0x02;
|
||||||
arr_pad[2] = 0x03;
|
arr_pad[2] = 0x03;
|
||||||
arr_pad[3] = 0x04;
|
arr_pad[3] = 0x04;
|
||||||
@@ -253,208 +271,196 @@ 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
|
round = 10 ;
|
||||||
round = 10 ;
|
break;
|
||||||
break;
|
case 24:
|
||||||
case 24:
|
case 192:
|
||||||
case 192:
|
keylen = 24; // 12 rounds
|
||||||
keylen = 24; // 12 rounds
|
round = 12 ;
|
||||||
round = 12 ;
|
break;
|
||||||
break;
|
case 32:
|
||||||
case 32:
|
case 256:
|
||||||
case 256:
|
keylen = 32; // 14 rounds
|
||||||
keylen = 32; // 14 rounds
|
round = 14 ;
|
||||||
round = 14 ;
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
round = 0;
|
||||||
round = 0;
|
return AES_FAILURE;
|
||||||
return AES_FAILURE;
|
}
|
||||||
}
|
hi = (round + 1) << 4 ;
|
||||||
hi = (round + 1) << 4 ;
|
copy_n_bytes (key_sched, key, keylen) ;
|
||||||
copy_n_bytes (key_sched, key, keylen) ;
|
byte t[4] ;
|
||||||
byte t[4] ;
|
byte next = keylen ;
|
||||||
byte next = keylen ;
|
for (byte cc = keylen, rc = 1 ; cc < hi ; cc += N_COL) {
|
||||||
for (byte cc = keylen, rc = 1 ; cc < hi ; cc += N_COL)
|
for (byte i = 0 ; i < N_COL ; i++) {
|
||||||
{
|
t[i] = key_sched [cc-4+i] ;
|
||||||
for (byte i = 0 ; i < N_COL ; i++) {
|
}
|
||||||
t[i] = key_sched [cc-4+i] ;
|
if (cc == next) {
|
||||||
}
|
next += keylen ;
|
||||||
if (cc == next)
|
byte ttt = t[0] ;
|
||||||
{
|
t[0] = s_box (t[1]) ^ rc ;
|
||||||
next += keylen ;
|
t[1] = s_box (t[2]) ;
|
||||||
byte ttt = t[0] ;
|
t[2] = s_box (t[3]) ;
|
||||||
t[0] = s_box (t[1]) ^ rc ;
|
t[3] = s_box (ttt) ;
|
||||||
t[1] = s_box (t[2]) ;
|
rc = f2 (rc) ;
|
||||||
t[2] = s_box (t[3]) ;
|
} else if (keylen == 32 && (cc & 31) == 16) {
|
||||||
t[3] = s_box (ttt) ;
|
for (byte i = 0 ; i < 4 ; i++) {
|
||||||
rc = f2 (rc) ;
|
t[i] = s_box (t[i]) ;
|
||||||
}
|
}
|
||||||
else if (keylen == 32 && (cc & 31) == 16)
|
}
|
||||||
{
|
byte tt = cc - keylen ;
|
||||||
for (byte i = 0 ; i < 4 ; i++) {
|
for (byte i = 0 ; i < N_COL ; i++) {
|
||||||
t[i] = s_box (t[i]) ;
|
key_sched [cc + i] = key_sched [tt + i] ^ t[i] ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
byte tt = cc - keylen ;
|
return AES_SUCCESS ;
|
||||||
for (byte i = 0 ; i < N_COL ; i++) {
|
|
||||||
key_sched [cc + i] = key_sched [tt + i] ^ t[i] ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return AES_SUCCESS ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
void AES::clean ()
|
void AES::clean ()
|
||||||
{
|
{
|
||||||
for (byte i = 0 ; i < KEY_SCHEDULE_BYTES ; i++) {
|
for (byte i = 0 ; i < KEY_SCHEDULE_BYTES ; i++) {
|
||||||
key_sched [i] = 0 ;
|
key_sched [i] = 0 ;
|
||||||
}
|
}
|
||||||
round = 0 ;
|
round = 0 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
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 {
|
||||||
}
|
return AES_FAILURE ;
|
||||||
else
|
}
|
||||||
return AES_FAILURE ;
|
return AES_SUCCESS ;
|
||||||
return AES_SUCCESS ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
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 ;
|
}
|
||||||
}
|
copy_n_bytes (cipher, iv, N_BLOCK) ;
|
||||||
copy_n_bytes (cipher, iv, N_BLOCK) ;
|
plain += N_BLOCK ;
|
||||||
plain += N_BLOCK ;
|
cipher += N_BLOCK ;
|
||||||
cipher += N_BLOCK ;
|
}
|
||||||
}
|
return AES_SUCCESS ;
|
||||||
return AES_SUCCESS ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
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 ;
|
}
|
||||||
}
|
copy_n_bytes (cipher, iv, N_BLOCK) ;
|
||||||
copy_n_bytes (cipher, iv, N_BLOCK) ;
|
plain += N_BLOCK ;
|
||||||
plain += N_BLOCK ;
|
cipher += N_BLOCK ;
|
||||||
cipher += N_BLOCK ;
|
}
|
||||||
}
|
return AES_SUCCESS ;
|
||||||
return AES_SUCCESS ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
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 {
|
||||||
}
|
return AES_FAILURE ;
|
||||||
else
|
}
|
||||||
return AES_FAILURE ;
|
return AES_SUCCESS ;
|
||||||
return AES_SUCCESS ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK])
|
byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK])
|
||||||
{
|
{
|
||||||
while (n_block--)
|
while (n_block--) {
|
||||||
{
|
byte tmp [N_BLOCK] ;
|
||||||
byte tmp [N_BLOCK] ;
|
copy_n_bytes (tmp, cipher, N_BLOCK) ;
|
||||||
copy_n_bytes (tmp, cipher, N_BLOCK) ;
|
if (decrypt (cipher, plain) != AES_SUCCESS) {
|
||||||
if (decrypt (cipher, plain) != AES_SUCCESS) {
|
return AES_FAILURE ;
|
||||||
return AES_FAILURE ;
|
}
|
||||||
}
|
xor_block (plain, iv) ;
|
||||||
xor_block (plain, iv) ;
|
copy_n_bytes (iv, tmp, N_BLOCK) ;
|
||||||
copy_n_bytes (iv, tmp, N_BLOCK) ;
|
plain += N_BLOCK ;
|
||||||
plain += N_BLOCK ;
|
cipher += N_BLOCK;
|
||||||
cipher += N_BLOCK;
|
}
|
||||||
}
|
return AES_SUCCESS ;
|
||||||
return AES_SUCCESS ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block)
|
byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block)
|
||||||
{
|
{
|
||||||
while (n_block--)
|
while (n_block--) {
|
||||||
{
|
byte tmp [N_BLOCK] ;
|
||||||
byte tmp [N_BLOCK] ;
|
copy_n_bytes (tmp, cipher, N_BLOCK) ;
|
||||||
copy_n_bytes (tmp, cipher, N_BLOCK) ;
|
if (decrypt (cipher, plain) != AES_SUCCESS) {
|
||||||
if (decrypt (cipher, plain) != AES_SUCCESS) {
|
return AES_FAILURE ;
|
||||||
return AES_FAILURE ;
|
}
|
||||||
}
|
xor_block (plain, iv) ;
|
||||||
xor_block (plain, iv) ;
|
copy_n_bytes (iv, tmp, N_BLOCK) ;
|
||||||
copy_n_bytes (iv, tmp, N_BLOCK) ;
|
plain += N_BLOCK ;
|
||||||
plain += N_BLOCK ;
|
cipher += N_BLOCK;
|
||||||
cipher += N_BLOCK;
|
}
|
||||||
}
|
return AES_SUCCESS ;
|
||||||
return AES_SUCCESS ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void AES::set_IV(unsigned long long int IVCl){
|
void AES::set_IV(unsigned long long int IVCl)
|
||||||
|
{
|
||||||
memcpy(iv,&IVCl,8);
|
memcpy(iv,&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,59 +516,63 @@ 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;
|
||||||
{
|
}
|
||||||
printf_P(PSTR("%c"),output[j*N_BLOCK + i]);
|
for (i = 0; i < outp; i++) {
|
||||||
}
|
printf_P(PSTR("%c"),output[j*N_BLOCK + i]);
|
||||||
}
|
}
|
||||||
printf_P(PSTR("\n"));
|
}
|
||||||
|
printf_P(PSTR("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
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"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|||||||
+53
-52
@@ -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]
|
||||||
unsigned long long int IVC;/**< holds the initialization vector counter in numerical format. */
|
;/**< holds the pre-computed key for the encryption/decrpytion. */
|
||||||
byte iv[16];/**< holds the initialization vector that will be used in the cipher. */
|
unsigned long long int IVC;/**< holds the initialization vector counter in numerical format. */
|
||||||
int pad;/**< holds the size of the padding. */
|
byte iv[16];/**< holds the initialization vector that will be used in the cipher. */
|
||||||
int size;/**< hold the size of the plaintext to be ciphered */
|
int pad;/**< holds the size of the padding. */
|
||||||
#if defined(AES_LINUX)
|
int size;/**< hold the size of the plaintext to be ciphered */
|
||||||
|
#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
@@ -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
|
||||||
|
|||||||
@@ -15,33 +15,33 @@ unsigned long long int my_iv = 01234567;
|
|||||||
|
|
||||||
int main(int argc, char** argv)
|
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 () ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void prekey (int bits)
|
void prekey (int bits)
|
||||||
{
|
{
|
||||||
byte iv [N_BLOCK] ;
|
byte iv [N_BLOCK] ;
|
||||||
byte plain_p[sizeof(plain) + (N_BLOCK - (sizeof(plain) % 16)) - 1];
|
byte plain_p[sizeof(plain) + (N_BLOCK - (sizeof(plain) % 16)) - 1];
|
||||||
byte cipher[sizeof(plain_p)];
|
byte cipher[sizeof(plain_p)];
|
||||||
aes.do_aes_encrypt(plain,sizeof(plain),cipher,key,bits);
|
aes.do_aes_encrypt(plain,sizeof(plain),cipher,key,bits);
|
||||||
aes.get_IV(iv);
|
aes.get_IV(iv);
|
||||||
aes.do_aes_dencrypt(cipher,aes.get_size(),plain_p,key,bits,iv);
|
aes.do_aes_dencrypt(cipher,aes.get_size(),plain_p,key,bits,iv);
|
||||||
//normally u have sizeof(cipher) but if its in the same sketch you cannot determin it dynamically
|
//normally u have sizeof(cipher) but if its in the same sketch you cannot determin it dynamically
|
||||||
|
|
||||||
printf("\n\nPLAIN :");
|
printf("\n\nPLAIN :");
|
||||||
aes.printArray(plain);
|
aes.printArray(plain);
|
||||||
printf("\nCIPHER:");
|
printf("\nCIPHER:");
|
||||||
aes.printArray(cipher);
|
aes.printArray(cipher);
|
||||||
printf("\nPlain2:");
|
printf("\nPlain2:");
|
||||||
aes.printArray(plain_p);
|
aes.printArray(plain_p);
|
||||||
printf("\n============================================================\n");
|
printf("\n============================================================\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void prekey_test ()
|
void prekey_test ()
|
||||||
{
|
{
|
||||||
prekey (128) ;
|
prekey (128) ;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,108 +18,113 @@ void monte_carlo (int bits);
|
|||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
printf ("AES library test vectors") ;
|
printf ("AES library test vectors") ;
|
||||||
|
|
||||||
monte_carlo (128) ;
|
monte_carlo (128) ;
|
||||||
|
|
||||||
for (int keysize = 128 ; keysize <= 256 ; keysize += 64)
|
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) ;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void prekey_test_var_plaintext (int bits)
|
void prekey_test_var_plaintext (int bits)
|
||||||
{
|
{
|
||||||
printf ("\nECB Varying Plaintext %i bits\n",bits) ;
|
printf ("\nECB Varying Plaintext %i bits\n",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) ;
|
|
||||||
|
|
||||||
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) ;
|
||||||
printf ("\n") ;
|
printf ("\n") ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void prekey_test_var_key (int bits)
|
void prekey_test_var_key (int bits)
|
||||||
{
|
{
|
||||||
printf ("\nECB Varying key %i bits\n",bits);
|
printf ("\nECB Varying key %i bits\n",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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_bits (int bits, byte * a, int count)
|
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)
|
}
|
||||||
a [bcount++] = 0xFF & (0xFF00 >> (count & 7)) ;
|
if ((count & 7) != 0) {
|
||||||
for (byte i = bcount ; i < bits ; i++)
|
a [bcount++] = 0xFF & (0xFF00 >> (count & 7)) ;
|
||||||
a [i] = 0x00 ;
|
}
|
||||||
|
for (byte i = bcount ; i < bits ; i++) {
|
||||||
|
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 ;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char hex[] = "0123456789abcdef" ;
|
char hex[] = "0123456789abcdef" ;
|
||||||
@@ -127,57 +132,51 @@ char hex[] = "0123456789abcdef" ;
|
|||||||
|
|
||||||
void print_value (const char * str, byte * a, int bits)
|
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]) ;
|
//Serial.print (hex [b & 15]) ;
|
||||||
//Serial.print (hex [b & 15]) ;
|
}
|
||||||
}
|
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);
|
||||||
{
|
print_value ("KEY = ", key, bits) ;
|
||||||
printf ("COUNT = %i\n",i);
|
print_value ("PLAINTEXT = ", plain, 128) ;
|
||||||
print_value ("KEY = ", key, bits) ;
|
succ = aes.set_key (key, bits) ;
|
||||||
print_value ("PLAINTEXT = ", plain, 128) ;
|
for (int j = 0 ; j < 1000 ; j++) {
|
||||||
succ = aes.set_key (key, bits) ;
|
succ = aes.encrypt (plain, cipher) ;
|
||||||
for (int j = 0 ; j < 1000 ; j++)
|
aes.copy_n_bytes (plain, cipher, 16) ;
|
||||||
{
|
}
|
||||||
succ = aes.encrypt (plain, cipher) ;
|
print_value ("CIPHERTEXT = ", cipher, 128) ;
|
||||||
aes.copy_n_bytes (plain, cipher, 16) ;
|
printf("\n");
|
||||||
}
|
if (bits == 128) {
|
||||||
print_value ("CIPHERTEXT = ", cipher, 128) ;
|
for (byte k = 0 ; k < 16 ; k++) {
|
||||||
printf("\n");
|
key [k] ^= cipher [k] ;
|
||||||
if (bits == 128)
|
}
|
||||||
{
|
} else if (bits == 192) {
|
||||||
for (byte k = 0 ; k < 16 ; k++)
|
} else {
|
||||||
key [k] ^= cipher [k] ;
|
}
|
||||||
}
|
}
|
||||||
else if (bits == 192)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-12
@@ -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
|
||||||
@@ -21,36 +21,36 @@
|
|||||||
|
|
||||||
int serial_putc( char c, FILE * )
|
int serial_putc( char c, FILE * )
|
||||||
{
|
{
|
||||||
Serial.write( c );
|
Serial.write( c );
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printf_begin(void)
|
void printf_begin(void)
|
||||||
{
|
{
|
||||||
fdevopen( &serial_putc, 0 );
|
fdevopen( &serial_putc, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
#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 * )
|
||||||
{
|
{
|
||||||
Serial.write( c );
|
Serial.write( c );
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printf_begin(void)
|
void printf_begin(void)
|
||||||
{
|
{
|
||||||
//JESUS - For reddirect stdout to /dev/ttyGS0 (Serial Monitor port)
|
//JESUS - For reddirect stdout to /dev/ttyGS0 (Serial Monitor port)
|
||||||
stdout = freopen("/dev/ttyGS0","w",stdout);
|
stdout = freopen("/dev/ttyGS0","w",stdout);
|
||||||
delay(500);
|
delay(500);
|
||||||
printf("redirecting to Serial...");
|
printf("redirecting to Serial...");
|
||||||
|
|
||||||
//JESUS -----------------------------------------------------------
|
//JESUS -----------------------------------------------------------
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#error This example is only for use on Arduino.
|
#error This example is only for use on Arduino.
|
||||||
|
|||||||
+408
-445
File diff suppressed because it is too large
Load Diff
@@ -244,8 +244,8 @@ void atsha204_idle(void);
|
|||||||
void atsha204_sleep(void);
|
void atsha204_sleep(void);
|
||||||
uint8_t atsha204_wakeup(uint8_t *response);
|
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 datalen1, uint8_t *data1, uint8_t tx_size,
|
||||||
uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer);
|
uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer);
|
||||||
uint8_t atsha204_getSerialNumber(uint8_t *response);
|
uint8_t atsha204_getSerialNumber(uint8_t *response);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+142
-126
@@ -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
|
||||||
@@ -9,132 +9,146 @@
|
|||||||
|
|
||||||
|
|
||||||
const uint32_t sha256K[] PROGMEM = {
|
const uint32_t sha256K[] PROGMEM = {
|
||||||
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
|
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
|
||||||
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
|
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
|
||||||
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
|
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
|
||||||
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
|
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
|
||||||
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
|
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
|
||||||
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
|
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
|
||||||
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
|
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
|
||||||
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
|
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BUFFER_SIZE 64
|
#define BUFFER_SIZE 64
|
||||||
|
|
||||||
const uint8_t sha256InitState[] PROGMEM = {
|
const uint8_t sha256InitState[] PROGMEM = {
|
||||||
0x67,0xe6,0x09,0x6a, // H0
|
0x67,0xe6,0x09,0x6a, // H0
|
||||||
0x85,0xae,0x67,0xbb, // H1
|
0x85,0xae,0x67,0xbb, // H1
|
||||||
0x72,0xf3,0x6e,0x3c, // H2
|
0x72,0xf3,0x6e,0x3c, // H2
|
||||||
0x3a,0xf5,0x4f,0xa5, // H3
|
0x3a,0xf5,0x4f,0xa5, // H3
|
||||||
0x7f,0x52,0x0e,0x51, // H4
|
0x7f,0x52,0x0e,0x51, // H4
|
||||||
0x8c,0x68,0x05,0x9b, // H5
|
0x8c,0x68,0x05,0x9b, // H5
|
||||||
0xab,0xd9,0x83,0x1f, // H6
|
0xab,0xd9,0x83,0x1f, // H6
|
||||||
0x19,0xcd,0xe0,0x5b // H7
|
0x19,0xcd,0xe0,0x5b // H7
|
||||||
};
|
};
|
||||||
|
|
||||||
void Sha256Class::init(void) {
|
void Sha256Class::init(void)
|
||||||
memcpy_P(state.b,sha256InitState,32);
|
{
|
||||||
byteCount = 0;
|
memcpy_P(state.b,sha256InitState,32);
|
||||||
bufferOffset = 0;
|
byteCount = 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;
|
{
|
||||||
uint32_t a,b,c,d,e,f,g,h,t1,t2;
|
uint8_t i;
|
||||||
|
uint32_t a,b,c,d,e,f,g,h,t1,t2;
|
||||||
|
|
||||||
a=state.w[0];
|
a=state.w[0];
|
||||||
b=state.w[1];
|
b=state.w[1];
|
||||||
c=state.w[2];
|
c=state.w[2];
|
||||||
d=state.w[3];
|
d=state.w[3];
|
||||||
e=state.w[4];
|
e=state.w[4];
|
||||||
f=state.w[5];
|
f=state.w[5];
|
||||||
g=state.w[6];
|
g=state.w[6];
|
||||||
h=state.w[7];
|
h=state.w[7];
|
||||||
|
|
||||||
for (i=0; i<64; i++) {
|
for (i=0; i<64; i++) {
|
||||||
if (i>=16) {
|
if (i>=16) {
|
||||||
t1 = buffer.w[i&15] + buffer.w[(i-7)&15];
|
t1 = buffer.w[i&15] + buffer.w[(i-7)&15];
|
||||||
t2 = buffer.w[(i-2)&15];
|
t2 = buffer.w[(i-2)&15];
|
||||||
t1 += ror32(t2,17) ^ ror32(t2,19) ^ (t2>>10);
|
t1 += ror32(t2,17) ^ ror32(t2,19) ^ (t2>>10);
|
||||||
t2 = buffer.w[(i-15)&15];
|
t2 = buffer.w[(i-15)&15];
|
||||||
t1 += ror32(t2,7) ^ ror32(t2,18) ^ (t2>>3);
|
t1 += ror32(t2,7) ^ ror32(t2,18) ^ (t2>>3);
|
||||||
buffer.w[i&15] = t1;
|
buffer.w[i&15] = t1;
|
||||||
}
|
}
|
||||||
t1 = h;
|
t1 = h;
|
||||||
t1 += ror32(e,6) ^ ror32(e,11) ^ ror32(e,25); // ∑1(e)
|
t1 += ror32(e,6) ^ ror32(e,11) ^ ror32(e,25); // ∑1(e)
|
||||||
t1 += g ^ (e & (g ^ f)); // Ch(e,f,g)
|
t1 += g ^ (e & (g ^ f)); // Ch(e,f,g)
|
||||||
t1 += pgm_read_dword(sha256K+i); // Ki
|
t1 += pgm_read_dword(sha256K+i); // Ki
|
||||||
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;
|
||||||
state.w[0] += a;
|
f=e;
|
||||||
state.w[1] += b;
|
e=d+t1;
|
||||||
state.w[2] += c;
|
d=c;
|
||||||
state.w[3] += d;
|
c=b;
|
||||||
state.w[4] += e;
|
b=a;
|
||||||
state.w[5] += f;
|
a=t1+t2;
|
||||||
state.w[6] += g;
|
}
|
||||||
state.w[7] += h;
|
state.w[0] += a;
|
||||||
|
state.w[1] += b;
|
||||||
|
state.w[2] += c;
|
||||||
|
state.w[3] += d;
|
||||||
|
state.w[4] += e;
|
||||||
|
state.w[5] += f;
|
||||||
|
state.w[6] += g;
|
||||||
|
state.w[7] += h;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sha256Class::addUncounted(uint8_t data) {
|
void Sha256Class::addUncounted(uint8_t data)
|
||||||
buffer.b[bufferOffset ^ 3] = data;
|
{
|
||||||
bufferOffset++;
|
buffer.b[bufferOffset ^ 3] = data;
|
||||||
if (bufferOffset == BUFFER_SIZE) {
|
bufferOffset++;
|
||||||
hashBlock();
|
if (bufferOffset == BUFFER_SIZE) {
|
||||||
bufferOffset = 0;
|
hashBlock();
|
||||||
}
|
bufferOffset = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sha256Class::write(uint8_t data) {
|
void Sha256Class::write(uint8_t data)
|
||||||
++byteCount;
|
{
|
||||||
addUncounted(data);
|
++byteCount;
|
||||||
|
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
|
||||||
addUncounted(0x80);
|
addUncounted(0x80);
|
||||||
while (bufferOffset != 56) {
|
while (bufferOffset != 56) {
|
||||||
addUncounted(0x00);
|
addUncounted(0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append length in the last 8 bytes
|
// Append length in the last 8 bytes
|
||||||
addUncounted(0); // We're only using 32 bit lengths
|
addUncounted(0); // We're only using 32 bit lengths
|
||||||
addUncounted(0); // But SHA-1 supports 64 bit lengths
|
addUncounted(0); // But SHA-1 supports 64 bit lengths
|
||||||
addUncounted(0); // So zero pad the top bits
|
addUncounted(0); // So zero pad the top bits
|
||||||
addUncounted(byteCount >> 29); // Shifting to multiply by 8
|
addUncounted(byteCount >> 29); // Shifting to multiply by 8
|
||||||
addUncounted(byteCount >> 21); // as SHA-1 supports bitstreams as well as
|
addUncounted(byteCount >> 21); // as SHA-1 supports bitstreams as well as
|
||||||
addUncounted(byteCount >> 13); // byte.
|
addUncounted(byteCount >> 13); // byte.
|
||||||
addUncounted(byteCount >> 5);
|
addUncounted(byteCount >> 5);
|
||||||
addUncounted(byteCount << 3);
|
addUncounted(byteCount << 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t* Sha256Class::result(void) {
|
uint8_t* Sha256Class::result(void)
|
||||||
// Pad to complete the last block
|
{
|
||||||
pad();
|
// Pad to complete the last block
|
||||||
|
pad();
|
||||||
|
|
||||||
// Swap byte order back
|
// Swap byte order back
|
||||||
for (int i=0; i<8; i++) {
|
for (int i=0; i<8; i++) {
|
||||||
uint32_t a,b;
|
uint32_t a,b;
|
||||||
a=state.w[i];
|
a=state.w[i];
|
||||||
b=a<<24;
|
b=a<<24;
|
||||||
b|=(a<<8) & 0x00ff0000;
|
b|=(a<<8) & 0x00ff0000;
|
||||||
b|=(a>>8) & 0x0000ff00;
|
b|=(a>>8) & 0x0000ff00;
|
||||||
b|=a>>24;
|
b|=a>>24;
|
||||||
state.w[i]=b;
|
state.w[i]=b;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return pointer to hash (20 characters)
|
// Return pointer to hash (20 characters)
|
||||||
return state.b;
|
return state.b;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HMAC_IPAD 0x36
|
#define HMAC_IPAD 0x36
|
||||||
@@ -143,38 +157,40 @@ 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;
|
{
|
||||||
memset(keyBuffer,0,BLOCK_LENGTH);
|
uint8_t i;
|
||||||
if (keyLength > BLOCK_LENGTH) {
|
memset(keyBuffer,0,BLOCK_LENGTH);
|
||||||
// Hash long keys
|
if (keyLength > BLOCK_LENGTH) {
|
||||||
init();
|
// Hash long keys
|
||||||
for (;keyLength--;) {
|
init();
|
||||||
|
for (; keyLength--;) {
|
||||||
write(*key++);
|
write(*key++);
|
||||||
}
|
}
|
||||||
memcpy(keyBuffer,result(),HASH_LENGTH);
|
memcpy(keyBuffer,result(),HASH_LENGTH);
|
||||||
} else {
|
} else {
|
||||||
// Block length keys are used as is
|
// Block length keys are used as is
|
||||||
memcpy(keyBuffer,key,keyLength);
|
memcpy(keyBuffer,key,keyLength);
|
||||||
}
|
}
|
||||||
// Start inner hash
|
// Start inner hash
|
||||||
init();
|
init();
|
||||||
for (i=0; i<BLOCK_LENGTH; i++) {
|
for (i=0; i<BLOCK_LENGTH; i++) {
|
||||||
write(keyBuffer[i] ^ HMAC_IPAD);
|
write(keyBuffer[i] ^ HMAC_IPAD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* Sha256Class::resultHmac(void) {
|
uint8_t* Sha256Class::resultHmac(void)
|
||||||
uint8_t i;
|
{
|
||||||
// Complete inner hash
|
uint8_t i;
|
||||||
memcpy(innerHash,result(),HASH_LENGTH);
|
// Complete inner hash
|
||||||
// Calculate outer hash
|
memcpy(innerHash,result(),HASH_LENGTH);
|
||||||
init();
|
// Calculate outer hash
|
||||||
for (i=0; i<BLOCK_LENGTH; i++) {
|
init();
|
||||||
|
for (i=0; i<BLOCK_LENGTH; i++) {
|
||||||
write(keyBuffer[i] ^ HMAC_OPAD);
|
write(keyBuffer[i] ^ HMAC_OPAD);
|
||||||
}
|
}
|
||||||
for (i=0; i<HASH_LENGTH; i++) {
|
for (i=0; i<HASH_LENGTH; i++) {
|
||||||
write(innerHash[i]);
|
write(innerHash[i]);
|
||||||
}
|
}
|
||||||
return result();
|
return result();
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-21
@@ -8,33 +8,33 @@
|
|||||||
#define BLOCK_LENGTH 64
|
#define BLOCK_LENGTH 64
|
||||||
|
|
||||||
union _buffer {
|
union _buffer {
|
||||||
uint8_t b[BLOCK_LENGTH];
|
uint8_t b[BLOCK_LENGTH];
|
||||||
uint32_t w[BLOCK_LENGTH/4];
|
uint32_t w[BLOCK_LENGTH/4];
|
||||||
};
|
};
|
||||||
union _state {
|
union _state {
|
||||||
uint8_t b[HASH_LENGTH];
|
uint8_t b[HASH_LENGTH];
|
||||||
uint32_t w[HASH_LENGTH/4];
|
uint32_t w[HASH_LENGTH/4];
|
||||||
};
|
};
|
||||||
|
|
||||||
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();
|
||||||
uint32_t ror32(uint32_t number, uint8_t bits);
|
uint32_t ror32(uint32_t number, uint8_t bits);
|
||||||
_buffer buffer;
|
_buffer buffer;
|
||||||
uint8_t bufferOffset;
|
uint8_t bufferOffset;
|
||||||
_state state;
|
_state state;
|
||||||
uint32_t byteCount;
|
uint32_t byteCount;
|
||||||
uint8_t keyBuffer[BLOCK_LENGTH];
|
uint8_t keyBuffer[BLOCK_LENGTH];
|
||||||
uint8_t innerHash[HASH_LENGTH];
|
uint8_t innerHash[HASH_LENGTH];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+444
-421
@@ -39,10 +39,10 @@
|
|||||||
* @brief struct for mapping digital pins
|
* @brief struct for mapping digital pins
|
||||||
*/
|
*/
|
||||||
struct pin_map_t {
|
struct pin_map_t {
|
||||||
volatile uint8_t* ddr; /**< address of DDR for this pin */
|
volatile uint8_t* ddr; /**< address of DDR for this pin */
|
||||||
volatile uint8_t* pin; /**< address of PIN for this pin */
|
volatile uint8_t* pin; /**< address of PIN for this pin */
|
||||||
volatile uint8_t* port; /**< address of PORT for this pin */
|
volatile uint8_t* port; /**< address of PORT for this pin */
|
||||||
uint8_t bit; /**< bit number for this pin */
|
uint8_t bit; /**< bit number for this pin */
|
||||||
};
|
};
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
#if defined(__AVR_ATmega168__)\
|
#if defined(__AVR_ATmega168__)\
|
||||||
@@ -50,102 +50,102 @@ struct pin_map_t {
|
|||||||
||defined(__AVR_ATmega328P__)
|
||defined(__AVR_ATmega328P__)
|
||||||
// 168 and 328 Arduinos
|
// 168 and 328 Arduinos
|
||||||
const static pin_map_t pinMap[] = {
|
const static pin_map_t pinMap[] = {
|
||||||
{&DDRD, &PIND, &PORTD, 0}, // D0 0
|
{&DDRD, &PIND, &PORTD, 0}, // D0 0
|
||||||
{&DDRD, &PIND, &PORTD, 1}, // D1 1
|
{&DDRD, &PIND, &PORTD, 1}, // D1 1
|
||||||
{&DDRD, &PIND, &PORTD, 2}, // D2 2
|
{&DDRD, &PIND, &PORTD, 2}, // D2 2
|
||||||
{&DDRD, &PIND, &PORTD, 3}, // D3 3
|
{&DDRD, &PIND, &PORTD, 3}, // D3 3
|
||||||
{&DDRD, &PIND, &PORTD, 4}, // D4 4
|
{&DDRD, &PIND, &PORTD, 4}, // D4 4
|
||||||
{&DDRD, &PIND, &PORTD, 5}, // D5 5
|
{&DDRD, &PIND, &PORTD, 5}, // D5 5
|
||||||
{&DDRD, &PIND, &PORTD, 6}, // D6 6
|
{&DDRD, &PIND, &PORTD, 6}, // D6 6
|
||||||
{&DDRD, &PIND, &PORTD, 7}, // D7 7
|
{&DDRD, &PIND, &PORTD, 7}, // D7 7
|
||||||
{&DDRB, &PINB, &PORTB, 0}, // B0 8
|
{&DDRB, &PINB, &PORTB, 0}, // B0 8
|
||||||
{&DDRB, &PINB, &PORTB, 1}, // B1 9
|
{&DDRB, &PINB, &PORTB, 1}, // B1 9
|
||||||
{&DDRB, &PINB, &PORTB, 2}, // B2 10
|
{&DDRB, &PINB, &PORTB, 2}, // B2 10
|
||||||
{&DDRB, &PINB, &PORTB, 3}, // B3 11
|
{&DDRB, &PINB, &PORTB, 3}, // B3 11
|
||||||
{&DDRB, &PINB, &PORTB, 4}, // B4 12
|
{&DDRB, &PINB, &PORTB, 4}, // B4 12
|
||||||
{&DDRB, &PINB, &PORTB, 5}, // B5 13
|
{&DDRB, &PINB, &PORTB, 5}, // B5 13
|
||||||
{&DDRC, &PINC, &PORTC, 0}, // C0 14
|
{&DDRC, &PINC, &PORTC, 0}, // C0 14
|
||||||
{&DDRC, &PINC, &PORTC, 1}, // C1 15
|
{&DDRC, &PINC, &PORTC, 1}, // C1 15
|
||||||
{&DDRC, &PINC, &PORTC, 2}, // C2 16
|
{&DDRC, &PINC, &PORTC, 2}, // C2 16
|
||||||
{&DDRC, &PINC, &PORTC, 3}, // C3 17
|
{&DDRC, &PINC, &PORTC, 3}, // C3 17
|
||||||
{&DDRC, &PINC, &PORTC, 4}, // C4 18
|
{&DDRC, &PINC, &PORTC, 4}, // C4 18
|
||||||
{&DDRC, &PINC, &PORTC, 5} // C5 19
|
{&DDRC, &PINC, &PORTC, 5} // C5 19
|
||||||
};
|
};
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
#elif defined(__AVR_ATmega1280__)\
|
#elif defined(__AVR_ATmega1280__)\
|
||||||
|| defined(__AVR_ATmega2560__)
|
|| defined(__AVR_ATmega2560__)
|
||||||
// Mega
|
// Mega
|
||||||
static const pin_map_t pinMap[] = {
|
static const pin_map_t pinMap[] = {
|
||||||
{&DDRE, &PINE, &PORTE, 0}, // E0 0
|
{&DDRE, &PINE, &PORTE, 0}, // E0 0
|
||||||
{&DDRE, &PINE, &PORTE, 1}, // E1 1
|
{&DDRE, &PINE, &PORTE, 1}, // E1 1
|
||||||
{&DDRE, &PINE, &PORTE, 4}, // E4 2
|
{&DDRE, &PINE, &PORTE, 4}, // E4 2
|
||||||
{&DDRE, &PINE, &PORTE, 5}, // E5 3
|
{&DDRE, &PINE, &PORTE, 5}, // E5 3
|
||||||
{&DDRG, &PING, &PORTG, 5}, // G5 4
|
{&DDRG, &PING, &PORTG, 5}, // G5 4
|
||||||
{&DDRE, &PINE, &PORTE, 3}, // E3 5
|
{&DDRE, &PINE, &PORTE, 3}, // E3 5
|
||||||
{&DDRH, &PINH, &PORTH, 3}, // H3 6
|
{&DDRH, &PINH, &PORTH, 3}, // H3 6
|
||||||
{&DDRH, &PINH, &PORTH, 4}, // H4 7
|
{&DDRH, &PINH, &PORTH, 4}, // H4 7
|
||||||
{&DDRH, &PINH, &PORTH, 5}, // H5 8
|
{&DDRH, &PINH, &PORTH, 5}, // H5 8
|
||||||
{&DDRH, &PINH, &PORTH, 6}, // H6 9
|
{&DDRH, &PINH, &PORTH, 6}, // H6 9
|
||||||
{&DDRB, &PINB, &PORTB, 4}, // B4 10
|
{&DDRB, &PINB, &PORTB, 4}, // B4 10
|
||||||
{&DDRB, &PINB, &PORTB, 5}, // B5 11
|
{&DDRB, &PINB, &PORTB, 5}, // B5 11
|
||||||
{&DDRB, &PINB, &PORTB, 6}, // B6 12
|
{&DDRB, &PINB, &PORTB, 6}, // B6 12
|
||||||
{&DDRB, &PINB, &PORTB, 7}, // B7 13
|
{&DDRB, &PINB, &PORTB, 7}, // B7 13
|
||||||
{&DDRJ, &PINJ, &PORTJ, 1}, // J1 14
|
{&DDRJ, &PINJ, &PORTJ, 1}, // J1 14
|
||||||
{&DDRJ, &PINJ, &PORTJ, 0}, // J0 15
|
{&DDRJ, &PINJ, &PORTJ, 0}, // J0 15
|
||||||
{&DDRH, &PINH, &PORTH, 1}, // H1 16
|
{&DDRH, &PINH, &PORTH, 1}, // H1 16
|
||||||
{&DDRH, &PINH, &PORTH, 0}, // H0 17
|
{&DDRH, &PINH, &PORTH, 0}, // H0 17
|
||||||
{&DDRD, &PIND, &PORTD, 3}, // D3 18
|
{&DDRD, &PIND, &PORTD, 3}, // D3 18
|
||||||
{&DDRD, &PIND, &PORTD, 2}, // D2 19
|
{&DDRD, &PIND, &PORTD, 2}, // D2 19
|
||||||
{&DDRD, &PIND, &PORTD, 1}, // D1 20
|
{&DDRD, &PIND, &PORTD, 1}, // D1 20
|
||||||
{&DDRD, &PIND, &PORTD, 0}, // D0 21
|
{&DDRD, &PIND, &PORTD, 0}, // D0 21
|
||||||
{&DDRA, &PINA, &PORTA, 0}, // A0 22
|
{&DDRA, &PINA, &PORTA, 0}, // A0 22
|
||||||
{&DDRA, &PINA, &PORTA, 1}, // A1 23
|
{&DDRA, &PINA, &PORTA, 1}, // A1 23
|
||||||
{&DDRA, &PINA, &PORTA, 2}, // A2 24
|
{&DDRA, &PINA, &PORTA, 2}, // A2 24
|
||||||
{&DDRA, &PINA, &PORTA, 3}, // A3 25
|
{&DDRA, &PINA, &PORTA, 3}, // A3 25
|
||||||
{&DDRA, &PINA, &PORTA, 4}, // A4 26
|
{&DDRA, &PINA, &PORTA, 4}, // A4 26
|
||||||
{&DDRA, &PINA, &PORTA, 5}, // A5 27
|
{&DDRA, &PINA, &PORTA, 5}, // A5 27
|
||||||
{&DDRA, &PINA, &PORTA, 6}, // A6 28
|
{&DDRA, &PINA, &PORTA, 6}, // A6 28
|
||||||
{&DDRA, &PINA, &PORTA, 7}, // A7 29
|
{&DDRA, &PINA, &PORTA, 7}, // A7 29
|
||||||
{&DDRC, &PINC, &PORTC, 7}, // C7 30
|
{&DDRC, &PINC, &PORTC, 7}, // C7 30
|
||||||
{&DDRC, &PINC, &PORTC, 6}, // C6 31
|
{&DDRC, &PINC, &PORTC, 6}, // C6 31
|
||||||
{&DDRC, &PINC, &PORTC, 5}, // C5 32
|
{&DDRC, &PINC, &PORTC, 5}, // C5 32
|
||||||
{&DDRC, &PINC, &PORTC, 4}, // C4 33
|
{&DDRC, &PINC, &PORTC, 4}, // C4 33
|
||||||
{&DDRC, &PINC, &PORTC, 3}, // C3 34
|
{&DDRC, &PINC, &PORTC, 3}, // C3 34
|
||||||
{&DDRC, &PINC, &PORTC, 2}, // C2 35
|
{&DDRC, &PINC, &PORTC, 2}, // C2 35
|
||||||
{&DDRC, &PINC, &PORTC, 1}, // C1 36
|
{&DDRC, &PINC, &PORTC, 1}, // C1 36
|
||||||
{&DDRC, &PINC, &PORTC, 0}, // C0 37
|
{&DDRC, &PINC, &PORTC, 0}, // C0 37
|
||||||
{&DDRD, &PIND, &PORTD, 7}, // D7 38
|
{&DDRD, &PIND, &PORTD, 7}, // D7 38
|
||||||
{&DDRG, &PING, &PORTG, 2}, // G2 39
|
{&DDRG, &PING, &PORTG, 2}, // G2 39
|
||||||
{&DDRG, &PING, &PORTG, 1}, // G1 40
|
{&DDRG, &PING, &PORTG, 1}, // G1 40
|
||||||
{&DDRG, &PING, &PORTG, 0}, // G0 41
|
{&DDRG, &PING, &PORTG, 0}, // G0 41
|
||||||
{&DDRL, &PINL, &PORTL, 7}, // L7 42
|
{&DDRL, &PINL, &PORTL, 7}, // L7 42
|
||||||
{&DDRL, &PINL, &PORTL, 6}, // L6 43
|
{&DDRL, &PINL, &PORTL, 6}, // L6 43
|
||||||
{&DDRL, &PINL, &PORTL, 5}, // L5 44
|
{&DDRL, &PINL, &PORTL, 5}, // L5 44
|
||||||
{&DDRL, &PINL, &PORTL, 4}, // L4 45
|
{&DDRL, &PINL, &PORTL, 4}, // L4 45
|
||||||
{&DDRL, &PINL, &PORTL, 3}, // L3 46
|
{&DDRL, &PINL, &PORTL, 3}, // L3 46
|
||||||
{&DDRL, &PINL, &PORTL, 2}, // L2 47
|
{&DDRL, &PINL, &PORTL, 2}, // L2 47
|
||||||
{&DDRL, &PINL, &PORTL, 1}, // L1 48
|
{&DDRL, &PINL, &PORTL, 1}, // L1 48
|
||||||
{&DDRL, &PINL, &PORTL, 0}, // L0 49
|
{&DDRL, &PINL, &PORTL, 0}, // L0 49
|
||||||
{&DDRB, &PINB, &PORTB, 3}, // B3 50
|
{&DDRB, &PINB, &PORTB, 3}, // B3 50
|
||||||
{&DDRB, &PINB, &PORTB, 2}, // B2 51
|
{&DDRB, &PINB, &PORTB, 2}, // B2 51
|
||||||
{&DDRB, &PINB, &PORTB, 1}, // B1 52
|
{&DDRB, &PINB, &PORTB, 1}, // B1 52
|
||||||
{&DDRB, &PINB, &PORTB, 0}, // B0 53
|
{&DDRB, &PINB, &PORTB, 0}, // B0 53
|
||||||
{&DDRF, &PINF, &PORTF, 0}, // F0 54
|
{&DDRF, &PINF, &PORTF, 0}, // F0 54
|
||||||
{&DDRF, &PINF, &PORTF, 1}, // F1 55
|
{&DDRF, &PINF, &PORTF, 1}, // F1 55
|
||||||
{&DDRF, &PINF, &PORTF, 2}, // F2 56
|
{&DDRF, &PINF, &PORTF, 2}, // F2 56
|
||||||
{&DDRF, &PINF, &PORTF, 3}, // F3 57
|
{&DDRF, &PINF, &PORTF, 3}, // F3 57
|
||||||
{&DDRF, &PINF, &PORTF, 4}, // F4 58
|
{&DDRF, &PINF, &PORTF, 4}, // F4 58
|
||||||
{&DDRF, &PINF, &PORTF, 5}, // F5 59
|
{&DDRF, &PINF, &PORTF, 5}, // F5 59
|
||||||
{&DDRF, &PINF, &PORTF, 6}, // F6 60
|
{&DDRF, &PINF, &PORTF, 6}, // F6 60
|
||||||
{&DDRF, &PINF, &PORTF, 7}, // F7 61
|
{&DDRF, &PINF, &PORTF, 7}, // F7 61
|
||||||
{&DDRK, &PINK, &PORTK, 0}, // K0 62
|
{&DDRK, &PINK, &PORTK, 0}, // K0 62
|
||||||
{&DDRK, &PINK, &PORTK, 1}, // K1 63
|
{&DDRK, &PINK, &PORTK, 1}, // K1 63
|
||||||
{&DDRK, &PINK, &PORTK, 2}, // K2 64
|
{&DDRK, &PINK, &PORTK, 2}, // K2 64
|
||||||
{&DDRK, &PINK, &PORTK, 3}, // K3 65
|
{&DDRK, &PINK, &PORTK, 3}, // K3 65
|
||||||
{&DDRK, &PINK, &PORTK, 4}, // K4 66
|
{&DDRK, &PINK, &PORTK, 4}, // K4 66
|
||||||
{&DDRK, &PINK, &PORTK, 5}, // K5 67
|
{&DDRK, &PINK, &PORTK, 5}, // K5 67
|
||||||
{&DDRK, &PINK, &PORTK, 6}, // K6 68
|
{&DDRK, &PINK, &PORTK, 6}, // K6 68
|
||||||
{&DDRK, &PINK, &PORTK, 7} // K7 69
|
{&DDRK, &PINK, &PORTK, 7} // K7 69
|
||||||
};
|
};
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
#elif defined(__AVR_ATmega1284P__)\
|
#elif defined(__AVR_ATmega1284P__)\
|
||||||
@@ -160,110 +160,110 @@ static const pin_map_t pinMap[] = {
|
|||||||
#ifdef defined(VARIANT_MIGHTY)
|
#ifdef defined(VARIANT_MIGHTY)
|
||||||
// Mighty Layout
|
// Mighty Layout
|
||||||
static const pin_map_t pinMap[] = {
|
static const pin_map_t pinMap[] = {
|
||||||
{&DDRB, &PINB, &PORTB, 0}, // B0 0
|
{&DDRB, &PINB, &PORTB, 0}, // B0 0
|
||||||
{&DDRB, &PINB, &PORTB, 1}, // B1 1
|
{&DDRB, &PINB, &PORTB, 1}, // B1 1
|
||||||
{&DDRB, &PINB, &PORTB, 2}, // B2 2
|
{&DDRB, &PINB, &PORTB, 2}, // B2 2
|
||||||
{&DDRB, &PINB, &PORTB, 3}, // B3 3
|
{&DDRB, &PINB, &PORTB, 3}, // B3 3
|
||||||
{&DDRB, &PINB, &PORTB, 4}, // B4 4
|
{&DDRB, &PINB, &PORTB, 4}, // B4 4
|
||||||
{&DDRB, &PINB, &PORTB, 5}, // B5 5
|
{&DDRB, &PINB, &PORTB, 5}, // B5 5
|
||||||
{&DDRB, &PINB, &PORTB, 6}, // B6 6
|
{&DDRB, &PINB, &PORTB, 6}, // B6 6
|
||||||
{&DDRB, &PINB, &PORTB, 7}, // B7 7
|
{&DDRB, &PINB, &PORTB, 7}, // B7 7
|
||||||
{&DDRD, &PIND, &PORTD, 0}, // D0 8
|
{&DDRD, &PIND, &PORTD, 0}, // D0 8
|
||||||
{&DDRD, &PIND, &PORTD, 1}, // D1 9
|
{&DDRD, &PIND, &PORTD, 1}, // D1 9
|
||||||
{&DDRD, &PIND, &PORTD, 2}, // D2 10
|
{&DDRD, &PIND, &PORTD, 2}, // D2 10
|
||||||
{&DDRD, &PIND, &PORTD, 3}, // D3 11
|
{&DDRD, &PIND, &PORTD, 3}, // D3 11
|
||||||
{&DDRD, &PIND, &PORTD, 4}, // D4 12
|
{&DDRD, &PIND, &PORTD, 4}, // D4 12
|
||||||
{&DDRD, &PIND, &PORTD, 5}, // D5 13
|
{&DDRD, &PIND, &PORTD, 5}, // D5 13
|
||||||
{&DDRD, &PIND, &PORTD, 6}, // D6 14
|
{&DDRD, &PIND, &PORTD, 6}, // D6 14
|
||||||
{&DDRD, &PIND, &PORTD, 7}, // D7 15
|
{&DDRD, &PIND, &PORTD, 7}, // D7 15
|
||||||
{&DDRC, &PINC, &PORTC, 0}, // C0 16
|
{&DDRC, &PINC, &PORTC, 0}, // C0 16
|
||||||
{&DDRC, &PINC, &PORTC, 1}, // C1 17
|
{&DDRC, &PINC, &PORTC, 1}, // C1 17
|
||||||
{&DDRC, &PINC, &PORTC, 2}, // C2 18
|
{&DDRC, &PINC, &PORTC, 2}, // C2 18
|
||||||
{&DDRC, &PINC, &PORTC, 3}, // C3 19
|
{&DDRC, &PINC, &PORTC, 3}, // C3 19
|
||||||
{&DDRC, &PINC, &PORTC, 4}, // C4 20
|
{&DDRC, &PINC, &PORTC, 4}, // C4 20
|
||||||
{&DDRC, &PINC, &PORTC, 5}, // C5 21
|
{&DDRC, &PINC, &PORTC, 5}, // C5 21
|
||||||
{&DDRC, &PINC, &PORTC, 6}, // C6 22
|
{&DDRC, &PINC, &PORTC, 6}, // C6 22
|
||||||
{&DDRC, &PINC, &PORTC, 7}, // C7 23
|
{&DDRC, &PINC, &PORTC, 7}, // C7 23
|
||||||
{&DDRA, &PINA, &PORTA, 0}, // A0 24
|
{&DDRA, &PINA, &PORTA, 0}, // A0 24
|
||||||
{&DDRA, &PINA, &PORTA, 1}, // A1 25
|
{&DDRA, &PINA, &PORTA, 1}, // A1 25
|
||||||
{&DDRA, &PINA, &PORTA, 2}, // A2 26
|
{&DDRA, &PINA, &PORTA, 2}, // A2 26
|
||||||
{&DDRA, &PINA, &PORTA, 3}, // A3 27
|
{&DDRA, &PINA, &PORTA, 3}, // A3 27
|
||||||
{&DDRA, &PINA, &PORTA, 4}, // A4 28
|
{&DDRA, &PINA, &PORTA, 4}, // A4 28
|
||||||
{&DDRA, &PINA, &PORTA, 5}, // A5 29
|
{&DDRA, &PINA, &PORTA, 5}, // A5 29
|
||||||
{&DDRA, &PINA, &PORTA, 6}, // A6 30
|
{&DDRA, &PINA, &PORTA, 6}, // A6 30
|
||||||
{&DDRA, &PINA, &PORTA, 7} // A7 31
|
{&DDRA, &PINA, &PORTA, 7} // A7 31
|
||||||
};
|
};
|
||||||
#elif defined(VARIANT_BOBUINO)
|
#elif defined(VARIANT_BOBUINO)
|
||||||
// Bobuino Layout
|
// Bobuino Layout
|
||||||
static const pin_map_t pinMap[] = {
|
static const pin_map_t pinMap[] = {
|
||||||
{&DDRD, &PIND, &PORTD, 0}, // D0 0
|
{&DDRD, &PIND, &PORTD, 0}, // D0 0
|
||||||
{&DDRD, &PIND, &PORTD, 1}, // D1 1
|
{&DDRD, &PIND, &PORTD, 1}, // D1 1
|
||||||
{&DDRD, &PIND, &PORTD, 2}, // D2 2
|
{&DDRD, &PIND, &PORTD, 2}, // D2 2
|
||||||
{&DDRD, &PIND, &PORTD, 3}, // D3 3
|
{&DDRD, &PIND, &PORTD, 3}, // D3 3
|
||||||
{&DDRB, &PINB, &PORTB, 0}, // B0 4
|
{&DDRB, &PINB, &PORTB, 0}, // B0 4
|
||||||
{&DDRB, &PINB, &PORTB, 1}, // B1 5
|
{&DDRB, &PINB, &PORTB, 1}, // B1 5
|
||||||
{&DDRB, &PINB, &PORTB, 2}, // B2 6
|
{&DDRB, &PINB, &PORTB, 2}, // B2 6
|
||||||
{&DDRB, &PINB, &PORTB, 3}, // B3 7
|
{&DDRB, &PINB, &PORTB, 3}, // B3 7
|
||||||
{&DDRD, &PIND, &PORTD, 5}, // D5 8
|
{&DDRD, &PIND, &PORTD, 5}, // D5 8
|
||||||
{&DDRD, &PIND, &PORTD, 6}, // D6 9
|
{&DDRD, &PIND, &PORTD, 6}, // D6 9
|
||||||
{&DDRB, &PINB, &PORTB, 4}, // B4 10
|
{&DDRB, &PINB, &PORTB, 4}, // B4 10
|
||||||
{&DDRB, &PINB, &PORTB, 5}, // B5 11
|
{&DDRB, &PINB, &PORTB, 5}, // B5 11
|
||||||
{&DDRB, &PINB, &PORTB, 6}, // B6 12
|
{&DDRB, &PINB, &PORTB, 6}, // B6 12
|
||||||
{&DDRB, &PINB, &PORTB, 7}, // B7 13
|
{&DDRB, &PINB, &PORTB, 7}, // B7 13
|
||||||
{&DDRA, &PINA, &PORTA, 7}, // A7 14
|
{&DDRA, &PINA, &PORTA, 7}, // A7 14
|
||||||
{&DDRA, &PINA, &PORTA, 6}, // A6 15
|
{&DDRA, &PINA, &PORTA, 6}, // A6 15
|
||||||
{&DDRA, &PINA, &PORTA, 5}, // A5 16
|
{&DDRA, &PINA, &PORTA, 5}, // A5 16
|
||||||
{&DDRA, &PINA, &PORTA, 4}, // A4 17
|
{&DDRA, &PINA, &PORTA, 4}, // A4 17
|
||||||
{&DDRA, &PINA, &PORTA, 3}, // A3 18
|
{&DDRA, &PINA, &PORTA, 3}, // A3 18
|
||||||
{&DDRA, &PINA, &PORTA, 2}, // A2 19
|
{&DDRA, &PINA, &PORTA, 2}, // A2 19
|
||||||
{&DDRA, &PINA, &PORTA, 1}, // A1 20
|
{&DDRA, &PINA, &PORTA, 1}, // A1 20
|
||||||
{&DDRA, &PINA, &PORTA, 0}, // A0 21
|
{&DDRA, &PINA, &PORTA, 0}, // A0 21
|
||||||
{&DDRC, &PINC, &PORTC, 0}, // C0 22
|
{&DDRC, &PINC, &PORTC, 0}, // C0 22
|
||||||
{&DDRC, &PINC, &PORTC, 1}, // C1 23
|
{&DDRC, &PINC, &PORTC, 1}, // C1 23
|
||||||
{&DDRC, &PINC, &PORTC, 2}, // C2 24
|
{&DDRC, &PINC, &PORTC, 2}, // C2 24
|
||||||
{&DDRC, &PINC, &PORTC, 3}, // C3 25
|
{&DDRC, &PINC, &PORTC, 3}, // C3 25
|
||||||
{&DDRC, &PINC, &PORTC, 4}, // C4 26
|
{&DDRC, &PINC, &PORTC, 4}, // C4 26
|
||||||
{&DDRC, &PINC, &PORTC, 5}, // C5 27
|
{&DDRC, &PINC, &PORTC, 5}, // C5 27
|
||||||
{&DDRC, &PINC, &PORTC, 6}, // C6 28
|
{&DDRC, &PINC, &PORTC, 6}, // C6 28
|
||||||
{&DDRC, &PINC, &PORTC, 7}, // C7 29
|
{&DDRC, &PINC, &PORTC, 7}, // C7 29
|
||||||
{&DDRD, &PIND, &PORTD, 4}, // D4 30
|
{&DDRD, &PIND, &PORTD, 4}, // D4 30
|
||||||
{&DDRD, &PIND, &PORTD, 7} // D7 31
|
{&DDRD, &PIND, &PORTD, 7} // D7 31
|
||||||
};
|
};
|
||||||
#elif defined(VARIANT_STANDARD)
|
#elif defined(VARIANT_STANDARD)
|
||||||
// Standard Layout
|
// Standard Layout
|
||||||
static const pin_map_t pinMap[] = {
|
static const pin_map_t pinMap[] = {
|
||||||
{&DDRB, &PINB, &PORTB, 0}, // B0 0
|
{&DDRB, &PINB, &PORTB, 0}, // B0 0
|
||||||
{&DDRB, &PINB, &PORTB, 1}, // B1 1
|
{&DDRB, &PINB, &PORTB, 1}, // B1 1
|
||||||
{&DDRB, &PINB, &PORTB, 2}, // B2 2
|
{&DDRB, &PINB, &PORTB, 2}, // B2 2
|
||||||
{&DDRB, &PINB, &PORTB, 3}, // B3 3
|
{&DDRB, &PINB, &PORTB, 3}, // B3 3
|
||||||
{&DDRB, &PINB, &PORTB, 4}, // B4 4
|
{&DDRB, &PINB, &PORTB, 4}, // B4 4
|
||||||
{&DDRB, &PINB, &PORTB, 5}, // B5 5
|
{&DDRB, &PINB, &PORTB, 5}, // B5 5
|
||||||
{&DDRB, &PINB, &PORTB, 6}, // B6 6
|
{&DDRB, &PINB, &PORTB, 6}, // B6 6
|
||||||
{&DDRB, &PINB, &PORTB, 7}, // B7 7
|
{&DDRB, &PINB, &PORTB, 7}, // B7 7
|
||||||
{&DDRD, &PIND, &PORTD, 0}, // D0 8
|
{&DDRD, &PIND, &PORTD, 0}, // D0 8
|
||||||
{&DDRD, &PIND, &PORTD, 1}, // D1 9
|
{&DDRD, &PIND, &PORTD, 1}, // D1 9
|
||||||
{&DDRD, &PIND, &PORTD, 2}, // D2 10
|
{&DDRD, &PIND, &PORTD, 2}, // D2 10
|
||||||
{&DDRD, &PIND, &PORTD, 3}, // D3 11
|
{&DDRD, &PIND, &PORTD, 3}, // D3 11
|
||||||
{&DDRD, &PIND, &PORTD, 4}, // D4 12
|
{&DDRD, &PIND, &PORTD, 4}, // D4 12
|
||||||
{&DDRD, &PIND, &PORTD, 5}, // D5 13
|
{&DDRD, &PIND, &PORTD, 5}, // D5 13
|
||||||
{&DDRD, &PIND, &PORTD, 6}, // D6 14
|
{&DDRD, &PIND, &PORTD, 6}, // D6 14
|
||||||
{&DDRD, &PIND, &PORTD, 7}, // D7 15
|
{&DDRD, &PIND, &PORTD, 7}, // D7 15
|
||||||
{&DDRC, &PINC, &PORTC, 0}, // C0 16
|
{&DDRC, &PINC, &PORTC, 0}, // C0 16
|
||||||
{&DDRC, &PINC, &PORTC, 1}, // C1 17
|
{&DDRC, &PINC, &PORTC, 1}, // C1 17
|
||||||
{&DDRC, &PINC, &PORTC, 2}, // C2 18
|
{&DDRC, &PINC, &PORTC, 2}, // C2 18
|
||||||
{&DDRC, &PINC, &PORTC, 3}, // C3 19
|
{&DDRC, &PINC, &PORTC, 3}, // C3 19
|
||||||
{&DDRC, &PINC, &PORTC, 4}, // C4 20
|
{&DDRC, &PINC, &PORTC, 4}, // C4 20
|
||||||
{&DDRC, &PINC, &PORTC, 5}, // C5 21
|
{&DDRC, &PINC, &PORTC, 5}, // C5 21
|
||||||
{&DDRC, &PINC, &PORTC, 6}, // C6 22
|
{&DDRC, &PINC, &PORTC, 6}, // C6 22
|
||||||
{&DDRC, &PINC, &PORTC, 7}, // C7 23
|
{&DDRC, &PINC, &PORTC, 7}, // C7 23
|
||||||
{&DDRA, &PINA, &PORTA, 7}, // A7 24
|
{&DDRA, &PINA, &PORTA, 7}, // A7 24
|
||||||
{&DDRA, &PINA, &PORTA, 6}, // A6 25
|
{&DDRA, &PINA, &PORTA, 6}, // A6 25
|
||||||
{&DDRA, &PINA, &PORTA, 5}, // A5 26
|
{&DDRA, &PINA, &PORTA, 5}, // A5 26
|
||||||
{&DDRA, &PINA, &PORTA, 4}, // A4 27
|
{&DDRA, &PINA, &PORTA, 4}, // A4 27
|
||||||
{&DDRA, &PINA, &PORTA, 3}, // A3 28
|
{&DDRA, &PINA, &PORTA, 3}, // A3 28
|
||||||
{&DDRA, &PINA, &PORTA, 2}, // A2 29
|
{&DDRA, &PINA, &PORTA, 2}, // A2 29
|
||||||
{&DDRA, &PINA, &PORTA, 1}, // A1 30
|
{&DDRA, &PINA, &PORTA, 1}, // A1 30
|
||||||
{&DDRA, &PINA, &PORTA, 0} // A0 31
|
{&DDRA, &PINA, &PORTA, 0} // A0 31
|
||||||
};
|
};
|
||||||
#else // VARIANT_MIGHTY
|
#else // VARIANT_MIGHTY
|
||||||
#error Undefined variant 1284, 644, 324, 64, 32
|
#error Undefined variant 1284, 644, 324, 64, 32
|
||||||
@@ -273,66 +273,66 @@ static const pin_map_t pinMap[] = {
|
|||||||
#ifdef CORE_TEENSY
|
#ifdef CORE_TEENSY
|
||||||
// Teensy 2.0
|
// Teensy 2.0
|
||||||
static const pin_map_t pinMap[] = {
|
static const pin_map_t pinMap[] = {
|
||||||
{&DDRB, &PINB, &PORTB, 0}, // B0 0
|
{&DDRB, &PINB, &PORTB, 0}, // B0 0
|
||||||
{&DDRB, &PINB, &PORTB, 1}, // B1 1
|
{&DDRB, &PINB, &PORTB, 1}, // B1 1
|
||||||
{&DDRB, &PINB, &PORTB, 2}, // B2 2
|
{&DDRB, &PINB, &PORTB, 2}, // B2 2
|
||||||
{&DDRB, &PINB, &PORTB, 3}, // B3 3
|
{&DDRB, &PINB, &PORTB, 3}, // B3 3
|
||||||
{&DDRB, &PINB, &PORTB, 7}, // B7 4
|
{&DDRB, &PINB, &PORTB, 7}, // B7 4
|
||||||
{&DDRD, &PIND, &PORTD, 0}, // D0 5
|
{&DDRD, &PIND, &PORTD, 0}, // D0 5
|
||||||
{&DDRD, &PIND, &PORTD, 1}, // D1 6
|
{&DDRD, &PIND, &PORTD, 1}, // D1 6
|
||||||
{&DDRD, &PIND, &PORTD, 2}, // D2 7
|
{&DDRD, &PIND, &PORTD, 2}, // D2 7
|
||||||
{&DDRD, &PIND, &PORTD, 3}, // D3 8
|
{&DDRD, &PIND, &PORTD, 3}, // D3 8
|
||||||
{&DDRC, &PINC, &PORTC, 6}, // C6 9
|
{&DDRC, &PINC, &PORTC, 6}, // C6 9
|
||||||
{&DDRC, &PINC, &PORTC, 7}, // C7 10
|
{&DDRC, &PINC, &PORTC, 7}, // C7 10
|
||||||
{&DDRD, &PIND, &PORTD, 6}, // D6 11
|
{&DDRD, &PIND, &PORTD, 6}, // D6 11
|
||||||
{&DDRD, &PIND, &PORTD, 7}, // D7 12
|
{&DDRD, &PIND, &PORTD, 7}, // D7 12
|
||||||
{&DDRB, &PINB, &PORTB, 4}, // B4 13
|
{&DDRB, &PINB, &PORTB, 4}, // B4 13
|
||||||
{&DDRB, &PINB, &PORTB, 5}, // B5 14
|
{&DDRB, &PINB, &PORTB, 5}, // B5 14
|
||||||
{&DDRB, &PINB, &PORTB, 6}, // B6 15
|
{&DDRB, &PINB, &PORTB, 6}, // B6 15
|
||||||
{&DDRF, &PINF, &PORTF, 7}, // F7 16
|
{&DDRF, &PINF, &PORTF, 7}, // F7 16
|
||||||
{&DDRF, &PINF, &PORTF, 6}, // F6 17
|
{&DDRF, &PINF, &PORTF, 6}, // F6 17
|
||||||
{&DDRF, &PINF, &PORTF, 5}, // F5 18
|
{&DDRF, &PINF, &PORTF, 5}, // F5 18
|
||||||
{&DDRF, &PINF, &PORTF, 4}, // F4 19
|
{&DDRF, &PINF, &PORTF, 4}, // F4 19
|
||||||
{&DDRF, &PINF, &PORTF, 1}, // F1 20
|
{&DDRF, &PINF, &PORTF, 1}, // F1 20
|
||||||
{&DDRF, &PINF, &PORTF, 0}, // F0 21
|
{&DDRF, &PINF, &PORTF, 0}, // F0 21
|
||||||
{&DDRD, &PIND, &PORTD, 4}, // D4 22
|
{&DDRD, &PIND, &PORTD, 4}, // D4 22
|
||||||
{&DDRD, &PIND, &PORTD, 5}, // D5 23
|
{&DDRD, &PIND, &PORTD, 5}, // D5 23
|
||||||
{&DDRE, &PINE, &PORTE, 6} // E6 24
|
{&DDRE, &PINE, &PORTE, 6} // E6 24
|
||||||
};
|
};
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
#else // CORE_TEENSY
|
#else // CORE_TEENSY
|
||||||
// Leonardo
|
// Leonardo
|
||||||
static const pin_map_t pinMap[] = {
|
static const pin_map_t pinMap[] = {
|
||||||
{&DDRD, &PIND, &PORTD, 2}, // D2 0
|
{&DDRD, &PIND, &PORTD, 2}, // D2 0
|
||||||
{&DDRD, &PIND, &PORTD, 3}, // D3 1
|
{&DDRD, &PIND, &PORTD, 3}, // D3 1
|
||||||
{&DDRD, &PIND, &PORTD, 1}, // D1 2
|
{&DDRD, &PIND, &PORTD, 1}, // D1 2
|
||||||
{&DDRD, &PIND, &PORTD, 0}, // D0 3
|
{&DDRD, &PIND, &PORTD, 0}, // D0 3
|
||||||
{&DDRD, &PIND, &PORTD, 4}, // D4 4
|
{&DDRD, &PIND, &PORTD, 4}, // D4 4
|
||||||
{&DDRC, &PINC, &PORTC, 6}, // C6 5
|
{&DDRC, &PINC, &PORTC, 6}, // C6 5
|
||||||
{&DDRD, &PIND, &PORTD, 7}, // D7 6
|
{&DDRD, &PIND, &PORTD, 7}, // D7 6
|
||||||
{&DDRE, &PINE, &PORTE, 6}, // E6 7
|
{&DDRE, &PINE, &PORTE, 6}, // E6 7
|
||||||
{&DDRB, &PINB, &PORTB, 4}, // B4 8
|
{&DDRB, &PINB, &PORTB, 4}, // B4 8
|
||||||
{&DDRB, &PINB, &PORTB, 5}, // B5 9
|
{&DDRB, &PINB, &PORTB, 5}, // B5 9
|
||||||
{&DDRB, &PINB, &PORTB, 6}, // B6 10
|
{&DDRB, &PINB, &PORTB, 6}, // B6 10
|
||||||
{&DDRB, &PINB, &PORTB, 7}, // B7 11
|
{&DDRB, &PINB, &PORTB, 7}, // B7 11
|
||||||
{&DDRD, &PIND, &PORTD, 6}, // D6 12
|
{&DDRD, &PIND, &PORTD, 6}, // D6 12
|
||||||
{&DDRC, &PINC, &PORTC, 7}, // C7 13
|
{&DDRC, &PINC, &PORTC, 7}, // C7 13
|
||||||
{&DDRB, &PINB, &PORTB, 3}, // B3 14
|
{&DDRB, &PINB, &PORTB, 3}, // B3 14
|
||||||
{&DDRB, &PINB, &PORTB, 1}, // B1 15
|
{&DDRB, &PINB, &PORTB, 1}, // B1 15
|
||||||
{&DDRB, &PINB, &PORTB, 2}, // B2 16
|
{&DDRB, &PINB, &PORTB, 2}, // B2 16
|
||||||
{&DDRB, &PINB, &PORTB, 0}, // B0 17
|
{&DDRB, &PINB, &PORTB, 0}, // B0 17
|
||||||
{&DDRF, &PINF, &PORTF, 7}, // F7 18
|
{&DDRF, &PINF, &PORTF, 7}, // F7 18
|
||||||
{&DDRF, &PINF, &PORTF, 6}, // F6 19
|
{&DDRF, &PINF, &PORTF, 6}, // F6 19
|
||||||
{&DDRF, &PINF, &PORTF, 5}, // F5 20
|
{&DDRF, &PINF, &PORTF, 5}, // F5 20
|
||||||
{&DDRF, &PINF, &PORTF, 4}, // F4 21
|
{&DDRF, &PINF, &PORTF, 4}, // F4 21
|
||||||
{&DDRF, &PINF, &PORTF, 1}, // F1 22
|
{&DDRF, &PINF, &PORTF, 1}, // F1 22
|
||||||
{&DDRF, &PINF, &PORTF, 0}, // F0 23
|
{&DDRF, &PINF, &PORTF, 0}, // F0 23
|
||||||
{&DDRD, &PIND, &PORTD, 4}, // D4 24
|
{&DDRD, &PIND, &PORTD, 4}, // D4 24
|
||||||
{&DDRD, &PIND, &PORTD, 7}, // D7 25
|
{&DDRD, &PIND, &PORTD, 7}, // D7 25
|
||||||
{&DDRB, &PINB, &PORTB, 4}, // B4 26
|
{&DDRB, &PINB, &PORTB, 4}, // B4 26
|
||||||
{&DDRB, &PINB, &PORTB, 5}, // B5 27
|
{&DDRB, &PINB, &PORTB, 5}, // B5 27
|
||||||
{&DDRB, &PINB, &PORTB, 6}, // B6 28
|
{&DDRB, &PINB, &PORTB, 6}, // B6 28
|
||||||
{&DDRD, &PIND, &PORTD, 6} // D6 29
|
{&DDRD, &PIND, &PORTD, 6} // D6 29
|
||||||
};
|
};
|
||||||
#endif // CORE_TEENSY
|
#endif // CORE_TEENSY
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -340,52 +340,52 @@ static const pin_map_t pinMap[] = {
|
|||||||
|| defined(__AVR_AT90USB1286__)
|
|| defined(__AVR_AT90USB1286__)
|
||||||
// Teensy++ 1.0 & 2.0
|
// Teensy++ 1.0 & 2.0
|
||||||
static const pin_map_t pinMap[] = {
|
static const pin_map_t pinMap[] = {
|
||||||
{&DDRD, &PIND, &PORTD, 0}, // D0 0
|
{&DDRD, &PIND, &PORTD, 0}, // D0 0
|
||||||
{&DDRD, &PIND, &PORTD, 1}, // D1 1
|
{&DDRD, &PIND, &PORTD, 1}, // D1 1
|
||||||
{&DDRD, &PIND, &PORTD, 2}, // D2 2
|
{&DDRD, &PIND, &PORTD, 2}, // D2 2
|
||||||
{&DDRD, &PIND, &PORTD, 3}, // D3 3
|
{&DDRD, &PIND, &PORTD, 3}, // D3 3
|
||||||
{&DDRD, &PIND, &PORTD, 4}, // D4 4
|
{&DDRD, &PIND, &PORTD, 4}, // D4 4
|
||||||
{&DDRD, &PIND, &PORTD, 5}, // D5 5
|
{&DDRD, &PIND, &PORTD, 5}, // D5 5
|
||||||
{&DDRD, &PIND, &PORTD, 6}, // D6 6
|
{&DDRD, &PIND, &PORTD, 6}, // D6 6
|
||||||
{&DDRD, &PIND, &PORTD, 7}, // D7 7
|
{&DDRD, &PIND, &PORTD, 7}, // D7 7
|
||||||
{&DDRE, &PINE, &PORTE, 0}, // E0 8
|
{&DDRE, &PINE, &PORTE, 0}, // E0 8
|
||||||
{&DDRE, &PINE, &PORTE, 1}, // E1 9
|
{&DDRE, &PINE, &PORTE, 1}, // E1 9
|
||||||
{&DDRC, &PINC, &PORTC, 0}, // C0 10
|
{&DDRC, &PINC, &PORTC, 0}, // C0 10
|
||||||
{&DDRC, &PINC, &PORTC, 1}, // C1 11
|
{&DDRC, &PINC, &PORTC, 1}, // C1 11
|
||||||
{&DDRC, &PINC, &PORTC, 2}, // C2 12
|
{&DDRC, &PINC, &PORTC, 2}, // C2 12
|
||||||
{&DDRC, &PINC, &PORTC, 3}, // C3 13
|
{&DDRC, &PINC, &PORTC, 3}, // C3 13
|
||||||
{&DDRC, &PINC, &PORTC, 4}, // C4 14
|
{&DDRC, &PINC, &PORTC, 4}, // C4 14
|
||||||
{&DDRC, &PINC, &PORTC, 5}, // C5 15
|
{&DDRC, &PINC, &PORTC, 5}, // C5 15
|
||||||
{&DDRC, &PINC, &PORTC, 6}, // C6 16
|
{&DDRC, &PINC, &PORTC, 6}, // C6 16
|
||||||
{&DDRC, &PINC, &PORTC, 7}, // C7 17
|
{&DDRC, &PINC, &PORTC, 7}, // C7 17
|
||||||
{&DDRE, &PINE, &PORTE, 6}, // E6 18
|
{&DDRE, &PINE, &PORTE, 6}, // E6 18
|
||||||
{&DDRE, &PINE, &PORTE, 7}, // E7 19
|
{&DDRE, &PINE, &PORTE, 7}, // E7 19
|
||||||
{&DDRB, &PINB, &PORTB, 0}, // B0 20
|
{&DDRB, &PINB, &PORTB, 0}, // B0 20
|
||||||
{&DDRB, &PINB, &PORTB, 1}, // B1 21
|
{&DDRB, &PINB, &PORTB, 1}, // B1 21
|
||||||
{&DDRB, &PINB, &PORTB, 2}, // B2 22
|
{&DDRB, &PINB, &PORTB, 2}, // B2 22
|
||||||
{&DDRB, &PINB, &PORTB, 3}, // B3 23
|
{&DDRB, &PINB, &PORTB, 3}, // B3 23
|
||||||
{&DDRB, &PINB, &PORTB, 4}, // B4 24
|
{&DDRB, &PINB, &PORTB, 4}, // B4 24
|
||||||
{&DDRB, &PINB, &PORTB, 5}, // B5 25
|
{&DDRB, &PINB, &PORTB, 5}, // B5 25
|
||||||
{&DDRB, &PINB, &PORTB, 6}, // B6 26
|
{&DDRB, &PINB, &PORTB, 6}, // B6 26
|
||||||
{&DDRB, &PINB, &PORTB, 7}, // B7 27
|
{&DDRB, &PINB, &PORTB, 7}, // B7 27
|
||||||
{&DDRA, &PINA, &PORTA, 0}, // A0 28
|
{&DDRA, &PINA, &PORTA, 0}, // A0 28
|
||||||
{&DDRA, &PINA, &PORTA, 1}, // A1 29
|
{&DDRA, &PINA, &PORTA, 1}, // A1 29
|
||||||
{&DDRA, &PINA, &PORTA, 2}, // A2 30
|
{&DDRA, &PINA, &PORTA, 2}, // A2 30
|
||||||
{&DDRA, &PINA, &PORTA, 3}, // A3 31
|
{&DDRA, &PINA, &PORTA, 3}, // A3 31
|
||||||
{&DDRA, &PINA, &PORTA, 4}, // A4 32
|
{&DDRA, &PINA, &PORTA, 4}, // A4 32
|
||||||
{&DDRA, &PINA, &PORTA, 5}, // A5 33
|
{&DDRA, &PINA, &PORTA, 5}, // A5 33
|
||||||
{&DDRA, &PINA, &PORTA, 6}, // A6 34
|
{&DDRA, &PINA, &PORTA, 6}, // A6 34
|
||||||
{&DDRA, &PINA, &PORTA, 7}, // A7 35
|
{&DDRA, &PINA, &PORTA, 7}, // A7 35
|
||||||
{&DDRE, &PINE, &PORTE, 4}, // E4 36
|
{&DDRE, &PINE, &PORTE, 4}, // E4 36
|
||||||
{&DDRE, &PINE, &PORTE, 5}, // E5 37
|
{&DDRE, &PINE, &PORTE, 5}, // E5 37
|
||||||
{&DDRF, &PINF, &PORTF, 0}, // F0 38
|
{&DDRF, &PINF, &PORTF, 0}, // F0 38
|
||||||
{&DDRF, &PINF, &PORTF, 1}, // F1 39
|
{&DDRF, &PINF, &PORTF, 1}, // F1 39
|
||||||
{&DDRF, &PINF, &PORTF, 2}, // F2 40
|
{&DDRF, &PINF, &PORTF, 2}, // F2 40
|
||||||
{&DDRF, &PINF, &PORTF, 3}, // F3 41
|
{&DDRF, &PINF, &PORTF, 3}, // F3 41
|
||||||
{&DDRF, &PINF, &PORTF, 4}, // F4 42
|
{&DDRF, &PINF, &PORTF, 4}, // F4 42
|
||||||
{&DDRF, &PINF, &PORTF, 5}, // F5 43
|
{&DDRF, &PINF, &PORTF, 5}, // F5 43
|
||||||
{&DDRF, &PINF, &PORTF, 6}, // F6 44
|
{&DDRF, &PINF, &PORTF, 6}, // F6 44
|
||||||
{&DDRF, &PINF, &PORTF, 7} // F7 45
|
{&DDRF, &PINF, &PORTF, 7} // F7 45
|
||||||
};
|
};
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
#else // CPU type
|
#else // CPU type
|
||||||
@@ -397,15 +397,16 @@ 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) {
|
{
|
||||||
badPinNumber();
|
if (!__builtin_constant_p(pin) || pin >= digitalPinCount) {
|
||||||
}
|
badPinNumber();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** fast write helper
|
/** fast write helper
|
||||||
@@ -413,29 +414,31 @@ 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;
|
{
|
||||||
if (address > (uint8_t*)0X5F) {
|
uint8_t oldSREG;
|
||||||
oldSREG = SREG;
|
if (address > (uint8_t*)0X5F) {
|
||||||
cli();
|
oldSREG = SREG;
|
||||||
}
|
cli();
|
||||||
if (level) {
|
}
|
||||||
*address |= 1 << bit;
|
if (level) {
|
||||||
} else {
|
*address |= 1 << bit;
|
||||||
*address &= ~(1 << bit);
|
} else {
|
||||||
}
|
*address &= ~(1 << bit);
|
||||||
if (address > (uint8_t*)0X5F) {
|
}
|
||||||
SREG = oldSREG;
|
if (address > (uint8_t*)0X5F) {
|
||||||
}
|
SREG = oldSREG;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** read pin value
|
/** read pin value
|
||||||
* @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);
|
{
|
||||||
return (*pinMap[pin].pin >> pinMap[pin].bit) & 1;
|
badPinCheck(pin);
|
||||||
|
return (*pinMap[pin].pin >> pinMap[pin].bit) & 1;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** toggle a pin
|
/** toggle a pin
|
||||||
@@ -444,24 +447,26 @@ static ALWAYS_INLINE bool fastDigitalRead(uint8_t pin) {
|
|||||||
* If the pin is in output mode toggle the pin level.
|
* If the pin is in 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);
|
{
|
||||||
if (pinMap[pin].pin > (uint8_t*)0X5F) {
|
badPinCheck(pin);
|
||||||
// must write bit to high address port
|
if (pinMap[pin].pin > (uint8_t*)0X5F) {
|
||||||
*pinMap[pin].pin = 1 << pinMap[pin].bit;
|
// must write bit to high address port
|
||||||
} else {
|
*pinMap[pin].pin = 1 << pinMap[pin].bit;
|
||||||
// will compile to sbi and PIN register will not be read.
|
} else {
|
||||||
*pinMap[pin].pin |= 1 << pinMap[pin].bit;
|
// will compile to sbi and PIN register will not be read.
|
||||||
}
|
*pinMap[pin].pin |= 1 << pinMap[pin].bit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** Set pin value
|
/** Set pin value
|
||||||
* @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);
|
{
|
||||||
fastBitWriteSafe(pinMap[pin].port, pinMap[pin].bit, level);
|
badPinCheck(pin);
|
||||||
|
fastBitWriteSafe(pinMap[pin].port, pinMap[pin].bit, level);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** set pin mode
|
/** set pin mode
|
||||||
@@ -470,9 +475,10 @@ static ALWAYS_INLINE void fastDigitalWrite(uint8_t pin, bool level) {
|
|||||||
*
|
*
|
||||||
* fastPinMode does not enable or disable the 20K pullup for input mode.
|
* 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);
|
{
|
||||||
fastBitWriteSafe(pinMap[pin].ddr, pinMap[pin].bit, mode);
|
badPinCheck(pin);
|
||||||
|
fastBitWriteSafe(pinMap[pin].ddr, pinMap[pin].bit, mode);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** set pin configuration
|
/** set pin configuration
|
||||||
@@ -481,9 +487,10 @@ static ALWAYS_INLINE void fastPinMode(uint8_t pin, bool mode) {
|
|||||||
* @param[in] level If mode is output, set level high/low.
|
* @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);
|
{
|
||||||
fastDigitalWrite(pin, level);
|
fastPinMode(pin, mode);
|
||||||
|
fastDigitalWrite(pin, level);
|
||||||
}
|
}
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/**
|
/**
|
||||||
@@ -491,96 +498,112 @@ static ALWAYS_INLINE void fastPinConfig(uint8_t pin, bool mode, bool level) {
|
|||||||
* @brief Fast AVR digital port I/O
|
* @brief Fast AVR digital port I/O
|
||||||
*/
|
*/
|
||||||
template<uint8_t PinNumber>
|
template<uint8_t PinNumber>
|
||||||
class DigitalPin {
|
class DigitalPin
|
||||||
public:
|
{
|
||||||
//----------------------------------------------------------------------------
|
public:
|
||||||
/** Constructor */
|
//----------------------------------------------------------------------------
|
||||||
DigitalPin() {}
|
/** Constructor */
|
||||||
//----------------------------------------------------------------------------
|
DigitalPin() {}
|
||||||
/** Constructor
|
//----------------------------------------------------------------------------
|
||||||
* @param[in] pinMode if true set output mode else input mode.
|
/** Constructor
|
||||||
*/
|
* @param[in] pinMode if true set output mode else input mode.
|
||||||
explicit DigitalPin(bool pinMode) {
|
*/
|
||||||
mode(pinMode);
|
explicit DigitalPin(bool pinMode)
|
||||||
}
|
{
|
||||||
//----------------------------------------------------------------------------
|
mode(pinMode);
|
||||||
/** Constructor
|
}
|
||||||
* @param[in] mode If true set output mode else input mode
|
//----------------------------------------------------------------------------
|
||||||
* @param[in] level If mode is output, set level high/low.
|
/** Constructor
|
||||||
* If mode is input, enable or disable the pin's 20K pullup.
|
* @param[in] mode If true set output mode else input mode
|
||||||
*/
|
* @param[in] level If mode is output, set level high/low.
|
||||||
DigitalPin(bool mode, bool level) {
|
* If mode is input, enable or disable the pin's 20K pullup.
|
||||||
config(mode, level);
|
*/
|
||||||
}
|
DigitalPin(bool mode, bool level)
|
||||||
//----------------------------------------------------------------------------
|
{
|
||||||
/** Asignment operator
|
config(mode, level);
|
||||||
* @param[in] value If true set the pin's level high else set the
|
}
|
||||||
* pin's level low.
|
//----------------------------------------------------------------------------
|
||||||
*
|
/** Asignment operator
|
||||||
* @return This DigitalPin instance.
|
* @param[in] value If true set the pin's level high else set the
|
||||||
*/
|
* pin's level low.
|
||||||
inline DigitalPin & operator = (bool value) __attribute__((always_inline)) {
|
*
|
||||||
write(value);
|
* @return This DigitalPin instance.
|
||||||
return *this;
|
*/
|
||||||
}
|
inline DigitalPin & operator = (bool value) __attribute__((always_inline))
|
||||||
//----------------------------------------------------------------------------
|
{
|
||||||
/** Parenthesis operator
|
write(value);
|
||||||
* @return Pin's level
|
return *this;
|
||||||
*/
|
}
|
||||||
inline operator bool () const __attribute__((always_inline)) {
|
//----------------------------------------------------------------------------
|
||||||
return read();
|
/** Parenthesis operator
|
||||||
}
|
* @return Pin's level
|
||||||
//----------------------------------------------------------------------------
|
*/
|
||||||
/** set pin configuration
|
inline operator bool () const __attribute__((always_inline))
|
||||||
* @param[in] mode If true set output mode else input mode
|
{
|
||||||
* @param[in] level If mode is output, set level high/low.
|
return read();
|
||||||
* If mode is input, enable or disable the pin's 20K pullup.
|
}
|
||||||
*/
|
//----------------------------------------------------------------------------
|
||||||
ALWAYS_INLINE void config(bool mode, bool level) {
|
/** set pin configuration
|
||||||
fastPinConfig(PinNumber, mode, level);
|
* @param[in] mode If true set output mode else input mode
|
||||||
}
|
* @param[in] level If mode is output, set level high/low.
|
||||||
//----------------------------------------------------------------------------
|
* If mode is input, enable or disable the pin's 20K pullup.
|
||||||
/**
|
*/
|
||||||
* Set pin level high if output mode or enable 20K pullup if input mode.
|
ALWAYS_INLINE void config(bool mode, bool level)
|
||||||
*/
|
{
|
||||||
ALWAYS_INLINE void high() {write(true);}
|
fastPinConfig(PinNumber, mode, level);
|
||||||
//----------------------------------------------------------------------------
|
}
|
||||||
/**
|
//----------------------------------------------------------------------------
|
||||||
* Set pin level low if output mode or disable 20K pullup if input mode.
|
/**
|
||||||
*/
|
* Set pin level high if output mode or enable 20K pullup if input mode.
|
||||||
ALWAYS_INLINE void low() {write(false);}
|
*/
|
||||||
//----------------------------------------------------------------------------
|
ALWAYS_INLINE void high()
|
||||||
/**
|
{
|
||||||
* Set pin mode
|
write(true);
|
||||||
* @param[in] pinMode if true set output mode else input mode.
|
}
|
||||||
*
|
//----------------------------------------------------------------------------
|
||||||
* mode() does not enable or disable the 20K pullup for input mode.
|
/**
|
||||||
*/
|
* Set pin level low if output mode or disable 20K pullup if input mode.
|
||||||
ALWAYS_INLINE void mode(bool pinMode) {
|
*/
|
||||||
fastPinMode(PinNumber, pinMode);
|
ALWAYS_INLINE void low()
|
||||||
}
|
{
|
||||||
//----------------------------------------------------------------------------
|
write(false);
|
||||||
/** @return Pin's level */
|
}
|
||||||
ALWAYS_INLINE bool read() const {
|
//----------------------------------------------------------------------------
|
||||||
return fastDigitalRead(PinNumber);
|
/**
|
||||||
}
|
* Set pin mode
|
||||||
//----------------------------------------------------------------------------
|
* @param[in] pinMode if true set output mode else input mode.
|
||||||
/** toggle a pin
|
*
|
||||||
*
|
* mode() does not enable or disable the 20K pullup for input mode.
|
||||||
* If the pin is in output mode toggle the pin's level.
|
*/
|
||||||
* If the pin is in input mode toggle the state of the 20K pullup.
|
ALWAYS_INLINE void mode(bool pinMode)
|
||||||
*/
|
{
|
||||||
ALWAYS_INLINE void toggle() {
|
fastPinMode(PinNumber, pinMode);
|
||||||
fastDigitalToggle(PinNumber);
|
}
|
||||||
}
|
//----------------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------------
|
/** @return Pin's level */
|
||||||
/** Write the pin's level.
|
ALWAYS_INLINE bool read() const
|
||||||
* @param[in] value If true set the pin's level high else set the
|
{
|
||||||
* pin's level low.
|
return fastDigitalRead(PinNumber);
|
||||||
*/
|
}
|
||||||
ALWAYS_INLINE void write(bool value) {
|
//----------------------------------------------------------------------------
|
||||||
fastDigitalWrite(PinNumber, value);
|
/** toggle a pin
|
||||||
}
|
*
|
||||||
|
* If the pin is in output mode toggle the pin's level.
|
||||||
|
* If the pin is in input mode toggle the state of the 20K pullup.
|
||||||
|
*/
|
||||||
|
ALWAYS_INLINE void toggle()
|
||||||
|
{
|
||||||
|
fastDigitalToggle(PinNumber);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
/** Write the pin's level.
|
||||||
|
* @param[in] value If true set the pin's level high else set the
|
||||||
|
* pin's level low.
|
||||||
|
*/
|
||||||
|
ALWAYS_INLINE void write(bool value)
|
||||||
|
{
|
||||||
|
fastDigitalWrite(PinNumber, value);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
#endif // DigitalPin_h
|
#endif // DigitalPin_h
|
||||||
/** @} */
|
/** @} */
|
||||||
@@ -32,22 +32,26 @@
|
|||||||
/** 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);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** Initialize pin bit mask and port address.
|
/** Initialize pin bit mask and port address.
|
||||||
* @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;
|
{
|
||||||
uint8_t port = digitalPinToPort(pin);
|
if (pin >= NUM_DIGITAL_PINS) {
|
||||||
pinReg_ = portInputRegister(port);
|
return false;
|
||||||
bit_ = digitalPinToBitMask(pin);
|
}
|
||||||
mask_ = ~bit_;
|
uint8_t port = digitalPinToPort(pin);
|
||||||
portReg_ = pinReg_ + 2;
|
pinReg_ = portInputRegister(port);
|
||||||
return true;
|
bit_ = digitalPinToBitMask(pin);
|
||||||
|
mask_ = ~bit_;
|
||||||
|
portReg_ = pinReg_ + 2;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** Configure the pin
|
/** Configure the pin
|
||||||
@@ -59,10 +63,11 @@ 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) {
|
{
|
||||||
modeI(mode);
|
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||||
writeI(data);
|
modeI(mode);
|
||||||
}
|
writeI(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|||||||
+147
-112
@@ -37,118 +37,153 @@
|
|||||||
* @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:
|
{
|
||||||
/** Create a PinIO object with no assigned pin. */
|
public:
|
||||||
PinIO() : bit_(0), mask_(0XFF) {}
|
/** Create a PinIO object with no assigned pin. */
|
||||||
/** Constructor
|
PinIO() : bit_(0), mask_(0XFF) {}
|
||||||
* @param[in] pin Pin assigned to this object.
|
/** Constructor
|
||||||
*/
|
* @param[in] pin Pin assigned to this object.
|
||||||
explicit PinIO(uint8_t pin);
|
*/
|
||||||
/** Initialize pin bit mask and port address.
|
explicit PinIO(uint8_t pin);
|
||||||
* @param[in] pin Arduino board pin number.
|
/** Initialize pin bit mask and port address.
|
||||||
* @return true for success or false if invalid pin number.
|
* @param[in] pin Arduino board pin number.
|
||||||
*/
|
* @return true for success or false if invalid pin number.
|
||||||
bool begin(uint8_t pin);
|
*/
|
||||||
/** Configure the pin
|
bool begin(uint8_t pin);
|
||||||
*
|
/** Configure the pin
|
||||||
* @param[in] mode Configure as output mode if true else input mode.
|
*
|
||||||
* @param[in] data For output mode set pin high if true else low.
|
* @param[in] mode Configure as output mode if true else input mode.
|
||||||
* For input mode enable 20K pullup if true else Hi-Z.
|
* @param[in] data For output mode set pin high if true else low.
|
||||||
*
|
* For input mode enable 20K pullup if true else Hi-Z.
|
||||||
* This function may be used with interrupts enabled or disabled.
|
*
|
||||||
* The previous interrupt state will be restored.
|
* This function may be used with interrupts enabled or disabled.
|
||||||
*/
|
* The previous interrupt state will be restored.
|
||||||
void config(bool mode, bool data);
|
*/
|
||||||
//----------------------------------------------------------------------------
|
void config(bool mode, bool data);
|
||||||
/** @return Pin's level */
|
//----------------------------------------------------------------------------
|
||||||
ALWAYS_INLINE bool read() {return *pinReg_ & bit_;}
|
/** @return Pin's level */
|
||||||
//----------------------------------------------------------------------------
|
ALWAYS_INLINE bool read()
|
||||||
/** toggle a pin
|
{
|
||||||
*
|
return *pinReg_ & bit_;
|
||||||
* 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.
|
//----------------------------------------------------------------------------
|
||||||
*/
|
/** toggle a pin
|
||||||
ALWAYS_INLINE void toggle() {*pinReg_ = bit_;}
|
*
|
||||||
//============================================================================
|
* 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.
|
||||||
* Set pin high if output mode or enable 20K pullup if input mode.
|
*/
|
||||||
*
|
ALWAYS_INLINE void toggle()
|
||||||
* This function must be called with interrupts disabled.
|
{
|
||||||
* This function will not change the interrupt state.
|
*pinReg_ = bit_;
|
||||||
*/
|
}
|
||||||
ALWAYS_INLINE void highI() {writeI(1);}
|
//============================================================================
|
||||||
/**
|
/**
|
||||||
* Set pin low if output mode or disable 20K pullup if input mode.
|
* Set pin high if output mode or enable 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 highI()
|
||||||
/**
|
{
|
||||||
* Set pin mode
|
writeI(1);
|
||||||
* @param[in] mode if true set output mode else input mode.
|
}
|
||||||
*
|
/**
|
||||||
* mode() does not enable or disable the 20K pullup for 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 modeI(bool mode) {
|
ALWAYS_INLINE void lowI()
|
||||||
volatile uint8_t* ddrReg = pinReg_ + 1;
|
{
|
||||||
*ddrReg = mode ? *ddrReg | bit_ : *ddrReg & mask_;
|
writeI(0);
|
||||||
}
|
}
|
||||||
/** Write pin.
|
/**
|
||||||
*
|
* Set pin mode
|
||||||
* @param[in] level If output mode set pin high if true else low.
|
* @param[in] mode if true set output mode else input mode.
|
||||||
* If input mode enable 20K pullup if true else disable pullup.
|
*
|
||||||
*
|
* mode() does not enable or disable the 20K pullup for input mode.
|
||||||
* This function must be called with interrupts disabled.
|
*
|
||||||
* This function will not change the interrupt state.
|
* This function must be called with interrupts disabled.
|
||||||
*/
|
* This function will not change the interrupt state.
|
||||||
ALWAYS_INLINE void writeI(bool level) {
|
*/
|
||||||
*portReg_ = level ? *portReg_ | bit_ : *portReg_ & mask_;
|
ALWAYS_INLINE void modeI(bool mode)
|
||||||
}
|
{
|
||||||
//============================================================================
|
volatile uint8_t* ddrReg = pinReg_ + 1;
|
||||||
/**
|
*ddrReg = mode ? *ddrReg | bit_ : *ddrReg & mask_;
|
||||||
* Set pin level high if output mode or enable 20K pullup if input mode.
|
}
|
||||||
*
|
/** Write pin.
|
||||||
* This function will enable interrupts. This function should not be
|
*
|
||||||
* called in an ISR or where interrupts are disabled.
|
* @param[in] level If output mode set pin high if true else low.
|
||||||
*/
|
* If input mode enable 20K pullup if true else disable pullup.
|
||||||
ALWAYS_INLINE void high() {ATOMIC_BLOCK(ATOMIC_FORCEON) {highI();}}
|
*
|
||||||
/**
|
* This function must be called with interrupts disabled.
|
||||||
* Set pin level low if output mode or disable 20K pullup if input mode.
|
* This function will not change the interrupt state.
|
||||||
*
|
*/
|
||||||
* This function will enable interrupts. This function should not be
|
ALWAYS_INLINE void writeI(bool level)
|
||||||
* called in an ISR or where interrupts are disabled.
|
{
|
||||||
*/
|
*portReg_ = level ? *portReg_ | bit_ : *portReg_ & mask_;
|
||||||
ALWAYS_INLINE void low() {ATOMIC_BLOCK(ATOMIC_FORCEON) {lowI();}}
|
}
|
||||||
/**
|
//============================================================================
|
||||||
* Set pin mode
|
/**
|
||||||
* @param[in] pinMode if true set output mode else input mode.
|
* Set pin level high if output mode or enable 20K pullup if input mode.
|
||||||
*
|
*
|
||||||
* mode() does not enable or disable the 20K pullup for input mode.
|
* This function will enable interrupts. This function should not be
|
||||||
*
|
* called in an ISR or where interrupts are disabled.
|
||||||
* This function will enable interrupts. This function should not be
|
*/
|
||||||
* called in an ISR or where interrupts are disabled.
|
ALWAYS_INLINE void high()
|
||||||
*/
|
{
|
||||||
ALWAYS_INLINE void mode(bool pinMode) {ATOMIC_BLOCK(ATOMIC_FORCEON) {modeI(pinMode);}}
|
ATOMIC_BLOCK(ATOMIC_FORCEON) {
|
||||||
/** Write pin.
|
highI();
|
||||||
*
|
}
|
||||||
* @param[in] level If output mode set pin high if true else low.
|
}
|
||||||
* If input mode enable 20K pullup if true else disable pullup.
|
/**
|
||||||
*
|
* Set pin level low if output mode or disable 20K pullup if input mode.
|
||||||
* This function will enable interrupts. This function should not be
|
*
|
||||||
* called in an ISR or where interrupts are disabled.
|
* This function will enable interrupts. This function should not be
|
||||||
*/
|
* called in an ISR or where interrupts are disabled.
|
||||||
ALWAYS_INLINE void write(bool level) {ATOMIC_BLOCK(ATOMIC_FORCEON) {writeI(level);}}
|
*/
|
||||||
//----------------------------------------------------------------------------
|
ALWAYS_INLINE void low()
|
||||||
private:
|
{
|
||||||
uint8_t bit_;
|
ATOMIC_BLOCK(ATOMIC_FORCEON) {
|
||||||
uint8_t mask_;
|
lowI();
|
||||||
volatile uint8_t* pinReg_;
|
}
|
||||||
volatile uint8_t* portReg_;
|
}
|
||||||
|
/**
|
||||||
|
* Set pin mode
|
||||||
|
* @param[in] pinMode if true set output mode else input mode.
|
||||||
|
*
|
||||||
|
* mode() does not enable or disable the 20K pullup for input mode.
|
||||||
|
*
|
||||||
|
* This function will enable interrupts. This function should not be
|
||||||
|
* called in an ISR or where interrupts are disabled.
|
||||||
|
*/
|
||||||
|
ALWAYS_INLINE void mode(bool pinMode)
|
||||||
|
{
|
||||||
|
ATOMIC_BLOCK(ATOMIC_FORCEON) {
|
||||||
|
modeI(pinMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** Write pin.
|
||||||
|
*
|
||||||
|
* @param[in] level If output mode set pin high if true else low.
|
||||||
|
* If input mode enable 20K pullup if true else disable pullup.
|
||||||
|
*
|
||||||
|
* This function will enable interrupts. This function should not be
|
||||||
|
* called in an ISR or where interrupts are disabled.
|
||||||
|
*/
|
||||||
|
ALWAYS_INLINE void write(bool level)
|
||||||
|
{
|
||||||
|
ATOMIC_BLOCK(ATOMIC_FORCEON) {
|
||||||
|
writeI(level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
uint8_t bit_;
|
||||||
|
uint8_t mask_;
|
||||||
|
volatile uint8_t* pinReg_;
|
||||||
|
volatile uint8_t* portReg_;
|
||||||
};
|
};
|
||||||
#endif // PinIO_h
|
#endif // PinIO_h
|
||||||
/** @} */
|
/** @} */
|
||||||
@@ -49,16 +49,17 @@
|
|||||||
* @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) {
|
{
|
||||||
start();
|
if (_state != STATE_REP_START) {
|
||||||
}
|
start();
|
||||||
if (!write(addrRW)) {
|
}
|
||||||
_state = addrRW & I2C_READ ? STATE_RX_ADDR_NACK : STATE_TX_ADDR_NACK;
|
if (!write(addrRW)) {
|
||||||
return false;
|
_state = addrRW & I2C_READ ? STATE_RX_ADDR_NACK : STATE_TX_ADDR_NACK;
|
||||||
}
|
return false;
|
||||||
_state = addrRW & I2C_READ ? STATE_RX_DATA : STATE_TX_DATA;
|
}
|
||||||
return transferContinue(buf, nbytes, option);
|
_state = addrRW & I2C_READ ? STATE_RX_DATA : STATE_TX_DATA;
|
||||||
|
return transferContinue(buf, nbytes, option);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
@@ -76,30 +77,31 @@ bool I2cMasterBase::transfer(uint8_t addrRW,
|
|||||||
* .
|
* .
|
||||||
* @return true for success else false.
|
* @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);
|
{
|
||||||
if (_state == STATE_RX_DATA) {
|
uint8_t* p = reinterpret_cast<uint8_t*>(buf);
|
||||||
for (size_t i = 0; i < nbytes; i++) {
|
if (_state == STATE_RX_DATA) {
|
||||||
p[i] = read(i == (nbytes - 1) && option != I2C_CONTINUE);
|
for (size_t i = 0; i < nbytes; i++) {
|
||||||
}
|
p[i] = read(i == (nbytes - 1) && option != I2C_CONTINUE);
|
||||||
} else if (_state == STATE_TX_DATA) {
|
}
|
||||||
for (size_t i = 0; i < nbytes; i++) {
|
} else if (_state == STATE_TX_DATA) {
|
||||||
if (!write(p[i])) {
|
for (size_t i = 0; i < nbytes; i++) {
|
||||||
_state = STATE_TX_DATA_NACK;
|
if (!write(p[i])) {
|
||||||
return false;
|
_state = STATE_TX_DATA_NACK;
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
return false;
|
} else {
|
||||||
}
|
return false;
|
||||||
if (option == I2C_STOP) {
|
}
|
||||||
stop();
|
if (option == I2C_STOP) {
|
||||||
_state = STATE_STOP;
|
stop();
|
||||||
} else if (option == I2C_REP_START) {
|
_state = STATE_STOP;
|
||||||
start();
|
} else if (option == I2C_REP_START) {
|
||||||
_state = STATE_STOP;
|
start();
|
||||||
}
|
_state = STATE_STOP;
|
||||||
return true;
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
// WARNING don't change SoftI2cMaster unless you verify the change with a scope
|
// WARNING don't change SoftI2cMaster unless you verify the change with a scope
|
||||||
@@ -111,8 +113,9 @@ bool I2cMasterBase::transferContinue(void *buf, size_t nbytes, uint8_t option) {
|
|||||||
*
|
*
|
||||||
* @param[in] sclPin The software SCL pin number.
|
* @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,32 +125,33 @@ 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.
|
||||||
_sclBit = digitalPinToBitMask(sclPin);
|
_sclBit = digitalPinToBitMask(sclPin);
|
||||||
port = digitalPinToPort(sclPin);
|
port = digitalPinToPort(sclPin);
|
||||||
_sclDDR = portModeRegister(port);
|
_sclDDR = portModeRegister(port);
|
||||||
volatile uint8_t* sclOutReg = portOutputRegister(port);
|
volatile uint8_t* sclOutReg = portOutputRegister(port);
|
||||||
|
|
||||||
// Get bit mask and address of sda registers.
|
// Get bit mask and address of sda registers.
|
||||||
_sdaBit = digitalPinToBitMask(sdaPin);
|
_sdaBit = digitalPinToBitMask(sdaPin);
|
||||||
port = digitalPinToPort(sdaPin);
|
port = digitalPinToPort(sdaPin);
|
||||||
_sdaDDR = portModeRegister(port);
|
_sdaDDR = portModeRegister(port);
|
||||||
_sdaInReg = portInputRegister(port);
|
_sdaInReg = portInputRegister(port);
|
||||||
volatile uint8_t* sdaOutReg = portOutputRegister(port);
|
volatile uint8_t* sdaOutReg = portOutputRegister(port);
|
||||||
|
|
||||||
// Clear PORT bit for scl and sda.
|
// Clear PORT bit for scl and sda.
|
||||||
uint8_t s = SREG;
|
uint8_t s = SREG;
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
*sclOutReg &= ~_sclBit;
|
*sclOutReg &= ~_sclBit;
|
||||||
*sdaOutReg &= ~_sdaBit;
|
*sdaOutReg &= ~_sdaBit;
|
||||||
SREG = s;
|
SREG = s;
|
||||||
|
|
||||||
// Set scl and sda high.
|
// Set scl and sda high.
|
||||||
writeScl(HIGH);
|
writeScl(HIGH);
|
||||||
writeSda(HIGH);
|
writeSda(HIGH);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/* Read a byte and send ACK if more reads follow else NACK to terminate read.
|
/* Read a byte and send ACK if more reads follow else NACK to terminate read.
|
||||||
@@ -156,51 +160,56 @@ void SoftI2cMaster::begin(uint8_t sclPin, uint8_t sdaPin) {
|
|||||||
*
|
*
|
||||||
* @return The byte read from the I2C bus.
|
* @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.
|
||||||
writeSda(HIGH);
|
writeSda(HIGH);
|
||||||
// Read a byte.
|
// Read a byte.
|
||||||
for (uint8_t i = 0; i < 8; i++) {
|
for (uint8_t i = 0; i < 8; i++) {
|
||||||
// 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.
|
||||||
b <<= 1;
|
b <<= 1;
|
||||||
sclDelay(16);
|
sclDelay(16);
|
||||||
writeScl(HIGH);
|
writeScl(HIGH);
|
||||||
sclDelay(12);
|
sclDelay(12);
|
||||||
if (readSda()) b |= 1;
|
if (readSda()) {
|
||||||
writeScl(LOW);
|
b |= 1;
|
||||||
}
|
}
|
||||||
// send ACK or NACK
|
writeScl(LOW);
|
||||||
writeSda(last);
|
}
|
||||||
sclDelay(12);
|
// send ACK or NACK
|
||||||
writeScl(HIGH);
|
writeSda(last);
|
||||||
sclDelay(18);
|
sclDelay(12);
|
||||||
writeScl(LOW);
|
writeScl(HIGH);
|
||||||
writeSda(LOW);
|
sclDelay(18);
|
||||||
return b;
|
writeScl(LOW);
|
||||||
|
writeSda(LOW);
|
||||||
|
return b;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/* Issue a start condition. */
|
/* Issue a start condition. */
|
||||||
void SoftI2cMaster::start() {
|
void SoftI2cMaster::start()
|
||||||
if (!readSda()) {
|
{
|
||||||
writeSda(HIGH);
|
if (!readSda()) {
|
||||||
writeScl(HIGH);
|
writeSda(HIGH);
|
||||||
sclDelay(20);
|
writeScl(HIGH);
|
||||||
}
|
sclDelay(20);
|
||||||
writeSda(LOW);
|
}
|
||||||
sclDelay(20);
|
writeSda(LOW);
|
||||||
writeScl(LOW);
|
sclDelay(20);
|
||||||
|
writeScl(LOW);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/* Issue a stop condition. */
|
/* Issue a stop condition. */
|
||||||
void SoftI2cMaster::stop(void) {
|
void SoftI2cMaster::stop(void)
|
||||||
writeSda(LOW);
|
{
|
||||||
sclDelay(20);
|
writeSda(LOW);
|
||||||
writeScl(HIGH);
|
sclDelay(20);
|
||||||
sclDelay(20);
|
writeScl(HIGH);
|
||||||
writeSda(HIGH);
|
sclDelay(20);
|
||||||
sclDelay(20);
|
writeSda(HIGH);
|
||||||
|
sclDelay(20);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/*
|
/*
|
||||||
@@ -210,30 +219,31 @@ void SoftI2cMaster::stop(void) {
|
|||||||
*
|
*
|
||||||
* @return The value true, 1, if the slave returned an ACK or false for NACK.
|
* @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
|
{
|
||||||
for (uint8_t m = 0X80; m != 0; m >>= 1) {
|
// write byte
|
||||||
// don't change this loop unless you verify the change with a scope
|
for (uint8_t m = 0X80; m != 0; m >>= 1) {
|
||||||
writeSda(m & data);
|
// don't change this loop unless you verify the change with a scope
|
||||||
sclDelay(8);
|
writeSda(m & data);
|
||||||
writeScl(HIGH);
|
sclDelay(8);
|
||||||
sclDelay(18);
|
writeScl(HIGH);
|
||||||
writeScl(LOW);
|
sclDelay(18);
|
||||||
}
|
writeScl(LOW);
|
||||||
sclDelay(8);
|
}
|
||||||
// Go to sda high Z mode for input.
|
sclDelay(8);
|
||||||
writeSda(HIGH);
|
// Go to sda high Z mode for input.
|
||||||
writeScl(HIGH);
|
writeSda(HIGH);
|
||||||
sclDelay(16);
|
writeScl(HIGH);
|
||||||
|
sclDelay(16);
|
||||||
|
|
||||||
// Get ACK or NACK.
|
// Get ACK or NACK.
|
||||||
uint8_t rtn = readSda();
|
uint8_t rtn = readSda();
|
||||||
|
|
||||||
// pull scl low.
|
// pull scl low.
|
||||||
writeScl(LOW);
|
writeScl(LOW);
|
||||||
|
|
||||||
// Pull sda low.
|
// Pull sda low.
|
||||||
writeSda(LOW);
|
writeSda(LOW);
|
||||||
return rtn == 0;
|
return rtn == 0;
|
||||||
}
|
}
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|||||||
@@ -63,151 +63,161 @@ 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:
|
{
|
||||||
I2cMasterBase() : _state(STATE_STOP) {}
|
public:
|
||||||
/** Read a byte
|
I2cMasterBase() : _state(STATE_STOP) {}
|
||||||
*
|
/** Read a byte
|
||||||
* @note This function should only be used by experts. Data should be
|
*
|
||||||
* accessed by calling transfer() and transferContinue()
|
* @note This function should only be used by experts. Data should be
|
||||||
*
|
* accessed by calling transfer() and transferContinue()
|
||||||
* @param[in] last send a NACK to terminate read if last is true else
|
*
|
||||||
* send an ACK to continue the read.
|
* @param[in] last send a NACK to terminate read if last is true else
|
||||||
*
|
* send an ACK to continue the read.
|
||||||
* @return byte read from I2C bus
|
*
|
||||||
*/
|
* @return byte read from I2C bus
|
||||||
virtual uint8_t read(uint8_t last) = 0;
|
*/
|
||||||
|
virtual uint8_t read(uint8_t last) = 0;
|
||||||
|
|
||||||
/** Issue a start condition
|
/** Issue a start condition
|
||||||
*
|
*
|
||||||
* @note This function should only be used by experts. Data should be
|
* @note This function should only be used by experts. Data should be
|
||||||
* accessed by calling transfer() and transferContinue()
|
* accessed by calling transfer() and transferContinue()
|
||||||
*/
|
*/
|
||||||
virtual void start() = 0;
|
virtual void start() = 0;
|
||||||
/** Issue a stop condition.
|
/** Issue a stop condition.
|
||||||
*
|
*
|
||||||
* @note This function should only be used by experts. Data should be
|
* @note This function should only be used by experts. Data should be
|
||||||
* accessed by calling transfer() and transferContinue()
|
* accessed by calling transfer() and transferContinue()
|
||||||
*/
|
*/
|
||||||
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.
|
||||||
* The I2C slave address is in the high seven bits
|
* The I2C slave address is in the high seven bits
|
||||||
* and is ORed with on of the following:
|
* and is ORed with on of the following:
|
||||||
* - I2C_READ for a read transfer.
|
* - I2C_READ for a read transfer.
|
||||||
* - I2C_WRITE for a write transfer.
|
* - I2C_WRITE for a write transfer.
|
||||||
* .
|
* .
|
||||||
* @param[in,out] buf Source or destination for transfer.
|
* @param[in,out] buf Source or destination for transfer.
|
||||||
* @param[in] nbyte Number of bytes to transfer (may be zero).
|
* @param[in] nbyte Number of bytes to transfer (may be zero).
|
||||||
* @param[in] option Option for ending the transfer, one of:
|
* @param[in] option Option for ending the transfer, one of:
|
||||||
* - I2C_STOP end the transfer with an I2C stop
|
* - I2C_STOP end the transfer with an I2C stop
|
||||||
* condition.
|
* condition.
|
||||||
* - I2C_REP_START end the transfer with an I2C
|
* - I2C_REP_START end the transfer with an I2C
|
||||||
* repeated start condition.
|
* repeated start condition.
|
||||||
* - I2C_CONTINUE allow additional transferContinue()
|
* - I2C_CONTINUE allow additional transferContinue()
|
||||||
* calls.
|
* calls.
|
||||||
* .
|
* .
|
||||||
* @return true for success else false.
|
* @return true for success else false.
|
||||||
*/
|
*/
|
||||||
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.
|
||||||
* @param[in] nbyte Number of bytes to transfer (may be zero).
|
* @param[in] nbyte Number of bytes to transfer (may be zero).
|
||||||
* @param[in] option Option for ending the transfer, one of:
|
* @param[in] option Option for ending the transfer, one of:
|
||||||
* - I2C_STOP end the transfer with an I2C stop
|
* - I2C_STOP end the transfer with an I2C stop
|
||||||
* condition.
|
* condition.
|
||||||
* - I2C_REP_START end the transfer with an I2C
|
* - I2C_REP_START end the transfer with an I2C
|
||||||
* repeated start condition.
|
* repeated start condition.
|
||||||
* - I2C_CONTINUE allow additional transferContinue()
|
* - I2C_CONTINUE allow additional transferContinue()
|
||||||
* calls.
|
* calls.
|
||||||
* .
|
* .
|
||||||
* @return true for success else false.
|
* @return true for success else false.
|
||||||
*/
|
*/
|
||||||
bool transferContinue(void *buf, size_t nbyte, uint8_t option = I2C_STOP);
|
bool transferContinue(void *buf, size_t nbyte, uint8_t option = I2C_STOP);
|
||||||
/** Write a byte
|
/** Write a byte
|
||||||
*
|
*
|
||||||
* @note This function should only be used by experts. Data should be
|
* @note This function should only be used by experts. Data should be
|
||||||
* accessed by calling transfer() and transferContinue()
|
* accessed by calling transfer() and transferContinue()
|
||||||
*
|
*
|
||||||
* @param[in] data byte to write
|
* @param[in] data byte to write
|
||||||
* @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;
|
||||||
};
|
};
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/**
|
/**
|
||||||
* @class SoftI2cMaster
|
* @class SoftI2cMaster
|
||||||
* @brief Software I2C master class
|
* @brief Software I2C master class
|
||||||
*/
|
*/
|
||||||
class SoftI2cMaster : public I2cMasterBase {
|
class SoftI2cMaster : public I2cMasterBase
|
||||||
public:
|
{
|
||||||
SoftI2cMaster() {}
|
public:
|
||||||
/**
|
SoftI2cMaster() {}
|
||||||
* Constructor, initialize SCL/SDA pins and set the bus high.
|
/**
|
||||||
*
|
* Constructor, initialize SCL/SDA pins and set the bus high.
|
||||||
* @param[in] sdaPin The software SDA pin number.
|
*
|
||||||
*
|
* @param[in] sdaPin The software SDA pin number.
|
||||||
* @param[in] sclPin The software SCL pin number.
|
*
|
||||||
*/
|
* @param[in] sclPin The software SCL pin number.
|
||||||
SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin);
|
*/
|
||||||
/**
|
SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin);
|
||||||
* Initialize SCL/SDA pins and set the bus high.
|
/**
|
||||||
*
|
* Initialize SCL/SDA pins and set the bus high.
|
||||||
* @param[in] sdaPin The software SDA pin number.
|
*
|
||||||
*
|
* @param[in] sdaPin The software SDA pin number.
|
||||||
* @param[in] sclPin The software SCL pin number.
|
*
|
||||||
*/
|
* @param[in] sclPin The software SCL pin number.
|
||||||
void begin(uint8_t sclPin, uint8_t sdaPin);
|
*/
|
||||||
uint8_t read(uint8_t last);
|
void begin(uint8_t sclPin, uint8_t sdaPin);
|
||||||
void start();
|
uint8_t read(uint8_t last);
|
||||||
void stop(void);
|
void start();
|
||||||
bool write(uint8_t b);
|
void stop(void);
|
||||||
|
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()
|
||||||
//----------------------------------------------------------------------------
|
{
|
||||||
void sclDelay(uint8_t n) {_delay_loop_1(n);}
|
return *_sdaInReg & _sdaBit;
|
||||||
//----------------------------------------------------------------------------
|
}
|
||||||
void writeScl(bool value) {
|
//----------------------------------------------------------------------------
|
||||||
uint8_t s = SREG;
|
void sclDelay(uint8_t n)
|
||||||
noInterrupts();
|
{
|
||||||
if (value == LOW) {
|
_delay_loop_1(n);
|
||||||
// Pull scl low.
|
}
|
||||||
*_sclDDR |= _sclBit;
|
//----------------------------------------------------------------------------
|
||||||
} else {
|
void writeScl(bool value)
|
||||||
// Put scl in high Z input mode.
|
{
|
||||||
*_sclDDR &= ~_sclBit;
|
uint8_t s = SREG;
|
||||||
}
|
noInterrupts();
|
||||||
SREG = s;
|
if (value == LOW) {
|
||||||
}
|
// Pull scl low.
|
||||||
//----------------------------------------------------------------------------
|
*_sclDDR |= _sclBit;
|
||||||
void writeSda(bool value) {
|
} else {
|
||||||
uint8_t s = SREG;
|
// Put scl in high Z input mode.
|
||||||
noInterrupts();
|
*_sclDDR &= ~_sclBit;
|
||||||
if (value == LOW) {
|
}
|
||||||
// Pull sda low.
|
SREG = s;
|
||||||
*_sdaDDR |= _sdaBit;
|
}
|
||||||
} else {
|
//----------------------------------------------------------------------------
|
||||||
// Put sda in high Z input mode.
|
void writeSda(bool value)
|
||||||
*_sdaDDR &= ~_sdaBit;
|
{
|
||||||
}
|
uint8_t s = SREG;
|
||||||
SREG = s;
|
noInterrupts();
|
||||||
}
|
if (value == LOW) {
|
||||||
|
// Pull sda low.
|
||||||
|
*_sdaDDR |= _sdaBit;
|
||||||
|
} else {
|
||||||
|
// Put sda in high Z input mode.
|
||||||
|
*_sdaDDR &= ~_sdaBit;
|
||||||
|
}
|
||||||
|
SREG = s;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
// Template based fast software I2C
|
// Template based fast software I2C
|
||||||
@@ -217,118 +227,140 @@ 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() {
|
//----------------------------------------------------------------------------
|
||||||
begin();
|
FastI2cMaster()
|
||||||
}
|
{
|
||||||
//----------------------------------------------------------------------------
|
begin();
|
||||||
/** Initialize I2C bus pins. */
|
}
|
||||||
void begin() {
|
//----------------------------------------------------------------------------
|
||||||
fastDigitalWrite(sclPin, LOW);
|
/** Initialize I2C bus pins. */
|
||||||
fastDigitalWrite(sdaPin, LOW);
|
void begin()
|
||||||
|
{
|
||||||
|
fastDigitalWrite(sclPin, LOW);
|
||||||
|
fastDigitalWrite(sdaPin, LOW);
|
||||||
|
|
||||||
sclWrite(HIGH);
|
sclWrite(HIGH);
|
||||||
sdaWrite(HIGH);
|
sdaWrite(HIGH);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
uint8_t read(uint8_t last) {
|
uint8_t read(uint8_t last)
|
||||||
uint8_t data = 0;
|
{
|
||||||
sdaWrite(HIGH);
|
uint8_t data = 0;
|
||||||
|
sdaWrite(HIGH);
|
||||||
|
|
||||||
readBit(7, &data);
|
readBit(7, &data);
|
||||||
readBit(6, &data);
|
readBit(6, &data);
|
||||||
readBit(5, &data);
|
readBit(5, &data);
|
||||||
readBit(4, &data);
|
readBit(4, &data);
|
||||||
readBit(3, &data);
|
readBit(3, &data);
|
||||||
readBit(2, &data);
|
readBit(2, &data);
|
||||||
readBit(1, &data);
|
readBit(1, &data);
|
||||||
readBit(0, &data);
|
readBit(0, &data);
|
||||||
|
|
||||||
// send ACK or NACK
|
// send ACK or NACK
|
||||||
sdaWrite(last);
|
sdaWrite(last);
|
||||||
sclDelay(4);
|
sclDelay(4);
|
||||||
sclWrite(HIGH);
|
sclWrite(HIGH);
|
||||||
sclDelay(6);
|
sclDelay(6);
|
||||||
sclWrite(LOW);
|
sclWrite(LOW);
|
||||||
sdaWrite(LOW);
|
sdaWrite(LOW);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void start() {
|
void start()
|
||||||
if (!fastDigitalRead(sdaPin)) {
|
{
|
||||||
// It's a repeat start.
|
if (!fastDigitalRead(sdaPin)) {
|
||||||
sdaWrite(HIGH);
|
// It's a repeat start.
|
||||||
sclDelay(8);
|
sdaWrite(HIGH);
|
||||||
sclWrite(HIGH);
|
sclDelay(8);
|
||||||
sclDelay(8);
|
sclWrite(HIGH);
|
||||||
}
|
sclDelay(8);
|
||||||
sdaWrite(LOW);
|
}
|
||||||
sclDelay(8);
|
sdaWrite(LOW);
|
||||||
sclWrite(LOW);
|
sclDelay(8);
|
||||||
sclDelay(8);
|
sclWrite(LOW);
|
||||||
}
|
sclDelay(8);
|
||||||
//----------------------------------------------------------------------------
|
}
|
||||||
void stop(void) {
|
//----------------------------------------------------------------------------
|
||||||
sdaWrite(LOW);
|
void stop(void)
|
||||||
sclDelay(8);
|
{
|
||||||
sclWrite(HIGH);
|
sdaWrite(LOW);
|
||||||
sclDelay(8);
|
sclDelay(8);
|
||||||
sdaWrite(HIGH);
|
sclWrite(HIGH);
|
||||||
sclDelay(8);
|
sclDelay(8);
|
||||||
}
|
sdaWrite(HIGH);
|
||||||
//----------------------------------------------------------------------------
|
sclDelay(8);
|
||||||
bool write(uint8_t data) {
|
}
|
||||||
// write byte
|
//----------------------------------------------------------------------------
|
||||||
writeBit(7, data);
|
bool write(uint8_t data)
|
||||||
writeBit(6, data);
|
{
|
||||||
writeBit(5, data);
|
// write byte
|
||||||
writeBit(4, data);
|
writeBit(7, data);
|
||||||
writeBit(3, data);
|
writeBit(6, data);
|
||||||
writeBit(2, data);
|
writeBit(5, data);
|
||||||
writeBit(1, data);
|
writeBit(4, data);
|
||||||
writeBit(0, data);
|
writeBit(3, data);
|
||||||
|
writeBit(2, data);
|
||||||
|
writeBit(1, data);
|
||||||
|
writeBit(0, data);
|
||||||
|
|
||||||
// get ACK or NACK
|
// get ACK or NACK
|
||||||
sdaWrite(HIGH);
|
sdaWrite(HIGH);
|
||||||
|
|
||||||
sclWrite(HIGH);
|
sclWrite(HIGH);
|
||||||
sclDelay(5);
|
sclDelay(5);
|
||||||
bool rtn = fastDigitalRead(sdaPin);
|
bool rtn = fastDigitalRead(sdaPin);
|
||||||
sclWrite(LOW);
|
sclWrite(LOW);
|
||||||
sdaWrite(LOW);
|
sdaWrite(LOW);
|
||||||
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))
|
inline __attribute__((always_inline))
|
||||||
void readBit(uint8_t bit, uint8_t* data) {
|
void sdaWrite(bool value)
|
||||||
sclWrite(HIGH);
|
{
|
||||||
sclDelay(5);
|
fastPinMode(sdaPin, !value);
|
||||||
if (fastDigitalRead(sdaPin)) *data |= 1 << bit;
|
}
|
||||||
sclWrite(LOW);
|
//----------------------------------------------------------------------------
|
||||||
if (bit) sclDelay(6);
|
inline __attribute__((always_inline))
|
||||||
}
|
void readBit(uint8_t bit, uint8_t* data)
|
||||||
//----------------------------------------------------------------------------
|
{
|
||||||
void sclDelay(uint8_t n) {_delay_loop_1(n);}
|
sclWrite(HIGH);
|
||||||
//----------------------------------------------------------------------------
|
sclDelay(5);
|
||||||
inline __attribute__((always_inline))
|
if (fastDigitalRead(sdaPin)) {
|
||||||
void writeBit(uint8_t bit, uint8_t data) {
|
*data |= 1 << bit;
|
||||||
uint8_t mask = 1 << bit;
|
}
|
||||||
sdaWrite(data & mask);
|
sclWrite(LOW);
|
||||||
sclWrite(HIGH);
|
if (bit) {
|
||||||
sclDelay(5);
|
sclDelay(6);
|
||||||
sclWrite(LOW);
|
}
|
||||||
sclDelay(5);
|
}
|
||||||
}
|
//----------------------------------------------------------------------------
|
||||||
|
void sclDelay(uint8_t n)
|
||||||
|
{
|
||||||
|
_delay_loop_1(n);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
inline __attribute__((always_inline))
|
||||||
|
void writeBit(uint8_t bit, uint8_t data)
|
||||||
|
{
|
||||||
|
uint8_t mask = 1 << bit;
|
||||||
|
sdaWrite(data & mask);
|
||||||
|
sclWrite(HIGH);
|
||||||
|
sclDelay(5);
|
||||||
|
sclWrite(LOW);
|
||||||
|
sclDelay(5);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
#endif // SOFT_I2C_MASTER_H
|
#endif // SOFT_I2C_MASTER_H
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|||||||
+119
-101
@@ -48,108 +48,126 @@ 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. */
|
//----------------------------------------------------------------------------
|
||||||
void begin() {
|
/** Initialize SoftSPI pins. */
|
||||||
fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL);
|
void begin()
|
||||||
fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode));
|
{
|
||||||
fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode));
|
fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL);
|
||||||
}
|
fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode));
|
||||||
//----------------------------------------------------------------------------
|
fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode));
|
||||||
/** Soft SPI receive byte.
|
}
|
||||||
* @return Data byte received.
|
//----------------------------------------------------------------------------
|
||||||
*/
|
/** Soft SPI receive byte.
|
||||||
ALWAYS_INLINE uint8_t receive() {
|
* @return Data byte received.
|
||||||
uint8_t data = 0;
|
*/
|
||||||
receiveBit(7, &data);
|
ALWAYS_INLINE uint8_t receive()
|
||||||
receiveBit(6, &data);
|
{
|
||||||
receiveBit(5, &data);
|
uint8_t data = 0;
|
||||||
receiveBit(4, &data);
|
receiveBit(7, &data);
|
||||||
receiveBit(3, &data);
|
receiveBit(6, &data);
|
||||||
receiveBit(2, &data);
|
receiveBit(5, &data);
|
||||||
receiveBit(1, &data);
|
receiveBit(4, &data);
|
||||||
receiveBit(0, &data);
|
receiveBit(3, &data);
|
||||||
return data;
|
receiveBit(2, &data);
|
||||||
}
|
receiveBit(1, &data);
|
||||||
//----------------------------------------------------------------------------
|
receiveBit(0, &data);
|
||||||
/** Soft SPI send byte.
|
return data;
|
||||||
* @param[in] data Data byte to send.
|
}
|
||||||
*/
|
//----------------------------------------------------------------------------
|
||||||
ALWAYS_INLINE void send(uint8_t data) {
|
/** Soft SPI send byte.
|
||||||
sendBit(7, data);
|
* @param[in] data Data byte to send.
|
||||||
sendBit(6, data);
|
*/
|
||||||
sendBit(5, data);
|
ALWAYS_INLINE void send(uint8_t data)
|
||||||
sendBit(4, data);
|
{
|
||||||
sendBit(3, data);
|
sendBit(7, data);
|
||||||
sendBit(2, data);
|
sendBit(6, data);
|
||||||
sendBit(1, data);
|
sendBit(5, data);
|
||||||
sendBit(0, data);
|
sendBit(4, data);
|
||||||
}
|
sendBit(3, data);
|
||||||
//----------------------------------------------------------------------------
|
sendBit(2, data);
|
||||||
/** Soft SPI transfer byte.
|
sendBit(1, data);
|
||||||
* @param[in] txData Data byte to send.
|
sendBit(0, data);
|
||||||
* @return Data byte received.
|
}
|
||||||
*/
|
//----------------------------------------------------------------------------
|
||||||
ALWAYS_INLINE uint8_t transfer(uint8_t txData) {
|
/** Soft SPI transfer byte.
|
||||||
uint8_t rxData = 0;
|
* @param[in] txData Data byte to send.
|
||||||
transferBit(7, &rxData, txData);
|
* @return Data byte received.
|
||||||
transferBit(6, &rxData, txData);
|
*/
|
||||||
transferBit(5, &rxData, txData);
|
ALWAYS_INLINE uint8_t transfer(uint8_t txData)
|
||||||
transferBit(4, &rxData, txData);
|
{
|
||||||
transferBit(3, &rxData, txData);
|
uint8_t rxData = 0;
|
||||||
transferBit(2, &rxData, txData);
|
transferBit(7, &rxData, txData);
|
||||||
transferBit(1, &rxData, txData);
|
transferBit(6, &rxData, txData);
|
||||||
transferBit(0, &rxData, txData);
|
transferBit(5, &rxData, txData);
|
||||||
return rxData;
|
transferBit(4, &rxData, txData);
|
||||||
}
|
transferBit(3, &rxData, txData);
|
||||||
|
transferBit(2, &rxData, txData);
|
||||||
|
transferBit(1, &rxData, txData);
|
||||||
|
transferBit(0, &rxData, txData);
|
||||||
|
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;
|
||||||
if (MODE_CPHA(Mode)) {
|
}
|
||||||
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
ALWAYS_INLINE bool MODE_CPOL(uint8_t mode)
|
||||||
}
|
{
|
||||||
nop;
|
return (mode & 2) != 0;
|
||||||
nop;
|
}
|
||||||
fastDigitalWrite(SckPin,
|
ALWAYS_INLINE void receiveBit(uint8_t bit, uint8_t* data)
|
||||||
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
|
{
|
||||||
if (fastDigitalRead(MisoPin)) *data |= 1 << bit;
|
if (MODE_CPHA(Mode)) {
|
||||||
if (!MODE_CPHA(Mode)) {
|
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
||||||
fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
}
|
||||||
}
|
nop;
|
||||||
}
|
nop;
|
||||||
//----------------------------------------------------------------------------
|
fastDigitalWrite(SckPin,
|
||||||
ALWAYS_INLINE void sendBit(uint8_t bit, uint8_t data) {
|
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
|
||||||
if (MODE_CPHA(Mode)) {
|
if (fastDigitalRead(MisoPin)) {
|
||||||
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
*data |= 1 << bit;
|
||||||
}
|
}
|
||||||
fastDigitalWrite(MosiPin, data & (1 << bit));
|
if (!MODE_CPHA(Mode)) {
|
||||||
fastDigitalWrite(SckPin,
|
fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
||||||
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
|
}
|
||||||
nop;
|
}
|
||||||
nop;
|
//----------------------------------------------------------------------------
|
||||||
if (!MODE_CPHA(Mode)) {
|
ALWAYS_INLINE void sendBit(uint8_t bit, uint8_t data)
|
||||||
fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
{
|
||||||
}
|
if (MODE_CPHA(Mode)) {
|
||||||
}
|
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
||||||
//----------------------------------------------------------------------------
|
}
|
||||||
ALWAYS_INLINE void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData) {
|
fastDigitalWrite(MosiPin, data & (1 << bit));
|
||||||
if (MODE_CPHA(Mode)) {
|
fastDigitalWrite(SckPin,
|
||||||
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
|
||||||
}
|
nop;
|
||||||
fastDigitalWrite(MosiPin, txData & (1 << bit));
|
nop;
|
||||||
fastDigitalWrite(SckPin,
|
if (!MODE_CPHA(Mode)) {
|
||||||
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
|
fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
||||||
if (fastDigitalRead(MisoPin)) *rxData |= 1 << bit;
|
}
|
||||||
if (!MODE_CPHA(Mode)) {
|
}
|
||||||
fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
//----------------------------------------------------------------------------
|
||||||
}
|
ALWAYS_INLINE void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData)
|
||||||
}
|
{
|
||||||
//----------------------------------------------------------------------------
|
if (MODE_CPHA(Mode)) {
|
||||||
|
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
||||||
|
}
|
||||||
|
fastDigitalWrite(MosiPin, txData & (1 << bit));
|
||||||
|
fastDigitalWrite(SckPin,
|
||||||
|
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
|
||||||
|
if (fastDigitalRead(MisoPin)) {
|
||||||
|
*rxData |= 1 << bit;
|
||||||
|
}
|
||||||
|
if (!MODE_CPHA(Mode)) {
|
||||||
|
fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
};
|
};
|
||||||
#endif // SoftSPI_h
|
#endif // SoftSPI_h
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|||||||
@@ -9,118 +9,132 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
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. */
|
//----------------------------------------------------------------------------
|
||||||
void begin() {
|
/** Set pin modes and initial levels. */
|
||||||
fastPinMode(ClkPin, 1);
|
void begin()
|
||||||
fastDigitalWrite(ClkPin, 0);
|
{
|
||||||
fastPinMode(ConvPin, 1);
|
fastPinMode(ClkPin, 1);
|
||||||
fastDigitalWrite(ConvPin, 1);
|
fastDigitalWrite(ClkPin, 0);
|
||||||
fastPinMode(DataPin, 0);
|
fastPinMode(ConvPin, 1);
|
||||||
}
|
fastDigitalWrite(ConvPin, 1);
|
||||||
//----------------------------------------------------------------------------
|
fastPinMode(DataPin, 0);
|
||||||
/** Read ADS7818 12-bit ADC
|
}
|
||||||
* \return 16-bit value read.
|
//----------------------------------------------------------------------------
|
||||||
*/
|
/** Read ADS7818 12-bit ADC
|
||||||
inline __attribute__((always_inline))
|
* \return 16-bit value read.
|
||||||
uint16_t read() {
|
*/
|
||||||
uint16_t v = 0;
|
inline __attribute__((always_inline))
|
||||||
fastDigitalWrite(ConvPin, 0);
|
uint16_t read()
|
||||||
fastDigitalWrite(ClkPin, 1);
|
{
|
||||||
fastDigitalWrite(ClkPin, 0);
|
uint16_t v = 0;
|
||||||
fastDigitalWrite(ConvPin, 1);
|
fastDigitalWrite(ConvPin, 0);
|
||||||
fastDigitalWrite(ClkPin, 1);
|
fastDigitalWrite(ClkPin, 1);
|
||||||
fastDigitalWrite(ClkPin, 0);
|
fastDigitalWrite(ClkPin, 0);
|
||||||
|
fastDigitalWrite(ConvPin, 1);
|
||||||
|
fastDigitalWrite(ClkPin, 1);
|
||||||
|
fastDigitalWrite(ClkPin, 0);
|
||||||
|
|
||||||
readBitFast16(v, 11);
|
readBitFast16(v, 11);
|
||||||
readBitFast16(v, 10);
|
readBitFast16(v, 10);
|
||||||
readBitFast16(v, 9);
|
readBitFast16(v, 9);
|
||||||
readBitFast16(v, 8);
|
readBitFast16(v, 8);
|
||||||
readBitFast16(v, 7);
|
readBitFast16(v, 7);
|
||||||
readBitFast16(v, 6);
|
readBitFast16(v, 6);
|
||||||
readBitFast16(v, 5);
|
readBitFast16(v, 5);
|
||||||
readBitFast16(v, 4);
|
readBitFast16(v, 4);
|
||||||
readBitFast16(v, 3);
|
readBitFast16(v, 3);
|
||||||
readBitFast16(v, 2);
|
readBitFast16(v, 2);
|
||||||
readBitFast16(v, 1);
|
readBitFast16(v, 1);
|
||||||
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);
|
{
|
||||||
if (fastDigitalRead(DataPin)) v |= (1 << b);
|
fastDigitalWrite(ClkPin, 1);
|
||||||
fastDigitalWrite(ClkPin, 0);
|
if (fastDigitalRead(DataPin)) {
|
||||||
}
|
v |= (1 << b);
|
||||||
|
}
|
||||||
|
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);
|
{
|
||||||
fastDigitalWrite(ADC_CLK_PIN, 0);
|
fastPinMode(ADC_CLK_PIN, 1);
|
||||||
fastPinMode(ADC_CONV_PIN, 1);
|
fastDigitalWrite(ADC_CLK_PIN, 0);
|
||||||
fastDigitalWrite(ADC_CONV_PIN, 1);
|
fastPinMode(ADC_CONV_PIN, 1);
|
||||||
fastPinMode(ADC_DATA_PIN, 0);
|
fastDigitalWrite(ADC_CONV_PIN, 1);
|
||||||
|
fastPinMode(ADC_DATA_PIN, 0);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** 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;
|
{
|
||||||
fastDigitalWrite(ADC_CLK_PIN, 1);
|
if (!first) {
|
||||||
nop;
|
nop;
|
||||||
fastDigitalWrite(ADC_CLK_PIN, 0);
|
}
|
||||||
|
fastDigitalWrite(ADC_CLK_PIN, 1);
|
||||||
|
nop;
|
||||||
|
fastDigitalWrite(ADC_CLK_PIN, 0);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** read next bit fast as possible
|
/** read next bit fast as possible
|
||||||
* \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);
|
{
|
||||||
if (fastDigitalRead(ADC_DATA_PIN)) v |= (1 << b);
|
fastDigitalWrite(ADC_CLK_PIN, 1);
|
||||||
fastDigitalWrite(ADC_CLK_PIN, 0);
|
if (fastDigitalRead(ADC_DATA_PIN)) {
|
||||||
|
v |= (1 << b);
|
||||||
|
}
|
||||||
|
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;
|
{
|
||||||
fastDigitalWrite(ADC_CONV_PIN, 0);
|
uint16_t v = 0;
|
||||||
fastDigitalWrite(ADC_CLK_PIN, 1);
|
fastDigitalWrite(ADC_CONV_PIN, 0);
|
||||||
fastDigitalWrite(ADC_CLK_PIN, 0);
|
fastDigitalWrite(ADC_CLK_PIN, 1);
|
||||||
fastDigitalWrite(ADC_CONV_PIN, 1);
|
fastDigitalWrite(ADC_CLK_PIN, 0);
|
||||||
fastDigitalWrite(ADC_CLK_PIN, 1);
|
fastDigitalWrite(ADC_CONV_PIN, 1);
|
||||||
fastDigitalWrite(ADC_CLK_PIN, 0);
|
fastDigitalWrite(ADC_CLK_PIN, 1);
|
||||||
// uint16_t v = 0;
|
fastDigitalWrite(ADC_CLK_PIN, 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);
|
||||||
readBitFast16(v, 8);
|
readBitFast16(v, 8);
|
||||||
readBitFast16(v, 7);
|
readBitFast16(v, 7);
|
||||||
readBitFast16(v, 6);
|
readBitFast16(v, 6);
|
||||||
readBitFast16(v, 5);
|
readBitFast16(v, 5);
|
||||||
readBitFast16(v, 4);
|
readBitFast16(v, 4);
|
||||||
readBitFast16(v, 3);
|
readBitFast16(v, 3);
|
||||||
readBitFast16(v, 2);
|
readBitFast16(v, 2);
|
||||||
readBitFast16(v, 1);
|
readBitFast16(v, 1);
|
||||||
readBitFast16(v, 0);
|
readBitFast16(v, 0);
|
||||||
return centered ? v ^ 0X8000 : v;
|
return centered ? v ^ 0X8000 : v;
|
||||||
}
|
}
|
||||||
#endif // 0
|
#endif // 0
|
||||||
#endif // ADS7818_h
|
#endif // ADS7818_h
|
||||||
@@ -4,259 +4,302 @@
|
|||||||
//==============================================================================
|
//==============================================================================
|
||||||
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. */
|
//----------------------------------------------------------------------------
|
||||||
void begin() {
|
/** Set pin modes and initial levels. */
|
||||||
fastPinMode(ClkPin, 1);
|
void begin()
|
||||||
fastDigitalWrite(ClkPin, 0);
|
{
|
||||||
fastPinMode(CsPin, 1);
|
fastPinMode(ClkPin, 1);
|
||||||
fastDigitalWrite(CsPin, 1);
|
fastDigitalWrite(ClkPin, 0);
|
||||||
fastPinMode(DoutPin, 0);
|
fastPinMode(CsPin, 1);
|
||||||
}
|
fastDigitalWrite(CsPin, 1);
|
||||||
//----------------------------------------------------------------------------
|
fastPinMode(DoutPin, 0);
|
||||||
/** Read MCP3201 12-bit ADC
|
}
|
||||||
* \return 16-bit value read.
|
//----------------------------------------------------------------------------
|
||||||
*/
|
/** Read MCP3201 12-bit ADC
|
||||||
inline __attribute__((always_inline))
|
* \return 16-bit value read.
|
||||||
uint16_t read() {
|
*/
|
||||||
fastDigitalWrite(CsPin, 0);
|
inline __attribute__((always_inline))
|
||||||
// Start sample.
|
uint16_t read()
|
||||||
mcpAdcDummy(3);
|
{
|
||||||
// Extra sample time.
|
fastDigitalWrite(CsPin, 0);
|
||||||
if (UsecDelay){
|
// Start sample.
|
||||||
delayMicroseconds(UsecDelay);
|
mcpAdcDummy(3);
|
||||||
}
|
// Extra sample time.
|
||||||
// End sample.
|
if (UsecDelay) {
|
||||||
mcpAdcDummy(3);
|
delayMicroseconds(UsecDelay);
|
||||||
// Null bit.
|
}
|
||||||
mcpAdcDummy(3);
|
// End sample.
|
||||||
uint16_t v = 0;
|
mcpAdcDummy(3);
|
||||||
readBit(v, 11);
|
// Null bit.
|
||||||
readBit(v, 10);
|
mcpAdcDummy(3);
|
||||||
readBit(v, 9);
|
uint16_t v = 0;
|
||||||
readBit(v, 8);
|
readBit(v, 11);
|
||||||
readBit(v, 7);
|
readBit(v, 10);
|
||||||
readBit(v, 6);
|
readBit(v, 9);
|
||||||
readBit(v, 5);
|
readBit(v, 8);
|
||||||
readBit(v, 4);
|
readBit(v, 7);
|
||||||
readBit(v, 3);
|
readBit(v, 6);
|
||||||
readBit(v, 2);
|
readBit(v, 5);
|
||||||
readBit(v, 1);
|
readBit(v, 4);
|
||||||
readBit(v, 0);
|
readBit(v, 3);
|
||||||
fastDigitalWrite(CsPin, 1);
|
readBit(v, 2);
|
||||||
return v;
|
readBit(v, 1);
|
||||||
}
|
readBit(v, 0);
|
||||||
private:
|
fastDigitalWrite(CsPin, 1);
|
||||||
//----------------------------------------------------------------------------
|
return v;
|
||||||
/** delay n nops
|
}
|
||||||
* \param[in] n nops to delay, must be a constant so compiler optimizes if().
|
private:
|
||||||
*/
|
//----------------------------------------------------------------------------
|
||||||
inline __attribute__((always_inline))
|
/** delay n nops
|
||||||
void delayCycles(uint8_t n) {
|
* \param[in] n nops to delay, must be a constant so compiler optimizes if().
|
||||||
if (n & 1) asm volatile("nop\n\t");
|
*/
|
||||||
if (n & 2) asm volatile("nop\n\t" "nop\n\t");
|
inline __attribute__((always_inline))
|
||||||
if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
|
void delayCycles(uint8_t n)
|
||||||
}
|
{
|
||||||
//----------------------------------------------------------------------------
|
if (n & 1) {
|
||||||
/** clock for don't care bits
|
asm volatile("nop\n\t");
|
||||||
*\param[in] delayBefore if true, delay before raising clock*/
|
}
|
||||||
inline __attribute__((always_inline))
|
if (n & 2) {
|
||||||
void mcpAdcDummy(uint8_t delayBefore) {
|
asm volatile("nop\n\t" "nop\n\t");
|
||||||
delayCycles(delayBefore);
|
}
|
||||||
fastDigitalWrite(ClkPin, 1);
|
if (n & 4) {
|
||||||
delayCycles(3);
|
asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
|
||||||
fastDigitalWrite(ClkPin, 0);
|
}
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
inline __attribute__((always_inline))
|
/** clock for don't care bits
|
||||||
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 2) {
|
*\param[in] delayBefore if true, delay before raising clock*/
|
||||||
delayCycles(3);
|
inline __attribute__((always_inline))
|
||||||
fastDigitalWrite(ClkPin, 1);
|
void mcpAdcDummy(uint8_t delayBefore)
|
||||||
delayCycles(delayRead);
|
{
|
||||||
if (fastDigitalRead(DoutPin)) v |= (1 << b);
|
delayCycles(delayBefore);
|
||||||
fastDigitalWrite(ClkPin, 0);
|
fastDigitalWrite(ClkPin, 1);
|
||||||
}
|
delayCycles(3);
|
||||||
|
fastDigitalWrite(ClkPin, 0);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
inline __attribute__((always_inline))
|
||||||
|
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 2)
|
||||||
|
{
|
||||||
|
delayCycles(3);
|
||||||
|
fastDigitalWrite(ClkPin, 1);
|
||||||
|
delayCycles(delayRead);
|
||||||
|
if (fastDigitalRead(DoutPin)) {
|
||||||
|
v |= (1 << b);
|
||||||
|
}
|
||||||
|
fastDigitalWrite(ClkPin, 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
template<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. */
|
//----------------------------------------------------------------------------
|
||||||
void begin() {
|
/** Set pin modes and initial levels. */
|
||||||
fastPinMode(ClkPin, 1);
|
void begin()
|
||||||
fastDigitalWrite(ClkPin, 0);
|
{
|
||||||
fastPinMode(CsPin, 1);
|
fastPinMode(ClkPin, 1);
|
||||||
fastDigitalWrite(CsPin, 1);
|
fastDigitalWrite(ClkPin, 0);
|
||||||
fastPinMode(DoutPin, 0);
|
fastPinMode(CsPin, 1);
|
||||||
fastPinMode(DinPin, 1);
|
fastDigitalWrite(CsPin, 1);
|
||||||
}
|
fastPinMode(DoutPin, 0);
|
||||||
//----------------------------------------------------------------------------
|
fastPinMode(DinPin, 1);
|
||||||
/** Read MCP3202 12-bit ADC
|
}
|
||||||
* \return 16-bit value read.
|
//----------------------------------------------------------------------------
|
||||||
*/
|
/** Read MCP3202 12-bit ADC
|
||||||
inline __attribute__((always_inline))
|
* \return 16-bit value read.
|
||||||
uint16_t read(uint8_t config) {
|
*/
|
||||||
uint16_t v = 0;
|
inline __attribute__((always_inline))
|
||||||
fastDigitalWrite(CsPin, 0);
|
uint16_t read(uint8_t config)
|
||||||
// Start bit.
|
{
|
||||||
writeBit(true);
|
uint16_t v = 0;
|
||||||
// Mode bit.
|
fastDigitalWrite(CsPin, 0);
|
||||||
writeBit(config & 2);
|
// Start bit.
|
||||||
// Channel Selection and start sample.
|
writeBit(true);
|
||||||
writeBit(config & 1);
|
// Mode bit.
|
||||||
// Extra sample time.
|
writeBit(config & 2);
|
||||||
if (UsecDelay){
|
// Channel Selection and start sample.
|
||||||
delayMicroseconds(UsecDelay);
|
writeBit(config & 1);
|
||||||
}
|
// Extra sample time.
|
||||||
// MSB first format and end sample.
|
if (UsecDelay) {
|
||||||
writeBit(true);
|
delayMicroseconds(UsecDelay);
|
||||||
// Null bit.
|
}
|
||||||
writeBit(true);
|
// MSB first format and end sample.
|
||||||
// Data bits.
|
writeBit(true);
|
||||||
readBit(v, 11);
|
// Null bit.
|
||||||
readBit(v, 10);
|
writeBit(true);
|
||||||
readBit(v, 9);
|
// Data bits.
|
||||||
readBit(v, 8);
|
readBit(v, 11);
|
||||||
readBit(v, 7);
|
readBit(v, 10);
|
||||||
readBit(v, 6);
|
readBit(v, 9);
|
||||||
readBit(v, 5);
|
readBit(v, 8);
|
||||||
readBit(v, 4);
|
readBit(v, 7);
|
||||||
readBit(v, 3);
|
readBit(v, 6);
|
||||||
readBit(v, 2);
|
readBit(v, 5);
|
||||||
readBit(v, 1);
|
readBit(v, 4);
|
||||||
readBit(v, 0);
|
readBit(v, 3);
|
||||||
fastDigitalWrite(CsPin, 1);
|
readBit(v, 2);
|
||||||
return v;
|
readBit(v, 1);
|
||||||
}
|
readBit(v, 0);
|
||||||
private:
|
fastDigitalWrite(CsPin, 1);
|
||||||
//----------------------------------------------------------------------------
|
return v;
|
||||||
/** delay n nops
|
}
|
||||||
* \param[in] n nops to delay, must be a constant so compiler optimizes if().
|
private:
|
||||||
*/
|
//----------------------------------------------------------------------------
|
||||||
inline __attribute__((always_inline))
|
/** delay n nops
|
||||||
void delayCycles(uint8_t n) {
|
* \param[in] n nops to delay, must be a constant so compiler optimizes if().
|
||||||
if (n & 1) asm volatile("nop\n\t");
|
*/
|
||||||
if (n & 2) asm volatile("nop\n\t" "nop\n\t");
|
inline __attribute__((always_inline))
|
||||||
if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
|
void delayCycles(uint8_t n)
|
||||||
}
|
{
|
||||||
//----------------------------------------------------------------------------
|
if (n & 1) {
|
||||||
/** clock for don't care bits
|
asm volatile("nop\n\t");
|
||||||
*\param[in] delayBefore if true, delay before raising clock*/
|
}
|
||||||
inline __attribute__((always_inline))
|
if (n & 2) {
|
||||||
void writeBit(bool value) {
|
asm volatile("nop\n\t" "nop\n\t");
|
||||||
fastDigitalWrite(DinPin, value);
|
}
|
||||||
fastDigitalWrite(ClkPin, 1);
|
if (n & 4) {
|
||||||
delayCycles(2);
|
asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
|
||||||
fastDigitalWrite(ClkPin, 0);
|
}
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
inline __attribute__((always_inline))
|
/** clock for don't care bits
|
||||||
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1) {
|
*\param[in] delayBefore if true, delay before raising clock*/
|
||||||
delayCycles(2);
|
inline __attribute__((always_inline))
|
||||||
fastDigitalWrite(ClkPin, 1);
|
void writeBit(bool value)
|
||||||
delayCycles(delayRead);
|
{
|
||||||
if (fastDigitalRead(DoutPin)) v |= (1 << b);
|
fastDigitalWrite(DinPin, value);
|
||||||
fastDigitalWrite(ClkPin, 0);
|
fastDigitalWrite(ClkPin, 1);
|
||||||
}
|
delayCycles(2);
|
||||||
|
fastDigitalWrite(ClkPin, 0);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
inline __attribute__((always_inline))
|
||||||
|
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1)
|
||||||
|
{
|
||||||
|
delayCycles(2);
|
||||||
|
fastDigitalWrite(ClkPin, 1);
|
||||||
|
delayCycles(delayRead);
|
||||||
|
if (fastDigitalRead(DoutPin)) {
|
||||||
|
v |= (1 << b);
|
||||||
|
}
|
||||||
|
fastDigitalWrite(ClkPin, 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
template<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. */
|
//----------------------------------------------------------------------------
|
||||||
void begin() {
|
/** Set pin modes and initial levels. */
|
||||||
fastPinMode(ClkPin, 1);
|
void begin()
|
||||||
fastDigitalWrite(ClkPin, 0);
|
{
|
||||||
fastPinMode(CsPin, 1);
|
fastPinMode(ClkPin, 1);
|
||||||
fastDigitalWrite(CsPin, 1);
|
fastDigitalWrite(ClkPin, 0);
|
||||||
fastPinMode(DoutPin, 0);
|
fastPinMode(CsPin, 1);
|
||||||
fastPinMode(DinPin, 1);
|
fastDigitalWrite(CsPin, 1);
|
||||||
}
|
fastPinMode(DoutPin, 0);
|
||||||
//----------------------------------------------------------------------------
|
fastPinMode(DinPin, 1);
|
||||||
/** Read MCP3204 12-bit ADC
|
}
|
||||||
* \return 16-bit value read.
|
//----------------------------------------------------------------------------
|
||||||
*/
|
/** Read MCP3204 12-bit ADC
|
||||||
inline __attribute__((always_inline))
|
* \return 16-bit value read.
|
||||||
uint16_t read(uint8_t config) {
|
*/
|
||||||
uint16_t v = 0;
|
inline __attribute__((always_inline))
|
||||||
fastDigitalWrite(CsPin, 0);
|
uint16_t read(uint8_t config)
|
||||||
// Start bit.
|
{
|
||||||
writeBit(true);
|
uint16_t v = 0;
|
||||||
// Mode bit.
|
fastDigitalWrite(CsPin, 0);
|
||||||
writeBit(config & 8);
|
// Start bit.
|
||||||
// D2 channel bit.
|
writeBit(true);
|
||||||
writeBit(config & 4);
|
// Mode bit.
|
||||||
// D1 channel bit.
|
writeBit(config & 8);
|
||||||
writeBit(config & 2);
|
// D2 channel bit.
|
||||||
// D0 channel bit and start sample.
|
writeBit(config & 4);
|
||||||
writeBit(config & 1);
|
// D1 channel bit.
|
||||||
// Extra sample time.
|
writeBit(config & 2);
|
||||||
if (UsecDelay){
|
// D0 channel bit and start sample.
|
||||||
delayMicroseconds(UsecDelay);
|
writeBit(config & 1);
|
||||||
}
|
// Extra sample time.
|
||||||
// End sample cycle.
|
if (UsecDelay) {
|
||||||
writeBit(true);
|
delayMicroseconds(UsecDelay);
|
||||||
// Null bit.
|
}
|
||||||
writeBit(true);
|
// End sample cycle.
|
||||||
// Data bits.
|
writeBit(true);
|
||||||
readBit(v, 11);
|
// Null bit.
|
||||||
readBit(v, 10);
|
writeBit(true);
|
||||||
readBit(v, 9);
|
// Data bits.
|
||||||
readBit(v, 8);
|
readBit(v, 11);
|
||||||
readBit(v, 7);
|
readBit(v, 10);
|
||||||
readBit(v, 6);
|
readBit(v, 9);
|
||||||
readBit(v, 5);
|
readBit(v, 8);
|
||||||
readBit(v, 4);
|
readBit(v, 7);
|
||||||
readBit(v, 3);
|
readBit(v, 6);
|
||||||
readBit(v, 2);
|
readBit(v, 5);
|
||||||
readBit(v, 1);
|
readBit(v, 4);
|
||||||
readBit(v, 0);
|
readBit(v, 3);
|
||||||
fastDigitalWrite(CsPin, 1);
|
readBit(v, 2);
|
||||||
return v;
|
readBit(v, 1);
|
||||||
}
|
readBit(v, 0);
|
||||||
private:
|
fastDigitalWrite(CsPin, 1);
|
||||||
//----------------------------------------------------------------------------
|
return v;
|
||||||
/** delay n nops
|
}
|
||||||
* \param[in] n nops to delay, must be a constant so compiler optimizes if().
|
private:
|
||||||
*/
|
//----------------------------------------------------------------------------
|
||||||
inline __attribute__((always_inline))
|
/** delay n nops
|
||||||
void delayCycles(uint8_t n) {
|
* \param[in] n nops to delay, must be a constant so compiler optimizes if().
|
||||||
if (n & 1) asm volatile("nop\n\t");
|
*/
|
||||||
if (n & 2) asm volatile("nop\n\t" "nop\n\t");
|
inline __attribute__((always_inline))
|
||||||
if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
|
void delayCycles(uint8_t n)
|
||||||
}
|
{
|
||||||
//----------------------------------------------------------------------------
|
if (n & 1) {
|
||||||
/** clock for don't care bits
|
asm volatile("nop\n\t");
|
||||||
*\param[in] delayBefore if true, delay before raising clock*/
|
}
|
||||||
inline __attribute__((always_inline))
|
if (n & 2) {
|
||||||
void writeBit(bool value) {
|
asm volatile("nop\n\t" "nop\n\t");
|
||||||
fastDigitalWrite(DinPin, value);
|
}
|
||||||
fastDigitalWrite(ClkPin, 1);
|
if (n & 4) {
|
||||||
delayCycles(2);
|
asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
|
||||||
fastDigitalWrite(ClkPin, 0);
|
}
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
inline __attribute__((always_inline))
|
/** clock for don't care bits
|
||||||
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1) {
|
*\param[in] delayBefore if true, delay before raising clock*/
|
||||||
delayCycles(2);
|
inline __attribute__((always_inline))
|
||||||
fastDigitalWrite(ClkPin, 1);
|
void writeBit(bool value)
|
||||||
delayCycles(delayRead);
|
{
|
||||||
if (fastDigitalRead(DoutPin)) v |= (1 << b);
|
fastDigitalWrite(DinPin, value);
|
||||||
fastDigitalWrite(ClkPin, 0);
|
fastDigitalWrite(ClkPin, 1);
|
||||||
}
|
delayCycles(2);
|
||||||
|
fastDigitalWrite(ClkPin, 0);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
inline __attribute__((always_inline))
|
||||||
|
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1)
|
||||||
|
{
|
||||||
|
delayCycles(2);
|
||||||
|
fastDigitalWrite(ClkPin, 1);
|
||||||
|
delayCycles(delayRead);
|
||||||
|
if (fastDigitalRead(DoutPin)) {
|
||||||
|
v |= (1 << b);
|
||||||
|
}
|
||||||
|
fastDigitalWrite(ClkPin, 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
// MCP3204 and MCP3208 use the same code.
|
// 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
|
||||||
@@ -9,119 +9,145 @@ 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. */
|
//----------------------------------------------------------------------------
|
||||||
void begin(bool singleMode = true) {
|
/** Set pin modes and initial levels. */
|
||||||
m_singleMode = singleMode;
|
void begin(bool singleMode = true)
|
||||||
fastPinMode(SdoPin, 0);
|
{
|
||||||
fastPinMode(SckPin, 1);
|
m_singleMode = singleMode;
|
||||||
fastDigitalWrite(SckPin, 1);
|
fastPinMode(SdoPin, 0);
|
||||||
fastPinMode(CsPin, 1);
|
fastPinMode(SckPin, 1);
|
||||||
fastDigitalWrite(CsPin, 1);
|
fastDigitalWrite(SckPin, 1);
|
||||||
if (!m_singleMode) {
|
fastPinMode(CsPin, 1);
|
||||||
// Wait for conversion to complete.
|
fastDigitalWrite(CsPin, 1);
|
||||||
delay(100);
|
if (!m_singleMode) {
|
||||||
// Start continuous conversion mode.
|
// Wait for conversion to complete.
|
||||||
fastDigitalWrite(CsPin, 0);
|
delay(100);
|
||||||
}
|
// Start continuous conversion mode.
|
||||||
}
|
fastDigitalWrite(CsPin, 0);
|
||||||
//----------------------------------------------------------------------------
|
}
|
||||||
/** Read MCP355X 22-bit ADC
|
}
|
||||||
* \return 22-bit value.
|
//----------------------------------------------------------------------------
|
||||||
*/
|
/** Read MCP355X 22-bit ADC
|
||||||
inline __attribute__((always_inline))
|
* \return 22-bit value.
|
||||||
int32_t read() {
|
*/
|
||||||
uint8_t t = 0;
|
inline __attribute__((always_inline))
|
||||||
uint8_t v3 = 0;
|
int32_t read()
|
||||||
if (m_singleMode) {
|
{
|
||||||
// Start conversion.
|
uint8_t t = 0;
|
||||||
fastDigitalWrite(CsPin, 0);
|
uint8_t v3 = 0;
|
||||||
// Delay at least 10 usec to avoid RDY glitch on exit from Shutdown.
|
if (m_singleMode) {
|
||||||
delay(1);
|
// Start conversion.
|
||||||
// Toggle CsPin to indicate single conversion mode.
|
fastDigitalWrite(CsPin, 0);
|
||||||
fastDigitalWrite(CsPin, 1);
|
// Delay at least 10 usec to avoid RDY glitch on exit from Shutdown.
|
||||||
// Wait for conversion to complete.
|
delay(1);
|
||||||
while (1) {
|
// Toggle CsPin to indicate single conversion mode.
|
||||||
delay(1);
|
fastDigitalWrite(CsPin, 1);
|
||||||
fastDigitalWrite(CsPin, 0);
|
// Wait for conversion to complete.
|
||||||
// Delay while RDY settles.
|
while (1) {
|
||||||
delayCycles(4);
|
delay(1);
|
||||||
if (!fastDigitalRead(SdoPin)) break;
|
fastDigitalWrite(CsPin, 0);
|
||||||
fastDigitalWrite(CsPin, 1);
|
// Delay while RDY settles.
|
||||||
if (t++ > MCP355X_TO_MS) return MCP355X_ERR;
|
delayCycles(4);
|
||||||
}
|
if (!fastDigitalRead(SdoPin)) {
|
||||||
} else {
|
break;
|
||||||
while (1) {
|
}
|
||||||
if (!fastDigitalRead(SdoPin)) break;
|
fastDigitalWrite(CsPin, 1);
|
||||||
delay(1);
|
if (t++ > MCP355X_TO_MS) {
|
||||||
if (t++ > MCP355X_TO_MS) return MCP355X_ERR;
|
return MCP355X_ERR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint8_t v2 = readByte();
|
} else {
|
||||||
uint8_t v1 = readByte();
|
while (1) {
|
||||||
uint8_t v0 = readByte();
|
if (!fastDigitalRead(SdoPin)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
delay(1);
|
||||||
|
if (t++ > MCP355X_TO_MS) {
|
||||||
|
return MCP355X_ERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t v2 = readByte();
|
||||||
|
uint8_t v1 = readByte();
|
||||||
|
uint8_t v0 = readByte();
|
||||||
|
|
||||||
// The 25th falling edge of SCK changes SDO/RDY from Data mode to RDY mode.
|
// The 25th falling edge of SCK changes SDO/RDY from Data mode to RDY mode.
|
||||||
uint8_t dummy = 0;
|
uint8_t dummy = 0;
|
||||||
readBit(dummy, 0);
|
readBit(dummy, 0);
|
||||||
|
|
||||||
if (m_singleMode) {
|
if (m_singleMode) {
|
||||||
fastDigitalWrite(CsPin, 1);
|
fastDigitalWrite(CsPin, 1);
|
||||||
}
|
}
|
||||||
if ((v2 & 0XE0) == 0X20) {
|
if ((v2 & 0XE0) == 0X20) {
|
||||||
// Negative in range so extend sign bit.
|
// Negative in range so extend sign bit.
|
||||||
v2 |= 0XC0;
|
v2 |= 0XC0;
|
||||||
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) {
|
||||||
} else if (v2 & 0X80) {
|
v2 &= 0X3F;
|
||||||
// Overflow low. Cause value to be <= MCP355X_OVH.
|
}
|
||||||
if ((v2 & 0X20) == 0) v2 |= 0X40;
|
} else if (v2 & 0X80) {
|
||||||
v3 = 0XFF;
|
// Overflow low. Cause value to be <= MCP355X_OVH.
|
||||||
}
|
if ((v2 & 0X20) == 0) {
|
||||||
uint16_t v_high = (v3 << 8) | v2;
|
v2 |= 0X40;
|
||||||
uint16_t v_low = (v1 << 8) | v0;
|
}
|
||||||
return ((uint32_t)v_high << 16) | v_low;
|
v3 = 0XFF;
|
||||||
}
|
}
|
||||||
private:
|
uint16_t v_high = (v3 << 8) | v2;
|
||||||
//----------------------------------------------------------------------------
|
uint16_t v_low = (v1 << 8) | v0;
|
||||||
/** delay n nops
|
return ((uint32_t)v_high << 16) | v_low;
|
||||||
* \param[in] n nops to delay, must be a constant so compiler optimizes if().
|
}
|
||||||
*/
|
private:
|
||||||
inline __attribute__((always_inline))
|
//----------------------------------------------------------------------------
|
||||||
void delayCycles(uint8_t n) {
|
/** delay n nops
|
||||||
if (n & 1) asm volatile("nop\n\t");
|
* \param[in] n nops to delay, must be a constant so compiler optimizes if().
|
||||||
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");
|
inline __attribute__((always_inline))
|
||||||
}
|
void delayCycles(uint8_t n)
|
||||||
//----------------------------------------------------------------------------
|
{
|
||||||
// Default delay yields about 2 MHz clock.
|
if (n & 1) {
|
||||||
inline __attribute__((always_inline))
|
asm volatile("nop\n\t");
|
||||||
void readBit(uint8_t &v, uint8_t b, uint8_t delayRead = 0) {
|
}
|
||||||
fastDigitalWrite(SckPin, 0);
|
if (n & 2) {
|
||||||
delayCycles(2 + delayRead);
|
asm volatile("nop\n\t" "nop\n\t");
|
||||||
fastDigitalWrite(SckPin, 1);
|
}
|
||||||
if (fastDigitalRead(SdoPin)) v |= (1 << b);
|
if (n & 4) {
|
||||||
delayCycles(delayRead);
|
asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------
|
}
|
||||||
inline __attribute__((always_inline))
|
//----------------------------------------------------------------------------
|
||||||
uint8_t readByte() {
|
// Default delay yields about 2 MHz clock.
|
||||||
uint8_t v = 0;
|
inline __attribute__((always_inline))
|
||||||
readBit(v, 7);
|
void readBit(uint8_t &v, uint8_t b, uint8_t delayRead = 0)
|
||||||
readBit(v, 6);
|
{
|
||||||
readBit(v, 5);
|
fastDigitalWrite(SckPin, 0);
|
||||||
readBit(v, 4);
|
delayCycles(2 + delayRead);
|
||||||
readBit(v, 3);
|
fastDigitalWrite(SckPin, 1);
|
||||||
readBit(v, 2);
|
if (fastDigitalRead(SdoPin)) {
|
||||||
readBit(v, 1);
|
v |= (1 << b);
|
||||||
readBit(v, 0);
|
}
|
||||||
return v;
|
delayCycles(delayRead);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool m_singleMode;
|
inline __attribute__((always_inline))
|
||||||
|
uint8_t readByte()
|
||||||
|
{
|
||||||
|
uint8_t v = 0;
|
||||||
|
readBit(v, 7);
|
||||||
|
readBit(v, 6);
|
||||||
|
readBit(v, 5);
|
||||||
|
readBit(v, 4);
|
||||||
|
readBit(v, 3);
|
||||||
|
readBit(v, 2);
|
||||||
|
readBit(v, 1);
|
||||||
|
readBit(v, 0);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
bool m_singleMode;
|
||||||
};
|
};
|
||||||
#endif // MCP355X_h
|
#endif // MCP355X_h
|
||||||
@@ -4,9 +4,10 @@ DigitalPin<13> pin13(OUTPUT);
|
|||||||
|
|
||||||
void setup() {}
|
void setup() {}
|
||||||
|
|
||||||
void loop() {
|
void loop()
|
||||||
// toggle is a two byte instruction that executes
|
{
|
||||||
// in two cycles or 125 ns on a 16 MHz CPU
|
// toggle is a two byte instruction that executes
|
||||||
pin13.toggle();
|
// in two cycles or 125 ns on a 16 MHz CPU
|
||||||
delay(250);
|
pin13.toggle();
|
||||||
|
delay(250);
|
||||||
}
|
}
|
||||||
@@ -4,15 +4,17 @@
|
|||||||
// 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.
|
{
|
||||||
pin13.config(OUTPUT, LOW);
|
// Set mode to OUTPUT and level LOW.
|
||||||
|
pin13.config(OUTPUT, LOW);
|
||||||
}
|
}
|
||||||
void loop() {
|
void loop()
|
||||||
// toggle is a two byte instruction that executes
|
{
|
||||||
// in two cycles or 125 ns on a 16 MHz CPU
|
// toggle is a two byte instruction that executes
|
||||||
pin13.toggle();
|
// in two cycles or 125 ns on a 16 MHz CPU
|
||||||
delay(100);
|
pin13.toggle();
|
||||||
pin13.toggle();
|
delay(100);
|
||||||
delay(400);
|
pin13.toggle();
|
||||||
|
delay(400);
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ DigitalPin<13> pin13(OUTPUT);
|
|||||||
|
|
||||||
void setup() {}
|
void setup() {}
|
||||||
|
|
||||||
void loop() {
|
void loop()
|
||||||
pin13 = pin12;
|
{
|
||||||
|
pin13 = pin12;
|
||||||
}
|
}
|
||||||
@@ -10,30 +10,34 @@ 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);
|
{
|
||||||
clockPin = 1;
|
dataPin = data & (1 << bit);
|
||||||
// may want a nop here - clock pulse is 125 ns wide
|
clockPin = 1;
|
||||||
clockPin = 0;
|
// may want a nop here - clock pulse is 125 ns wide
|
||||||
|
clockPin = 0;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// 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(6, bits);
|
sendBit(7, bits);
|
||||||
sendBit(5, bits);
|
sendBit(6, bits);
|
||||||
sendBit(4, bits);
|
sendBit(5, bits);
|
||||||
sendBit(3, bits);
|
sendBit(4, bits);
|
||||||
sendBit(2, bits);
|
sendBit(3, bits);
|
||||||
sendBit(1, bits);
|
sendBit(2, bits);
|
||||||
sendBit(0, bits);
|
sendBit(1, bits);
|
||||||
|
sendBit(0, bits);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void setup() {
|
void setup()
|
||||||
// Not used.
|
{
|
||||||
|
// Not used.
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void loop() {
|
void loop()
|
||||||
shiftOut(0X55);
|
{
|
||||||
delay(2);
|
shiftOut(0X55);
|
||||||
|
delay(2);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,19 +6,21 @@
|
|||||||
PinIO readPin;
|
PinIO readPin;
|
||||||
PinIO writePin;
|
PinIO writePin;
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void setup() {
|
void setup()
|
||||||
// Assign pin 12 to readPin.
|
{
|
||||||
readPin.begin(12);
|
// Assign pin 12 to readPin.
|
||||||
|
readPin.begin(12);
|
||||||
|
|
||||||
// input mode with pull-ups disabled
|
// input mode with pull-ups disabled
|
||||||
readPin.config(INPUT, LOW);
|
readPin.config(INPUT, LOW);
|
||||||
|
|
||||||
// Assign pin 13 to writePin and set mode to output.
|
// Assign pin 13 to writePin and set mode to output.
|
||||||
writePin.begin(13);
|
writePin.begin(13);
|
||||||
writePin.mode(OUTPUT);
|
writePin.mode(OUTPUT);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void loop() {
|
void loop()
|
||||||
// Copy the value read from readPin to writePin.
|
{
|
||||||
writePin.write(readPin.read());
|
// Copy the value read from readPin to writePin.
|
||||||
|
writePin.write(readPin.read());
|
||||||
}
|
}
|
||||||
@@ -4,13 +4,15 @@
|
|||||||
// 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
|
{
|
||||||
pin13.config(OUTPUT, LOW);
|
// set mode to OUTPUT and level LOW
|
||||||
|
pin13.config(OUTPUT, LOW);
|
||||||
}
|
}
|
||||||
void loop() {
|
void loop()
|
||||||
pin13.toggle();
|
{
|
||||||
delay(100);
|
pin13.toggle();
|
||||||
pin13.toggle();
|
delay(100);
|
||||||
delay(400);
|
pin13.toggle();
|
||||||
|
delay(400);
|
||||||
}
|
}
|
||||||
@@ -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.
|
{
|
||||||
readPin.config(INPUT, LOW);
|
// Set input mode and disable pull-up.
|
||||||
|
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,52 +26,59 @@ 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);
|
||||||
|
|
||||||
if (!digitalRead(SDA_PIN) && !digitalRead(SCL_PIN)) {
|
if (!digitalRead(SDA_PIN) && !digitalRead(SCL_PIN)) {
|
||||||
Serial.println("External pull-up resistors appear to be missing.");
|
Serial.println("External pull-up resistors appear to be missing.");
|
||||||
Serial.println("Many false responses may be detected.");
|
Serial.println("Many false responses may be detected.");
|
||||||
Serial.println("Type any character to continue.");
|
Serial.println("Type any character to continue.");
|
||||||
|
|
||||||
while (!Serial.available());
|
while (!Serial.available());
|
||||||
Serial.println();
|
Serial.println();
|
||||||
|
|
||||||
}
|
}
|
||||||
uint8_t add = 0;
|
uint8_t add = 0;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
do {
|
do {
|
||||||
bool wr = i2c.transfer(add | I2C_WRITE, 0, 0);
|
bool wr = i2c.transfer(add | I2C_WRITE, 0, 0);
|
||||||
bool rd = i2c.transfer(add | I2C_READ, 0, 0, I2C_CONTINUE);
|
bool rd = i2c.transfer(add | I2C_READ, 0, 0, I2C_CONTINUE);
|
||||||
if (rd) {
|
if (rd) {
|
||||||
uint8_t dummy;
|
uint8_t dummy;
|
||||||
// Must read byte, send NACK, and issue STOP.
|
// Must read byte, send NACK, and issue STOP.
|
||||||
i2c.transferContinue(&dummy, 1);
|
i2c.transferContinue(&dummy, 1);
|
||||||
}
|
}
|
||||||
if (rd || wr) {
|
if (rd || wr) {
|
||||||
found = true;
|
found = true;
|
||||||
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");
|
}
|
||||||
Serial.println('.');
|
if (rd && wr) {
|
||||||
}
|
Serial.print(" and ");
|
||||||
add += 2;
|
}
|
||||||
}
|
if (wr) {
|
||||||
while (add);
|
Serial.print("Write");
|
||||||
|
}
|
||||||
|
Serial.println('.');
|
||||||
|
}
|
||||||
|
add += 2;
|
||||||
|
} while (add);
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
Serial.println("No devices found.");
|
Serial.println("No devices found.");
|
||||||
}
|
}
|
||||||
Serial.println("Done");
|
Serial.println("Done");
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void loop() {
|
void loop()
|
||||||
// Not used.
|
{
|
||||||
|
// Not used.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,30 +16,35 @@ 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);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/*
|
/*
|
||||||
* 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)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Write data.
|
// Write data.
|
||||||
return rtc.transferContinue(buf, count);
|
return rtc.transferContinue(buf, count);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void setup(void) {
|
void setup(void)
|
||||||
Serial.begin(9600);
|
{
|
||||||
|
Serial.begin(9600);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** Store and print a string in flash memory.*/
|
/** Store and print a string in flash memory.*/
|
||||||
@@ -50,134 +55,142 @@ 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 & 0XF, HEX);
|
Serial.print(v >> 4, HEX);
|
||||||
|
Serial.print(v & 0XF, HEX);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void hexPrintln(uint8_t v) {
|
void hexPrintln(uint8_t v)
|
||||||
hexPrint(v);
|
{
|
||||||
Serial.println();
|
hexPrint(v);
|
||||||
|
Serial.println();
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// read hex input
|
// read hex input
|
||||||
uint8_t hexRead(uint16_t* v) {
|
uint8_t hexRead(uint16_t* v)
|
||||||
bool valid = false;
|
{
|
||||||
uint16_t n = 0;
|
bool valid = false;
|
||||||
while (!Serial.available());
|
uint16_t n = 0;
|
||||||
while (Serial.available()) {
|
while (!Serial.available());
|
||||||
uint8_t c = Serial.read();
|
while (Serial.available()) {
|
||||||
// Exit if end-of-line.
|
uint8_t c = Serial.read();
|
||||||
if (c == '\n' || c == '\r') {
|
// Exit if end-of-line.
|
||||||
delay(10);
|
if (c == '\n' || c == '\r') {
|
||||||
// If CR/LF.
|
delay(10);
|
||||||
Serial.read();
|
// If CR/LF.
|
||||||
break;
|
Serial.read();
|
||||||
}
|
break;
|
||||||
n <<= 4;
|
}
|
||||||
if ('a' <= c && c <= 'f') {
|
n <<= 4;
|
||||||
n += c - ('a' - 10);
|
if ('a' <= c && c <= 'f') {
|
||||||
}
|
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 {
|
||||||
}
|
valid = false;
|
||||||
else {
|
break;
|
||||||
valid = false;
|
}
|
||||||
break;
|
delay(10);
|
||||||
}
|
valid = true;
|
||||||
delay(10);
|
}
|
||||||
valid = true;
|
if (!valid) {
|
||||||
}
|
PgmPrintln("Invalid entry");
|
||||||
if (!valid) {
|
return false;
|
||||||
PgmPrintln("Invalid entry");
|
}
|
||||||
return false;
|
*v = n;
|
||||||
}
|
return true;
|
||||||
*v = n;
|
|
||||||
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;
|
{
|
||||||
if (!hexRead(&v)) return false;
|
uint16_t v;
|
||||||
uint8_t d = 10 * (v >> 4) + (v & 0XF);
|
if (!hexRead(&v)) {
|
||||||
if ((v >> 4) > 9 || (v & 0XF) > 9 || d < min || d > max) {
|
return false;
|
||||||
PgmPrintln("Invalid");
|
}
|
||||||
return false;
|
uint8_t d = 10 * (v >> 4) + (v & 0XF);
|
||||||
}
|
if ((v >> 4) > 9 || (v & 0XF) > 9 || d < min || d > max) {
|
||||||
*n = v;
|
PgmPrintln("Invalid");
|
||||||
return true;
|
return false;
|
||||||
|
}
|
||||||
|
*n = v;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void displayTime(void) {
|
void displayTime(void)
|
||||||
uint8_t r[8];
|
{
|
||||||
if (!readDS1307(0, r, 8)) {
|
uint8_t r[8];
|
||||||
PgmPrintln("Read Failed for display time");
|
if (!readDS1307(0, r, 8)) {
|
||||||
return;
|
PgmPrintln("Read Failed for display time");
|
||||||
}
|
return;
|
||||||
PgmPrint("The current time is 20");
|
}
|
||||||
// year
|
PgmPrint("The current time is 20");
|
||||||
hexPrint(r[6]);
|
// year
|
||||||
Serial.write('-');
|
hexPrint(r[6]);
|
||||||
|
Serial.write('-');
|
||||||
|
|
||||||
// month
|
// month
|
||||||
hexPrint(r[5]);
|
hexPrint(r[5]);
|
||||||
Serial.write('-');
|
Serial.write('-');
|
||||||
|
|
||||||
// day
|
// day
|
||||||
hexPrint(r[4]);
|
hexPrint(r[4]);
|
||||||
Serial.write(' ');
|
Serial.write(' ');
|
||||||
|
|
||||||
Serial.print(Ddd[r[3] < 8 ? r[3] : 0]);
|
Serial.print(Ddd[r[3] < 8 ? r[3] : 0]);
|
||||||
Serial.write(' ');
|
Serial.write(' ');
|
||||||
|
|
||||||
// hour
|
// hour
|
||||||
hexPrint(r[2]);
|
hexPrint(r[2]);
|
||||||
Serial.write(':');
|
Serial.write(':');
|
||||||
|
|
||||||
// minute
|
// minute
|
||||||
hexPrint(r[1]);
|
hexPrint(r[1]);
|
||||||
Serial.write(':');
|
Serial.write(':');
|
||||||
|
|
||||||
// second
|
// second
|
||||||
hexPrintln(r[0]);
|
hexPrintln(r[0]);
|
||||||
|
|
||||||
// Control register.
|
// Control register.
|
||||||
PgmPrint("Control Register: ");
|
PgmPrint("Control Register: ");
|
||||||
hexPrintln(r[7]);
|
hexPrintln(r[7]);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// dump registers and 56 bytes of RAM
|
// dump registers and 56 bytes of RAM
|
||||||
void dumpAll(void) {
|
void dumpAll(void)
|
||||||
uint8_t buf[8];
|
{
|
||||||
for (uint8_t a = 0; a < 64; a += 8) {
|
uint8_t buf[8];
|
||||||
hexPrint(a);
|
for (uint8_t a = 0; a < 64; a += 8) {
|
||||||
Serial.write(' ');
|
hexPrint(a);
|
||||||
if (!readDS1307(a, buf, 8)) {
|
Serial.write(' ');
|
||||||
PgmPrint("read failed for dumpAll");
|
if (!readDS1307(a, buf, 8)) {
|
||||||
return;
|
PgmPrint("read failed for dumpAll");
|
||||||
}
|
return;
|
||||||
for (uint8_t i = 0; i < 8; i++) {
|
}
|
||||||
Serial.write(' ');
|
for (uint8_t i = 0; i < 8; i++) {
|
||||||
hexPrint(buf[i]);
|
Serial.write(' ');
|
||||||
}
|
hexPrint(buf[i]);
|
||||||
Serial.println();
|
}
|
||||||
}
|
Serial.println();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void fillNvRam(void) {
|
void fillNvRam(void)
|
||||||
uint8_t buf[8];
|
{
|
||||||
PgmPrint("Enter HEX value for all NV RAM locations (00-FF): ");
|
uint8_t buf[8];
|
||||||
uint16_t v;
|
PgmPrint("Enter HEX value for all NV RAM locations (00-FF): ");
|
||||||
if (!hexRead(&v)) return;
|
uint16_t v;
|
||||||
hexPrint(v);
|
if (!hexRead(&v)) {
|
||||||
for (uint8_t a = 8; a < 64; a ++) {
|
return;
|
||||||
if (!writeDS1307(a, (uint8_t *)&v, 1)) {
|
}
|
||||||
PgmPrintln("write failed for fillNvRam");
|
hexPrint(v);
|
||||||
}
|
for (uint8_t a = 8; a < 64; a ++) {
|
||||||
}
|
if (!writeDS1307(a, (uint8_t *)&v, 1)) {
|
||||||
|
PgmPrintln("write failed for fillNvRam");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// set control register
|
// set control register
|
||||||
@@ -205,120 +218,149 @@ 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("(00) Low");
|
PgmPrintln("SQW/OUT pin: ");
|
||||||
PgmPrintln("(10) 1Hz");
|
PgmPrintln("(00) Low");
|
||||||
PgmPrintln("(11) 4.096kHz");
|
PgmPrintln("(10) 1Hz");
|
||||||
PgmPrintln("(12) 8.192kHz");
|
PgmPrintln("(11) 4.096kHz");
|
||||||
PgmPrintln("(13) 32.768kHz");
|
PgmPrintln("(12) 8.192kHz");
|
||||||
PgmPrintln("(80) High");
|
PgmPrintln("(13) 32.768kHz");
|
||||||
PgmPrint("Enter control: ");
|
PgmPrintln("(80) High");
|
||||||
uint16_t r;
|
PgmPrint("Enter control: ");
|
||||||
if (!hexRead(&r)) return;
|
uint16_t r;
|
||||||
hexPrintln(r);
|
if (!hexRead(&r)) {
|
||||||
if (!writeDS1307(7, (uint8_t *)&r, 1)) {
|
return;
|
||||||
PgmPrint("Write Failed for setControl");
|
}
|
||||||
}
|
hexPrintln(r);
|
||||||
|
if (!writeDS1307(7, (uint8_t *)&r, 1)) {
|
||||||
|
PgmPrint("Write Failed for setControl");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void setDate(void) {
|
void setDate(void)
|
||||||
uint8_t r[4];
|
{
|
||||||
PgmPrint("Enter year (00-99): ");
|
uint8_t r[4];
|
||||||
if (!bcdRead(0, 99, &r[3])) return;
|
PgmPrint("Enter year (00-99): ");
|
||||||
hexPrintln(r[3]);
|
if (!bcdRead(0, 99, &r[3])) {
|
||||||
PgmPrint("Enter month (01-12): ");
|
return;
|
||||||
if (!bcdRead(1, 12, &r[2])) return;
|
}
|
||||||
hexPrintln(r[2]);
|
hexPrintln(r[3]);
|
||||||
PgmPrint("Enter day (01-31): ");
|
PgmPrint("Enter month (01-12): ");
|
||||||
if (!bcdRead(1, 31, &r[1])) return;
|
if (!bcdRead(1, 12, &r[2])) {
|
||||||
hexPrintln(r[1]);
|
return;
|
||||||
PgmPrint("Enter day of week (01-07, Sun-Sat): ");
|
}
|
||||||
if (!bcdRead(1, 7, &r[0])) return;
|
hexPrintln(r[2]);
|
||||||
hexPrintln(r[0]);
|
PgmPrint("Enter day (01-31): ");
|
||||||
|
if (!bcdRead(1, 31, &r[1])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hexPrintln(r[1]);
|
||||||
|
PgmPrint("Enter day of week (01-07, Sun-Sat): ");
|
||||||
|
if (!bcdRead(1, 7, &r[0])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hexPrintln(r[0]);
|
||||||
|
|
||||||
if (!writeDS1307(3, r, 4)) {
|
if (!writeDS1307(3, r, 4)) {
|
||||||
PgmPrintln("Write failed for setDate");
|
PgmPrintln("Write failed for setDate");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void setNvRam() {
|
void setNvRam()
|
||||||
uint8_t u;
|
{
|
||||||
uint16_t a, v;
|
uint8_t u;
|
||||||
while (true) {
|
uint16_t a, v;
|
||||||
PgmPrint("Enter zero to quit or Hex address (8-3F):");
|
while (true) {
|
||||||
if (!hexRead(&a) || a == 0) return;
|
PgmPrint("Enter zero to quit or Hex address (8-3F):");
|
||||||
if (a < 8 || a > 0X3F) {
|
if (!hexRead(&a) || a == 0) {
|
||||||
PgmPrintln("Invalid address");
|
return;
|
||||||
return;
|
}
|
||||||
}
|
if (a < 8 || a > 0X3F) {
|
||||||
hexPrintln(a);
|
PgmPrintln("Invalid address");
|
||||||
if (!readDS1307(a, &u, 1)) {
|
return;
|
||||||
PgmPrintln("Read failed");
|
}
|
||||||
return;
|
hexPrintln(a);
|
||||||
}
|
if (!readDS1307(a, &u, 1)) {
|
||||||
PgmPrint("Current value: ");
|
PgmPrintln("Read failed");
|
||||||
hexPrintln(u);
|
return;
|
||||||
PgmPrint("Enter new HEX value (00-FF): ");
|
}
|
||||||
if (!hexRead(&v)) return;
|
PgmPrint("Current value: ");
|
||||||
hexPrintln(v);
|
hexPrintln(u);
|
||||||
if (!writeDS1307(a, (uint8_t *)&v, 1)) {
|
PgmPrint("Enter new HEX value (00-FF): ");
|
||||||
PgmPrint("Write Failed");
|
if (!hexRead(&v)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
hexPrintln(v);
|
||||||
|
if (!writeDS1307(a, (uint8_t *)&v, 1)) {
|
||||||
|
PgmPrint("Write Failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void setTime(void) {
|
void setTime(void)
|
||||||
uint8_t r[3];
|
{
|
||||||
PgmPrint("Enter hours (00-23): ");
|
uint8_t r[3];
|
||||||
if (!bcdRead(0, 23, &r[2])) return;
|
PgmPrint("Enter hours (00-23): ");
|
||||||
hexPrintln(r[2]);
|
if (!bcdRead(0, 23, &r[2])) {
|
||||||
PgmPrint("Enter minutes (00-59): ");
|
return;
|
||||||
if (!bcdRead(0, 59, &r[1])) return;
|
}
|
||||||
hexPrintln(r[1]);
|
hexPrintln(r[2]);
|
||||||
PgmPrint("Enter seconds (00-59): ");
|
PgmPrint("Enter minutes (00-59): ");
|
||||||
if (!bcdRead(0, 59, &r[0])) return;
|
if (!bcdRead(0, 59, &r[1])) {
|
||||||
hexPrintln(r[0]);
|
return;
|
||||||
|
}
|
||||||
|
hexPrintln(r[1]);
|
||||||
|
PgmPrint("Enter seconds (00-59): ");
|
||||||
|
if (!bcdRead(0, 59, &r[0])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hexPrintln(r[0]);
|
||||||
|
|
||||||
if (!writeDS1307(0, r, 3)) {
|
if (!writeDS1307(0, r, 3)) {
|
||||||
PgmPrintln("write failed in setTime");
|
PgmPrintln("write failed in setTime");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void loop(void) {
|
void loop(void)
|
||||||
Serial.println();
|
{
|
||||||
displayTime();
|
Serial.println();
|
||||||
while (Serial.read() >= 0) {}
|
displayTime();
|
||||||
PgmPrintln("\nOptions are:");
|
while (Serial.read() >= 0) {}
|
||||||
PgmPrintln("(0) Display date and time");
|
PgmPrintln("\nOptions are:");
|
||||||
PgmPrintln("(1) Set time");
|
PgmPrintln("(0) Display date and time");
|
||||||
PgmPrintln("(2) Set date");
|
PgmPrintln("(1) Set time");
|
||||||
PgmPrintln("(3) Set Control");
|
PgmPrintln("(2) Set date");
|
||||||
PgmPrintln("(4) Dump all");
|
PgmPrintln("(3) Set Control");
|
||||||
PgmPrintln("(5) Fill NV RAM");
|
PgmPrintln("(4) Dump all");
|
||||||
PgmPrintln("(6) Set NV RAM value");
|
PgmPrintln("(5) Fill NV RAM");
|
||||||
PgmPrint("Enter option: ");
|
PgmPrintln("(6) Set NV RAM value");
|
||||||
|
PgmPrint("Enter option: ");
|
||||||
|
|
||||||
uint16_t n;
|
uint16_t n;
|
||||||
if (!hexRead(&n)) return;
|
if (!hexRead(&n)) {
|
||||||
Serial.println(n, DEC);
|
return;
|
||||||
if (n == 0) return;
|
}
|
||||||
Serial.println();
|
Serial.println(n, DEC);
|
||||||
if (n == 1) {
|
if (n == 0) {
|
||||||
setTime();
|
return;
|
||||||
} else if (n == 2) {
|
}
|
||||||
setDate();
|
Serial.println();
|
||||||
} else if (n == 3) {
|
if (n == 1) {
|
||||||
setControl();
|
setTime();
|
||||||
} else if (n == 4) {
|
} else if (n == 2) {
|
||||||
dumpAll();
|
setDate();
|
||||||
} else if (n == 5) {
|
} else if (n == 3) {
|
||||||
fillNvRam();
|
setControl();
|
||||||
} else if (n == 6) {
|
} else if (n == 4) {
|
||||||
setNvRam();
|
dumpAll();
|
||||||
} else {
|
} else if (n == 5) {
|
||||||
PgmPrintln("Invalid option");
|
fillNvRam();
|
||||||
}
|
} else if (n == 6) {
|
||||||
|
setNvRam();
|
||||||
|
} else {
|
||||||
|
PgmPrintln("Invalid option");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,16 @@
|
|||||||
// 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.
|
{
|
||||||
pinMode(PIN13, OUTPUT);
|
// Set mode to OUTPUT.
|
||||||
|
pinMode(PIN13, OUTPUT);
|
||||||
}
|
}
|
||||||
void loop() {
|
void loop()
|
||||||
digitalWrite(PIN13, HIGH);
|
{
|
||||||
digitalWrite(PIN13, LOW);
|
digitalWrite(PIN13, HIGH);
|
||||||
digitalWrite(PIN13, HIGH);
|
digitalWrite(PIN13, LOW);
|
||||||
digitalWrite(PIN13, LOW);
|
digitalWrite(PIN13, HIGH);
|
||||||
delay(1);
|
digitalWrite(PIN13, LOW);
|
||||||
|
delay(1);
|
||||||
}
|
}
|
||||||
@@ -4,16 +4,18 @@
|
|||||||
// 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
|
{
|
||||||
pin13.mode(OUTPUT);
|
// set mode to OUTPUT
|
||||||
|
pin13.mode(OUTPUT);
|
||||||
}
|
}
|
||||||
void loop() {
|
void loop()
|
||||||
pin13.high();
|
{
|
||||||
pin13.low();
|
pin13.high();
|
||||||
pin13.write(1);
|
pin13.low();
|
||||||
pin13.write(0);
|
pin13.write(1);
|
||||||
pin13.toggle();
|
pin13.write(0);
|
||||||
pin13.toggle();
|
pin13.toggle();
|
||||||
delay(1);
|
pin13.toggle();
|
||||||
|
delay(1);
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,15 @@
|
|||||||
// 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, LOW);
|
fastDigitalWrite(PIN, HIGH);
|
||||||
fastDigitalToggle(PIN);
|
fastDigitalWrite(PIN, LOW);
|
||||||
fastDigitalToggle(PIN);
|
fastDigitalToggle(PIN);
|
||||||
delay(1);
|
fastDigitalToggle(PIN);
|
||||||
|
delay(1);
|
||||||
}
|
}
|
||||||
@@ -4,16 +4,18 @@
|
|||||||
// Class with runtime pin numbers.
|
// Class with runtime pin numbers.
|
||||||
PinIO pin(13);
|
PinIO pin(13);
|
||||||
|
|
||||||
void setup() {
|
void setup()
|
||||||
// Set mode to OUTPUT.
|
{
|
||||||
pin.mode(OUTPUT);
|
// Set mode to OUTPUT.
|
||||||
|
pin.mode(OUTPUT);
|
||||||
}
|
}
|
||||||
void loop() {
|
void loop()
|
||||||
pin.high();
|
{
|
||||||
pin.low();
|
pin.high();
|
||||||
pin.write(1);
|
pin.low();
|
||||||
pin.write(0);
|
pin.write(1);
|
||||||
pin.toggle();
|
pin.write(0);
|
||||||
pin.toggle();
|
pin.toggle();
|
||||||
delay(1);
|
pin.toggle();
|
||||||
|
delay(1);
|
||||||
}
|
}
|
||||||
@@ -9,29 +9,35 @@ 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);
|
{
|
||||||
spi.begin();
|
Serial.begin(9600);
|
||||||
while(1) {
|
spi.begin();
|
||||||
Serial.println("Enter:");
|
while(1) {
|
||||||
Serial.println("R - Receive");
|
Serial.println("Enter:");
|
||||||
Serial.println("S - Send");
|
Serial.println("R - Receive");
|
||||||
Serial.println("T - Transfer");
|
Serial.println("S - Send");
|
||||||
while ((test = Serial.read()) <= 0) {}
|
Serial.println("T - Transfer");
|
||||||
test = toupper(test);
|
while ((test = Serial.read()) <= 0) {}
|
||||||
if (strchr("RST", test)) break;
|
test = toupper(test);
|
||||||
Serial.println("Invalid entry");
|
if (strchr("RST", test)) {
|
||||||
};
|
break;
|
||||||
Serial.print("Starting test ");
|
}
|
||||||
Serial.println((char)test);
|
Serial.println("Invalid entry");
|
||||||
|
};
|
||||||
|
Serial.print("Starting test ");
|
||||||
|
Serial.println((char)test);
|
||||||
}
|
}
|
||||||
void loop() {
|
void loop()
|
||||||
if (test == 'S') spi.send(0X55);
|
{
|
||||||
if (test == 'R') {
|
if (test == 'S') {
|
||||||
Serial.println(spi.receive(), HEX);
|
spi.send(0X55);
|
||||||
}
|
}
|
||||||
if (test == 'T') {
|
if (test == 'R') {
|
||||||
Serial.println(spi.transfer(0XAA), HEX);
|
Serial.println(spi.receive(), HEX);
|
||||||
}
|
}
|
||||||
delay(10);
|
if (test == 'T') {
|
||||||
|
Serial.println(spi.transfer(0XAA), HEX);
|
||||||
|
}
|
||||||
|
delay(10);
|
||||||
}
|
}
|
||||||
@@ -7,92 +7,92 @@
|
|||||||
#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 : \
|
||||||
((((__pin) >= 18 && (__pin) <= 21) || (__pin) == 38) ? &PORTD : \
|
((((__pin) >= 18 && (__pin) <= 21) || (__pin) == 38) ? &PORTD : \
|
||||||
((((__pin) <= 3) || (__pin) == 5) ? &PORTE : \
|
((((__pin) <= 3) || (__pin) == 5) ? &PORTE : \
|
||||||
(((__pin) >= 54 && (__pin) <= 61) ? &PORTF : \
|
(((__pin) >= 54 && (__pin) <= 61) ? &PORTF : \
|
||||||
((((__pin) >= 39 && (__pin) <= 41) || (__pin) == 4) ? &PORTG : \
|
((((__pin) >= 39 && (__pin) <= 41) || (__pin) == 4) ? &PORTG : \
|
||||||
((((__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 : \
|
||||||
((((__pin) >= 18 && (__pin) <= 21) || (__pin) == 38) ? &DDRD : \
|
((((__pin) >= 18 && (__pin) <= 21) || (__pin) == 38) ? &DDRD : \
|
||||||
((((__pin) <= 3) || (__pin) == 5) ? &DDRE : \
|
((((__pin) <= 3) || (__pin) == 5) ? &DDRE : \
|
||||||
(((__pin) >= 54 && (__pin) <= 61) ? &DDRF : \
|
(((__pin) >= 54 && (__pin) <= 61) ? &DDRF : \
|
||||||
((((__pin) >= 39 && (__pin) <= 41) || (__pin) == 4) ? &DDRG : \
|
((((__pin) >= 39 && (__pin) <= 41) || (__pin) == 4) ? &DDRG : \
|
||||||
((((__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 : \
|
||||||
((((__pin) >= 18 && (__pin) <= 21) || (__pin) == 38) ? &PIND : \
|
((((__pin) >= 18 && (__pin) <= 21) || (__pin) == 38) ? &PIND : \
|
||||||
((((__pin) <= 3) || (__pin) == 5) ? &PINE : \
|
((((__pin) <= 3) || (__pin) == 5) ? &PINE : \
|
||||||
(((__pin) >= 54 && (__pin) <= 61) ? &PINF : \
|
(((__pin) >= 54 && (__pin) <= 61) ? &PINF : \
|
||||||
((((__pin) >= 39 && (__pin) <= 41) || (__pin) == 4) ? &PING : \
|
((((__pin) >= 39 && (__pin) <= 41) || (__pin) == 4) ? &PING : \
|
||||||
((((__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 : \
|
||||||
(((__pin) >= 30 && (__pin) <= 37) ? 37 - (__pin) : \
|
(((__pin) >= 30 && (__pin) <= 37) ? 37 - (__pin) : \
|
||||||
(((__pin) >= 39 && (__pin) <= 41) ? 41 - (__pin) : \
|
(((__pin) >= 39 && (__pin) <= 41) ? 41 - (__pin) : \
|
||||||
(((__pin) >= 42 && (__pin) <= 49) ? 49 - (__pin) : \
|
(((__pin) >= 42 && (__pin) <= 49) ? 49 - (__pin) : \
|
||||||
(((__pin) >= 50 && (__pin) <= 53) ? 53 - (__pin) : \
|
(((__pin) >= 50 && (__pin) <= 53) ? 53 - (__pin) : \
|
||||||
(((__pin) >= 54 && (__pin) <= 61) ? (__pin) - 54 : \
|
(((__pin) >= 54 && (__pin) <= 61) ? (__pin) - 54 : \
|
||||||
(((__pin) >= 62 && (__pin) <= 69) ? (__pin) - 62 : \
|
(((__pin) >= 62 && (__pin) <= 69) ? (__pin) - 62 : \
|
||||||
(((__pin) == 0 || (__pin) == 15 || (__pin) == 17 || (__pin) == 21) ? 0 : \
|
(((__pin) == 0 || (__pin) == 15 || (__pin) == 17 || (__pin) == 21) ? 0 : \
|
||||||
(((__pin) == 1 || (__pin) == 14 || (__pin) == 16 || (__pin) == 20) ? 1 : \
|
(((__pin) == 1 || (__pin) == 14 || (__pin) == 16 || (__pin) == 20) ? 1 : \
|
||||||
(((__pin) == 19) ? 2 : \
|
(((__pin) == 19) ? 2 : \
|
||||||
(((__pin) == 5 || (__pin) == 6 || (__pin) == 18) ? 3 : \
|
(((__pin) == 5 || (__pin) == 6 || (__pin) == 18) ? 3 : \
|
||||||
(((__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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,164 +33,163 @@
|
|||||||
*/
|
*/
|
||||||
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.
|
||||||
* @param size Number of records available in the buffer.
|
* @param size Number of records available in the buffer.
|
||||||
*/
|
*/
|
||||||
CircularBuffer(T* buffer, const uint8_t size )
|
CircularBuffer(T* buffer, const uint8_t size )
|
||||||
: m_size(size), m_buff(buffer)
|
: m_size(size), m_buff(buffer)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all entries in the circular buffer.
|
* Clear all entries in the circular buffer.
|
||||||
*/
|
*/
|
||||||
void clear(void)
|
void clear(void)
|
||||||
{
|
{
|
||||||
MY_CRITICAL_SECTION
|
MY_CRITICAL_SECTION {
|
||||||
{
|
m_front = 0;
|
||||||
m_front = 0;
|
m_fill = 0;
|
||||||
m_fill = 0;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if the circular buffer is empty.
|
* Test if the circular buffer is empty.
|
||||||
* @return True, when empty.
|
* @return True, when empty.
|
||||||
*/
|
*/
|
||||||
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;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if the circular buffer is full.
|
* Test if the circular buffer is full.
|
||||||
* @return True, when full.
|
* @return True, when full.
|
||||||
*/
|
*/
|
||||||
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;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the number of records stored in the buffer.
|
* Return the number of records stored in the buffer.
|
||||||
* @return number of records.
|
* @return number of records.
|
||||||
*/
|
*/
|
||||||
inline uint8_t available(void) const
|
inline uint8_t available(void) const
|
||||||
{
|
{
|
||||||
MY_CRITICAL_SECTION
|
MY_CRITICAL_SECTION {
|
||||||
{
|
return m_fill;
|
||||||
return m_fill;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aquire unused record on front of the buffer, for writing.
|
* Aquire unused record on front of the buffer, for writing.
|
||||||
* After filling the record, it has to be pushed to actually
|
* After filling the record, it has to be pushed to actually
|
||||||
* add it to the buffer.
|
* add it to the buffer.
|
||||||
* @return Pointer to record, or NULL when buffer is full.
|
* @return Pointer to record, or NULL when buffer is full.
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Push record to front of the buffer.
|
* Push record to front of the buffer.
|
||||||
* @param record Record to push. If record was aquired previously (using getFront) its
|
* @param record Record to push. If record was aquired previously (using getFront) its
|
||||||
* data will not be copied as it is already present in the buffer.
|
* data will not be copied as it is already present in the buffer.
|
||||||
* @return True, when record was pushed successfully.
|
* @return True, when record was pushed successfully.
|
||||||
*/
|
*/
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aquire record on back of the buffer, for reading.
|
* Aquire record on back of the buffer, for reading.
|
||||||
* After reading the record, it has to be pop'ed to actually
|
* After reading the record, it has to be pop'ed to actually
|
||||||
* remove it from the buffer.
|
* remove it from the buffer.
|
||||||
* @return Pointer to record, or NULL when buffer is empty.
|
* @return Pointer to record, or NULL when buffer is empty.
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove record from back of the buffer.
|
* Remove record from back of the buffer.
|
||||||
* @return True, when record was pop'ed successfully.
|
* @return True, when record was pop'ed successfully.
|
||||||
*/
|
*/
|
||||||
bool popBack(void)
|
bool popBack(void)
|
||||||
{
|
{
|
||||||
MY_CRITICAL_SECTION
|
MY_CRITICAL_SECTION {
|
||||||
{
|
if (!empty())
|
||||||
if (!empty())
|
{
|
||||||
{
|
m_fill--;
|
||||||
m_fill--;
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
}
|
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.
|
||||||
* @return Ptr to record.
|
* @return Ptr to record.
|
||||||
*/
|
*/
|
||||||
inline T * get(const uint8_t idx) const
|
inline T * get(const uint8_t idx) const
|
||||||
{
|
{
|
||||||
return &(m_buff[idx]);
|
return &(m_buff[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal getter for index of last used record in buffer.
|
* Internal getter for index of last used record in buffer.
|
||||||
* @return Index of last record.
|
* @return Index of last record.
|
||||||
*/
|
*/
|
||||||
inline uint8_t back(void) const
|
inline uint8_t back(void) const
|
||||||
{
|
{
|
||||||
return (m_front - m_fill + m_size) % m_size;
|
return (m_front - m_fill + m_size) % m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t m_size; //!< Total number of records that can be stored in the buffer.
|
const uint8_t m_size; //!< Total number of records that can be stored in the buffer.
|
||||||
T* const m_buff; //!< Ptr to buffer holding all records.
|
T* const m_buff; //!< Ptr to buffer holding all records.
|
||||||
volatile uint8_t m_front; //!< Index of front element (not pushed yet).
|
volatile uint8_t m_front; //!< Index of front element (not pushed yet).
|
||||||
volatile uint8_t m_fill; //!< Amount of records currently pushed.
|
volatile uint8_t m_fill; //!< Amount of records currently pushed.
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CircularBuffer_h
|
#endif // CircularBuffer_h
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -51,14 +54,14 @@ int EthernetClient::connect(const char* host, uint16_t port) {
|
|||||||
|
|
||||||
sprintf(port_str, "%hu", port);
|
sprintf(port_str, "%hu", port);
|
||||||
if ((rv = getaddrinfo(host, port_str, &hints, &servinfo)) != 0) {
|
if ((rv = getaddrinfo(host, port_str, &hints, &servinfo)) != 0) {
|
||||||
logError("getaddrinfo: %s\n", gai_strerror(rv));
|
logError("getaddrinfo: %s\n", gai_strerror(rv));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop through all the results and connect to the first we can
|
// loop through all the results and connect to the first we can
|
||||||
for (p = servinfo; p != NULL; p = p->ai_next) {
|
for (p = servinfo; p != NULL; p = p->ai_next) {
|
||||||
if ((sockfd = socket(p->ai_family, p->ai_socktype,
|
if ((sockfd = socket(p->ai_family, p->ai_socktype,
|
||||||
p->ai_protocol)) == -1) {
|
p->ai_protocol)) == -1) {
|
||||||
logError("socket: %s\n", strerror(errno));
|
logError("socket: %s\n", strerror(errno));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -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,36 +218,38 @@ 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;
|
||||||
case TCP_SYN_SENT:
|
case TCP_SYN_SENT:
|
||||||
return ETHERNETCLIENT_W5100_SYNSENT;
|
return ETHERNETCLIENT_W5100_SYNSENT;
|
||||||
case TCP_SYN_RECV:
|
case TCP_SYN_RECV:
|
||||||
return ETHERNETCLIENT_W5100_SYNRECV;
|
return ETHERNETCLIENT_W5100_SYNRECV;
|
||||||
case TCP_FIN_WAIT1:
|
case TCP_FIN_WAIT1:
|
||||||
case TCP_FIN_WAIT2:
|
case TCP_FIN_WAIT2:
|
||||||
return ETHERNETCLIENT_W5100_FIN_WAIT;
|
return ETHERNETCLIENT_W5100_FIN_WAIT;
|
||||||
case TCP_TIME_WAIT:
|
case TCP_TIME_WAIT:
|
||||||
return TCP_TIME_WAIT;
|
return TCP_TIME_WAIT;
|
||||||
case TCP_CLOSE:
|
case TCP_CLOSE:
|
||||||
return ETHERNETCLIENT_W5100_CLOSED;
|
return ETHERNETCLIENT_W5100_CLOSED;
|
||||||
case TCP_CLOSE_WAIT:
|
case TCP_CLOSE_WAIT:
|
||||||
return ETHERNETCLIENT_W5100_CLOSING;
|
return ETHERNETCLIENT_W5100_CLOSING;
|
||||||
case TCP_LAST_ACK:
|
case TCP_LAST_ACK:
|
||||||
return ETHERNETCLIENT_W5100_LAST_ACK;
|
return ETHERNETCLIENT_W5100_LAST_ACK;
|
||||||
case TCP_LISTEN:
|
case TCP_LISTEN:
|
||||||
return ETHERNETCLIENT_W5100_LISTEN;
|
return ETHERNETCLIENT_W5100_LISTEN;
|
||||||
case TCP_CLOSING:
|
case TCP_CLOSING:
|
||||||
return ETHERNETCLIENT_W5100_CLOSING;
|
return ETHERNETCLIENT_W5100_CLOSING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
+128
-118
@@ -29,127 +29,137 @@
|
|||||||
/**
|
/**
|
||||||
* @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:
|
{
|
||||||
union {
|
private:
|
||||||
uint8_t bytes[4]; //!< IPv4 address as an array
|
union {
|
||||||
uint32_t dword; //!< IPv4 address in 32 bits format
|
uint8_t bytes[4]; //!< IPv4 address as an array
|
||||||
} _address;
|
uint32_t dword; //!< IPv4 address in 32 bits format
|
||||||
|
} _address;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Access the raw byte array containing the address.
|
* @brief Access the raw byte array containing the address.
|
||||||
*
|
*
|
||||||
* Because this returns a pointer to the internal structure rather than a copy of the address
|
* Because this returns a pointer to the internal structure rather than a copy of the address
|
||||||
* this function should only be used when you know that the usage of the returned uint8_t* will
|
* this function should only be used when you know that the usage of the returned uint8_t* will
|
||||||
* be transient and not stored.
|
* be transient and not stored.
|
||||||
*
|
*
|
||||||
* @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.
|
||||||
*/
|
*/
|
||||||
IPAddress();
|
IPAddress();
|
||||||
/**
|
/**
|
||||||
* @brief IPAddress constructor.
|
* @brief IPAddress constructor.
|
||||||
*
|
*
|
||||||
* @param first_octet first octet of the IPv4 address.
|
* @param first_octet first octet of the IPv4 address.
|
||||||
* @param second_octet second octet of the IPv4 address.
|
* @param second_octet second octet of the IPv4 address.
|
||||||
* @param third_octet third octet of the IPv4 address.
|
* @param third_octet third octet of the IPv4 address.
|
||||||
* @param fourth_octet fourth octet of the IPv4 address.
|
* @param fourth_octet fourth octet of the IPv4 address.
|
||||||
*/
|
*/
|
||||||
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
|
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
|
||||||
/**
|
/**
|
||||||
* @brief IPAddress constructor.
|
* @brief IPAddress constructor.
|
||||||
*
|
*
|
||||||
* @param address to be set from a 32 bits integer.
|
* @param address to be set from a 32 bits integer.
|
||||||
*/
|
*/
|
||||||
IPAddress(uint32_t address);
|
IPAddress(uint32_t address);
|
||||||
/**
|
/**
|
||||||
* @brief IPAddress constructor.
|
* @brief IPAddress constructor.
|
||||||
*
|
*
|
||||||
* @param address to be set from a byte array.
|
* @param address to be set from a byte array.
|
||||||
*/
|
*/
|
||||||
IPAddress(const uint8_t *address);
|
IPAddress(const uint8_t *address);
|
||||||
/**
|
/**
|
||||||
* @brief Set the IP from a array of characters.
|
* @brief Set the IP from a array of characters.
|
||||||
*
|
*
|
||||||
* @param address to be set.
|
* @param address to be set.
|
||||||
*/
|
*/
|
||||||
bool fromString(const char *address);
|
bool fromString(const char *address);
|
||||||
/**
|
/**
|
||||||
* @brief Set the IP from a string class type.
|
* @brief Set the IP from a string class type.
|
||||||
*
|
*
|
||||||
* @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)
|
||||||
/**
|
{
|
||||||
* @brief Overloaded cast operator
|
return fromString(address.c_str());
|
||||||
*
|
}
|
||||||
* Allow IPAddress objects to be used where a pointer to a four-byte uint8_t array is expected
|
/**
|
||||||
*/
|
* @brief Overloaded cast operator
|
||||||
operator uint32_t() const {
|
*
|
||||||
return _address.dword;
|
* Allow IPAddress objects to be used where a pointer to a four-byte uint8_t array is expected
|
||||||
}
|
*/
|
||||||
/**
|
operator uint32_t() const
|
||||||
* @brief Overloaded cast operator
|
{
|
||||||
*
|
return _address.dword;
|
||||||
*/
|
}
|
||||||
bool operator==(const IPAddress& addr) const {
|
/**
|
||||||
return _address.dword == addr._address.dword;
|
* @brief Overloaded cast operator
|
||||||
}
|
*
|
||||||
/**
|
*/
|
||||||
* @brief Overloaded cast operator
|
bool operator==(const IPAddress& addr) const
|
||||||
*
|
{
|
||||||
*/
|
return _address.dword == addr._address.dword;
|
||||||
bool operator==(uint32_t addr) const {
|
}
|
||||||
return _address.dword == addr;
|
/**
|
||||||
}
|
* @brief Overloaded cast operator
|
||||||
/**
|
*
|
||||||
* @brief Overloaded cast operator
|
*/
|
||||||
*
|
bool operator==(uint32_t addr) const
|
||||||
*/
|
{
|
||||||
bool operator==(const uint8_t* addr) const;
|
return _address.dword == addr;
|
||||||
/**
|
}
|
||||||
* @brief Overloaded index operator.
|
/**
|
||||||
*
|
* @brief Overloaded cast operator
|
||||||
* Allow getting and setting individual octets of the address.
|
*
|
||||||
*
|
*/
|
||||||
*/
|
bool operator==(const uint8_t* addr) const;
|
||||||
uint8_t operator[](int index) const {
|
/**
|
||||||
return _address.bytes[index];
|
* @brief Overloaded index operator.
|
||||||
}
|
*
|
||||||
/**
|
* Allow getting and setting individual octets of the address.
|
||||||
* @brief Overloaded index operator
|
*
|
||||||
*
|
*/
|
||||||
*/
|
uint8_t operator[](int index) const
|
||||||
uint8_t& operator[](int index) {
|
{
|
||||||
return _address.bytes[index];
|
return _address.bytes[index];
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @brief Overloaded copy operators.
|
* @brief Overloaded index operator
|
||||||
*
|
*
|
||||||
* Allow initialisation of IPAddress objects from byte array.
|
*/
|
||||||
*/
|
uint8_t& operator[](int index)
|
||||||
IPAddress& operator=(const uint8_t *address);
|
{
|
||||||
/**
|
return _address.bytes[index];
|
||||||
* @brief Overloaded copy operator.
|
}
|
||||||
*
|
/**
|
||||||
* Allow initialisation of IPAddress objects from a 32 bits integer.
|
* @brief Overloaded copy operators.
|
||||||
*/
|
*
|
||||||
IPAddress& operator=(uint32_t address);
|
* Allow initialisation of IPAddress objects from byte array.
|
||||||
/**
|
*/
|
||||||
* @brief Convert the IP address to a string.
|
IPAddress& operator=(const uint8_t *address);
|
||||||
*
|
/**
|
||||||
* @return A stringified IP address
|
* @brief Overloaded copy operator.
|
||||||
*/
|
*
|
||||||
std::string toString();
|
* Allow initialisation of IPAddress objects from a 32 bits integer.
|
||||||
|
*/
|
||||||
|
IPAddress& operator=(uint32_t address);
|
||||||
|
/**
|
||||||
|
* @brief Convert the IP address to a string.
|
||||||
|
*
|
||||||
|
* @return A stringified IP address
|
||||||
|
*/
|
||||||
|
std::string toString();
|
||||||
|
|
||||||
friend class Client;
|
friend class Client;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+47
-25
@@ -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)) {
|
||||||
|
|||||||
+54
-41
@@ -32,54 +32,67 @@
|
|||||||
#define OCT 8
|
#define OCT 8
|
||||||
#define BIN 2
|
#define BIN 2
|
||||||
|
|
||||||
class Print {
|
class Print
|
||||||
private:
|
{
|
||||||
int write_error;
|
private:
|
||||||
size_t printNumber(unsigned long n, uint8_t base);
|
int write_error;
|
||||||
size_t printFloat(double number, uint8_t digits);
|
size_t printNumber(unsigned long n, uint8_t base);
|
||||||
|
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)
|
{
|
||||||
return 0;
|
if (str == NULL) {
|
||||||
return write((const uint8_t *) str, strlen(str));
|
return 0;
|
||||||
}
|
|
||||||
virtual size_t write(const uint8_t *buffer, size_t size);
|
|
||||||
size_t write(const char *buffer, size_t size) {
|
|
||||||
return write((const uint8_t *) buffer, size);
|
|
||||||
}
|
}
|
||||||
|
return write((const uint8_t *) str, strlen(str));
|
||||||
|
}
|
||||||
|
virtual size_t write(const uint8_t *buffer, size_t size);
|
||||||
|
size_t write(const char *buffer, size_t size)
|
||||||
|
{
|
||||||
|
return write((const uint8_t *) buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3)));
|
size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3)));
|
||||||
size_t print(const std::string &);
|
size_t print(const std::string &);
|
||||||
size_t print(const char[]);
|
size_t print(const char[]);
|
||||||
size_t print(char);
|
size_t print(char);
|
||||||
size_t print(unsigned char, int = DEC);
|
size_t print(unsigned char, int = DEC);
|
||||||
size_t print(int, int = DEC);
|
size_t print(int, int = DEC);
|
||||||
size_t print(unsigned int, int = DEC);
|
size_t print(unsigned int, int = DEC);
|
||||||
size_t print(long, int = DEC);
|
size_t print(long, int = DEC);
|
||||||
size_t print(unsigned long, int = DEC);
|
size_t print(unsigned long, int = DEC);
|
||||||
size_t print(double, int = 2);
|
size_t print(double, int = 2);
|
||||||
|
|
||||||
size_t println(const std::string &s);
|
size_t println(const std::string &s);
|
||||||
size_t println(const char[]);
|
size_t println(const char[]);
|
||||||
size_t println(char);
|
size_t println(char);
|
||||||
size_t println(unsigned char, int = DEC);
|
size_t println(unsigned char, int = DEC);
|
||||||
size_t println(int, int = DEC);
|
size_t println(int, int = DEC);
|
||||||
size_t println(unsigned int, int = DEC);
|
size_t println(unsigned int, int = DEC);
|
||||||
size_t println(long, int = DEC);
|
size_t println(long, int = DEC);
|
||||||
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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -23,9 +23,10 @@
|
|||||||
#include "Print.h"
|
#include "Print.h"
|
||||||
|
|
||||||
#if !DOXYGEN
|
#if !DOXYGEN
|
||||||
class Server : public Print {
|
class Server : public Print
|
||||||
public:
|
{
|
||||||
virtual void begin() =0;
|
public:
|
||||||
|
virtual void begin() =0;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
+190
-180
@@ -28,50 +28,53 @@
|
|||||||
#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;
|
{
|
||||||
_startMillis = millis();
|
int c;
|
||||||
do {
|
_startMillis = millis();
|
||||||
c = read();
|
do {
|
||||||
if(c >= 0) {
|
c = read();
|
||||||
return c;
|
if(c >= 0) {
|
||||||
}
|
return c;
|
||||||
yield();
|
}
|
||||||
} while(millis() - _startMillis < _timeout);
|
yield();
|
||||||
return -1; // -1 indicates timeout
|
} while(millis() - _startMillis < _timeout);
|
||||||
|
return -1; // -1 indicates timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
// private method to peek stream with timeout
|
// private method to peek stream with timeout
|
||||||
int Stream::timedPeek() {
|
int Stream::timedPeek()
|
||||||
int c;
|
{
|
||||||
_startMillis = millis();
|
int c;
|
||||||
do {
|
_startMillis = millis();
|
||||||
c = peek();
|
do {
|
||||||
if(c >= 0) {
|
c = peek();
|
||||||
return c;
|
if(c >= 0) {
|
||||||
}
|
return c;
|
||||||
yield();
|
}
|
||||||
} while(millis() - _startMillis < _timeout);
|
yield();
|
||||||
return -1; // -1 indicates timeout
|
} while(millis() - _startMillis < _timeout);
|
||||||
|
return -1; // -1 indicates timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
{
|
||||||
while(1) {
|
int c;
|
||||||
c = timedPeek();
|
while(1) {
|
||||||
if(c < 0) {
|
c = timedPeek();
|
||||||
return c; // timeout
|
if(c < 0) {
|
||||||
}
|
return c; // timeout
|
||||||
if(c == '-') {
|
}
|
||||||
return c;
|
if(c == '-') {
|
||||||
}
|
return c;
|
||||||
if(c >= '0' && c <= '9') {
|
}
|
||||||
return c;
|
if(c >= '0' && c <= '9') {
|
||||||
}
|
return c;
|
||||||
read(); // discard non-numeric
|
}
|
||||||
}
|
read(); // discard non-numeric
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public Methods
|
// Public Methods
|
||||||
@@ -79,148 +82,151 @@ int Stream::peekNextDigit() {
|
|||||||
|
|
||||||
void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait
|
void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait
|
||||||
{
|
{
|
||||||
_timeout = timeout;
|
_timeout = timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find returns true if the target string is found
|
// 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 index = 0; // maximum target string length is 64k bytes!
|
size_t termLen)
|
||||||
size_t termIndex = 0;
|
{
|
||||||
int c;
|
size_t index = 0; // maximum target string length is 64k bytes!
|
||||||
|
size_t termIndex = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
if(*target == 0) {
|
if(*target == 0) {
|
||||||
return true; // return true if target is a null string
|
return true; // return true if target is a null string
|
||||||
}
|
}
|
||||||
while((c = timedRead()) > 0) {
|
while((c = timedRead()) > 0) {
|
||||||
|
|
||||||
if(c != target[index]) {
|
if(c != target[index]) {
|
||||||
index = 0; // reset index if any char does not match
|
index = 0; // reset index if any char does not match
|
||||||
}
|
}
|
||||||
if(c == target[index]) {
|
if(c == target[index]) {
|
||||||
//////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
|
//////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
|
||||||
if(++index >= targetLen) { // return true if all chars in the target match
|
if(++index >= targetLen) { // return true if all chars in the target match
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(termLen > 0 && c == terminator[termIndex]) {
|
if(termLen > 0 && c == terminator[termIndex]) {
|
||||||
if(++termIndex >= termLen) {
|
if(++termIndex >= termLen) {
|
||||||
return false; // return false if terminate string found before target string
|
return false; // return false if terminate string found before target string
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
termIndex = 0;
|
termIndex = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
{
|
||||||
long value = 0;
|
boolean isNegative = false;
|
||||||
int c;
|
long value = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
c = peekNextDigit();
|
c = peekNextDigit();
|
||||||
// ignore non numeric leading characters
|
// ignore non numeric leading characters
|
||||||
if(c < 0) {
|
if(c < 0) {
|
||||||
return 0; // zero returned if timeout
|
return 0; // zero returned if timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(c == skipChar) {
|
if(c == skipChar) {
|
||||||
// ignore this charactor
|
// ignore this charactor
|
||||||
}
|
} else if(c == '-') {
|
||||||
else if(c == '-') {
|
isNegative = true;
|
||||||
isNegative = true;
|
} else if(c >= '0' && c <= '9') { // is c a digit?
|
||||||
}
|
value = value * 10 + c - '0';
|
||||||
else if(c >= '0' && c <= '9') { // is c a digit?
|
}
|
||||||
value = value * 10 + c - '0';
|
read(); // consume the character we got with peek
|
||||||
}
|
c = timedPeek();
|
||||||
read(); // consume the character we got with peek
|
} while((c >= '0' && c <= '9') || c == skipChar);
|
||||||
c = timedPeek();
|
|
||||||
} while((c >= '0' && c <= '9') || c == skipChar);
|
|
||||||
|
|
||||||
if(isNegative) {
|
if(isNegative) {
|
||||||
value = -value;
|
value = -value;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 isFraction = false;
|
boolean isNegative = false;
|
||||||
long value = 0;
|
boolean isFraction = false;
|
||||||
int c;
|
long value = 0;
|
||||||
float fraction = 1.0;
|
int c;
|
||||||
|
float fraction = 1.0;
|
||||||
|
|
||||||
c = peekNextDigit();
|
c = peekNextDigit();
|
||||||
// ignore non numeric leading characters
|
// ignore non numeric leading characters
|
||||||
if(c < 0) {
|
if(c < 0) {
|
||||||
return 0; // zero returned if timeout
|
return 0; // zero returned if timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(c == skipChar) {
|
if(c == skipChar) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
} else if(c == '-') {
|
||||||
else if(c == '-') {
|
isNegative = true;
|
||||||
isNegative = true;
|
} else if(c == '.') {
|
||||||
}
|
isFraction = true;
|
||||||
else if(c == '.') {
|
} else if(c >= '0' && c <= '9') { // is c a digit?
|
||||||
isFraction = true;
|
value = value * 10 + c - '0';
|
||||||
}
|
if(isFraction) {
|
||||||
else if(c >= '0' && c <= '9') { // is c a digit?
|
fraction *= 0.1;
|
||||||
value = value * 10 + c - '0';
|
}
|
||||||
if(isFraction) {
|
}
|
||||||
fraction *= 0.1;
|
read(); // consume the character we got with peek
|
||||||
}
|
c = timedPeek();
|
||||||
}
|
} while((c >= '0' && c <= '9') || c == '.' || c == skipChar);
|
||||||
read(); // consume the character we got with peek
|
|
||||||
c = timedPeek();
|
|
||||||
} while((c >= '0' && c <= '9') || c == '.' || c == skipChar);
|
|
||||||
|
|
||||||
if(isNegative) {
|
if(isNegative) {
|
||||||
value = -value;
|
value = -value;
|
||||||
}
|
}
|
||||||
if(isFraction) {
|
if(isFraction) {
|
||||||
return value * fraction;
|
return value * fraction;
|
||||||
}
|
} else {
|
||||||
else {
|
return value;
|
||||||
return value;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// read characters from stream into buffer
|
// read characters from stream into buffer
|
||||||
@@ -228,55 +234,59 @@ 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;
|
{
|
||||||
while(count < length) {
|
size_t count = 0;
|
||||||
int c = timedRead();
|
while(count < length) {
|
||||||
if(c < 0) {
|
int c = timedRead();
|
||||||
break;
|
if(c < 0) {
|
||||||
}
|
break;
|
||||||
*buffer++ = (char) c;
|
}
|
||||||
count++;
|
*buffer++ = (char) c;
|
||||||
}
|
count++;
|
||||||
return count;
|
}
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// as readBytes with terminator character
|
// as readBytes with terminator character
|
||||||
// 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) {
|
{
|
||||||
return 0;
|
if(length < 1) {
|
||||||
}
|
return 0;
|
||||||
size_t index = 0;
|
}
|
||||||
while(index < length) {
|
size_t index = 0;
|
||||||
int c = timedRead();
|
while(index < length) {
|
||||||
if(c < 0 || c == terminator) {
|
int c = timedRead();
|
||||||
break;
|
if(c < 0 || c == terminator) {
|
||||||
}
|
break;
|
||||||
*buffer++ = (char) c;
|
}
|
||||||
index++;
|
*buffer++ = (char) c;
|
||||||
}
|
index++;
|
||||||
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;
|
{
|
||||||
int c = timedRead();
|
std::string ret;
|
||||||
while(c >= 0) {
|
int c = timedRead();
|
||||||
ret += (char) c;
|
while(c >= 0) {
|
||||||
c = timedRead();
|
ret += (char) c;
|
||||||
}
|
c = timedRead();
|
||||||
return ret;
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Stream::readStringUntil(char terminator) {
|
std::string Stream::readStringUntil(char terminator)
|
||||||
std::string ret;
|
{
|
||||||
int c = timedRead();
|
std::string ret;
|
||||||
while(c >= 0 && c != terminator) {
|
int c = timedRead();
|
||||||
ret += (char) c;
|
while(c >= 0 && c != terminator) {
|
||||||
c = timedRead();
|
ret += (char) c;
|
||||||
}
|
c = timedRead();
|
||||||
return ret;
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user