MySensors Advanced features I2C patch
#define MY_DEFAULT_LED_EXT 1 | |
#define MY_INCLUSION_MODE_FEATURE | |
#define MY_INCLUSION_BUTTON_FEATURE | |
#define MY_INCLUSION_MODE_DURATION 10 | |
#include <MySensors.h> | |
#include <core/MyInclusionMode.h> | |
#include <PCF8574.h> | |
const uint8_t scl_PIN = D1; | |
const uint8_t sda_PIN = D2; | |
const uint8_t led_device[4] { 2U, 3U, 6U, 4U }; | |
const uint8_t btn_device[4] { 0U, 1U, 5U, 7U }; | |
PCF8574 expander(0x22, sda_PIN, scl_PIN); | |
void setup() { | |
Wire.begin(sda_PIN, scl_PIN); | |
Serial.begin(115200); | |
while (!Serial) delay(50); | |
for (uint8_t i = 0; i < 4U; i++) { | |
expander.pinMode(led_device[i], OUTPUT); | |
expander.digitalWrite(led_device[i], HIGH); | |
Serial.printf("Init LED expander: %u/%u\n", (uint16_t)i, (uint16_t)led_device[i]); | |
} | |
for (uint8_t i = 0; i < 4U; i++) { | |
expander.pinMode(btn_device[i], INPUT); | |
expander.digitalWrite(btn_device[i], HIGH); | |
Serial.printf("Init BTN expander: %u/%u\n", (uint16_t)i, (uint16_t)btn_device[i]); | |
} | |
expander.begin(); | |
ledsSetCb( | |
[=](uint8_t & state) { expander.digitalWrite(led_device[1], state); }, | |
[=](uint8_t & state) { expander.digitalWrite(led_device[2], state); }, | |
[=](uint8_t & state) { expander.digitalWrite(led_device[3], state); } | |
); | |
inclusionSetCb( | |
[=]() { return (expander.digitalRead(btn_device[0], true) == LOW); }, | |
[=](uint8_t & state) { expander.digitalWrite(led_device[0], state); } | |
); | |
} | |
void loop() {} |
--- E:/__BuildSource/__LIB__/Arduino/Sketch/MySensors-development/MySensors.h Sat Aug 22 11:07:35 2020 | |
+++ E:/__BuildSource/__LIB__/Arduino/Sketch/libraries/MySensors/MySensors.h Tue Oct 6 11:28:48 2020 | |
@@ -119,6 +119,8 @@ | |
#if defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) | |
#include "core/MyLeds.cpp" | |
+#elif defined(MY_DEFAULT_LED_EXT) | |
+#include "core/MyLedsExt.cpp" | |
#else | |
#include "core/MyLeds.h" | |
#endif | |
--- MyInclusionMode.cpp Sat Aug 22 11:07:35 2020 | |
+++ MyInclusionMode.cpp Tue Oct 6 13:44:58 2020 | |
@@ -18,25 +18,44 @@ | |
*/ | |
#include "MyInclusionMode.h" | |
+#if defined(ARDUINO_ARCH_ESP8266) | |
+# include <Esp.h> | |
+#endif | |
// global variables | |
extern MyMessage _msgTmp; | |
-unsigned long _inclusionStartTime; | |
-bool _inclusionMode; | |
+unsigned long _inclusionStartTime = 0U, _rebootStartTime = 0U; | |
+bool _inclusionMode, _rebootMode; | |
+ | |
+#if (defined(MY_INCLUSION_BUTTON_FEATURE) && defined(MY_DEFAULT_LED_EXT)) | |
+static btn_cb btnInclusionFunc = [](){ return false; }; | |
+static led_cb ledInclusionFunc = [](uint8_t&){}; | |
+ | |
+void inclusionSetCb(btn_cb btn, led_cb led) { | |
+ btnInclusionFunc = btn; | |
+ ledInclusionFunc = led; | |
+} | |
+#endif | |
inline void inclusionInit() | |
{ | |
+ _rebootMode = false; | |
_inclusionMode = false; | |
#if defined(MY_INCLUSION_BUTTON_FEATURE) | |
+# if defined(MY_DEFAULT_LED_EXT) | |
+ uint8_t state = static_cast<uint8_t>(LED_OFF); | |
+ ledInclusionFunc(state); | |
+# else | |
// Setup digital in that triggers inclusion mode | |
hwPinMode(MY_INCLUSION_MODE_BUTTON_PIN, INPUT_PULLUP); | |
-#endif | |
#if defined (MY_INCLUSION_LED_PIN) | |
// Setup LED pin that indicates inclusion mode | |
hwPinMode(MY_INCLUSION_LED_PIN, OUTPUT); | |
hwDigitalWrite(MY_INCLUSION_LED_PIN, LED_OFF); | |
#endif | |
+# endif | |
+#endif | |
} | |
@@ -51,21 +70,44 @@ | |
_inclusionStartTime = hwMillis(); | |
} | |
} | |
-#if defined (MY_INCLUSION_LED_PIN) | |
+#if defined(MY_INCLUSION_BUTTON_FEATURE) | |
+# if defined(MY_DEFAULT_LED_EXT) | |
+ uint8_t state = static_cast<uint8_t>(_inclusionMode); | |
+ ledInclusionFunc(state); | |
+# elif defined (MY_INCLUSION_LED_PIN) | |
hwDigitalWrite(MY_INCLUSION_LED_PIN, _inclusionMode ? LED_ON : LED_OFF); | |
#endif | |
+#endif | |
} | |
inline void inclusionProcess() | |
{ | |
-#ifdef MY_INCLUSION_BUTTON_FEATURE | |
- if (!_inclusionMode && hwDigitalRead(MY_INCLUSION_MODE_BUTTON_PIN) == MY_INCLUSION_BUTTON_PRESSED) { | |
+#if defined(MY_INCLUSION_BUTTON_FEATURE) | |
+# if defined(MY_DEFAULT_LED_EXT) | |
+ bool b = btnInclusionFunc(); | |
+# else | |
+ bool b = (hwDigitalRead(MY_INCLUSION_MODE_BUTTON_PIN) == MY_INCLUSION_BUTTON_PRESSED); | |
+# endif | |
+ | |
+ if (!_inclusionMode && b) { | |
// Start inclusion mode | |
inclusionModeSet(true); | |
} | |
-#endif | |
+# if defined(ARDUINO_ARCH_ESP8266) | |
+ if (!_rebootMode && b) { | |
+ _rebootStartTime = hwMillis() + 10000U; | |
+ _rebootMode = true; | |
+ | |
+ } else if (_rebootMode && b) { | |
+ if (_rebootStartTime < hwMillis()) | |
+ ESP.restart(); | |
- if (_inclusionMode && hwMillis()-_inclusionStartTime>MY_INCLUSION_MODE_DURATION*1000L) { | |
+ } else if (_rebootMode) { | |
+ _rebootMode = false; | |
+ } | |
+# endif | |
+#endif | |
+ if (_inclusionMode && (hwMillis() - _inclusionStartTime > MY_INCLUSION_MODE_DURATION * 1000L)) { | |
// inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode | |
inclusionModeSet(false); | |
} | |
--- MyInclusionMode.h Sat Aug 22 11:07:35 2020 | |
+++ MyInclusionMode.h Tue Oct 6 13:46:53 2020 | |
@@ -22,6 +22,11 @@ | |
#include "MySensorsCore.h" | |
+#if (defined(MY_INCLUSION_BUTTON_FEATURE) && defined(MY_DEFAULT_LED_EXT)) | |
+typedef bool (*btn_cb)(); | |
+typedef void (*led_cb)(uint8_t&); | |
+void inclusionSetCb(btn_cb, led_cb); | |
+#endif | |
extern bool gatewayTransportSend(MyMessage &message); | |
--- MyIndication.cpp Sat Aug 22 11:07:35 2020 | |
+++ MyIndication.cpp Tue Oct 6 11:54:37 2020 | |
@@ -18,23 +18,23 @@ | |
*/ | |
#include "MyIndication.h" | |
-#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) || defined(MY_DEFAULT_LED_EXT) | |
#include "MyLeds.h" | |
#endif | |
void setIndication( const indication_t ind ) | |
{ | |
-#if defined(MY_DEFAULT_TX_LED_PIN) | |
+#if (defined(MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_LED_EXT)) | |
if ((INDICATION_TX == ind) || (INDICATION_GW_TX == ind)) { | |
ledsBlinkTx(1); | |
} else | |
#endif | |
-#if defined(MY_DEFAULT_RX_LED_PIN) | |
+#if (defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_LED_EXT)) | |
if ((INDICATION_RX == ind) || (INDICATION_GW_RX == ind)) { | |
ledsBlinkRx(1); | |
} else | |
#endif | |
-#if defined(MY_DEFAULT_ERR_LED_PIN) | |
+#if (defined(MY_DEFAULT_ERR_LED_PIN) || defined(MY_DEFAULT_LED_EXT)) | |
if (ind > INDICATION_ERR_START) { | |
// Number of blinks indicates which error occurred. | |
ledsBlinkErr(ind-INDICATION_ERR_START); | |
--- MyLeds.h Sat Aug 22 11:07:35 2020 | |
+++ MyLeds.h Tue Oct 6 11:45:46 2020 | |
@@ -29,7 +29,12 @@ | |
#define LED_OFF 0x1 | |
#endif | |
-#if defined(MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) | |
+#if defined(MY_DEFAULT_LED_EXT) | |
+typedef void (*led_cb)(uint8_t&); | |
+void ledsSetCb(led_cb, led_cb, led_cb); | |
+#endif | |
+ | |
+#if defined(MY_DEFAULT_TX_LED_PIN) || defined(MY_DEFAULT_RX_LED_PIN) || defined(MY_DEFAULT_ERR_LED_PIN) || defined(MY_DEFAULT_LED_EXT) | |
#define ledBlinkTx(x,...) ledsBlinkTx(x) | |
#define ledBlinkRx(x,...) ledsBlinkRx(x) | |
#define ledBlinkErr(x,...) ledsBlinkErr(x) | |
--- /dev/null Thu Jan 1 03:00:00 1970 | |
+++ MyLedsExt.cpp Tue Oct 6 13:46:02 2020 | |
@@ -0,0 +1,111 @@ | |
+/* | |
+ * The MySensors Arduino library handles the wireless radio link and protocol | |
+ * between your home built sensors/actuators and HA controller of choice. | |
+ * The sensors forms a self healing radio network with optional repeaters. Each | |
+ * repeater and gateway builds a routing tables in EEPROM which keeps track of the | |
+ * network topology allowing messages to be routed to nodes. | |
+ * | |
+ * Created by Henrik Ekblad <henrik.ekblad@mysensors.org> | |
+ * Copyright (C) 2013-2019 Sensnology AB | |
+ * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors | |
+ * | |
+ * Documentation: http://www.mysensors.org | |
+ * Support Forum: http://forum.mysensors.org | |
+ * | |
+ * This program is free software; you can redistribute it and/or | |
+ * modify it under the terms of the GNU General Public License | |
+ * version 2 as published by the Free Software Foundation. | |
+ */ | |
+ | |
+#include "MyLeds.h" | |
+ | |
+#define LED_ON_OFF_RATIO (4) // Power of 2 please | |
+#define LED_PROCESS_INTERVAL_MS (MY_DEFAULT_LED_BLINK_PERIOD/LED_ON_OFF_RATIO) | |
+ | |
+// these variables don't need to be volatile, since we are not using interrupts | |
+static uint8_t countRx; | |
+static uint8_t countTx; | |
+static uint8_t countErr; | |
+static unsigned long prevTime; | |
+ | |
+static led_cb ledsInfoFunc[3]{ | |
+ [](uint8_t&){}, | |
+ [](uint8_t&){}, | |
+ [](uint8_t&){} | |
+}; | |
+ | |
+void ledsSetCb(led_cb rxLed, led_cb txLed, led_cb errLed) { | |
+ ledsInfoFunc[0] = rxLed; | |
+ ledsInfoFunc[1] = txLed; | |
+ ledsInfoFunc[2] = errLed; | |
+} | |
+ | |
+inline void ledsInit() | |
+{ | |
+ // initialize counters | |
+ countRx = 0; | |
+ countTx = 0; | |
+ countErr = 0; | |
+ | |
+ // Setup led pins | |
+ prevTime = hwMillis() - | |
+ LED_PROCESS_INTERVAL_MS; // Subtract some, to make sure leds gets updated on first run. | |
+ ledsProcess(); | |
+} | |
+ | |
+void ledsProcess() | |
+{ | |
+ // Just return if it is not the time... | |
+ if ((hwMillis() - prevTime) < LED_PROCESS_INTERVAL_MS) { | |
+ return; | |
+ } | |
+ prevTime = hwMillis(); | |
+ uint8_t state; | |
+ | |
+ // For an On/Off ratio of 4, the pattern repeated will be [on, on, on, off] | |
+ // until the counter becomes 0. | |
+ if (countRx) { | |
+ --countRx; | |
+ } | |
+ state = (countRx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; | |
+ ledsInfoFunc[0](state); // MY_DEFAULT_RX_LED_PIN | |
+ if (countTx) { | |
+ --countTx; | |
+ } | |
+ state = (countTx & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; | |
+ ledsInfoFunc[1](state); // MY_DEFAULT_TX_LED_PIN | |
+ if (countErr) { | |
+ --countErr; | |
+ } | |
+ state = (countErr & (LED_ON_OFF_RATIO-1)) ? LED_ON : LED_OFF; | |
+ ledsInfoFunc[2](state); // MY_DEFAULT_ERR_LED_PIN | |
+} | |
+ | |
+void ledsBlinkRx(uint8_t cnt) | |
+{ | |
+ if (!countRx) { | |
+ countRx = cnt*LED_ON_OFF_RATIO; | |
+ } | |
+ ledsProcess(); | |
+} | |
+ | |
+void ledsBlinkTx(uint8_t cnt) | |
+{ | |
+ if(!countTx) { | |
+ countTx = cnt*LED_ON_OFF_RATIO; | |
+ } | |
+ ledsProcess(); | |
+} | |
+ | |
+void ledsBlinkErr(uint8_t cnt) | |
+{ | |
+ if(!countErr) { | |
+ countErr = cnt*LED_ON_OFF_RATIO; | |
+ } | |
+ ledsProcess(); | |
+} | |
+ | |
+bool ledsBlinking() | |
+{ | |
+ return countRx || countTx || countErr; | |
+} | |
--- MySensorsCore.cpp Sat Aug 22 11:07:35 2020 | |
+++ MySensorsCore.cpp Tue Oct 6 11:56:07 2020 | |
@@ -144,7 +144,7 @@ | |
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) || defined(MY_DEFAULT_LED_EXT) | |
ledsInit(); | |
#endif | |
@@ -310,7 +310,7 @@ | |
return _coreConfig.controllerConfig; | |
} | |
-// cppcheck-suppress constParameter | |
+ | |
bool _sendRoute(MyMessage &message) | |
{ | |
#if defined(MY_CORE_ONLY) | |
@@ -620,20 +620,11 @@ | |
{ | |
hwWatchdogReset(); | |
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) || defined(MY_DEFAULT_LED_EXT) | |
ledsProcess(); | |
#endif | |
} | |
-#if !defined(MY_SLEEP_HANDLER) | |
-void sleepHandler(bool sleep) | |
-{ | |
- (void)sleep; | |
- // empty function, resolves AVR-specific GCC optimization bug (<5.5) if handler not used | |
- // see here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77326 | |
-} | |
-#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) | |
{ | |
@@ -709,16 +700,13 @@ | |
#endif | |
setIndication(INDICATION_SLEEP); | |
-#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) || defined(MY_DEFAULT_LED_EXT) | |
// Wait until leds finish their blinking pattern | |
while (ledsBlinking()) { | |
doYield(); | |
} | |
#endif | |
- // Call the sleep handler to turn off peripherals optimally | |
- sleepHandler(true); | |
- | |
int8_t result = MY_SLEEP_NOT_POSSIBLE; // default | |
if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 != INTERRUPT_NOT_DEFINED) { | |
// both IRQs | |
@@ -730,10 +718,6 @@ | |
// no IRQ | |
result = hwSleep(sleepingTimeMS); | |
} | |
- | |
- // Call the sleep handler to turn on peripherals optimally | |
- sleepHandler(false); | |
- | |
setIndication(INDICATION_WAKEUP); | |
CORE_DEBUG(PSTR("MCO:SLP:WUP=%" PRIi8 "\n"), result); // sleep wake-up | |
#if defined(MY_SENSOR_NETWORK) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment