From 9e85fac74546456552d38b9feeeaaa7c710bf4b3 Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Thu, 12 Mar 2015 22:59:51 +0100 Subject: [PATCH] Separate the HW specifics from the MySensor library --- libraries/MySensors/MyConfig.h | 2 + libraries/MySensors/MyHw.cpp | 4 + libraries/MySensors/MyHw.h | 35 +++ libraries/MySensors/MyHwATMega328.cpp | 141 ++++++++++++ libraries/MySensors/MyHwATMega328.h | 40 ++++ libraries/MySensors/MySensor.cpp | 206 +++++------------- libraries/MySensors/MySensor.h | 38 ++-- libraries/MySensors/MyTransport.h | 2 +- .../ClearEepromConfig/ClearEepromConfig.ino | 4 + .../examples/RelayActuator/RelayActuator.ino | 12 +- 10 files changed, 308 insertions(+), 176 deletions(-) create mode 100644 libraries/MySensors/MyHw.cpp create mode 100644 libraries/MySensors/MyHw.h create mode 100644 libraries/MySensors/MyHwATMega328.cpp create mode 100644 libraries/MySensors/MyHwATMega328.h diff --git a/libraries/MySensors/MyConfig.h b/libraries/MySensors/MyConfig.h index 9898fab..3e09981 100644 --- a/libraries/MySensors/MyConfig.h +++ b/libraries/MySensors/MyConfig.h @@ -6,6 +6,8 @@ ***********************************/ #define DEBUG +#define BAUD_RATE 115200 + /********************************** * Message Signing Settings diff --git a/libraries/MySensors/MyHw.cpp b/libraries/MySensors/MyHw.cpp new file mode 100644 index 0000000..75f020d --- /dev/null +++ b/libraries/MySensors/MyHw.cpp @@ -0,0 +1,4 @@ +#include "MyHw.h" + +MyHw::MyHw() { +} diff --git a/libraries/MySensors/MyHw.h b/libraries/MySensors/MyHw.h new file mode 100644 index 0000000..a7ce870 --- /dev/null +++ b/libraries/MySensors/MyHw.h @@ -0,0 +1,35 @@ +#ifndef MyHw_h +#define MyHw_h + +#include +#include +#include "MyConfig.h" + +//#include "MySensor.h" +/** + * The Hw contains all hardware specific details of the platform + */ + +class MyHw +{ +public: + // MyHw constructor + MyHw(); + virtual void init() = 0; + virtual void watchdogReset() = 0; + virtual void reboot() = 0; + virtual unsigned long millisec() = 0; + virtual void sleep(unsigned long ms) = 0; + virtual bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) = 0; + virtual uint8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) = 0; + virtual uint8_t readConfigByte(uint8_t pos) = 0; + virtual void writeConfigByte(uint8_t pos, uint8_t value) = 0; + virtual void readConfigBlock(void* buf, void * pos, size_t length) = 0; + virtual void writeConfigBlock(void* pos, void* buf, uint16_t length) = 0; + #ifdef DEBUG + virtual void debugPrint(bool isGW, const char *fmt, ... ) = 0; + #endif + +}; + +#endif diff --git a/libraries/MySensors/MyHwATMega328.cpp b/libraries/MySensors/MyHwATMega328.cpp new file mode 100644 index 0000000..3f42fc9 --- /dev/null +++ b/libraries/MySensors/MyHwATMega328.cpp @@ -0,0 +1,141 @@ +#include "MyHw.h" +#include "MyHwATMega328.h" + +int8_t pinIntTrigger = 0; +void wakeUp() //place to send the interrupts +{ + pinIntTrigger = 1; +} +void wakeUp2() //place to send the second interrupts +{ + pinIntTrigger = 2; +} + +MyHwATMega328::MyHwATMega328() : MyHw() +{ +} + + +void MyHwATMega328::init() { + Serial.begin(BAUD_RATE); +} + +void MyHwATMega328::watchdogReset() { + wdt_reset(); +} + +void MyHwATMega328::reboot() { + wdt_enable(WDTO_15MS); + for (;;); +} + +unsigned long MyHwATMega328::millisec() { + return millis(); +} + + +void MyHwATMega328::sleep(unsigned long ms) { + // Let serial prints finish (debug, log etc) + Serial.flush(); + pinIntTrigger = 0; + while (!pinIntTrigger && ms >= 8000) { LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); ms -= 8000; } + if (!pinIntTrigger && ms >= 4000) { LowPower.powerDown(SLEEP_4S, ADC_OFF, BOD_OFF); ms -= 4000; } + if (!pinIntTrigger && ms >= 2000) { LowPower.powerDown(SLEEP_2S, ADC_OFF, BOD_OFF); ms -= 2000; } + if (!pinIntTrigger && ms >= 1000) { LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); ms -= 1000; } + if (!pinIntTrigger && ms >= 500) { LowPower.powerDown(SLEEP_500MS, ADC_OFF, BOD_OFF); ms -= 500; } + if (!pinIntTrigger && ms >= 250) { LowPower.powerDown(SLEEP_250MS, ADC_OFF, BOD_OFF); ms -= 250; } + if (!pinIntTrigger && ms >= 125) { LowPower.powerDown(SLEEP_120MS, ADC_OFF, BOD_OFF); ms -= 120; } + if (!pinIntTrigger && ms >= 64) { LowPower.powerDown(SLEEP_60MS, ADC_OFF, BOD_OFF); ms -= 60; } + if (!pinIntTrigger && ms >= 32) { LowPower.powerDown(SLEEP_30MS, ADC_OFF, BOD_OFF); ms -= 30; } + if (!pinIntTrigger && ms >= 16) { LowPower.powerDown(SLEEP_15Ms, ADC_OFF, BOD_OFF); ms -= 15; } +} + +bool MyHwATMega328::sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { + // Let serial prints finish (debug, log etc) + bool pinTriggeredWakeup = true; + Serial.flush(); + attachInterrupt(interrupt, wakeUp, mode); + if (ms>0) { + pinIntTrigger = 0; + sleep(ms); + if (0 == pinIntTrigger) { + pinTriggeredWakeup = false; + } + } else { + Serial.flush(); + LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); + } + detachInterrupt(interrupt); + return pinTriggeredWakeup; +} + +uint8_t MyHwATMega328::sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { + int8_t retVal = 1; + Serial.flush(); // Let serial prints finish (debug, log etc) + attachInterrupt(interrupt1, wakeUp, mode1); + attachInterrupt(interrupt2, wakeUp2, mode2); + if (ms>0) { + pinIntTrigger = 0; + sleep(ms); + if (0 == pinIntTrigger) { + retVal = -1; + } + } else { + Serial.flush(); + LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); + } + detachInterrupt(interrupt1); + detachInterrupt(interrupt2); + + if (1 == pinIntTrigger) { + retVal = (int8_t)interrupt1; + } else if (2 == pinIntTrigger) { + retVal = (int8_t)interrupt2; + } + return retVal; +} + +uint8_t MyHwATMega328::readConfigByte(uint8_t pos) { + return eeprom_read_byte((uint8_t*)pos); +} + +void MyHwATMega328::writeConfigByte(uint8_t pos, uint8_t value) { + eeprom_update_byte((uint8_t*)pos, value); +} + +void MyHwATMega328::readConfigBlock(void* buf, void * pos, size_t length) { + eeprom_read_block(buf, (void*)pos, length); +} + +void MyHwATMega328::writeConfigBlock(void* pos, void* buf, size_t length) { + eeprom_write_block((void*)pos, (void*)buf, length); +} + + +#ifdef DEBUG +void MyHwATMega328::debugPrint(bool isGW, const char *fmt, ... ) { + char fmtBuffer[300]; + if (isGW) { + // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) + snprintf_P(fmtBuffer, 299, PSTR("0;0;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE); + Serial.print(fmtBuffer); + } + va_list args; + va_start (args, fmt ); + va_end (args); + if (isGW) { + // Truncate message if this is gateway node + vsnprintf_P(fmtBuffer, 60, fmt, args); + fmtBuffer[59] = '\n'; + fmtBuffer[60] = '\0'; + } else { + vsnprintf_P(fmtBuffer, 299, fmt, args); + } + va_end (args); + Serial.print(fmtBuffer); + Serial.flush(); + + //Serial.write(freeRam()); +} +#endif + diff --git a/libraries/MySensors/MyHwATMega328.h b/libraries/MySensors/MyHwATMega328.h new file mode 100644 index 0000000..90e6e82 --- /dev/null +++ b/libraries/MySensors/MyHwATMega328.h @@ -0,0 +1,40 @@ +#ifndef MyHwATMega328_h +#define MyHwATMega328_h + +#include "MyConfig.h" +#include "MyMessage.h" +#include +#include +#include +#include "utility/LowPower.h" + +#include "MyHw.h" + +#ifdef __cplusplus +#include +#include +#endif + + +class MyHwATMega328 : public MyHw +{ +public: + MyHwATMega328(); + + void init(); + void watchdogReset(); + void reboot(); + unsigned long millisec(); + void sleep(unsigned long ms); + bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms); + uint8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms); + uint8_t readConfigByte(uint8_t pos); + void writeConfigByte(uint8_t pos, uint8_t value); + void readConfigBlock(void* buf, void * pos, size_t length); + void writeConfigBlock(void* pos, void* buf, size_t length); +#ifdef DEBUG + void debugPrint(bool isGW, const char *fmt, ... ); +#endif +private: +}; +#endif diff --git a/libraries/MySensors/MySensor.cpp b/libraries/MySensors/MySensor.cpp index c558e43..bb69787 100755 --- a/libraries/MySensors/MySensor.cpp +++ b/libraries/MySensors/MySensor.cpp @@ -37,16 +37,17 @@ static inline bool isValidDistance( const uint8_t distance ) { return distance != DISTANCE_INVALID; } -MySensor::MySensor(MyTransport &_radio, MySigning &_signer) +MySensor::MySensor(MyTransport &_radio, MySigning &_signer, MyHw &_hw) : radio(_radio), - signer(_signer) + signer(_signer), + hw(_hw) { } void MySensor::begin(void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, boolean _repeaterMode, uint8_t _parentNodeId) { - Serial.begin(BAUD_RATE); + hw.init(); repeaterMode = _repeaterMode; msgCallback = _msgCallback; failedTransmissions = 0; @@ -62,11 +63,11 @@ void MySensor::begin(void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, b radio.init(); // Read settings from eeprom - eeprom_read_block((void*)&nc, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(NodeConfig)); + hw.readConfigBlock((void*)&nc, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(NodeConfig)); // Read latest received controller configuration from EEPROM - eeprom_read_block((void*)&cc, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(ControllerConfig)); + hw.readConfigBlock((void*)&cc, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(ControllerConfig)); // Read out the signing requirements from EEPROM - eeprom_read_block((void*)doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, sizeof(doSign)); + hw.readConfigBlock((void*)doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, sizeof(doSign)); if (isGateway) { nc.distance = 0; @@ -81,7 +82,7 @@ void MySensor::begin(void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, b if (!autoFindParent) { nc.parentNodeId = _parentNodeId; // Save static parent id in eeprom (used by bootloader) - eeprom_update_byte((uint8_t*)EEPROM_PARENT_NODE_ID_ADDRESS, _parentNodeId); + hw.writeConfigByte(EEPROM_PARENT_NODE_ID_ADDRESS, _parentNodeId); // We don't actually know the distance to gw here. Let's pretend it is 1. // If the current node is also repeater, be aware of this. nc.distance = 1; @@ -90,24 +91,26 @@ void MySensor::begin(void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, b findParentNode(); } - if (_nodeId != AUTO) { - // Set static id - nc.nodeId = _nodeId; - // Save static id in eeprom - eeprom_update_byte((uint8_t*)EEPROM_NODE_ID_ADDRESS, _nodeId); - } else if (isValidParent(nc.parentNodeId)) { - // Try to fetch node-id from gateway - requestNodeId(); + if (!isGateway) { + if (_nodeId != AUTO) { + // Set static id + nc.nodeId = _nodeId; + // Save static id in eeprom + if (_nodeId > 0) + hw.writeConfigByte(EEPROM_NODE_ID_ADDRESS, _nodeId); + } else if (isValidParent(nc.parentNodeId)) { + // Try to fetch node-id from gateway + requestNodeId(); + } } setupNode(); - debug(PSTR("%s started, id=%d, parent=%d, distance=%d\n"), isGateway?"gateway":(repeaterMode?"repeater":"sensor"), nc.nodeId, nc.parentNodeId, nc.distance); } void MySensor::setupRepeaterMode(){ // childNodeTable = new uint8_t[256]; - eeprom_read_block((void*)childNodeTable, (void*)EEPROM_ROUTES_ADDRESS, 256); + hw.readConfigBlock((void*)childNodeTable, (void *)EEPROM_ROUTES_ADDRESS, 256); } uint8_t MySensor::getNodeId() { @@ -119,7 +122,7 @@ ControllerConfig MySensor::getConfig() { } void MySensor::requestNodeId() { - debug(PSTR("req node id\n")); + debug(PSTR("req id\n")); radio.setAddress(nc.nodeId); build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_ID_REQUEST, false).set(""); sendWrite(nc.parentNodeId, msg); @@ -135,7 +138,7 @@ void MySensor::setupNode() { // Notify gateway (and possibly controller) about the signing preferences of this node sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(signer.requestSignatures())); - // If we do require signing, wait for the gateway to tell us how it perfer us to transmit our messages + // If we do require signing, wait for the gateway to tell us how it prefer us to transmit our messages if (signer.requestSignatures()) { wait(2000); } @@ -197,7 +200,7 @@ boolean MySensor::sendRoute(MyMessage &message) { message.type != I_ID_REQUEST && message.type != I_ID_RESPONSE && message.type != I_FIND_PARENT && message.type != I_FIND_PARENT_RESPONSE))) { if (!sign(message)) { - debug(PSTR("Message signing failed\n")); + debug(PSTR("sign fail\n")); return false; } // After this point, only the 'last' member of the message structure is allowed to be altered if the message has been signed, @@ -312,6 +315,7 @@ void MySensor::requestTime(void (* _timeCallback)(unsigned long)) { } boolean MySensor::process() { + hw.watchdogReset(); uint8_t to = 0; if (!radio.available(&to)) return false; @@ -328,11 +332,12 @@ boolean MySensor::process() { msg.type != I_ID_REQUEST && msg.type != I_ID_RESPONSE && msg.type != I_FIND_PARENT && msg.type != I_FIND_PARENT_RESPONSE))) { if (!mGetSigned(msg)) { - debug(PSTR("Got unsigned message that should have been signed\n")); + // Got unsigned message that should have been signed + debug(PSTR("no sign\n")); return false; } else if (!signer.verifyMsg(msg)) { - debug(PSTR("Message verification failed\n")); + debug(PSTR("verify fail\n")); return false; // This signed message has been tampered with! } } @@ -344,8 +349,7 @@ boolean MySensor::process() { mSetSigned(msg,0); // Clear the sign-flag now as verification (and debug printing) is completed if(!(mGetVersion(msg) == PROTOCOL_VERSION)) { - debug(PSTR("version: %d\n"),mGetVersion(msg)); - debug(PSTR("version mismatch\n")); + debug(PSTR("ver mismatch\n")); return false; } @@ -388,9 +392,9 @@ boolean MySensor::process() { // Found a neighbor closer to GW than previously found nc.distance = distance; nc.parentNodeId = msg.sender; - eeprom_update_byte((uint8_t*)EEPROM_PARENT_NODE_ID_ADDRESS, nc.parentNodeId); - eeprom_update_byte((uint8_t*)EEPROM_DISTANCE_ADDRESS, nc.distance); - debug(PSTR("new parent=%d, d=%d\n"), nc.parentNodeId, nc.distance); + hw.writeConfigByte(EEPROM_PARENT_NODE_ID_ADDRESS, nc.parentNodeId); + hw.writeConfigByte(EEPROM_DISTANCE_ADDRESS, nc.distance); + debug(PSTR("parent=%d, d=%d\n"), nc.parentNodeId, nc.distance); } } } @@ -409,7 +413,7 @@ boolean MySensor::process() { CLEAR_SIGN(msg.sender); } // Save updated table - eeprom_update_block((void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, (void*)doSign, sizeof(doSign)); + hw.writeConfigBlock((void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, (void*)doSign, sizeof(doSign)); // Inform sender about our preference if we are a gateway, but only require signing if the sender required signing // We do not currently want a gateway to require signing from all nodes in a network just because it wants one node @@ -428,8 +432,7 @@ boolean MySensor::process() { if (type == I_REBOOT) { // Requires MySensors or other bootloader with watchdogs enabled - wdt_enable(WDTO_15MS); - for (;;); + hw.reboot(); } else if (type == I_ID_RESPONSE) { if (nc.nodeId == AUTO) { nc.nodeId = msg.getByte(); @@ -440,7 +443,7 @@ boolean MySensor::process() { } setupNode(); // Write id to EEPROM - eeprom_update_byte((uint8_t*)EEPROM_NODE_ID_ADDRESS, nc.nodeId); + hw.writeConfigByte(EEPROM_NODE_ID_ADDRESS, nc.nodeId); debug(PSTR("id=%d\n"), nc.nodeId); } } else if (type == I_CONFIG) { @@ -448,18 +451,18 @@ boolean MySensor::process() { // and store it in eeprom if changed isMetric = msg.getString()[0] == 'M' ; cc.isMetric = isMetric; - eeprom_update_byte((uint8_t*)EEPROM_CONTROLLER_CONFIG_ADDRESS, isMetric); + hw.writeConfigByte(EEPROM_CONTROLLER_CONFIG_ADDRESS, isMetric); } else if (type == I_CHILDREN) { if (repeaterMode && msg.getString()[0] == 'C') { // Clears child relay data for this node - debug(PSTR("rd=clear\n")); + debug(PSTR("clear\n")); uint8_t i = 255; do { removeChildRoute(i); } while (i--); // Clear parent node id & distance to gw - eeprom_update_byte((uint8_t*)EEPROM_PARENT_NODE_ID_ADDRESS, 0xFF); - eeprom_update_byte((uint8_t*)EEPROM_DISTANCE_ADDRESS, 0xFF); + hw.writeConfigByte(EEPROM_PARENT_NODE_ID_ADDRESS, 0xFF); + hw.writeConfigByte(EEPROM_DISTANCE_ADDRESS, 0xFF); // Find parent node findParentNode(); sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN,false).set("")); @@ -484,7 +487,7 @@ boolean MySensor::process() { // Relaying nodes should always answer ping messages // Wait a random delay of 0-2 seconds to minimize collision // between ping ack messages from other relaying nodes - delay(millis() & 0x3ff); + wait(hw.millisec() & 0x3ff); sendWrite(sender, build(msg, nc.nodeId, sender, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_RESPONSE, false).set(nc.distance)); } } else if (to == nc.nodeId) { @@ -500,113 +503,48 @@ MyMessage& MySensor::getLastMessage() { } void MySensor::saveState(uint8_t pos, uint8_t value) { - eeprom_update_byte((uint8_t*)(EEPROM_LOCAL_CONFIG_ADDRESS+pos), value); + hw.writeConfigByte(EEPROM_LOCAL_CONFIG_ADDRESS+pos, value); } uint8_t MySensor::loadState(uint8_t pos) { - return eeprom_read_byte((uint8_t*)(EEPROM_LOCAL_CONFIG_ADDRESS+pos)); + return hw.readConfigByte(EEPROM_LOCAL_CONFIG_ADDRESS+pos); } void MySensor::addChildRoute(uint8_t childId, uint8_t route) { childNodeTable[childId] = route; - eeprom_update_byte((uint8_t*)EEPROM_ROUTES_ADDRESS+childId, route); + hw.writeConfigByte(EEPROM_ROUTES_ADDRESS+childId, route); } void MySensor::removeChildRoute(uint8_t childId) { childNodeTable[childId] = 0xff; - eeprom_update_byte((uint8_t*)EEPROM_ROUTES_ADDRESS+childId, 0xff); + hw.writeConfigByte(EEPROM_ROUTES_ADDRESS+childId, 0xff); } uint8_t MySensor::getChildRoute(uint8_t childId) { return childNodeTable[childId]; } -int8_t pinIntTrigger = 0; -void wakeUp() //place to send the interrupts -{ - pinIntTrigger = 1; -} -void wakeUp2() //place to send the second interrupts -{ - pinIntTrigger = 2; -} -void MySensor::internalSleep(unsigned long ms) { - while (!pinIntTrigger && ms >= 8000) { LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); ms -= 8000; } - if (!pinIntTrigger && ms >= 4000) { LowPower.powerDown(SLEEP_4S, ADC_OFF, BOD_OFF); ms -= 4000; } - if (!pinIntTrigger && ms >= 2000) { LowPower.powerDown(SLEEP_2S, ADC_OFF, BOD_OFF); ms -= 2000; } - if (!pinIntTrigger && ms >= 1000) { LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); ms -= 1000; } - if (!pinIntTrigger && ms >= 500) { LowPower.powerDown(SLEEP_500MS, ADC_OFF, BOD_OFF); ms -= 500; } - if (!pinIntTrigger && ms >= 250) { LowPower.powerDown(SLEEP_250MS, ADC_OFF, BOD_OFF); ms -= 250; } - if (!pinIntTrigger && ms >= 125) { LowPower.powerDown(SLEEP_120MS, ADC_OFF, BOD_OFF); ms -= 120; } - if (!pinIntTrigger && ms >= 64) { LowPower.powerDown(SLEEP_60MS, ADC_OFF, BOD_OFF); ms -= 60; } - if (!pinIntTrigger && ms >= 32) { LowPower.powerDown(SLEEP_30MS, ADC_OFF, BOD_OFF); ms -= 30; } - if (!pinIntTrigger && ms >= 16) { LowPower.powerDown(SLEEP_15Ms, ADC_OFF, BOD_OFF); ms -= 15; } -} - -void MySensor::sleep(unsigned long ms) { - // Let serial prints finish (debug, log etc) - Serial.flush(); - radio.powerDown(); - pinIntTrigger = 0; - internalSleep(ms); -} void MySensor::wait(unsigned long ms) { - // Let serial prints finish (debug, log etc) - Serial.flush(); - unsigned long enter = millis(); - while (millis() - enter < ms) { - // reset watchdog - wdt_reset(); + unsigned long enter = hw.millisec(); + while (hw.millisec() - enter < ms) { process(); } } -bool MySensor::sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { - // Let serial prints finish (debug, log etc) - bool pinTriggeredWakeup = true; - Serial.flush(); +void MySensor::sleep(unsigned long ms) { radio.powerDown(); - attachInterrupt(interrupt, wakeUp, mode); - if (ms>0) { - pinIntTrigger = 0; - sleep(ms); - if (0 == pinIntTrigger) { - pinTriggeredWakeup = false; - } - } else { - Serial.flush(); - LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); - } - detachInterrupt(interrupt); - return pinTriggeredWakeup; + hw.sleep(ms); +} + +bool MySensor::sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { + radio.powerDown(); + return hw.sleep(interrupt, mode, ms) ; } int8_t MySensor::sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { - int8_t retVal = 1; - Serial.flush(); // Let serial prints finish (debug, log etc) radio.powerDown(); - attachInterrupt(interrupt1, wakeUp, mode1); - attachInterrupt(interrupt2, wakeUp2, mode2); - if (ms>0) { - pinIntTrigger = 0; - sleep(ms); - if (0 == pinIntTrigger) { - retVal = -1; - } - } else { - Serial.flush(); - LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); - } - detachInterrupt(interrupt1); - detachInterrupt(interrupt2); - - if (1 == pinIntTrigger) { - retVal = (int8_t)interrupt1; - } else if (2 == pinIntTrigger) { - retVal = (int8_t)interrupt2; - } - return retVal; + return hw.sleep(interrupt1, mode1, interrupt2, mode2, ms) ; } bool MySensor::sign(MyMessage &message) { @@ -615,9 +553,9 @@ bool MySensor::sign(MyMessage &message) { } else { // We have to wait for the nonce to arrive before we can sign our original message // Other messages could come in-between. We trust process() takes care of them - unsigned long enter = millis(); + unsigned long enter = hw.millisec(); msgSign = message; // Copy the message to sign since message buffer might be touched in process() - while (millis() - enter < 5000) { + while (hw.millisec() - enter < 5000) { if (process()) { if (mGetCommand(getLastMessage()) == C_INTERNAL && getLastMessage().type == I_GET_NONCE_RESPONSE) { // Proceed with signing if nonce has been received @@ -633,37 +571,3 @@ bool MySensor::sign(MyMessage &message) { return false; } -#ifdef DEBUG -void MySensor::debugPrint(const char *fmt, ... ) { - char fmtBuffer[300]; - if (isGateway) { - // prepend debug message to be handled correctly by gw (C_INTERNAL, I_LOG_MESSAGE) - snprintf_P(fmtBuffer, 299, PSTR("0;0;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE); - Serial.print(fmtBuffer); - } - va_list args; - va_start (args, fmt ); - va_end (args); - if (isGateway) { - // Truncate message if this is gateway node - vsnprintf_P(fmtBuffer, 60, fmt, args); - fmtBuffer[59] = '\n'; - fmtBuffer[60] = '\0'; - } else { - vsnprintf_P(fmtBuffer, 299, fmt, args); - } - va_end (args); - Serial.print(fmtBuffer); - Serial.flush(); - - //Serial.write(freeRam()); -} -#endif - -#ifdef DEBUG -int MySensor::freeRam (void) { - extern int __heap_start, *__brkval; - int v; - return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); -} -#endif diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index f9d75bb..5ccac1a 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -13,6 +13,8 @@ #define MySensor_h #include "Version.h" // Auto generated by bot +#include "MyHw.h" +#include "MyHwATMega328.h" #include "MyTransport.h" #include "MyTransportNRF24.h" #include "MyParser.h" @@ -21,24 +23,15 @@ #include "MyConfig.h" #include "MyMessage.h" #include -#include -#include -#include #include -#ifdef __cplusplus -#include -#include -#include "utility/LowPower.h" -#endif #ifdef DEBUG -#define debug(x,...) debugPrint(x, ##__VA_ARGS__) +#define debug(x,...) hw.debugPrint(isGateway, x, ##__VA_ARGS__) #else #define debug(x,...) #endif -#define BAUD_RATE 115200 // EEPROM start address for mysensors library data #define EEPROM_START 0 @@ -81,7 +74,7 @@ class MySensor * Creates a new instance of Sensor class. * */ - MySensor(MyTransport &radio =*new MyTransportNRF24(), MySigning &signer=*new MySigningNone()); + MySensor(MyTransport &radio =*new MyTransportNRF24(), MySigning &signer=*new MySigningNone(), MyHw &hw=*new MyHwATMega328()); /** * Begin operation of the MySensors library @@ -173,7 +166,7 @@ class MySensor * power cycles. * * You have 256 bytes to play with. Note that there is a limitation on the number - * of writes the EEPROM can handle (~100 000 cycles). + * of writes the EEPROM can handle (~100 000 cycles on ATMega328). * * @param pos The position to store value in (0-255) * @param Value to store in position @@ -193,11 +186,7 @@ class MySensor */ MyMessage& getLastMessage(void); - /** - * Sleep (PowerDownMode) the Arduino and radio. Wake up on timer. - * @param ms Number of milliseconds to sleep. - */ - void sleep(unsigned long ms); + /** * Wait for a specified amount of time to pass. Keeps process()ing. @@ -209,7 +198,13 @@ class MySensor void wait(unsigned long ms); /** - * Sleep (PowerDownMode) the Arduino and radio. Wake up on timer or pin change. + * Sleep (PowerDownMode) the MCU and radio. Wake up on timer. + * @param ms Number of milliseconds to sleep. + */ + void sleep(unsigned long ms); + + /** + * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change. * See: http://arduino.cc/en/Reference/attachInterrupt for details on modes and which pin * is assigned to what interrupt. On Nano/Pro Mini: 0=Pin2, 1=Pin3 * @param interrupt Interrupt that should trigger the wakeup @@ -220,7 +215,7 @@ class MySensor bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms=0); /** - * Sleep (PowerDownMode) the Arduino 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. * See: http://arduino.cc/en/Reference/attachInterrupt for details on modes and which pin * is assigned to what interrupt. On Nano/Pro Mini: 0=Pin2, 1=Pin3 * @param interrupt1 First interrupt that should trigger the wakeup @@ -232,10 +227,6 @@ class MySensor */ int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms=0); -#ifdef DEBUG - void debugPrint(const char *fmt, ... ); - int freeRam(); -#endif protected: NodeConfig nc; // Essential settings for node to work @@ -251,6 +242,7 @@ class MySensor MyTransport& radio; MySigning& signer; + MyHw& hw; void setupRepeaterMode(); boolean sendWrite(uint8_t dest, MyMessage &message); diff --git a/libraries/MySensors/MyTransport.h b/libraries/MySensors/MyTransport.h index 5c7b728..08ba0c6 100644 --- a/libraries/MySensors/MyTransport.h +++ b/libraries/MySensors/MyTransport.h @@ -17,7 +17,7 @@ #define BROADCAST_ADDRESS ((uint8_t)0xFF) class MyTransport -{ +{ public: // MyTransport constructor // different parameters would be needed depending on radio module (e.g. pins connected etc.) diff --git a/libraries/MySensors/examples/ClearEepromConfig/ClearEepromConfig.ino b/libraries/MySensors/examples/ClearEepromConfig/ClearEepromConfig.ino index 407d92d..ddbaaba 100644 --- a/libraries/MySensors/examples/ClearEepromConfig/ClearEepromConfig.ino +++ b/libraries/MySensors/examples/ClearEepromConfig/ClearEepromConfig.ino @@ -6,12 +6,16 @@ #include #include +#include void setup() { + Serial.begin(BAUD_RATE); + Serial.println("Started clearing. Please wait..."); for (int i=0;i<512;i++) { EEPROM.write(i, 0xff); } + Serial.println("Clering done. You're ready to go!"); } void loop() diff --git a/libraries/MySensors/examples/RelayActuator/RelayActuator.ino b/libraries/MySensors/examples/RelayActuator/RelayActuator.ino index 3f0e94f..2bb49ab 100644 --- a/libraries/MySensors/examples/RelayActuator/RelayActuator.ino +++ b/libraries/MySensors/examples/RelayActuator/RelayActuator.ino @@ -1,6 +1,9 @@ // Example sketch showing how to control physical relays. // This example will remember relay state even after power failure. +#include +#include +#include #include #include @@ -9,7 +12,14 @@ #define RELAY_ON 1 // GPIO value to write to turn on attached relay #define RELAY_OFF 0 // GPIO value to write to turn off attached relay -MySensor gw; +// NRFRF24L01 radio driver (set low transmit power by default) +MyTransportNRF24 radio(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW); +// Message signing driver (none default) +MySigningNone signer; +// Select AtMega328 hardware profile +MyHwATMega328 hw; +// Construct MySensors library +MySensor gw(radio, signer, hw); void setup() {