Fix #426: cater temporarily to defect in MCI Catena STM BSP

--- examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino
+++ examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino
@@ -581,6 +581,116 @@
     }
 }

+void setup() {
+    delay(5000);
+    while (! Serial)
+        ;
+    Serial.begin(115200);
+    setup_printSignOn();
+    setup_calibrateSystemClock();
+
+    // LMIC init using the computed target
+    const auto pPinMap = Arduino_LMIC::GetPinmap_ThisBoard();
+
+    // don't die mysteriously; die noisily.
+    if (pPinMap == nullptr) {
+        myFail("board not known to library; add pinmap or update getconfig_thisboard.cpp");
+    }
+
+    // now that we have a pinmap, initalize the low levels accordingly.
+    hal_set_failure_handler(log_assertion);
+    os_init_ex(pPinMap);
+
+    // LMIC_reset() doesn't affect callbacks, so we can do this first.
+    if (! (LMIC_registerRxMessageCb(myRxMessageCb, /* userData */ nullptr) &&
+           LMIC_registerEventCb(myEventCb, /* userData */ nullptr))) {
+        myFail("couldn't register callbacks");
+    }
+
+    // Reset the MAC state. Session and pending data transfers will be discarded.
+    LMIC_reset();
+
+    LMIC_setClockError(5 * MAX_CLOCK_ERROR / 100);
+
+    // do the network-specific setup prior to join.
+    setupForNetwork(false);
+
+    // Start job (sending automatically starts OTAA too)
+    do_send(&sendjob);
+}
+
+void setup_printSignOnDashLine(void)
+    {
+    for (unsigned i = 0; i < 78; ++i)
+        Serial.print('-');
+
+    printNl();
+    }
+
+static constexpr const char *filebasename2(const char *s, const char *p) {
+    return p[0] == '\0'                     ? s                             :
+           (p[0] == '/' || p[0] == '\\')    ? filebasename2(p + 1, p + 1)   :
+                                              filebasename2(s, p + 1)       ;
+}
+
+static constexpr const char *filebasename(const char *s)
+    {
+    return filebasename2(s, s);
+    }
+
+void printVersionFragment(char sep, uint8_t v) {
+    if (sep != 0) {
+        Serial.print(sep);
+    }
+    Serial.print(unsigned(v));
+}
+
+void printVersion(uint32_t v) {
+    printVersionFragment(0, uint8_t(v >> 24u));
+    printVersionFragment('.', uint8_t(v >> 16u));
+    printVersionFragment('.', uint8_t(v >> 8u));
+    if (uint8_t(v) != 0) {
+        printVersionFragment('.', uint8_t(v));
+    }
+}
+
+void setup_printSignOn()
+    {
+    printNl();
+
+    setup_printSignOnDashLine();
+
+    Serial.println(filebasename(__FILE__));
+    Serial.print(F("LMIC version "));
+    printVersion(ARDUINO_LMIC_VERSION);
+    Serial.print(F(" configured for region "));
+    Serial.print(CFG_region);
+    Serial.println('.');
+    Serial.println(F("Remember to select 'Line Ending: Newline' at the bottom of the monitor window."));
+
+    setup_printSignOnDashLine();
+    printNl();
+    }
+
+void setupForNetwork(bool preJoin) {
+#if defined(CFG_us915)
+    LMIC_selectSubBand(0);
+
+    if (! preJoin) {
+//        LMIC_setLinkCheckMode(0);
+//        LMIC_setDrTxpow(DR_SF7, 14);
+    }
+#endif
+}
+
+void loop() {
+    os_runloop_once();
+    while ((LMIC.opmode & OP_TXRXPEND) == 0 &&
+           ! os_queryTimeCriticalJobs(ms2osticks(1000)) &&
+           eventPrintOne())
+        ;
+}
+
 // there's a problem with running 2.5 of the MCCI STM32 BSPs;
 // hack around it.
 #ifdef ARDUINO_ARCH_STM32
@@ -593,111 +703,432 @@
 # endif // defined(_mcci_arduino_version)
 #endif // ARDUINO_ARCH_STM32

-void setup() {
-    delay(5000);
-    while (! Serial)
-        ;
-    Serial.begin(115200);
-    setup_printSignOn();
-
-    // LMIC init using the computed target
-    const auto pPinMap = Arduino_LMIC::GetPinmap_ThisBoard();
-
-    // don't die mysteriously; die noisily.
-    if (pPinMap == nullptr) {
-        myFail("board not known to library; add pinmap or update getconfig_thisboard.cpp");
-    }
-
-    // now that we have a pinmap, initalize the low levels accordingly.
-    hal_set_failure_handler(log_assertion);
-    os_init_ex(pPinMap);
-
-    // LMIC_reset() doesn't affect callbacks, so we can do this first.
-    if (! (LMIC_registerRxMessageCb(myRxMessageCb, /* userData */ nullptr) &&
-           LMIC_registerEventCb(myEventCb, /* userData */ nullptr))) {
-        myFail("couldn't register callbacks");
-    }
-
-    // Reset the MAC state. Session and pending data transfers will be discarded.
-    LMIC_reset();
-
-    LMIC_setClockError(5 * MAX_CLOCK_ERROR / 100);
-
-    // do the network-specific setup prior to join.
-    setupForNetwork(false);
-
-    // Start job (sending automatically starts OTAA too)
-    do_send(&sendjob);
-}
-
-void setup_printSignOnDashLine(void)
+#ifdef ARDUINO_ARCH_STM32
+# if defined(_mcci_arduino_version)
+#  if _mcci_arduino_version >= _mcci_arduino_version_calc(2,4,0,90)
+        static constexpr bool kUsesLSE = true;          // _mcci_arduino_version indicates that LSE clock is used.
+#  else
+        // versions before 2.4.0.90 use LSI clock. Can't calibrate.
+        static constexpr bool kUsesLSE = false;         // _mcci_arduino_version defined, too small
+#  endif
+# else
+        // versions before 2.4.0.90 use LSI clock. Can't calibrate.
+        static constexpr bool kUsesLSE = false;         // _mcci_arduino_version not defined
+# endif
+#else
+        static constexpr bool kUsesLSE = false;
+#endif
+
+
+void setup_calibrateSystemClock(void) {
+#ifdef ARDUINO_ARCH_STM32
+# ifdef _mcci_arduino_version
+#  if _mcci_arduino_version <= _mcci_arduino_version_calc(2, 5, 0, 0)
+    if (kUsesLSE) {
+        Serial.println("need to calibrate clock");
+        Stm32_CalibrateSystemClock();
+    } else {
+        Serial.println("calibration not supported");
+    }
+#  endif // _mcci_arduino_version
+# endif // defined(_mcci_arduino_version)
+#endif // ARDUINO_ARCH_STM32
+}
+
+#ifdef ARDUINO_ARCH_STM32
+# ifdef _mcci_arduino_version
+#  if _mcci_arduino_version <= _mcci_arduino_version_calc(2, 5, 0, 0)
+
+// RTC needs to be initialized before we calibrate the clock.
+bool rtcbegin() {
+    RTC_TimeTypeDef	Time;
+    RTC_DateTypeDef	Date;
+    uint32_t RtcClock;
+    RTC_HandleTypeDef	hRtc;
+
+    memset(&hRtc, 0, sizeof(hRtc));
+
+    hRtc.Instance = RTC;
+    hRtc.Init.HourFormat = RTC_HOURFORMAT_24;
+    RtcClock = __HAL_RCC_GET_RTC_SOURCE();
+    if (RtcClock == RCC_RTCCLKSOURCE_LSI)
+        {
+        hRtc.Init.AsynchPrediv = 37 - 1; /* 37kHz / 37 = 1000Hz */
+        hRtc.Init.SynchPrediv = 1000 - 1; /* 1000Hz / 1000 = 1Hz */
+        }
+    else if (RtcClock == RCC_RTCCLKSOURCE_LSE)
+        {
+        hRtc.Init.AsynchPrediv = 128 - 1; /* 32768Hz / 128 = 256Hz */
+        hRtc.Init.SynchPrediv = 256 - 1; /* 256Hz / 256 = 1Hz */
+        }
+    else
+        {
+        /*
+        || use HSE clock --
+        || we don't support use of HSE as RTC because it's connected to
+        || TCXO_OUT, and that's controlled by the LoRaWAN software.
+        */
+        Serial.println(
+            " HSE can not be used for RTC clock!"
+            );
+        return false;
+        }
+
+
+    hRtc.Init.OutPut = RTC_OUTPUT_DISABLE;
+    hRtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
+    hRtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
+    hRtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
+
+    if (HAL_RTC_Init(&hRtc) != HAL_OK)
+        {
+        Serial.println(
+            "HAL_RTC_Init() failed"
+            );
+        return false;
+        }
+
+    /* Initialize RTC and set the Time and Date */
+    if (HAL_RTCEx_BKUPRead(&hRtc, RTC_BKP_DR0) != 0x32F2)
+        {
+        Time.Hours = 0x0;
+        Time.Minutes = 0x0;
+        Time.Seconds = 0x0;
+        Time.SubSeconds = 0x0;
+        Time.TimeFormat = RTC_HOURFORMAT12_AM;
+        Time.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
+        Time.StoreOperation = RTC_STOREOPERATION_RESET;
+
+        if (HAL_RTC_SetTime(
+            &hRtc,
+            &Time,
+            RTC_FORMAT_BIN
+            ) != HAL_OK)
+            {
+            Serial.print(
+                "HAL_RTC_SetTime() failed"
+                );
+            return false;
+            }
+
+        /* Sunday 1st January 2017 */
+        Date.WeekDay = RTC_WEEKDAY_SUNDAY;
+        Date.Month = RTC_MONTH_JANUARY;
+        Date.Date = 0x1;
+        Date.Year = 0x0;
+
+        if (HAL_RTC_SetDate(
+            &hRtc,
+            &Date,
+            RTC_FORMAT_BIN
+            ) != HAL_OK)
+            {
+            Serial.print(
+                "HAL_RTC_SetDate() failed"
+                );
+            return false;
+            }
+
+        HAL_RTCEx_BKUPWrite(&hRtc, RTC_BKP_DR0, 0x32F2);
+        }
+
+    /* Enable Direct Read of the calendar registers (not through Shadow) */
+    HAL_RTCEx_EnableBypassShadow(&hRtc);
+
+    HAL_RTC_DeactivateAlarm(&hRtc, RTC_ALARM_A);
+    return true;
+}
+
+extern "C" {
+
+static volatile uint32_t *gs_pAlarm;
+static RTC_HandleTypeDef *gs_phRtc;
+
+void RTC_IRQHandler(void)
     {
-    for (unsigned i = 0; i < 78; ++i)
-        Serial.print('-');
-
-    printNl();
-    }
-
-static constexpr const char *filebasename2(const char *s, const char *p) {
-    return p[0] == '\0'                     ? s                             :
-           (p[0] == '/' || p[0] == '\\')    ? filebasename2(p + 1, p + 1)   :
-                                              filebasename2(s, p + 1)       ;
-}
-
-static constexpr const char *filebasename(const char *s)
+    HAL_RTC_AlarmIRQHandler(gs_phRtc);
+    }
+
+void HAL_RTC_AlarmAEventCallback(
+    RTC_HandleTypeDef *	hRtc
+    )
     {
-    return filebasename2(s, s);
-    }
-
-void printVersionFragment(char sep, uint8_t v) {
-    if (sep != 0) {
-        Serial.print(sep);
-    }
-    Serial.print(unsigned(v));
-}
-
-void printVersion(uint32_t v) {
-    printVersionFragment(0, uint8_t(v >> 24u));
-    printVersionFragment('.', uint8_t(v >> 16u));
-    printVersionFragment('.', uint8_t(v >> 8u));
-    if (uint8_t(v) != 0) {
-        printVersionFragment('.', uint8_t(v));
-    }
-}
-
-void setup_printSignOn()
+    if (gs_pAlarm)
+        *gs_pAlarm = 1;
+    }
+
+void HAL_RTC_MspInit(
+    RTC_HandleTypeDef *	hRtc
+    )
     {
-    printNl();
-
-    setup_printSignOnDashLine();
-
-    Serial.println(filebasename(__FILE__));
-    Serial.print(F("LMIC version "));
-    printVersion(ARDUINO_LMIC_VERSION);
-    Serial.print(F(" configured for region "));
-    Serial.print(CFG_region);
-    Serial.println('.');
-    Serial.println(F("Remember to select 'Line Ending: Newline' at the bottom of the monitor window."));
-
-    setup_printSignOnDashLine();
-    printNl();
-    }
-
-void setupForNetwork(bool preJoin) {
-#if defined(CFG_us915)
-    LMIC_selectSubBand(0);
-
-    if (! preJoin) {
-//        LMIC_setLinkCheckMode(0);
-//        LMIC_setDrTxpow(DR_SF7, 14);
-    }
-#endif
-}
-
-void loop() {
-    os_runloop_once();
-    while ((LMIC.opmode & OP_TXRXPEND) == 0 &&
-           ! os_queryTimeCriticalJobs(ms2osticks(1000)) &&
-           eventPrintOne())
-        ;
-}
+    if (hRtc->Instance == RTC)
+        {
+        /* USER CODE BEGIN RTC_MspInit 0 */
+
+        /* USER CODE END RTC_MspInit 0 */
+        /* Peripheral clock enable */
+        __HAL_RCC_RTC_ENABLE();
+        /* USER CODE BEGIN RTC_MspInit 1 */
+        HAL_NVIC_SetPriority(RTC_IRQn, TICK_INT_PRIORITY, 0U);
+        HAL_NVIC_EnableIRQ(RTC_IRQn);
+        /* USER CODE END RTC_MspInit 1 */
+        }
+    }
+
+void HAL_RTC_MspDeInit(
+    RTC_HandleTypeDef *	hRtc
+    )
+    {
+    if (hRtc->Instance == RTC)
+        {
+        /* USER CODE BEGIN RTC_MspDeInit 0 */
+        HAL_NVIC_DisableIRQ(RTC_IRQn);
+        /* USER CODE END RTC_MspDeInit 0 */
+        /* Peripheral clock disable */
+        __HAL_RCC_RTC_DISABLE();
+        /* USER CODE BEGIN RTC_MspDeInit 1 */
+
+        /* USER CODE END RTC_MspDeInit 1 */
+        }
+    }
+
+uint32_t HAL_AddTick(
+    uint32_t delta
+    )
+    {
+    extern __IO uint32_t uwTick;
+    // copy old interrupt-enable state to flags.
+    uint32_t const flags = __get_PRIMASK();
+
+    // disable interrupts
+    __set_PRIMASK(1);
+
+    // observe uwTick, and advance it.
+    uint32_t const tickCount = uwTick + delta;
+
+    // save uwTick
+    uwTick = tickCount;
+
+    // restore interrupts (does nothing if ints were disabled on entry)
+    __set_PRIMASK(flags);
+
+    // return the new value of uwTick.
+    return tickCount;
+    }
+
+} /* extern "C" */
+
+uint32_t Stm32_CalibrateSystemClock(void)
+    {
+    uint32_t Calib;
+    uint32_t CalibNew;
+    uint32_t CalibLow;
+    uint32_t CalibHigh;
+    uint32_t mSecond;
+    uint32_t mSecondNew;
+    uint32_t mSecondLow;
+    uint32_t mSecondHigh;
+    bool fHaveSeenLow;
+    bool fHaveSeenHigh;
+    const bool fCalibrateMSI =  HAL_RCC_GetHCLKFreq() < 16000000;
+
+    if (! rtcbegin()) {
+        return 0;
+    }
+
+    if (fCalibrateMSI)
+        {
+        Calib = (RCC->ICSCR & RCC_ICSCR_MSITRIM) >> 24;
+        }
+    else
+        {
+        Calib = (RCC->ICSCR & RCC_ICSCR_HSITRIM) >> 8;
+        }
+
+    /* preapre to loop, setting suitable defaults */
+    CalibNew = Calib;
+    CalibLow = 0;
+    CalibHigh = 0;
+    mSecondLow = 0;
+    mSecondHigh = 2000;
+    fHaveSeenLow = fHaveSeenHigh = false;
+
+    /* loop until we have a new value */
+    do	{
+        /* meassure the # of millis per RTC second */
+        mSecond = MeasureMillisPerRtcSecond();
+
+        /* invariant: */
+        if (Calib == CalibNew)
+            mSecondNew = mSecond;
+
+        /* if mSecond is low, this meaans we must increase the system clock */
+        if (mSecond <= 1000)
+            {
+            Serial.print('-');
+            /*
+            || the following condition establishes that we're
+            || below the target frequency, but closer than we've been
+            || before (mSecondLow is the previous "low" limit). If
+            || so, we reduce the limit, and capture the "low" calibration
+            || value.
+            */
+            if (mSecond > mSecondLow)
+                {
+                mSecondLow = mSecond;
+                CalibLow = Calib; /* save previous calibration value */
+                fHaveSeenLow = true;
+                }
+
+            /*
+            || if we are low, and we have never exceeded the high limit,
+            || we can  increase the clock.
+            */
+            if (! fHaveSeenHigh)
+                {
+                if (fCalibrateMSI)
+                    {
+                    if (Calib < 0xFF)
+                        {
+                        ++Calib;
+                        __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(Calib);
+                        }
+                    else
+                        break;
+                    }
+                else
+                    {
+                    if (Calib < 0x1F)
+                        {
+                        ++Calib;
+                        __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(Calib);
+                        }
+                    else
+                        {
+                        break;
+                        }
+                    }
+
+                /* let the clock settle */
+                delay(500);
+                }
+            }
+
+        /* if mSecond is high, we must reduce the system clock */
+        else
+            {
+            Serial.print('+');
+            /*
+            || the following condition establishes that we're
+            || above the target frequency, but closer than we've been
+            || before (mSecondHigh is the previous "high" limit). If
+            || so, we reduce the limit, and capture the calibration
+            || value.
+            */
+            if (mSecond < mSecondHigh)
+                {
+                mSecondHigh = mSecond;
+                CalibHigh = Calib;
+                fHaveSeenHigh = true;
+                }
+
+            /*
+            || if we are above the target frequency, and we have
+            || never raised the frequence, we can lower the
+            || frequency
+            */
+            if (! fHaveSeenLow)
+                {
+                if (Calib == 0)
+                    break;
+
+                --Calib;
+                if (fCalibrateMSI)
+                    {
+                    __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(Calib);
+                    }
+                else
+                    {
+                    __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(Calib);
+                    }
+                delay(500);
+                }
+            }
+        } while ((Calib != CalibNew) &&
+                (! fHaveSeenLow || !fHaveSeenHigh));
+
+    //
+    // We are going to take higher calibration value first and
+    // it allows us not to call LMIC_setClockError().
+    //
+    if (fHaveSeenHigh)
+        {
+        mSecondNew = mSecondHigh;
+        CalibNew = CalibHigh;
+        }
+    else if (fHaveSeenLow)
+        {
+        mSecondNew = mSecondLow;
+        CalibNew = CalibLow;
+        }
+    else
+        {
+        // Use original value
+        Serial.println(
+            "?CatenaStm32L0::CalibrateSystemClock: can't calibrate"
+            );
+        }
+
+    if (CalibNew != Calib)
+        {
+        if (fCalibrateMSI)
+            {
+            __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(CalibNew);
+            }
+        else
+            {
+            __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(CalibNew);
+            }
+        delay(500);
+        }
+
+    return CalibNew;
+    }
+
+uint32_t
+MeasureMillisPerRtcSecond(
+    void
+    )
+    {
+    uint32_t second;
+    uint32_t now;
+    uint32_t start;
+    uint32_t end;
+
+    /* get the starting time */
+    second = RTC->TR & (RTC_TR_ST | RTC_TR_SU);
+
+    /* wait for a new second to start, and capture millis() in start */
+    do	{
+        now = RTC->TR & (RTC_TR_ST | RTC_TR_SU);
+        start = millis();
+        } while (second == now);
+
+    /* update our second of interest */
+    second = now;
+
+    /* no point in watching the register until we get close */
+    delay(500);
+
+    /* wait for the next second to start, and capture millis() */
+    do	{
+        now = RTC->TR & (RTC_TR_ST | RTC_TR_SU);
+        end = millis();
+        } while (second == now);
+
+    /* return the delta */
+    return end - start;
+    }
+#  endif // _mcci_arduino_version
+# endif // defined(_mcci_arduino_version)
+#endif // ARDUINO_ARCH_STM32


Clean-up serial print

Clean-up serial print

--- examples/Test_InputDebounce/Test_InputDebounce.ino
+++ examples/Test_InputDebounce/Test_InputDebounce.ino
@@ -23,6 +23,8 @@

   // init serial
   Serial.begin(9600);
+
+  Serial.println("Test InputDebounce library");

   // setup input button (debounced)
   buttonTest.setup(pinSwitch, BUTTON_DEBOUNCE_DELAY, InputDebounce::PIM_INT_PULL_UP_RES);
@@ -65,7 +67,7 @@
     if(buttonTest_OnTimeLast) {
       // handle released state
       digitalWrite(pinLED, LOW); // turn the LED off
-      Serial.print("LOW (");
+      Serial.print("LOW (last on-time: HIGH ");
       Serial.print(buttonTest_OnTimeLast);
       Serial.println("ms)");
       buttonTest_OnTimeLast = 0; // reset, do not handle this released state again


COH-71

--- COHEAT2015/20160316-COHEAT-M1/COHEAT-M1/COHEAT-M1.ino
+++ COHEAT2015/20160316-COHEAT-M1/COHEAT-M1/COHEAT-M1.ino
@@ -814,6 +814,95 @@
   };
 #endif

+#ifdef ENABLE_EXTENDED_CLI
+// Handle CLI extension commands.
+// Commands of form:
+//   +EXT .....
+// where EXT is the name of the extension, usually 3 letters.
+
+// It is acceptable for extCLIHandler() to alter the buffer passed,
+// eg with strtok_t().
+static bool extCLIHandler(Print *const p, char *const buf, const uint8_t n)
+  {
+
+#ifdef ALLOW_CC1_SUPPORT_RELAY
+  // If CC1 replay then allow +CC1 ! command to send an alert to the hub.
+  // Full command is:
+  //    +CC1 !
+  // This unit's housecode is used in the frame sent.
+  const uint8_t CC1_A_PREFIX_LEN = 6;
+  // Falling through rather than return(true) indicates failure.
+  if((n >= CC1_A_PREFIX_LEN) && (0 == strncmp("+CC1 !", buf, CC1_A_PREFIX_LEN)))
+    {
+    // Send the alert!
+    return(sendCC1AlertByRFM23B());
+    }
+#endif
+
+#ifdef ALLOW_CC1_SUPPORT_HUB
+  // If CC1 hub then allow +CC1 ? command to poll a remote relay.
+  // Full command is:
+  //    +CC1 ? hc1 hc2 rp lc lt lf
+  // ie six numeric arguments, see below, with out-of-range values coerced (other than housecodes):
+//            // Factory method to create instance.
+//            // Invalid parameters (except house codes) will be coerced into range.
+//            //   * House code (hc1, hc2) of valve controller that the poll/command is being sent to.
+//            //   * rad-open-percent     [0,100] 0-100 in 1% steps, percent open approx to set rad valve (rp)
+//            //   * light-colour         [0,3] bit flags 1==red 2==green (lc) 0 => stop everything
+//            //   * light-on-time        [1,15] (0 not allowed) 30-450s in units of 30s (lt) ???
+//            //   * light-flash          [1,3] (0 not allowed) 1==single 2==double 3==on (lf)
+//            // Returns instance; check isValid().
+//            static CC1PollAndCommand make(uint8_t hc1, uint8_t hc2,
+//                                          uint8_t rp,
+//                                          uint8_t lc, uint8_t lt, uint8_t lf);
+  const uint8_t CC1_Q_PREFIX_LEN = 7;
+  const uint8_t CC1_Q_PARAMS = 6;
+  // Falling through rather than return(true) indicates failure.
+  if((n >= CC1_Q_PREFIX_LEN) && (0 == strncmp("+CC1 ? ", buf, CC1_Q_PREFIX_LEN)))
+    {
+    char *last; // Used by strtok_r().
+    char *tok1;
+    // Attempt to parse the parameters.
+    if((n-CC1_Q_PREFIX_LEN >= CC1_Q_PARAMS*2-1) && (NULL != (tok1 = strtok_r(buf+CC1_Q_PREFIX_LEN, " ", &last))))
+      {
+      char *tok2 = strtok_r(NULL, " ", &last);
+      char *tok3 = (NULL == tok2) ? NULL : strtok_r(NULL, " ", &last);
+      char *tok4 = (NULL == tok3) ? NULL : strtok_r(NULL, " ", &last);
+      char *tok5 = (NULL == tok4) ? NULL : strtok_r(NULL, " ", &last);
+      char *tok6 = (NULL == tok5) ? NULL : strtok_r(NULL, " ", &last);
+      if(NULL != tok6)
+        {
+        OTProtocolCC::CC1PollAndCommand q = OTProtocolCC::CC1PollAndCommand::make(
+            atoi(tok1),
+            atoi(tok2),
+            atoi(tok3),
+            atoi(tok4),
+            atoi(tok5),
+            atoi(tok6));
+        if(q.isValid())
+          {
+          uint8_t txbuf[OTProtocolCC::CC1PollAndCommand::primary_frame_bytes+1]; // More than large enough for preamble + sync + alert message.
+          const uint8_t bodylen = q.encodeSimple(txbuf, sizeof(txbuf), true);
+#if 0 && defined(DEBUG)
+    OTRadioLink::printRXMsg(p, txbuf, bodylen);
+#endif
+          // TX at normal volume since ACKed and can be repeated if necessary.
+          if(PrimaryRadio.sendRaw(txbuf, bodylen))
+            { return(true); } // Done it!
+#if 1 && defined(DEBUG)
+          else { DEBUG_SERIAL_PRINT_FLASHSTRING("!TX failed"); }
+#endif
+          }
+        }
+      }
+    return(false); // FAILED if fallen through from above.
+    }
+#endif
+
+  return(false); // FAILED if not otherwise handled.
+  }
+#endif
+
 // Remaining minutes to keep CLI active; zero implies inactive.
 // Starts up with full value to allow easy setting of time, etc, without specially activating CLI.
 // Marked volatile for thread-safe lock-free non-read-modify-write access to byte-wide value.
@@ -895,22 +984,21 @@
         break; // Note that status is by default printed after processing input line.
         }

-// FIXME FIXME FIXME
-//#ifdef ENABLE_EXTENDED_CLI
-//      // Handle CLI extension commands.
-//      // Command of form:
-//      //   +EXT .....
-//      // where EXT is the name of the extension, usually 3 letters.
-//      //
-//      // It is acceptable for extCLIHandler() to alter the buffer passed,
-//      // eg with strtok_t().
-//      case '+':
-//        {
-//        const bool success = extCLIHandler(&Serial, buf, n);
-//        Serial.println(success ? F("OK") : F("FAILED"));
-//        break;
-//        }
-//#endif
+#ifdef ENABLE_EXTENDED_CLI
+      // Handle CLI extension commands.
+      // Command of form:
+      //   +EXT .....
+      // where EXT is the name of the extension, usually 3 letters.
+      //
+      // It is acceptable for extCLIHandler() to alter the buffer passed,
+      // eg with strtok_t().
+      case '+':
+        {
+        const bool success = extCLIHandler(&Serial, buf, n);
+        Serial.println(success ? F("OK") : F("FAILED"));
+        break;
+        }
+#endif
       }

     // Almost always show status line afterwards as feedback of command received and new state.


Correct wlan key

Correct wlan key

--- examples/05.ThingSpeak/ExecuteCommand/ExecuteCommand.ino
+++ examples/05.ThingSpeak/ExecuteCommand/ExecuteCommand.ino
@@ -1,4 +1,4 @@
-#include <SoftwareSerial.h>
+<#include <SoftwareSerial.h>
 #include <Esp8266.h>
 #include <IPDParser.h>
 #include <HttpRequest.h>
@@ -26,7 +26,7 @@
   // is not yet in API. We have to set it by an AT command.
   espSerial.print(F("AT+CWMODE=1\r\n"));

-  esp.joinAccessPoint("IEKnet", "wlanIEKnet19");
+  esp.joinAccessPoint("ti_iot", "ti_iot42!");
   esp.setMultipleConnections(true);
 }


Changed RX test to some off-center point.

Specifically, relative to the first transmitter, this is simulating
a receiver at (17,23).

--- arduino/test/rx_test/rx_test.ino
+++ arduino/test/rx_test/rx_test.ino
@@ -3,12 +3,12 @@
 // attempt position calculations.

 enum {
-  RX_PIN = 11,
+  RX_PIN = 13,
   NUM_TRANSMITTERS = 4u,
   DURATION = 5000u,  // μs
 };

-unsigned const long SPACINGS[4] = {100000u, 100000u, 100000u, 700000u};
+unsigned const long SPACINGS[4] = {117766u, 95420u, 77814u, 709001u};

 void setup() {
   pinMode(RX_PIN, OUTPUT);


Try this

Try this

--- interrupt_driven_rgb.ino
+++ interrupt_driven_rgb.ino
@@ -44,7 +44,7 @@
 const uint8_t buttonLEDPin   = 19;
 const uint8_t servoPowerPin  = 18;
 const uint8_t arm_address    = 1;
-const double threshold  = 0.0075; // ~40 ft seems optimal
+const double threshold       = 0.0075; // ~40 ft seems optimal
 double distanceTo;
 double course;

@@ -126,7 +126,11 @@
 void drawTitleBorder() {
   oled.clearScreen();

-  oled.setColor(0, 0, 255);
+  if(isArmed()) {
+    oled.setColor(0, 0, 255);
+  } else {
+    oled.setColor(255, 0, 255);
+  }
   oled.drawRFrame(0, 0, oled.getWidth(), 20, 3);

   oled.setFont(ucg_font_7x13Br);
@@ -185,7 +189,7 @@
   lockServo.write(150);
   delay(1000);
   digitalWrite(servoPowerPin, LOW);
-  EEPROM.write(arm_address, 0);
+  EEPROM.write(arm_address, 1);
 }

 void unlock() {
@@ -197,7 +201,7 @@
 }

 bool isArmed() {
-  return EEPROM.read(arm_address) == 0;
+  return EEPROM.read(arm_address) == 1;
 }

 /*
@@ -450,10 +454,11 @@
   }

   // Debug info formatted
+  /*char _debug[21];*/
+  /*sprintf(_debug, "hdop: %d WP: %s", gps.hdop.value(), _stats);*/
+
   char _stats[8];
-  char _debug[21];
   waypoint_manager.stats(_stats);
-  sprintf(_debug, "hdop: %d WP: %s", gps.hdop.value(), _stats);

   oled.setFont(ucg_font_9x15Br);
   oled.setColor(0, 255, 0);
@@ -471,8 +476,8 @@
   oled.printf(F("%d satellites  "), gps.satellites.value());

   // Debug info
-  oled.setPrintPos(0, l(-1, BOTTOM));
-  oled.printf(F("%-21s"), _debug);
+  /*oled.setPrintPos(0, l(-1, BOTTOM));
+  oled.printf(F("%-21s"), _debug);*/
 }

 void setup() {


corrected sending wrong value bug

corrected sending wrong value bug

--- power_measure_tool.ino
+++ power_measure_tool.ino
@@ -108,7 +108,7 @@
   output += outputVoltString;
   output += " ";

-  String outputAmpString = dtostrf(outputVolt, 0, 4, buff);
+  String outputAmpString = dtostrf(outputAmp, 0, 4, buff);
   output += outputAmpString;
   output += " ";


use 5V as a reference

use 5V as a reference

--- scriptor.ino
+++ scriptor.ino
@@ -20,7 +20,6 @@
 void setup() {
   // initialize serial communication
   Serial.begin(115200); // bits per second
-  analogReference(INTERNAL);
 }

 // the loop routine runs over and over again forever:


comparison changed

comparison changed

--- zamek.ino
+++ zamek.ino
@@ -232,7 +232,7 @@

 void cardAccepted()
 {
-	if (soundDelayTimeout == 0)
+	if (!soundDelayTimeout)
 	{
 		tone(pinPiezo, toneAccepted, toneDuration);
 		soundDelayTimeout = 500;
@@ -242,7 +242,7 @@
 }
 void cardRejected()
 {
-	if (soundDelayTimeout == 0)
+	if (!soundDelayTimeout)
 	{
 		tone(pinPiezo, toneRejected, toneDuration);
 		soundDelayTimeout = 500;


changed setpoint to warm

changed setpoint to warm

--- chillduino.ino
+++ chillduino.ino
@@ -43,12 +43,12 @@
 #define LED_ON_G         255
 #define LED_ON_B         255

-#define THERMISTOR_MIN_COLD    255
-#define THERMISTOR_MAX_COLD    357
-#define THERMISTOR_MIN_COLDER  255
-#define THERMISTOR_MAX_COLDER  357
-#define THERMISTOR_MIN_COLDEST 255
-#define THERMISTOR_MAX_COLDEST 357
+#define THERMISTOR_MIN_COLD    294
+#define THERMISTOR_MAX_COLD    392
+#define THERMISTOR_MIN_COLDER  294
+#define THERMISTOR_MAX_COLDER  392
+#define THERMISTOR_MIN_COLDEST 294
+#define THERMISTOR_MAX_COLDEST 392

 #define TICKS_PER_SECOND   ((unsigned long) 1000)
 #define TICKS_PER_MINUTE   (60 * TICKS_PER_SECOND)


[WifiDude] Request temperature and acceleration.

Signed-off-by: Juri Berlanda <5bfdca9e82c53adb0603ce7083f4ba4f2da5cacf@hotmail.com>

--- laundry-dude-xbee-bridge/laundry-dude-xbee-bridge.ino
+++ laundry-dude-xbee-bridge/laundry-dude-xbee-bridge.ino
@@ -20,9 +20,13 @@

 void loop() {
 	request('l');
-	delay(2500);
+	delay(1000);
 	request('h');
-	delay(2500);
+	delay(1000);
+	request('t');
+	delay(1000);
+	request('a');
+	delay(1000);
 }

 void request(char type) {


Updated cursor.ino

Updated cursor.ino

Previous commit broke the actual functionality. The code was confusing and worked until the previous commit.
The changes make it logically and functionally correct.

--- libraries/LiquidCrystal/examples/setCursor/setCursor.ino
+++ libraries/LiquidCrystal/examples/setCursor/setCursor.ino
@@ -7,7 +7,7 @@
  can usually tell them by the 16-pin interface.

  This sketch prints to all the positions of the LCD using the
- setCursor(0 method:
+ setCursor() method:

   The circuit:
  * LCD RS pin to digital pin 12
@@ -56,9 +56,9 @@
   // loop from ASCII 'a' to ASCII 'z':
   for (int thisLetter = 'a'; thisLetter <= 'z'; thisLetter++) {
     // loop over the columns:
-    for (int thisCol = 0; thisCol < numRows; thisCol++) {
+    for (int  thisRow = 0; thisRow < numRows; thisRow++) {
       // loop over the rows:
-      for (int thisRow = 0; thisRow < numCols; thisRow++) {
+      for (int thisCol = 0; thisCol < numCols; thisCol++) {
         // set the cursor position:
         lcd.setCursor(thisCol, thisRow);
         // print the letter:


More logging.

More logging.

--- temptask.ino
+++ temptask.ino
@@ -16,11 +16,13 @@
     snprintf( sensorUniqueId, sizeof( sensorUniqueId ), "%02x%02x%02x%02x%02x%02x%02x",
               currentAddr[1], currentAddr[2], currentAddr[3], currentAddr[4], currentAddr[5], currentAddr[6], currentAddr[7]  );

+    ESP_LOGI( TAG, "Finding saved name for sensor ID: %s", sensorUniqueId );
+
     /* and read value from NVS or use default name */
     snprintf( sensor[numberOfFoundSensors].name, sizeof( sensor[numberOfFoundSensors].name ),
               preferences.getString( sensorUniqueId, "temp sensor" ).c_str(), numberOfFoundSensors  );

-    ESP_LOGD( TAG, "Sensor %i: %s - Name: '%s'", numberOfFoundSensors, sensorUniqueId, sensor[numberOfFoundSensors].name );
+    ESP_LOGD( TAG, "Sensor %i ID: %s - Name: '%s'", numberOfFoundSensors, sensorUniqueId, sensor[numberOfFoundSensors].name );

     numberOfFoundSensors++;
   }


Reformat and clean up code

Reformat and clean up code

--- AzElSensor/AzElSensor.ino
+++ AzElSensor/AzElSensor.ino
@@ -16,59 +16,30 @@
 #include <Wire.h>
 #include <TimerOne.h>

-#define    MPU9250_ADDRESS            0x68
-#define    MAG_ADDRESS                0x0C
-
-#define    GYRO_FULL_SCALE_250_DPS    0x00
-#define    GYRO_FULL_SCALE_500_DPS    0x08
-#define    GYRO_FULL_SCALE_1000_DPS   0x10
-#define    GYRO_FULL_SCALE_2000_DPS   0x18
-
-#define    ACC_FULL_SCALE_2_G        0x00
-#define    ACC_FULL_SCALE_4_G        0x08
-#define    ACC_FULL_SCALE_8_G        0x10
-#define    ACC_FULL_SCALE_16_G       0x18
+const byte MPU9250_ADDRESS = 0x68;
+const byte MAG_ADDRESS = 0x0C;
+
+const byte GYRO_FULL_SCALE_250_DPS = 0x00;
+const byte GYRO_FULL_SCALE_500_DPS = 0x08;
+const byte GYRO_FULL_SCALE_1000_DPS = 0x10;
+const byte GYRO_FULL_SCALE_2000_DPS = 0x18;
+
+const byte ACC_FULL_SCALE_2_G = 0x00;
+const byte ACC_FULL_SCALE_4_G = 0x08;
+const byte ACC_FULL_SCALE_8_G = 0x10;
+const byte ACC_FULL_SCALE_16_G = 0x18;
+
+uint8_t Buf[6];
+int16_t ax, ay, az;
+int16_t gx, gy, gz;
+int16_t mx, my, mz;
+uint8_t Mag[7];

 boolean cmdPending;
 String cmdStr;

-// This function read Nbytes bytes from I2C device at address Address.
-// Put read bytes starting at register Register in the Data array.
-void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t* Data)
-{
-  // Set register address
-  Wire.beginTransmission(Address);
-  Wire.write(Register);
-  Wire.endTransmission();
-
-  // Read Nbytes
-  Wire.requestFrom(Address, Nbytes);
-  uint8_t index=0;
-  while (Wire.available())
-    Data[index++]=Wire.read();
-}
-
-
-// Write a byte (Data) in device (Address) at register (Register)
-void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data)
-{
-  // Set register address
-  Wire.beginTransmission(Address);
-  Wire.write(Register);
-  Wire.write(Data);
-  Wire.endTransmission();
-}
-
-
-
-// Initial time
-long int ti;
-volatile bool intFlag=false;
-
-// Initializations
-void setup()
-{
-  // Arduino initializations
+void setup() {
+
   Wire.begin();
   Serial.begin(9600);

@@ -88,37 +59,13 @@
   // Request continuous magnetometer measurements in 16 bits
   I2CwriteByte(MAG_ADDRESS,0x0A,0x16);

-   pinMode(13, OUTPUT);
-  //Timer1.initialize(1000000);         // initialize timer1, and set a 1/2 second period
-  //Timer1.attachInterrupt(callback);  // attaches callback() as a timer overflow interrupt
+  pinMode(13, OUTPUT);

   cmdPending = false;

-  // Store initial time
-  ti=millis();
-}
-
-
-// Counter
-long int cpt=0;
-
-uint8_t Buf[6];
-int16_t ax, ay, az;
-int16_t gx, gy, gz;
-int16_t mx, my, mz;
-uint8_t Mag[7];
-
-void callback()
-{
-  intFlag=true;
-  digitalWrite(13, digitalRead(13) ^ 1);
-}
-
-// Main loop, read and display data
-void loop()
-{
-  //while (!intFlag);
-  //intFlag=false;
+}
+
+void loop() {

   if ( Serial.available() ) getInByte();
   if ( cmdPending ) processCmd();
@@ -126,90 +73,87 @@
 }

 void processCmd() {
+
   if ( cmdStr == "read" ) getReadings();
   cmdPending = false;
   cmdStr = "";
+
 }

 void getReadings() {
-  accelerometer_subr();
+
+  accelerometer();
   Serial.print( "," );
-  subr_magnetometer();
+  magnetometer();
   Serial.print( "," );
-  gyro_subr();
+  gyro();
   Serial.println( "" );
-}
-
-  void accelerometer_subr()
-  {
- // Read accelerometer data
-    I2Cread(MPU9250_ADDRESS,0x3B,6,Buf);
-
+
+}
+
+void accelerometer() {
+
+  // Read accelerometer data
+  I2Cread(MPU9250_ADDRESS,0x3B,6,Buf);
+
   // Create 16 bits values from 8 bits data
-    ax=-(Buf[0]<<8 | Buf[1]);
-    ay=-(Buf[2]<<8 | Buf[3]);
-    az=Buf[4]<<8 | Buf[5];
+  ax=-(Buf[0]<<8 | Buf[1]);
+  ay=-(Buf[2]<<8 | Buf[3]);
+  az=Buf[4]<<8 | Buf[5];

   //print accelerometer data
-    Serial.print (ax,DEC);
-    Serial.print (",");
-    Serial.print (ay,DEC);
-    Serial.print (",");
-    Serial.print (az,DEC);
-  }
-
-
-  void gyro_subr()
-  {
-  // Read gyroscope data
-    I2Cread(MPU9250_ADDRESS,0x43,6,Buf);
-
-  // Create 16 bits values from 8 bits data
-    int16_t gx=-(Buf[0]<<8 | Buf[1]);
-    int16_t gy=-(Buf[2]<<8 | Buf[3]);
-    int16_t gz=Buf[4]<<8 | Buf[5];
-
-  // print gyroscope data
-    Serial.print (gx,DEC);
-    Serial.print (",");
-    Serial.print (gy,DEC);
-    Serial.print (",");
-    Serial.print (gz,DEC);
-
-  }
-  // _____________________
-  // :::  Magnetometer :::
-
-
-  // Read register Status 1 and wait for the DRDY: Data Ready
-
-  void subr_magnetometer()
-  {
-
+  Serial.print (ax,DEC);
+  Serial.print (",");
+  Serial.print (ay,DEC);
+  Serial.print (",");
+  Serial.print (az,DEC);
+
+}
+
+void gyro() {
+
+// Read gyroscope data
+  I2Cread(MPU9250_ADDRESS,0x43,6,Buf);
+
+// Create 16 bits values from 8 bits data
+  int16_t gx=-(Buf[0]<<8 | Buf[1]);
+  int16_t gy=-(Buf[2]<<8 | Buf[3]);
+  int16_t gz=Buf[4]<<8 | Buf[5];
+
+// print gyroscope data
+  Serial.print (gx,DEC);
+  Serial.print (",");
+  Serial.print (gy,DEC);
+  Serial.print (",");
+  Serial.print (gz,DEC);
+
+}
+
+void magnetometer() {
+
+// Read register Status 1 and wait for the DRDY: Data Ready
   uint8_t ST1;
-  do
-  {
+
+  do {
     I2Cread(MAG_ADDRESS,0x02,1,&ST1);
-  }
-  while (!(ST1&0x01));
-
-  // Read magnetometer data
-    I2Cread(MAG_ADDRESS,0x03,7,Mag);
-
-  // Create 16 bits values from 8 bits data
-    mx=-(Mag[3]<<8 | Mag[2]);
-    my=-(Mag[1]<<8 | Mag[0]);
-    mz=-(Mag[5]<<8 | Mag[4]);
-
-
-  // print magnetometer data
-    Serial.print (mx,DEC);//(mx+200,DEC);
-    Serial.print (",");
-    Serial.print (my,DEC);//(my-70,DEC);
-    Serial.print (",");
-    Serial.print (mz,DEC);//(mz-700,DEC);
-
-  }
+  } while (!(ST1&0x01));
+
+// Read magnetometer data
+  I2Cread(MAG_ADDRESS,0x03,7,Mag);
+
+// Create 16 bits values from 8 bits data
+  mx=-(Mag[3]<<8 | Mag[2]);
+  my=-(Mag[1]<<8 | Mag[0]);
+  mz=-(Mag[5]<<8 | Mag[4]);
+
+// print magnetometer data
+  Serial.print (mx,DEC);//(mx+200,DEC);
+  Serial.print (",");
+  Serial.print (my,DEC);//(my-70,DEC);
+  Serial.print (",");
+  Serial.print (mz,DEC);//(mz-700,DEC);
+
+}

 void getInByte() {
   char inByte = Serial.read();
@@ -221,6 +165,33 @@
     }
   }
 }
+
+// This function read Nbytes bytes from I2C device at address Address.
+// Put read bytes starting at register Register in the Data array.
+void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t* Data)
+{
+  // Set register address
+  Wire.beginTransmission(Address);
+  Wire.write(Register);
+  Wire.endTransmission();
+
+  // Read Nbytes
+  Wire.requestFrom(Address, Nbytes);
+  uint8_t index=0;
+  while (Wire.available())
+    Data[index++]=Wire.read();
+}
+
+// Write a byte (Data) in device (Address) at register (Register)
+void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data) {
+  // Set register address
+  Wire.beginTransmission(Address);
+  Wire.write(Register);
+  Wire.write(Data);
+  Wire.endTransmission();
+}
+
+


- changed temperature limits

- changed temperature limits

--- GeheimTuer.ino
+++ GeheimTuer.ino
@@ -244,9 +244,9 @@

 unsigned long dsMillis = 0;
 const unsigned long dsInterval = 1000; // sensor read interval
-const signed int tempMax = 40/0.0625; // run fan at full speed above tempMax
-const signed int tempMin = 33/0.0625; // run fan at minimum speed at tempMin
-const signed int tempHyst = 3/0.0625; // shut off fan at tempMin-tempHyst
+const signed int tempMax = 38/0.0625; // run fan at full speed above tempMax
+const signed int tempMin = 30/0.0625; // run fan at minimum speed at tempMin
+const signed int tempHyst = 2/0.0625; // shut off fan at tempMin-tempHyst

 byte fanPWM;
 const byte fanMin = 170; // minimum PWM limit at temp > tempMin


Removed functions that are duplicate with another file

--- FumeHoodMonitor/TMP36.ino
+++ FumeHoodMonitor/TMP36.ino
@@ -32,10 +32,10 @@
   }
 }

-bool isAirTempHigh(){
-  return readTMP36Temp() > maxTMP36Temperature;
-}
-
-bool isAirTempHigh(float tempF){
-  return tempF > maxTMP36Temperature;
-}
+// bool isAirTempHigh(){
+//   return readTMP36Temp() > maxTMP36Temperature;
+// }
+//
+// bool isAirTempHigh(float tempF){
+//   return tempF > maxTMP36Temperature;
+// }


Added: new function for reading hex-based dumps from a PIC chip Changed: improved command matching function

--- pic_programmer_prototype/pic_programmer_prototype.ino
+++ pic_programmer_prototype/pic_programmer_prototype.ino
@@ -37,7 +37,7 @@
     virtual void printHelpString() const;
 };

-const size_t COMMANDS_SIZE = 10;
+const size_t COMMANDS_SIZE = 16;
 Command::Ptr commands[COMMANDS_SIZE];

 class HelpCommand : public Command {
@@ -64,7 +64,7 @@
 class PowerControl : public Command {
   public:
     virtual bool match(const String& name) const {
-      return name.startsWith("power");
+      return name == "power";
     }

     virtual void execute(const String& commandString) {
@@ -89,7 +89,7 @@
 class ProgrammingModeControl : public Command {
   public:
     virtual bool match(const String& name) const {
-      return name.startsWith("prog_mode");
+      return name == "prog_mode";
     }

     virtual void execute(const String& commandString) {
@@ -113,12 +113,14 @@
     }
 };

-class ReadTextWordControl : public Command {
-  public:
-    virtual bool match(const String& name) const {
-      return name.startsWith("read");
-    }
-
+class ReadWordControlBase : public Command {
+  private:
+    bool readStopBits;
+  protected:
+    virtual void printWord(long location, int w) = 0;
+
+    ReadWordControlBase(bool rsb) : readStopBits(rsb) {}
+  public:
     virtual void execute(const String& commandString) {
       if (!programmer->inProgrammingMode()) {
         Serial.println("ERROR: Programmer not in programming mode");
@@ -133,14 +135,8 @@
         }

         do {
-          int w = programmer->readWord(true);
-          Serial.print("Word ");
-          Serial.print(String(programmer->getLocation(), HEX));
-          Serial.print(": ");
-          for (int i = 0; i < 16; i++) {
-            Serial.print(((w >> (15 - i)) & 1) == 1 ? "1 " : "0 ");
-          }
-          Serial.println();
+          const int w = programmer->readWord(readStopBits);
+          printWord(programmer->getLocation(), w);

           count--;
           if (count >= 0) {
@@ -149,16 +145,71 @@
         } while (count > 0);
       }
     }
+};
+
+class ReadTextWordControl : public ReadWordControlBase {
+  protected:
+    virtual void printWord(long location, int w) {
+      Serial.print("Word ");
+      Serial.print(String(programmer->getLocation(), HEX));
+      Serial.print(": ");
+      for (int i = 0; i < 16; i++) {
+        Serial.print(((w >> (15 - i)) & 1) == 1 ? "1 " : "0 ");
+      }
+      Serial.println();
+    }
+  public:
+    ReadTextWordControl() : ReadWordControlBase(true) {}
+
+    virtual bool match(const String& name) const {
+      return name == "read";
+    }

     virtual void printHelpString() const {
       Serial.println("  read [count]          reads a word from the current memory location and displayes it as text");
     }
 };

+class ReadHexWordControl : public ReadWordControlBase {
+  private:
+    int num;
+  protected:
+    virtual void printWord(long location, int w) {
+      if (num == 0) {
+        Serial.print(String(programmer->getLocation(), HEX));
+        Serial.print(": ");
+      }
+      Serial.print(String(w, HEX) + " ");
+      num++;
+      if (num % 0x10 == 0) {
+        Serial.println();
+        num = 0;
+      }
+    }
+  public:
+    ReadHexWordControl() : ReadWordControlBase(false) {}
+
+    virtual void execute(const String& commandString) {
+      num = 0;
+      ReadWordControlBase::execute(commandString);
+      if (num != 0) {
+        Serial.println();
+      }
+    }
+
+    virtual bool match(const String& name) const {
+      return name == "read_hex";
+    }
+
+    virtual void printHelpString() const {
+      Serial.println("  read_hex [count]      reads a word from the current memory location and displayes it as hex string");
+    }
+};
+
 class WriteTextWordControl : public Command {
   public:
     virtual bool match(const String& name) const {
-      return name.startsWith("write");
+      return name == "write";
     }

     virtual void execute(const String& commandString) {
@@ -189,7 +240,7 @@
 class IncAddressControl : public Command {
   public:
     virtual bool match(const String& name) const {
-      return name.startsWith("inc");
+      return name == "inc";
     }

     virtual void execute(const String& commandString) {
@@ -229,26 +280,40 @@
 class BurnProgramControl : public Command {
   public:
     virtual bool match(const String& name) const {
-      return name.startsWith("burn");
-    }
-
-    virtual void execute(const String& commandString) {
-      if (!programmer->inProgrammingMode()) {
-        Serial.println("ERROR: Programmer not in programming mode");
-      } else {
+      return name == "burn";
+    }
+
+    virtual void execute(const String& commandString) {
+      if (!programmer->inProgrammingMode()) {
+        Serial.println("ERROR: Programmer not in programming mode");
+      } else {
+        StringSplitter splitter(commandString, ' ', 2);
+        const bool numberGiven = splitter.getItemCount() > 1;
+        if (numberGiven) {
+          String parameter = splitter.getItemAtIndex(1);
+          parameter.toLowerCase();
+          const int value = hexToInt(parameter);
+          if (value < 0) {
+            Serial.println("ERROR: Invalid value. Value must be positive >= 0 and <= 3FFF");
+          }
+          programmer->writeWord(value);
+        }
+
         programmer->burn();
       }
     }

     virtual void printHelpString() const {
-      Serial.println("  burn                  burn the program into program memory");
+      Serial.println("  burn [hex-number]     Burns the currently written value into program memory. If");
+      Serial.println("                        hex-number is given, it will write that value into program");
+      Serial.println("                        memory before writing to flash memory.");
     }
 };

 class EraseControl : public Command {
   public:
     virtual bool match(const String& name) const {
-      return name.startsWith("erase");
+      return name == "erase";
     }

     virtual void execute(const String& commandString) {
@@ -269,7 +334,7 @@
 class RewriteChipCommand : public Command {
   public:
     virtual bool match(const String& name) const {
-      return name.startsWith("rewrite");
+      return name == "rewrite";
     }

     virtual void execute(const String& commandString) {
@@ -317,15 +382,18 @@

 void setup() {
   memset(&commands, COMMANDS_SIZE * sizeof(commands[0]), 0);
-  commands[0] = new HelpCommand();
-  commands[1] = new PowerControl();
-  commands[2] = new ProgrammingModeControl();
-  commands[3] = new IncAddressControl();
-  commands[4] = new ReadTextWordControl();
-  commands[5] = new WriteTextWordControl();
-  commands[6] = new BurnProgramControl();
-  commands[7] = new EraseControl();
-  commands[8] = new RewriteChipCommand();
+
+  int i = 0;
+  commands[i++] = new HelpCommand();
+  commands[i++] = new PowerControl();
+  commands[i++] = new ProgrammingModeControl();
+  commands[i++] = new IncAddressControl();
+  commands[i++] = new ReadTextWordControl();
+  commands[i++] = new ReadHexWordControl();
+  commands[i++] = new WriteTextWordControl();
+  commands[i++] = new BurnProgramControl();
+  commands[i++] = new EraseControl();
+  commands[i++] = new RewriteChipCommand();

   Serial.begin(57600);
   Serial.setTimeout(10);
@@ -334,16 +402,22 @@
 }

 void loop() {
-  String cmd = Serial.readStringUntil('\n');
-  cmd.trim();
-  if (cmd.length() > 0) {
+  String cmdline = Serial.readStringUntil('\n');
+  cmdline.trim();
+  if (cmdline.length() > 0) {
+    String cmd;
+    {
+      StringSplitter splitter(cmdline, ' ', 2);
+      cmd = splitter.getItemAtIndex(0);
+    }
+
     bool cmatched = false;
     for (int i = 0; i < COMMANDS_SIZE; i++) {
       if (commands[i] == nullptr) {
         break;
       }
       if (commands[i]->match(cmd)) {
-        commands[i]->execute(cmd);
+        commands[i]->execute(cmdline);
         cmatched = true;
         break;
       }


Update SW01_Altitude_Measurement.ino

Update SW01_Altitude_Measurement.ino

--- examples/SW01_Altitude_Measurement/SW01_Altitude_Measurement.ino
+++ examples/SW01_Altitude_Measurement/SW01_Altitude_Measurement.ino
@@ -63,7 +63,7 @@

 	// Request SW01 to get the altitude measurement and store in
 	// the altitude variable
-	alt = SW01.getAltitude();
+	alt = SW01.getAltitude(101325);

 	// Display the recoreded data over the Serial Monitor
 	Serial.print("Altitude: ");


parse date from http headers

parse date from http headers

--- SmartAlarm.ino
+++ SmartAlarm.ino
@@ -47,8 +47,39 @@

 DateTime now = DateTime(0);

+uint8_t parseMonth (char *mo) {
+  if (!strcmp(mo, "Jan")) {
+    return 1;
+  } else if (!strcmp(mo, "Feb")) {
+    return 2;
+  } else if (!strcmp(mo, "Mar")) {
+    return 3;
+  } else if (!strcmp(mo, "Apr")) {
+    return 4;
+  } else if (!strcmp(mo, "May")) {
+    return 5;
+  } else if (!strcmp(mo, "Jun")) {
+    return 6;
+  } else if (!strcmp(mo, "Jul")) {
+    return 7;
+  } else if (!strcmp(mo, "Aug")) {
+    return 8;
+  } else if (!strcmp(mo, "Sep")) {
+    return 9;
+  } else if (!strcmp(mo, "Oct")) {
+    return 10;
+  } else if (!strcmp(mo, "Nov")) {
+    return 11;
+  } else if (!strcmp(mo, "Dec")) {
+    return 12;
+  } else { // invalid
+    return 0;
+  }
+}
+
 DateTime parseHeader(uint32_t ip, uint16_t port, char *host, char *path) {
-    Adafruit_CC3000_Client www = cc3000.connectTCP(ip, port);
+  // first connect to the site we're gonna leech the datetime from
+  Adafruit_CC3000_Client www = cc3000.connectTCP(ip, port);
   if (www.connected()) {
     www.fastrprint(F("GET "));
     www.fastrprint(path);
@@ -61,9 +92,10 @@
     return NULL;
   }

-  /* Read data until either the connection is closed, or the idle timeout is reached. */
+  // try to read the Date line in the http headers
   char line[256];
   size_t pos = 0;
+  bool wehaveadate = 0;
   unsigned long lastRead = millis();
   while (www.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS)) {
     while (www.available()) {
@@ -76,10 +108,10 @@
             line[1] == 'a' &&
             line[2] == 't' &&
             line[3] == 'e' &&
-            line[4] == ':') { // please fucking refactor this shit
-          Serial.println(line);
+            line[4] == ':') { // seriously? TODO: fix this shit
+          wehaveadate = 1;
         }
-      } else { // if we haven't reached a newline, put it in the buffer
+      } else if (!wehaveadate) { // if we haven't reached a newline, put it in the buffer
         line[pos] = c;
         line[pos + 1] = 0;
         pos++;
@@ -88,7 +120,27 @@
     }
   }
   www.close();
-  Serial.println(F("-------------------------------------"));
+  if (wehaveadate) {
+    // please fucking refactor this shit
+    // this is the fucking worst way to parse shit
+    // TODO: refactor this into an union or something less fucking terrible
+    line[10] = 0; // null after dow
+    line[13] = 0; // null after dom
+    line[17] = 0; // null after month
+    line[22] = 0; // null after year
+    line[25] = 0; // null after hour
+    line[28] = 0; // null after minute
+    line[31] = 0; // null after second
+    char *s_year = line+18;
+    char *s_month = line+14;
+    char *s_day = line+11;
+    char *s_hour = line+23;
+    char *s_minute = line+26;
+    char *s_second = line+29;
+    return DateTime(atoi(s_year), parseMonth(s_month), atoi(s_day), atoi(s_hour), atoi(s_minute), atoi(s_second));
+  } else {
+    return NULL;
+  }

 }

@@ -138,6 +190,18 @@
   }

   now = parseHeader(ip, 80, WEBSITE, WEBPAGE);
+  Serial.print(F("year: "));
+  Serial.println(now.year());
+  Serial.print(F("month: "));
+  Serial.println(now.month());
+  Serial.print(F("day: "));
+  Serial.println(now.day());
+  Serial.print(F("hour: "));
+  Serial.println(now.hour());
+  Serial.print(F("minute: "));
+  Serial.println(now.minute());
+  Serial.print(F("second: "));
+  Serial.println(now.second());
 }

 void loop() {


re-add cast to normal int

re-add cast to normal int

--- MazeSolver/MazeSolver.ino
+++ MazeSolver/MazeSolver.ino
@@ -407,7 +407,7 @@
 	}

 	Serial.print(" linePosition: ");
-	Serial.println(position - 2500);
+	Serial.println((int)position - 2500);
 }

 void printPath()


Prevent same answer again

Prevent same answer again

--- Project_11/Project_11.ino
+++ Project_11/Project_11.ino
@@ -5,7 +5,8 @@
 const int contrastPin = 9;
 int switchState = 0;
 int prevSwitchState = 0;
-int reply;
+int reply = 0;
+int prevReply = 0;

 void setup() {
   Serial.begin(9600);
@@ -23,7 +24,10 @@
   switchState = digitalRead(switchPin);
   if (switchState != prevSwitchState) {
     if (switchState == LOW) {
-      reply = random(8);
+      while (reply == prevReply) {
+        reply = random(8);
+      }
+      prevReply = reply;
       lcd.clear();
       lcd.setCursor(0, 0);
       lcd.print("The ball says:");


TODO-632: *test* dependency on OTAESGCM

TODO-632: *test* dependency on OTAESGCM

The *tests* can depend on OTAESGCM,
but not the main library.

--- test_SECFRAME/test_SECFRAME.ino
+++ test_SECFRAME/test_SECFRAME.ino
@@ -35,6 +35,8 @@
 // Include the library under test.
 #include <OTV0p2Base.h>
 #include <OTRadioLink.h>
+// Also testing against crypto.
+#include <OTAESGCM.h>

 #if F_CPU == 1000000 // 1MHz CPU indicates V0p2 board.
 #define ON_V0P2_BOARD
@@ -96,7 +98,7 @@
   Serial.println("LibVersion");
 #if !(0 == ARDUINO_LIB_OTRADIOLINK_VERSION_MAJOR) || !(9 == ARDUINO_LIB_OTRADIOLINK_VERSION_MINOR)
 #error Wrong library version!
-#endif
+#endif
   }

 // Check that correct versions of underlying libraries are in use.
@@ -105,7 +107,11 @@
   Serial.println("LibVersions");
 #if !(0 == ARDUINO_LIB_OTV0P2BASE_VERSION_MAJOR) || !(9 == ARDUINO_LIB_OTV0P2BASE_VERSION_MINOR)
 #error Wrong library version!
-#endif
+#endif
+
+#if !(0 == ARDUINO_LIB_OTAESGCM_VERSION_MAJOR) || !(2 > ARDUINO_LIB_OTAESGCM_VERSION_MINOR)
+#error Wrong library version!
+#endif
   }


fix esp connection

fix esp connection

--- esp8266/esp8266.ino
+++ esp8266/esp8266.ino
@@ -39,30 +39,6 @@
   Serial.print(WiFi.localIP());
 }

-void reconnect()
-{
-  // Loop until we're reconnected
-  while (!client.connected()) {
-    Serial.print("Attempting MQTT connection...");
-    // Create a random client ID
-    String clientId = "ESP8266Client-";
-    clientId += String(random(0xffff), HEX);
-    // Attempt to connect
-    if (client.connect(clientId.c_str())) {
-      Serial.println("connected");
-      // Once connected, publish an announcement...
-      client.publish(host, "hello world");
-      // ... and resubscribe
-      client.subscribe(host);
-    } else {
-      Serial.print("failed");
-      Serial.println(" try again in 5 seconds");
-      // Wait 5 seconds before retrying
-      delay(5000);
-    }
-  }
-}
-
 void setup_ir()
 {
   Serial.println("Booting IR...");
@@ -82,10 +58,20 @@

 void loop()
 {
-  if (!client.connected()) {
-    reconnect();
+  if (WiFi.status() == WL_CONNECTED) {
+    if (!client.connected()) {
+      if (client.connect("ESP8266: Fountain")) {
+        client.subscribe(host);
+        Serial.print("Connected to ");
+        Serial.println(host);
+      }
+    }
+
+    if (client.connected())
+      client.loop();
+  } else {
+    Serial.println("Wifi not connected");
   }
-  client.loop();
 }

 unsigned int *integerArray(char *str, unsigned int *out_len) {
@@ -106,11 +92,9 @@
   return arr;
 }

-void sendIR(unsigned int *sequence)
+void sendIR(unsigned int *sequence, int len)
 {
   const unsigned int hz = 38;
-  const unsigned int len = sizeof(sequence) / sizeof(sequence[0]);
-
   Serial.print("Sending ");
   Serial.print(len);
   Serial.println(" IR commands");
@@ -130,6 +114,6 @@
   Serial.print("Parsed sequence with length: ");
   Serial.println(len);

-  sendIR(sequence);
+  sendIR(sequence, len);
 }


Improvements to SocketTestMaster

Improvements to SocketTestMaster

--- RS485/SocketTest/SocketTestMaster/SocketTestMaster.ino
+++ RS485/SocketTest/SocketTestMaster/SocketTestMaster.ino
@@ -1,25 +1,33 @@
-#include "EEPROM.h"
+/*
+ * Example of a minimal RS485Socket master
+ */
+
 #include <RS485_non_blocking.h>
 #include <SoftwareSerial.h>
-#include "SPI.h"
-#include "Adafruit_WS2801.h"
-#include "Wire.h"

 #define DEBUG_LEVEL DEBUG_HIGH
 #include "Debug.h"

-#include "GeneralUtils.h"
-#include "EEPromUtils.h"
-#include "HMTLTypes.h"
-#include "PixelUtil.h"
 #include "RS485Utils.h"
-#include "MPR121.h"

-#define PIN_RS485_1     4 // 2 on board v1
+//These headers shouldn't be required:
+//#include "SPI.h"
+//#include "Adafruit_WS2801.h"
+//#include "Wire.h"
+//#include "EEPROM.h"
+//#include "GeneralUtils.h"
+//#include "EEPromUtils.h"
+//#include "HMTLTypes.h"
+//#include "PixelUtil.h"
+//#include "MPR121.h"
+
+#define PIN_RS485_1     2 // 2 on board v1 // 4 on board v2
 #define PIN_RS485_2     7
-#define PIN_RS485_3     5 // 4 on board v1
+#define PIN_RS485_3     4 // 4 on board v1 // 5 on board v2

-RS485Socket rs485(PIN_RS485_1, PIN_RS485_2, PIN_RS485_3, (DEBUG_LEVEL != 0));
+#define DEBUG_PIN 13
+
+RS485Socket rs485(PIN_RS485_1, PIN_RS485_2, PIN_RS485_3, 0);

 #define SEND_BUFFER_SIZE (sizeof (rs485_socket_hdr_t) + 64)
 byte databuffer[SEND_BUFFER_SIZE];
@@ -28,6 +36,7 @@
 void setup()
 {
   Serial.begin(9600);
+  pinMode(DEBUG_PIN, OUTPUT);

   rs485.setup();
   send_buffer = rs485.initBuffer(databuffer);
@@ -37,6 +46,7 @@
 #define DEST_ADDR 1

 byte count = 0;
+boolean debugOn = false;
 void loop()
 {
   send_buffer[0] = 'T';
@@ -46,5 +56,10 @@

   rs485.sendMsgTo(DEST_ADDR, send_buffer, 2);

+  debugOn = !debugOn;
+  if (debugOn)
+    digitalWrite(DEBUG_PIN, HIGH);
+  else
+    digitalWrite(DEBUG_PIN, LOW);
   delay(1000);
 }


Calculate secondsToday only once.

Calculate secondsToday only once.

--- dimmertask.ino
+++ dimmertask.ino
@@ -4,11 +4,11 @@
   {
     if ( !programOverride )
     {
+      struct tm timeinfo;
+      getLocalTime(&timeinfo);
+      time_t secondsToday = ( timeinfo.tm_hour * 3600 ) + ( timeinfo.tm_min * 60 ) + timeinfo.tm_sec;
       for ( byte thisChannel = 0; thisChannel < NUMBER_OF_CHANNELS; thisChannel++ )
       {
-        struct tm timeinfo;
-        getLocalTime(&timeinfo);
-        time_t secondsToday = ( timeinfo.tm_hour * 3600 ) + ( timeinfo.tm_min * 60 ) + timeinfo.tm_sec;
         setPercentageFromProgram( thisChannel, secondsToday );
       }
     }


Removed routines replaced by stdlib code

--- DigitalVFO.ino
+++ DigitalVFO.ino
@@ -408,7 +408,7 @@
 void banner(void)
 {
   show_credits(false);
-  delay(900);    // wait a bit
+  delay(800);    // wait a bit

   // do a fade out, clear screen then normal brightness
   for (int i = LcdBrightness; i; --i)
@@ -428,7 +428,7 @@
 //     value    the Frequency value to convert
 // The function won't overflow the given buffer, it will truncate at the left.
 // For example, given the value 1234 and a buffer of length 7, will fill the
-// buffer with 0001234.  Given 123456789 it will fill with 3456789.
+// buffer with 0001234.  Given 123456789 and length 7 it will fill with 3456789.
 //
 // Each byte in the buffer is a number in [0, 9], NOT ['0', '9'].
 // The resultant buffer does NOT have a terminating '\0'!
@@ -445,77 +445,6 @@
     value = value / 10;
     *ptr-- = char(rem);     // FIXME: don't require char()?
   }
-}
-
-//----------------------------------------
-// Function to convert an unsigned long into a string.
-//     buf      address of buffer for byte results
-//     bufsize  the size of the buffer
-//     value    the unsigned long value to convert to a string
-// The buffer 'buf' is assumed long enough and is '\0' terminated.
-// Return address of first char in the string.
-//----------------------------------------
-
-char * ulong2str(char *buf, int bufsize, ULONG value)
-{
-  char *ptr = buf + bufsize - 1;    // rightmost char in 'buf'
-
-  if (value == 0L)
-  {
-    *ptr-- = '0';
-  }
-  else
-  {
-    while (value)
-    {
-      int rem = value % 10;
-
-      value = value / 10;
-      *ptr-- = rem + '0';
-    }
-  }
-
-  return ++ptr;
-}
-
-//----------------------------------------
-// Function to convert an array of byte digit values into an unsigned long.
-//     buf  address of buffer of byte digits, terminated with '\n'
-// Returns the unsigned long value.
-//----------------------------------------
-
-ULONG buff2ulong(char *buf)
-{
-  ULONG result = 0;
-
-  while (*buf)
-  {
-    result *= 10;
-    result += *buf;
-    ++buf;
-  }
-
-  return result;
-}
-
-//----------------------------------------
-// Function to convert a string into an unsigned long.
-//     str  start of string of digits, terminated with '\0'
-// Returns the unsigned long value.
-//----------------------------------------
-
-ULONG str2ulong(char *str)
-{
-  ULONG result = 0;
-
-  while (*str)
-  {
-    result *= 10;
-    result += *str - '0';
-    ++str;
-  }
-
-  return result;
 }

 //----------------------------------------
@@ -692,8 +621,8 @@
       // return VFO frequency
       if (strlen(cmd) == 3)
       {
-        FreqBuffer[FreqBufferLen-1] = '\0';
-        return ulong2str(FreqBuffer, FreqBufferLen-2, VfoFrequency);
+        sprintf(FreqBuffer, "%ld", VfoFrequency);
+        return FreqBuffer;
       }
       break;
     case 'S':
@@ -710,8 +639,7 @@
             return "ERROR";
           }
         }
-        *freq_ptr = '\0';    // remove terminating ';'
-        VfoFrequency = str2ulong(cmd+2);
+        VfoFrequency = strtol(cmd + 2, NULL, 10);
         display_sel_value(VfoFrequency, VfoSelectDigit, NumFreqChars,
                           NumCols - NumFreqChars - 2, 0);
         return "OK";


Define 'audio_settings' in BasicGain_wApp

--- examples/06-AppTutorial/BasicGain_wApp/BasicGain_wApp.ino
+++ examples/06-AppTutorial/BasicGain_wApp/BasicGain_wApp.ino
@@ -30,6 +30,11 @@

 //here are the libraries that we need
 #include <Tympan_Library.h>  //include the Tympan Library
+
+//set the sample rate and block size
+const float sample_rate_Hz = 44100.0f ; //24000 or 44100 (or 44117, or other frequencies in the table in AudioOutputI2S_F32)
+const int audio_block_samples = 32;     //do not make bigger than AUDIO_BLOCK_SAMPLES from AudioStream.h (which is 128)
+AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples);

 //create audio library objects for handling the audio
 Tympan                    myTympan(TympanRev::E, audio_settings);     //do TympanRev::D or TympanRev::E


Clean up.

Clean up.

--- examples/Benchmarks/CosaBenchmarkRTC/CosaBenchmarkRTC.ino
+++ examples/Benchmarks/CosaBenchmarkRTC/CosaBenchmarkRTC.ino
@@ -56,6 +56,9 @@
   TRACE(Watchdog::ms_per_tick());
   TRACE(Watchdog::ticks());
   TRACE(RTC::us_per_tick());
+  TRACE(RTC::us_per_timer_cycle());
+  TRACE(RTC::micros());
+  TRACE(RTC::millis());
   TRACE(RTC::seconds());

   // Measure baseline


Update rx5808-pro-diversityGc9n.ino

Update rx5808-pro-diversityGc9n.ino

--- rx5808-pro-diversityGc9n/rx5808-pro-diversityGc9n.ino
+++ rx5808-pro-diversityGc9n/rx5808-pro-diversityGc9n.ino
@@ -830,9 +830,8 @@
         else
         {
           //delay(KEY_DEBOUNCE); // debounce
-          //state = STATE_SCREEN_SAVER;
-           drawScreen.screenSaver(diversity_mode, pgm_read_byte_near(channelNames + channelIndex), pgm_read_word_near(channelFreqTable + channelIndex), call_sign);
-          // drawScreen.updateScreenSaver(active_receiver, rssi, readRSSI(useReceiverA), readRSSI(useReceiverB));
+           state = STATE_SCREEN_SAVER;
+
         }// IF YOU HAVE FAVS

     }


Make the DHT22 work with a clock frequency of 8MHz by playing with the undocumented _counter variable in the constructor.

Before, the sensor would return 0 for temperature and humidity because the timing (based on the clock speed) was off.
Use _counter to adapt for different clock speeds. I didn't have any luck when running with 1Mhz - maybe a oscilloscope would help here.

I modified the boards.txt to run the Sensor328p with 8MHz:
s328o1.name=Sensor328p (int1MHz, 1.8V, devduino v2)
s328o1.upload.protocol=arduino
s328o1.upload.maximum_size=30720
s328o1.upload.speed=19200
s328o1.bootloader.low_fuses=0x62
s328o1.bootloader.high_fuses=0xda
s328o1.bootloader.extended_fuses=0x06
s328o1.bootloader.path=atmega
s328o1.bootloader.file=ATmegaBOOT_168_atmega328_pro_8MHz.hex
s328o1.bootloader.unlock_bits=0x3F
s328o1.bootloader.lock_bits=0x0F
s328o1.build.mcu=atmega328p
s328o1.build.f_cpu=8000000L
s328o1.build.core=arduino
s328o1.build.variant=standard

--- sensorNode/sensorNode.ino
+++ sensorNode/sensorNode.ino
@@ -2,7 +2,6 @@
   Sensor node
   Gather temperature and humidity and send them to a master node
 */
-
 #include <DHT.h>
 #include <SPI.h>
 #include <RF24Network.h>
@@ -23,16 +22,19 @@
 const uint16_t otherNode = 0;

 // Init DHT22 sensor
-DHT dht(DHT22_PIN, DHTTYPE);
+DHT dht(DHT22_PIN, DHTTYPE, 3);
+

 ISR(WDT_vect) { Sleepy::watchdogEvent(); }

 void blink(int times) {
   for(int i=0; i<times; i++) {
      digitalWrite(LED_PIN, HIGH);
-     delay(5000);
+     delay(1000);
      digitalWrite(LED_PIN, LOW);
-     delay(5000);
+     if (i<times) {
+       delay(1000);
+     }
   }
 }

@@ -69,9 +71,7 @@
     sei();
 }

-void setup () {
-  setPrescaler(4); // Reduce clock speed to 1 MHz
-
+void setup () {
   // LED
   pinMode(LED_PIN, OUTPUT);
   // button
@@ -96,19 +96,20 @@
 void loop() {
   // pump network
   network.update();
-  setPrescaler(0);  // Reset clock speed to 16 MHz to get a reliable reading from the sensors
+  setPrescaler(0);  // Reset clock speed to 8 MHz to get a reliable reading from the sensors

   // Reading temperature or humidity takes about 250 milliseconds!
   // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
   float t = dht.readTemperature();
   float h = dht.readHumidity();
-
-  setPrescaler(4);  // Reduce clock speed back to 1 MHz
+
+  setPrescaler(3);  // Reduce clock speed back to 1 MHz while sending data and sleeping
   // TODO: Read the internal temperature sensor MCP9700 connected to A3?

   // check if returns are valid, if they are NaN (not a number) then something went wrong!
   if (isnan(t) || isnan(h)) {
       Serial.println("Failed to read from DHT");
+      blink(2);
   }
   else {
     long voltage = readVcc();
@@ -137,7 +138,7 @@
     radio.powerDown();

     // sleep for 30 minutes
-    for (byte i = 0; i < 30; ++i) {
+    for (byte i = 0; i < 15; ++i) {
         Sleepy::loseSomeTime(60000);
     }


Adapt ground code to trigger TX after RX, including received packet index.

--- software/XTendGroundTeensy/XTendGroundTeensy.ino
+++ software/XTendGroundTeensy/XTendGroundTeensy.ino
@@ -17,7 +17,7 @@
 String msgIn = "";

 int numb = 0;
-IntervalTimer txTimer;
+//IntervalTimer txTimer;

 void setup(){
   Serial.begin(9600);
@@ -28,7 +28,7 @@
   sentenceRdy = false;
   sentence[0] = 0;
   sentenceIndex = 0;
-  txTimer.begin(transmit, 10000000);
+  //txTimer.begin(transmit, 10000000);
   pinMode(5,INPUT_PULLUP);
   while( !Serial1 );
   while( !Serial2 );
@@ -56,6 +56,7 @@
       Serial.println( msgIn );
       rcvdNum = (int)msgIn.substring(1 + msgIn.indexOf(' ')).toInt();
       msgIn = "";
+      txFlag = true; //Set up to transmit response after RX
     }else{
       msgIn += lastChar;
     }
@@ -107,8 +108,8 @@
       i++;
     }
   }
-
-  printAndSendString( " " + (String)numb ); //also puts the 0 at the end of TX string
+
+  printAndSendString( " " + (String)rcvdNum ); //also puts the 0 at the end of TX string
   printAndSendChar( 10 );
 }

@@ -149,6 +150,7 @@
 void printDigits(int digits){
   // utility function for digital clock display: prints preceding colon and leading 0
   Serial.print(":");
-  if(digits < 10) Serial.print('0');
+  if(digits < 10)
+    Serial.print('0');
   Serial.print(digits);
-}+}


sms command read function

sms command read function

--- sms_thermo/sms_thermo.ino
+++ sms_thermo/sms_thermo.ino
@@ -11,11 +11,10 @@
 SoftwareSerial SIM900 (10, 11);                   //SIM900 is connected to 10 & 11 PINs RX, TX
 #define ONE_WIRE_BUS 13                           //Dallas OneWire sensors is connected to 13 PIN

-String phone_number[] =   {"+79000000000"};       // Phone number for SMS notification
 int HighAlarmTemp[] =     {28, 28, 28, 28};       // Highest temperature when user is notificated
 int DestroyAlarmTemp[] =  {60, 60, 60, 60};       // Temperature used to make forecast
 int LowAlarmTemp[] =      { -28, -28, -28, -28};  // Lowest thmperature when user is notificated
-                                // Set total connected sensors
+// Set total connected sensors

 String textForSMS;
 String last_alarm_time;
@@ -25,7 +24,7 @@

 int monPeriod1Len = 600;                              // 10 minutes
 int monPeriod2Len = 36000;                             // 60 minutes
-int monPeriod3Len = 21600;                            // 12 hours
+int monPeriod3Len = 21600;                            // 12 hours

 long count_t1,        count_t2,       count_t3;
@@ -316,7 +315,7 @@
       tt1mTrend[i] = (tt1m[i] - tt1mLast[i]) / count_t1;
       tt1mLast[i] = tt1m[i];
       tt1m[i] = 0;
-      if (debug)
+      if (debug)
       {
         Serial.print("[DBG] TREND "); Serial.print(i); Serial.print(":"); Serial.println(tt1mTrend[i]);
         Serial.print("[DBG] TTL: "); Serial.println( makeForecast(i) );
@@ -352,7 +351,7 @@
       tt3m[i] = 0;
     }
   }
-
+
   for (int i = 0; i < sizeof(thermalSensor) / sizeof(DeviceAddress); i++)
   {

@@ -525,20 +524,81 @@
   return true;
 }

+
+String readSMS(int smsID, bool debug)
+{
+  bool isMsgExists;
+  String readString;
+  String resultString;
+
+  SIM900.print("AT+CMGR=2AT+CMGR="); SIM900.println(smsID);
+  while (SIM900.available() > 0)
+  { char inchar = SIM900.read();
+    readString += inchar;
+    delay(10);
+  }
+  if (debug) {
+    Serial.print("[DBG] readSMSreadSMS AT+CMGR=2AT+CMGR=AT+CMGR=2AT+CMGR= return:");
+    Serial.print(readString);
+    readString = "";
+  }
+
+  for (int i = 0; i < 200; i++)
+  {
+    for (int j = 0; j < sizeof(phone_number); j++)
+    {
+      if (readString.substring(i, i + 12) == phone_number[j])
+      {
+        isMsgExists = true;
+        if (debug) {
+          Serial.print("FOUND:");
+          Serial.println(readString.substring(i, i + 12));
+        }
+      }
+      if (isMsgExists)
+      {
+        for (int k = i; k < 200 - i; k++)
+        {
+          if (readString.substring(k, k + 4) == "CMD:")
+          {
+            resultString = String(readString.substring(k + 4));
+            if (debug) {
+              Serial.print("COMMAND:");
+              Serial.println(readString.substring(k + 4));
+            }
+          }
+        }
+      }
+    }
+  }
+  return readString;
+}
+
+void execRemoteCommand ()
+{
+  String cmdLine;
+  for (int i = 1; i <= 15; i++)
+  {
+    cmdLine = String(readSMS(i, true));
+    Serial.println(cmdLine);
+  }
+}
+
 // main loop
 void loop()
 {

   sensors.requestTemperatures(); // Send the command to get temperatures
-  updateStats(true);
+  updateStats(false);

   for (int i = 0; i < sizeof(thermalSensor) / sizeof(DeviceAddress); i++)
   {
-    Serial.println(getData(thermalSensor[i]));
-
-  }
-
+  //  Serial.println(getData(thermalSensor[i]));
+
+  }
+
+  execRemoteCommand();
   //printAlarms(t0); // Вывод пороговых значений на экран
-  delay(3000);  // задержка проверки
+  delay(30000);  // задержка проверки
   //getNetworkStatus(false); Serial.println(toProgressBar(2, 30, gsm_signal)); // Network signal quality print
 }


Cleanup state handling, error reporting.

--- test/PoE-test/spacedeur-asis-2017/spacedeur-asis-2017.ino
+++ test/PoE-test/spacedeur-asis-2017/spacedeur-asis-2017.ino
@@ -29,18 +29,21 @@

 #define DOOR_CLOSED       (0)
 #define DOOR_OPEN         (1100)
+
 #define DOOR_OPEN_DELAY   (10*1000)

 #define REPORTING_PERIOD  (300*1000)

-typedef enum doorstates { CLOSED, OPENING, OPEN, CLOSING } doorstate_t;
+typedef enum doorstates { CLOSED, CHECKINGCARD, OPENING, OPEN, CLOSING } doorstate_t;
 doorstate_t doorstate;
 unsigned long long last_doorstatechange = 0;

-long cnt_cards = 0, cnt_opens = 0, cnt_closes  = 0, cnt_fails = 0, cnt_misreads = 0, cnt_minutes = 0, cnt_reconnects = 0;
+long cnt_cards = 0, cnt_opens = 0, cnt_closes  = 0, cnt_fails = 0, cnt_misreads = 0, cnt_minutes = 0, cnt_reconnects = 0, cnt_mqttfails = 0;

 #include <ETH.h>
 #include <SPI.h>
+#include <SPIFFS.h>
+#include <FS.h>

 #include <ArduinoOTA.h>
 #include <AccelStepper.h>
@@ -74,11 +77,15 @@
 const char mqtt_host[] = "space.vijn.org";
 const unsigned short mqtt_port = 1883;

+extern void callback(char* topic, byte * payload, unsigned int length);
+
+bool caching = false;
+
 #define PREFIX "test/"

 const char rfid_topic[] = PREFIX "deur/space2/rfid";
 const char door_topic[] = PREFIX "deur/space2/open";
-const char log_topic[] = PREFIX "log";
+const char log_topic[] =  PREFIX "log";

 WiFiClient wifiClient;
 PubSubClient client(wifiClient);
@@ -120,7 +127,7 @@
     client.publish(log_topic, buff);
     client.loop();

-    // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
+    SPIFFS.end();
   });

   ArduinoOTA.onEnd([]() {
@@ -294,9 +301,116 @@
   doorstate = CLOSED;
   last_doorstatechange = millis();

+  Serial.println("SPIFF setup");
+  if (!SPIFFS.begin()) {
+    Serial.println("SPIFFS Mount Failed - reformatting");
+    wipeCache();
+  } else {
+    caching = true;
+    listDir(SPIFFS, "/", "");
+  };
+
   Serial.println("setup() done.\n\n");
 }

+// This function is taken from the SPIFFS_Test example. Under the expressif ESP32 license.
+//
+void listDir(fs::FS &fs, const char * dirname, String prefix) {
+  Serial.print(prefix);
+  Serial.println(dirname);
+
+  File root = fs.open(dirname);
+  if (!root) {
+    Serial.println("Failed to open directory");
+    return;
+  }
+  if (!root.isDirectory()) {
+    Serial.println("Not a directory");
+    return;
+  }
+
+  File file = root.openNextFile();
+  while (file) {
+    if (file.isDirectory()) {
+      listDir(fs, file.name(), prefix + " ");
+    } else {
+      Serial.print(prefix + " ");
+      Serial.println(file.name());
+    }
+    file = root.openNextFile();
+  }
+  root.close();
+}
+
+void wipeCache() {
+  caching = false;
+
+  if (!SPIFFS.format()) {
+    Serial.println("SPIFFS formatting failed.");
+    return;
+  }
+
+  Serial.println("Formatted.");
+  if (!SPIFFS.begin()) {
+    Serial.println("SPIFFS mount after formatting failed.");
+    return;
+  };
+
+  for (int i = 0; i < 255; i++)
+    SPIFFS.mkdir(String(i));
+
+  Serial.println("Directory structure created.");
+  listDir(SPIFFS, "/", "");
+  caching = true;
+};
+
+String uid2path(MFRC522::Uid uid) {
+  String path = "/uid-";
+  for (int i = 0; i < uid.size; i++) {
+    path += String(uid.uidByte[i], DEC);
+    if (i == 0)
+      path += "/";
+    else
+      path += ".";
+  };
+  return path;
+}
+
+bool checkCache(MFRC522::Uid uid) {
+  String path = uid2path(uid) + ".lastOK";
+  return SPIFFS.exists(path);
+}
+
+void setCache(MFRC522::Uid uid, bool ok) {
+  String path = uid2path(uid) + ".lastOK";
+  if (ok) {
+    File f = SPIFFS.open(path, "w");
+    f.println(cnt_minutes);
+    f.close();
+  } else {
+    SPIFFS.remove(path);
+  }
+}
+
+void openDoor() {
+  doorstate = OPENING;
+  stepper.moveTo(DOOR_OPEN);
+};
+
+bool isOpen() {
+  return stepper.currentPosition() == DOOR_OPEN; // no sensors.
+}
+
+void closeDoor() {
+  stepper.moveTo(DOOR_CLOSED);
+  doorstate = CLOSING;
+}
+
+bool isClosed() {
+  return stepper.currentPosition() == DOOR_CLOSED; // no sensors.
+}
+
+MFRC522::Uid uid;

 void callback(char* topic, byte * payload, unsigned int length) {
   char buff[256];
@@ -307,7 +421,7 @@
     // risk of (amplification) loops due to a misconfiguration. We do increase the counter
     // so indirectly this does show up in the MQTT log.
     //
-    cnt_fails ++;
+    cnt_mqttfails ++;
     return;
   };

@@ -319,26 +433,68 @@
   };
   buff[l] = 0;

+  if (!strcmp(buff, "reboot")) {
+    ESP.restart();
+    return;
+  }
+
+  if (!strcmp(buff, "report")) {
+    reportStats();
+    return;
+  }
+
+  if (!strcmp(buff, "purge")) {
+    char msg[255];
+    wipeCache();
+
+    snprintf(msg, sizeof(msg), "[%s] Purged cache.", pname);
+    client.publish(log_topic, msg);
+    Serial.println(msg);
+
+    return;
+  }
+
   if (!strcmp(buff, "open")) {
-    doorstate = OPENING;
     Serial.println("Opening door.");
-
-    stepper.moveTo(DOOR_OPEN);
-    return;
-  };
-
-  snprintf(buff, sizeof(buff), "[%s] Cannot parse reply <%s> [len = %d, payload len = %d] or denied access.",
+    openDoor();
+    if (caching && uid.size)
+      setCache(uid, true);
+    uid.size = 0;
+    return;
+  };
+
+  if (caching)
+    setCache(uid, false);
+  uid.size = 0;
+
+  char msg[256];
+  snprintf(msg, sizeof(msg), "[%s] Cannot parse reply <%s> [len = %d, payload len = %d] or denied access.",
            pname, buff, l, length);

+  client.publish(log_topic, msg);
+  Serial.println(msg);
+
+  cnt_mqttfails ++;
+}
+
+void reportStats() {
+  char buff[255];
+  snprintf(buff, sizeof(buff),
+           "[%s] alive - uptime %02ld:%02ld: "
+           "swipes %ld, opens %ld, closes %ld, fails %ld, mis-swipes %ld, mqtt reconnects %ld, mqtt fails %ld, stepper %s at %ld (target %ld)",
+           pname, cnt_minutes / 60, (cnt_minutes % 60),
+           cnt_cards,
+           cnt_opens, cnt_closes, cnt_fails, cnt_misreads, cnt_reconnects, cnt_mqttfails,
+           stepper.run() ? "running" : "halted", stepper.currentPosition(), stepper.targetPosition()
+          );
   client.publish(log_topic, buff);
   Serial.println(buff);
-
-  cnt_fails ++;
-}
+}
+

 void loop()
 {
-  bool is_moving = stepper.run();
+  stepper.run();

   if (eth_connected) {
     if (ota)
@@ -365,8 +521,17 @@

   static doorstate_t lastdoorstate = CLOSED;
   switch (doorstate) {
+    case CHECKINGCARD:
+      if (millis() - last_doorstatechange > 1500 && caching && checkCache(uid)) {
+        char msg[255];
+        snprintf(msg, sizeof(msg), "[%s] Allowing door to open based on cached information.", pname);
+        Serial.println(msg);
+        client.publish(log_topic, msg);
+        openDoor();
+      }
+      break;
     case OPENING:
-      if (!is_moving) {
+      if (isOpen()) {
         char msg[256];
         snprintf(msg, sizeof(msg), "[%s] Door is open.", pname);
         Serial.println(msg);
@@ -378,11 +543,10 @@
     case OPEN:
       if (millis() - last_doorstatechange > DOOR_OPEN_DELAY) {
         Serial.println("Closing door.");
-        stepper.moveTo(DOOR_CLOSED);
-        doorstate = CLOSING;
+        closeDoor();
       };
     case CLOSING:
-      if (!is_moving) {
+      if (isClosed()) {
         char msg[256];
         snprintf(msg, sizeof(msg), "[%s] Door is closed.", pname);
         Serial.println(msg);
@@ -392,6 +556,9 @@
       };
       break;
     case CLOSED:
+      if (!isClosed()) {
+        /// some alerting ? clearly a bug ?
+      }
     default:
       break;
   };
@@ -401,24 +568,28 @@
     last_doorstatechange = millis();
   }

+  // catch any logic errors or strange cases where the door is open while we think
+  // we are not doing anything.
+  //
+  if ((millis() - last_doorstatechange > 10 * DOOR_OPEN_DELAY) && ((doorstate != CLOSED) || (!isClosed()))) {
+    closeDoor();
+    char msg[256];
+    snprintf(msg, sizeof(msg), "[%s] Door in an odd state - forcing close.", pname);
+    Serial.println(msg);
+    client.publish(log_topic, msg);
+    cnt_fails ++;
+  }
+
   if (millis() - tock  > REPORTING_PERIOD) {
     char buff[1024];
     cnt_minutes += ((millis() - tock) + 500) / 1000 / 60;
-
-    snprintf(buff, sizeof(buff),
-             "[%s] alive - uptime %02ld:%02ld: "
-             "swipes %ld, opens %ld, closes %ld, fails %ld, mis-swipes %ld, mqtt reconnects %ld",
-             pname, cnt_minutes / 60, (cnt_minutes % 60),
-             cnt_cards,
-             cnt_opens, cnt_closes, cnt_fails, cnt_misreads, cnt_reconnects);
-    client.publish(log_topic, buff);
-    Serial.println(buff);
+    reportStats();
     tock = millis();
   }

   if (irqCardSeen) {
     if (mfrc522.PICC_ReadCardSerial()) {
-      MFRC522::Uid uid = mfrc522.uid;
+      uid = mfrc522.uid;
       cnt_cards++;

       String uidStr = "";
@@ -431,6 +602,8 @@
       char msg[256];
       snprintf(msg, sizeof(msg), "[%s] Tag <%s> (len=%d) swiped", pname, uidStr.c_str(), uid.size);
       client.publish(log_topic, msg);
+
+      doorstate = CHECKINGCARD;
     } else {
       Serial.println("Misread.");
       cnt_misreads++;


Move motor control pin so it doesn't interfere with the SPI lines used by the SD card.

--- fed-arduino/fed-arduino.ino
+++ fed-arduino/fed-arduino.ino
@@ -40,8 +40,8 @@
 const int MOTOR_INPUT4_PIN = 4;
 const int steps = 64;
 const int MOTOR_STEPS_PER_REVOLUTION = 512;
-const int MOTOR_ENABLE12_PIN = 8;
-const int MOTOR_ENABLE34_PIN = 11;
+const int MOTOR_ENABLE34_PIN = 8;
+const int MOTOR_ENABLE12_PIN = 0;
 const int TTL = 3;

@@ -312,4 +312,5 @@
   LEDserial.print(value);
 }

+


Add support for motors and servos

Add support for motors and servos


added support sensor

added support sensor

--- src/main.ino
+++ src/main.ino
@@ -10,34 +10,34 @@

 // SETUP //
 void setup() {
+  // Attach motor variables to digital pin
   m1.attach(2);
   m2.attach(3);
   m3.attach(4);
   m4.attach(5);
   m5.attach(6);
+
+  // Set EMG pin to input
+  pinMode(A0, INPUT);
 }

 // LOOP //
 void loop() {
-  m1.write(0);
-  delay(500);
-  m1.write(180);
-  delay(500);
+  int emg = analogRead(A0);
+
+  switch (emg) {
+    case 70:
+      pinch();
+    case 81:
+      thumbsUp();
+    case 60:
+      middleFinger();
+  }
 }

 // FUNCTIONS //
-void blink(int howManyTimes) {
-  int i;
-  for (i = 0; i < howManyTimes; i++) {
-    digitalWrite(LED_BUILTIN, HIGH);
-    delay(200);
-    digitalWrite(LED_BUILTIN, LOW);
-    delay(200);
-  }
-}
-
 void pinch() {
   m1.write(90);
   m2.write(90);
@@ -53,3 +53,11 @@
   m4.write(180);
   m5.write(180);
 }
+
+void middleFinger() {
+  m1.write(180);
+  m2.write(180);
+  m3.write(0);
+  m4.write(180);
+  m5.write(180);
+}


implement second 1-wire network

implement second 1-wire network

--- src/rf24remotetemp.ino
+++ src/rf24remotetemp.ino
@@ -18,18 +18,23 @@
   float temp;
 } Reading;

-// Data wire is plugged into pin 7 on the Arduino
-#define ONE_WIRE_BUS 8
+// 1-wire busses on arduino D7 and D8
+#define ONE_WIRE_BUS_A 7
+#define ONE_WIRE_BUS_B 8
 #define TEMPERATURE_PRECISION 9

-// Setup a oneWire instance
-OneWire oneWire(ONE_WIRE_BUS);
-DallasTemperature sensors(&oneWire);
-DeviceAddress onewire_addresses[10];
-int sensorcount = 0;
+// Setup two oneWire instances
+OneWire oneWireA(ONE_WIRE_BUS_A);
+OneWire oneWireB(ONE_WIRE_BUS_B);
+DallasTemperature sensorsA(&oneWireA);
+DallasTemperature sensorsB(&oneWireB);
+DeviceAddress onewire_addressesA[10];
+DeviceAddress onewire_addressesB[10];
+int sensorcountA = 0;
+int sensorcountB = 0;

 // Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 9 & 10
-// ghpi rf24remote boards have ce and csn reversed
+// ghpi rf24remote boards have ce and csn reversed so use 10 & 9
 RF24 radio(10,9);

 byte rf_addresses[][6] = {"1Node","2Node"};
@@ -61,18 +66,25 @@
   printf_begin();
   printf("rF24RemoteTemp starting\n\r");

-  printf("1-wire startup ... ");
-  sensors.begin();
+  printf("1-wire A startup ... ");
+  sensorsA.begin();
   Serial.print("found ");
-  sensorcount = sensors.getDeviceCount();
-  Serial.print(sensorcount, DEC);
+  sensorcountA = sensorsA.getDeviceCount();
+  Serial.print(sensorcountA, DEC);
   Serial.println(" devices.");
-
-  // find 1-wire slave addresses
-  oneWire.reset_search();
-  for (int devidx = 0; devidx < sensorcount; devidx++)
-  {
-    if (!oneWire.search(onewire_addresses[devidx]))
+
+  printf("1-wire B startup ... ");
+  sensorsB.begin();
+  Serial.print("found ");
+  sensorcountB = sensorsB.getDeviceCount();
+  Serial.print(sensorcountB, DEC);
+  Serial.println(" devices.");
+
+  // find 1-wire A slave addresses
+  oneWireA.reset_search();
+  for (int devidx = 0; devidx < sensorcountA; devidx++)
+  {
+    if (!oneWireA.search(onewire_addressesA[devidx]))
     {
       Serial.print("Unable to find address for device ");
       Serial.println(devidx);
@@ -80,10 +92,29 @@
       Serial.print("1-wire device ");
       Serial.print(devidx);
       Serial.print(" address ");
-      Serial.print(getAddr(onewire_addresses[devidx]));
+      Serial.print(getAddr(onewire_addressesA[devidx]));
       Serial.println(" ");
-      // configure sensor
-      sensors.setResolution(onewire_addresses[devidx], TEMPERATURE_PRECISION);
+      // configure sensors
+      sensorsA.setResolution(onewire_addressesA[devidx], TEMPERATURE_PRECISION);
+    }
+  }
+
+  // find 1-wire B slave addresses
+  oneWireB.reset_search();
+  for (int devidx = 0; devidx < sensorcountB; devidx++)
+  {
+    if (!oneWireB.search(onewire_addressesB[devidx]))
+    {
+      Serial.print("Unable to find address for device ");
+      Serial.println(devidx);
+    } else {
+      Serial.print("1-wire device ");
+      Serial.print(devidx);
+      Serial.print(" address ");
+      Serial.print(getAddr(onewire_addressesB[devidx]));
+      Serial.println(" ");
+      // configure sensors
+      sensorsA.setResolution(onewire_addressesB[devidx], TEMPERATURE_PRECISION);
     }
   }

@@ -102,11 +133,11 @@

 // main loop
 void loop(void){
-  if (sensorcount)
-  {
-    // update sensor array
-    sensors.requestTemperatures();
-    for (int devidx = 0; devidx < sensorcount; devidx++)
+  if (sensorcountA || sensorcountB)
+  {
+    // update 1-wire A
+    sensorsA.requestTemperatures();
+    for (int devidx = 0; devidx < sensorcountA; devidx++)
     {
       String output;
       char outbuf[31];
@@ -116,9 +147,38 @@
       delay(2000);

       // build the output string as addr:temp.xx
-      output = getAddr(onewire_addresses[devidx]);
+      output = getAddr(onewire_addressesA[devidx]);
       output += ":";
-      float tempf = getTempF(onewire_addresses[devidx]);
+      float tempC = sensorsA.getTempC(onewire_addressesA[devidx]);
+      float tempf = DallasTemperature::toFahrenheit(tempC);
+      dtostrf(tempf, 3, 2, floatbuf);
+      output = output + String(floatbuf);
+      Serial.println(output);
+
+      // transmit the data
+      output.toCharArray(outbuf, (output.length() + 1));
+      radio.write(&outbuf, sizeof(outbuf));
+
+      // sleep a bit
+      Narcoleptic.delay(4000);
+    }
+
+    // update 1-wire B
+    sensorsB.requestTemperatures();
+    for (int devidx = 0; devidx < sensorcountB; devidx++)
+    {
+      String output;
+      char outbuf[31];
+      char floatbuf[7];
+
+      // wait for the sensor reply
+      delay(2000);
+
+      // build the output string as addr:temp.xx
+      output = getAddr(onewire_addressesB[devidx]);
+      output += ":";
+      float tempC = sensorsB.getTempC(onewire_addressesB[devidx]);
+      float tempf = DallasTemperature::toFahrenheit(tempC);
       dtostrf(tempf, 3, 2, floatbuf);
       output = output + String(floatbuf);
       Serial.println(output);


Fixed: examples/Fading/Fading.ino

Fixed: examples/Fading/Fading.ino

--- examples/Fading/Fading.ino
+++ examples/Fading/Fading.ino
@@ -15,20 +15,24 @@

  This example code is in the public domain.

+ ----------------------------------------------
+ Modifed by Valeriy V Dmitriev aka Valmat
+ As an example to the Pino library
+
  */

+#include <Pino.h>

-int ledPin = 9;    // LED connected to digital pin 9

-void setup() {
-  // nothing happens in setup
-}
+Pino led = 9;   // LED connected to digital pin 9
+
+void setup() {}

 void loop() {
   // fade in from min to max in increments of 5 points:
   for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {
     // sets the value (range from 0 to 255):
-    analogWrite(ledPin, fadeValue);
+    led.write(fadeValue);
     // wait for 30 milliseconds to see the dimming effect
     delay(30);
   }
@@ -36,7 +40,7 @@
   // fade out from max to min in increments of 5 points:
   for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {
     // sets the value (range from 0 to 255):
-    analogWrite(ledPin, fadeValue);
+    led.write(fadeValue);
     // wait for 30 milliseconds to see the dimming effect
     delay(30);
   }


update example

update example

--- examples/simple/simple.ino
+++ examples/simple/simple.ino
@@ -1,27 +1,13 @@
+#include <ADC.h>
 #include <t3_vdd.h>
-
-ADC* pAdc;
+ADC adc;

 void setup() {
-  pAdc = new ADC();
-  t3_Vdd vdd;
-  vdd.begin(pAdc);
-
-  elapsedMillis vddTimer;
-  const uint16_t vdd_update_period = 1000;
-  while(1)
-  {
-    if (vddTimer >= vdd_update_period)
-    {
-      vdd.update();
-      Serial.print("vdd = ");
-      Serial.print(vdd.get_mV());
-      Serial.println(" mv");
-      vddTimer = 0;
-    }
-  }
+  t3_vdd::enable_vref();
 }

 void loop() {
-  // put your main code here, to run repeatedly:
+  uint16_t mv = t3_vdd::measure_vdd_mV(adc);
+  Serial.printf("vdd: %04d mV\n", mv);
+  delay(500);
 }


Update main.ino

Update main.ino

--- main/main.ino
+++ main/main.ino
@@ -177,7 +177,7 @@
   // Prepair message
   message.id = 5E8;
   message.header.rtr = 0;
-  message.header.length = 11;
+  message.header.length = 8;
   message.data[0] = 0x02;
   message.data[1] = 0x01;
   message.data[2] = 0x5e8; //MegaSquirt base identifier


yaw/pitch/roll all now are [0,1] output

yaw/pitch/roll all now are [0,1] output

--- code/ESP8266_OSCExample/ESP8266_OSCExample/ESP8266_OSCExample.ino
+++ code/ESP8266_OSCExample/ESP8266_OSCExample/ESP8266_OSCExample.ino
@@ -4,7 +4,6 @@

 Included is a Max/MSP patch for controlling a single LED on board.
 Max patch uses CNMAT OSC externals*/
-
 #include <ESP8266WiFi.h>
 #include <ESP8266WiFiMulti.h>
 // #include <WiFiClient.h>
@@ -154,10 +153,9 @@
   ESP.reset();
 }

-float pi2float(float in){
-  //gotta change this later, the Pitch and Roll just use -Pi->Pi
-  return ((in / M_PI) + 1) / 2;
-}
+float max_ypr[3] = {-10, -10, -10};
+float min_ypr[3] = {10, 10, 10};
+

 void setup() {
   //Initialize serial and wait for port to open:
@@ -336,10 +334,10 @@
     //declare a bundle
     OSCBundle bndl;
     bndl.add("/time").add((int32_t)millis()); //time since active :: indicates a connection
-    bndl.add("/ypr").add(pi2float(ypr[0])).add(pi2float(ypr[1])).add(pi2float(ypr[2])); // yaw/pitch/roll
+    bndl.add("/ypr").add(ypr[0]).add(ypr[1]).add(ypr[2]); // yaw/pitch/roll
     bndl.add("/batt").add(float((analogRead(A0) >> 2)-SCALED_V_MIN)/(SCALED_V_MAX - SCALED_V_MIN)); //battery voltage [0,1]
-    bndl.add("/debug").add(ypr[0]).add(ypr[1]).add(ypr[2]);
-
+    bndl.add("/debug").add(min_ypr[0]).add(max_ypr[0]).add(min_ypr[1]).add(max_ypr[1]).add(min_ypr[2]).add(max_ypr[2]);
+
     Udp.beginPacket(outIp, outPort);
     bndl.send(Udp); // send the bytes to the SLIP stream
     Udp.endPacket(); // mark the end of the OSC Packet
@@ -403,6 +401,13 @@
     mpu.dmpGetQuaternion(&q, fifoBuffer);
     mpu.dmpGetGravity(&gravity, &q);
     mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
+
+    for (int i = 0; i < 3; ++i){
+      if (i == 0)
+        ypr[i] = ((ypr[i] / M_PI) + 1) / 2;
+      else
+        ypr[i] = ((ypr[i] / (M_PI/2.)) + 1) / 2;
+    }
   }
   //=========================================================================//
 }