From 316427e7d9c7878c1d2bcfd51751a1fabda44434 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Thu, 5 Sep 2019 23:59:23 -0400 Subject: [PATCH 01/31] Fix #423: don't get stuck if LMIC is busy --- examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino index 959644dd..7e752ec6 100644 --- a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino +++ b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino @@ -537,6 +537,7 @@ void do_send(osjob_t* j){ // Check if there is not a current TX/RX job running if (LMIC.opmode & OP_TXRXPEND) { Serial.println(F("OP_TXRXPEND, not sending")); + sendComplete(j, 0); } else if (g_fTestMode) { Serial.println(F("test mode, not sending")); } else { From af6649dbf1e05790b356a119260977f6593d70a0 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Fri, 6 Sep 2019 01:57:52 -0400 Subject: [PATCH 02/31] Fix #426: cater temporarily to defect in MCI Catena STM BSP --- .../compliance-otaa-halconfig.ino | 455 +++++++++++++++++- 1 file changed, 443 insertions(+), 12 deletions(-) diff --git a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino index 7e752ec6..ee5987e6 100644 --- a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino +++ b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino @@ -581,24 +581,13 @@ void myFail(const char *pMessage) { } } -// there's a problem with running 2.5 of the MCCI STM32 BSPs; -// hack around it. -#ifdef ARDUINO_ARCH_STM32 -# ifdef _mcci_arduino_version -# if _mcci_arduino_version <= _mcci_arduino_version_calc(2, 5, 0, 0) -uint32_t USBD_LL_ConnectionState(void) { - return 1; -} -# endif // _mcci_arduino_version -# endif // defined(_mcci_arduino_version) -#endif // ARDUINO_ARCH_STM32 - 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(); @@ -701,3 +690,445 @@ void loop() { eventPrintOne()) ; } + +// there's a problem with running 2.5 of the MCCI STM32 BSPs; +// hack around it. +#ifdef ARDUINO_ARCH_STM32 +# ifdef _mcci_arduino_version +# if _mcci_arduino_version <= _mcci_arduino_version_calc(2, 5, 0, 0) +uint32_t USBD_LL_ConnectionState(void) { + return 1; +} +# endif // _mcci_arduino_version +# endif // defined(_mcci_arduino_version) +#endif // ARDUINO_ARCH_STM32 + +#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) + { + HAL_RTC_AlarmIRQHandler(gs_phRtc); + } + +void HAL_RTC_AlarmAEventCallback( + RTC_HandleTypeDef * hRtc + ) + { + if (gs_pAlarm) + *gs_pAlarm = 1; + } + +void HAL_RTC_MspInit( + RTC_HandleTypeDef * hRtc + ) + { + 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 From b168b9d5d768baf9b1ae041416443a1b8c49663a Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Fri, 6 Sep 2019 01:59:43 -0400 Subject: [PATCH 03/31] Fix #427: select subband 0 for all US-like regions --- .../compliance-otaa-halconfig.ino | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino index ee5987e6..510f6f6a 100644 --- a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino +++ b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino @@ -673,13 +673,8 @@ void setup_printSignOn() } void setupForNetwork(bool preJoin) { -#if defined(CFG_us915) +#if CFG_LMIC_US_like LMIC_selectSubBand(0); - - if (! preJoin) { -// LMIC_setLinkCheckMode(0); -// LMIC_setDrTxpow(DR_SF7, 14); - } #endif } From d4c4a81beda378f0e01d9d31f96369a1d638aae0 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Fri, 6 Sep 2019 02:02:04 -0400 Subject: [PATCH 04/31] Fix #425: disable duty-cycle limitation during test --- src/lmic/lmic_compliance.c | 22 +++++++++++++++++++++- src/lmic/lmic_compliance.h | 10 ++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/lmic/lmic_compliance.c b/src/lmic/lmic_compliance.c index a7dbefd8..a946751f 100644 --- a/src/lmic/lmic_compliance.c +++ b/src/lmic/lmic_compliance.c @@ -212,6 +212,17 @@ static void evActivate(void) { LMIC_Compliance.saveEvent.pEventCb = LMIC.client.eventCb; LMIC_Compliance.saveEvent.pUserData = LMIC.client.eventUserData; +#if CFG_LMIC_EU_like + band_t *b = LMIC.bands; + lmic_compliance_band_t *b_save = LMIC_Compliance.saveBands; + + for (; b < &LMIC.bands[MAX_BANDS]; ++b, ++b_save) { + b_save->txcap = b->txcap; + b->txcap = 1; + b->avail = os_getTime(); + } +#endif // CFG_LMIC_EU_like + LMIC_registerEventCb(lmicEventCb, NULL); fsmEvalDeferred(); @@ -309,10 +320,19 @@ static void evDeactivate(void) { // restore user's event handler. LMIC_registerEventCb(LMIC_Compliance.saveEvent.pEventCb, LMIC_Compliance.saveEvent.pUserData); + // restore band settings +#if CFG_LMIC_EU_like + band_t *b = LMIC.bands; + lmic_compliance_band_t const *b_save = LMIC_Compliance.saveBands; + + for (; b < &LMIC.bands[MAX_BANDS]; ++b, ++b_save) { + b->txcap = b_save->txcap; + } +#endif // CFG_LMIC_EU_like + fsmEvalDeferred(); } - /* Name: evJoinCommand() diff --git a/src/lmic/lmic_compliance.h b/src/lmic/lmic_compliance.h index 7fceb3e4..759f9b3a 100644 --- a/src/lmic/lmic_compliance.h +++ b/src/lmic/lmic_compliance.h @@ -94,6 +94,12 @@ struct lmic_compliance_eventcb_s { void *pUserData; }; +// structure for saving band settings during test +typedef struct lmic_compliance_band_s lmic_compliance_band_t; +struct lmic_compliance_band_s { + u2_t txcap; // saved 1/duty cycle +}; + // the state of the compliance engine. struct lmic_compliance_s { // uint64 @@ -103,7 +109,11 @@ struct lmic_compliance_s { lmic_compliance_eventcb_t saveEvent; // the user's event handler. // uint32 + // uint16 +#if CFG_LMIC_EU_like + lmic_compliance_band_t saveBands[MAX_BANDS]; +#endif // CFG_LMIC_EU_like // we are required to maintain a downlink count // that is reset on join/test entry and incremented for From 7bf26f9fc4b52ce54ec0a0e8aa0dcefc63c91007 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Fri, 6 Sep 2019 02:03:50 -0400 Subject: [PATCH 05/31] Fix #424: return to app mode on port 224 join command --- src/lmic/lmic_compliance.c | 43 ++++++++++---------------------------- src/lmic/lmic_compliance.h | 13 +++++------- 2 files changed, 16 insertions(+), 40 deletions(-) diff --git a/src/lmic/lmic_compliance.c b/src/lmic/lmic_compliance.c index a946751f..81cb2e07 100644 --- a/src/lmic/lmic_compliance.c +++ b/src/lmic/lmic_compliance.c @@ -307,6 +307,9 @@ Name: evDeactivate() Description: We report a deactivation event, and re-evaluate the FSM. + We also set a flag so that we're return the appropriate + status from the compliance entry point to the real + application. Returns: No explicit result. @@ -344,8 +347,10 @@ Name: evJoinCommand() void evJoinCommand(void); Description: - We report a join-command event, and the kick the FSM. This - will cause the FSM to coordinate sending and the other activities. + We unjoin from the network, and then report a deactivation + of test mode. That will get us out of test mode and back + to the compliance app. The next message send will trigger + a join. Returns: No explicit result. @@ -355,8 +360,8 @@ Name: evJoinCommand() static void evJoinCommand( void ) { - LMIC_Compliance.eventflags |= LMIC_COMPLIANCE_EVENT_JOIN_CMD; - fsmEvalDeferred(); + LMIC_unjoin(); + evDeactivate(); } /* @@ -582,8 +587,6 @@ fsmDispatch( } if (eventflags_TestAndClear(LMIC_COMPLIANCE_EVENT_DEACTIVATE)) { newState = LMIC_COMPLIANCE_FSMSTATE_INACTIVE; - } else if (eventflags_TestAndClear(LMIC_COMPLIANCE_EVENT_JOIN_CMD)) { - newState = LMIC_COMPLIANCE_FSMSTATE_JOINING; } else if (eventflags_TestAndClear(LMIC_COMPLIANCE_EVENT_ECHO_REQUEST)) { newState = LMIC_COMPLIANCE_FSMSTATE_ECHOING; } else { @@ -592,16 +595,6 @@ fsmDispatch( break; } - case LMIC_COMPLIANCE_FSMSTATE_JOINING: { - if (fEntry) - acDoJoin(); - - if (eventflags_TestAndClear(LMIC_COMPLIANCE_EVENT_JOINED)) { - newState = LMIC_COMPLIANCE_FSMSTATE_RECOVERY; - } - break; - } - case LMIC_COMPLIANCE_FSMSTATE_ECHOING: { if (fEntry) acSendUplinkBuffer(); @@ -625,8 +618,7 @@ fsmDispatch( case LMIC_COMPLIANCE_FSMSTATE_RECOVERY: { if (fEntry) { if (LMIC_Compliance.eventflags & (LMIC_COMPLIANCE_EVENT_DEACTIVATE | - LMIC_COMPLIANCE_EVENT_ECHO_REQUEST | - LMIC_COMPLIANCE_EVENT_JOIN_CMD)) { + LMIC_COMPLIANCE_EVENT_ECHO_REQUEST)) { acSetTimer(sec2osticks(1)); } else { acSetTimer(sec2osticks(5)); @@ -677,10 +669,7 @@ static void lmicEventCb( } // if it's a EV_JOINED, or a TXCMOMPLETE, we should tell the FSM. - if (ev == EV_JOINED) { - LMIC_Compliance.eventflags |= LMIC_COMPLIANCE_EVENT_JOINED; - fsmEvalDeferred(); - } else if (ev == EV_TXCOMPLETE) { + if ((UINT32_C(1) << ev) & (EV_JOINED | EV_TXCOMPLETE)) { fsmEvalDeferred(); } } @@ -764,13 +753,3 @@ static void acSendUplinkBuffer(void) { static const char *txSuccessToString(int fSuccess) { return fSuccess ? "ok" : "failed"; } - -static void acDoJoin(void) { - LMIC_COMPLIANCE_PRINTF("acDoJoin\n"); - - LMIC_Compliance.eventflags &= ~LMIC_COMPLIANCE_EVENT_JOINED; - - LMIC_unjoin(); - LMIC_Compliance.downlinkCount = 0; - LMIC_startJoining(); -} diff --git a/src/lmic/lmic_compliance.h b/src/lmic/lmic_compliance.h index 759f9b3a..52775748 100644 --- a/src/lmic/lmic_compliance.h +++ b/src/lmic/lmic_compliance.h @@ -57,9 +57,7 @@ enum lmic_compliance_eventflags_e { LMIC_COMPLIANCE_EVENT_DEACTIVATE = 1u << 1, LMIC_COMPLIANCE_EVENT_TIMER_EXPIRED = 1u << 2, LMIC_COMPLIANCE_EVENT_UPLINK_COMPLETE = 1u << 3, - LMIC_COMPLIANCE_EVENT_JOIN_CMD = 1u << 4, - LMIC_COMPLIANCE_EVENT_JOINED = 1u << 5, - LMIC_COMPLIANCE_EVENT_ECHO_REQUEST = 1u << 6, + LMIC_COMPLIANCE_EVENT_ECHO_REQUEST = 1u << 4, }; typedef uint8_t lmic_compliance_fsmflags_t; @@ -76,14 +74,13 @@ enum lmic_compliance_fsmstate_e { LMIC_COMPLIANCE_FSMSTATE_ACTIVE = 2, LMIC_COMPLIANCE_FSMSTATE_INACTIVE = 3, LMIC_COMPLIANCE_FSMSTATE_TESTMODE = 4, // sending test uplinks - LMIC_COMPLIANCE_FSMSTATE_JOINING = 5, // joining (under command) - LMIC_COMPLIANCE_FSMSTATE_ECHOING = 6, - LMIC_COMPLIANCE_FSMSTATE_REPORTING = 7, - LMIC_COMPLIANCE_FSMSTATE_RECOVERY = 8, + LMIC_COMPLIANCE_FSMSTATE_ECHOING = 5, + LMIC_COMPLIANCE_FSMSTATE_REPORTING = 6, + LMIC_COMPLIANCE_FSMSTATE_RECOVERY = 7, }; #define LMIC_COMPLIANCE_FSMSTATE__NAMES \ - "INITIAL", "NOCHANGE", "ACTIVE", "INACTIVE", "TESTMODE", "JOINING", \ + "INITIAL", "NOCHANGE", "ACTIVE", "INACTIVE", "TESTMODE", \ "ECHOING", "REPORTING", "RECOVERY" typedef struct lmic_compliance_eventcb_s lmic_compliance_eventcb_t; From 34d61a67c100a374750aeaa9bb3852cfacf982d9 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Fri, 6 Sep 2019 02:04:08 -0400 Subject: [PATCH 06/31] Fix typo in comment --- src/lmic/lmic_compliance.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lmic/lmic_compliance.c b/src/lmic/lmic_compliance.c index 81cb2e07..6db476ac 100644 --- a/src/lmic/lmic_compliance.c +++ b/src/lmic/lmic_compliance.c @@ -283,7 +283,7 @@ static void evMessage( break; } case LORAWAN_COMPLIANCE_CMD_LINK: { - // not clear what theis request does. + // not clear what this request does. break; } case LORAWAN_COMPLIANCE_CMD_JOIN: { From eebb1cd8d6218d7c15646d2d5c7737fabc9c6784 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Fri, 6 Sep 2019 02:10:04 -0400 Subject: [PATCH 07/31] Fix #428: log the MIC bytes on error --- src/lmic/lmic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lmic/lmic.c b/src/lmic/lmic.c index db8fd75f..36e5bb4b 100644 --- a/src/lmic/lmic.c +++ b/src/lmic/lmic.c @@ -1232,7 +1232,7 @@ static bit_t decodeFrame (void) { } if( !aes_verifyMic(LMIC.nwkKey, LMIC.devaddr, seqno, /*dn*/1, d, pend) ) { - LMICOS_logEventUint32("decodeFrame: bad MIC", seqno); + LMICOS_logEventUint32("decodeFrame: bad MIC", os_rlsbf4(&d[pend])); EV(spe3Cond, ERR, (e_.reason = EV::spe3Cond_t::CORRUPTED_MIC, e_.eui1 = MAIN::CDEV->getEui(), e_.info1 = Base::lsbf4(&d[pend]), From f88f83ce43d90b36a0ccb1bd532da16d77cbfbfe Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Fri, 6 Sep 2019 02:45:41 -0400 Subject: [PATCH 08/31] Fix #429: dont set FSK power < 11 for PAboost mode --- src/lmic/radio.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lmic/radio.c b/src/lmic/radio.c index 0451d88f..321f633c 100644 --- a/src/lmic/radio.c +++ b/src/lmic/radio.c @@ -560,7 +560,7 @@ static void configChannel () { // 1) using RFO: power is -1 to 13 dBm (datasheet implies max OutputPower value is 14 for 13 dBm) // 2) using PA_BOOST, PaDac = 0x84: power is 2 to 17 dBm; // use this for 14..17 if authorized -// 3) using PA_BOOST, PaDac = 0x87, OutptuPower = 0xF: power is 20dBm +// 3) using PA_BOOST, PaDac = 0x87, OutputPower = 0xF: power is 20dBm // and duty cycle must be <= 1% // // The general policy is to use the lowest power variant that will get us where we @@ -626,6 +626,10 @@ static void configPower () { // we have to re-check eff_pw, which might be too small. // (And, of course, it might also be too large.) case LMICHAL_radio_tx_power_policy_paboost: + // It seems that SX127x doesn't like eff_pw 10 when in FSK mode. + if (getSf(LMIC.rps) == FSK && eff_pw < 11) { + eff_pw = 11; + } rPaDac = SX127X_PADAC_POWER_NORMAL; rOcp = SX127X_OCP_MAtoBITS(100); if (eff_pw > 17) From d2ed33f49a1b5461a043ab13be4ed85cbdb4ab9b Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Fri, 6 Sep 2019 02:48:37 -0400 Subject: [PATCH 09/31] Fix #430: increase min rx to tx gap to 0.5 sec --- src/lmic/lmic_bandplan.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lmic/lmic_bandplan.h b/src/lmic/lmic_bandplan.h index 28533f5b..62df760b 100644 --- a/src/lmic/lmic_bandplan.h +++ b/src/lmic/lmic_bandplan.h @@ -184,7 +184,7 @@ // this is probably regional, but for now default can be the same #if !defined(LMICbandplan_TX_RECOVERY_ms) -# define LMICbandplan_TX_RECOVERY_ms 100 +# define LMICbandplan_TX_RECOVERY_ms 500 #endif #define BCN_INTV_osticks sec2osticks(BCN_INTV_sec) From b30d0ba486d42291a0d5eee10ffc2b6c4f66ef58 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Fri, 6 Sep 2019 17:51:40 -0400 Subject: [PATCH 10/31] Add logging of frame counts in compliance app --- .../compliance-otaa-halconfig.ino | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino index 510f6f6a..1de552cc 100644 --- a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino +++ b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino @@ -20,6 +20,7 @@ Author: #include #include +class cEventQueue; // // For compliance tests with the RWC5020A, we use the default addresses @@ -93,8 +94,10 @@ public: ostime_t time; ostime_t txend; u4_t freq; - rps_t rps; u2_t opmode; + u2_t fcntDn; + u2_t fcntUp; + rps_t rps; u1_t txChnl; u1_t datarate; u1_t txrxFlags; @@ -125,10 +128,12 @@ public: pn->pMessage = pMessage; pn->datum = datum; pn->freq = LMIC.freq; - pn->txChnl = LMIC.txChnl; + pn->opmode = LMIC.opmode; + pn->fcntDn = (u2_t) LMIC.seqnoDn; + pn->fcntUp = (u2_t) LMIC.seqnoUp; pn->rps = LMIC.rps; + pn->txChnl = LMIC.txChnl; pn->datarate = LMIC.datarate; - pn->opmode = LMIC.opmode; pn->txrxFlags = LMIC.txrxFlags; pn->saveIrqFlags = LMIC.saveIrqFlags; m_tail = i; @@ -187,6 +192,8 @@ void myEventCb(void *pUserData, ev_t ev) { } void eventPrint(cEventQueue::eventnode_t &e); +void printFcnts(cEventQueue::eventnode_t &e); + void eventPrintAll(void) { while (eventPrintOne()) @@ -233,6 +240,11 @@ void printHex2(unsigned v) { Serial.print(v, HEX); } +void printHex4(unsigned v) { + printHex2(v >> 8u); + printHex2(v); +} + void printFreq(u4_t freq) { Serial.print(F(": freq=")); Serial.print(freq / 1000000); @@ -280,6 +292,13 @@ void printSaveIrqFlags(u1_t saveIrqFlags) { printHex2(saveIrqFlags); } +void printFcnts(cEventQueue::eventnode_t &e) { + Serial.print(F(", FcntUp=")); + printHex4(e.fcntUp); + Serial.print(F(", FcntDn=")); + printHex4(e.fcntDn); +} + // dump all the registers. Must have printf setup. void printAllRegisters(void) { uint8_t regbuf[0x80]; @@ -409,6 +428,7 @@ void eventPrint(cEventQueue::eventnode_t &e) { printTxChnl(e.txChnl); printRps(e.rps); printTxrxflags(e.txrxFlags); + printFcnts(e); break; case EV_LOST_TSYNC: break; @@ -610,7 +630,7 @@ void setup() { // Reset the MAC state. Session and pending data transfers will be discarded. LMIC_reset(); - LMIC_setClockError(5 * MAX_CLOCK_ERROR / 100); + LMIC_setClockError(1 * MAX_CLOCK_ERROR / 100); // do the network-specific setup prior to join. setupForNetwork(false); @@ -680,10 +700,10 @@ void setupForNetwork(bool preJoin) { void loop() { os_runloop_once(); - while ((LMIC.opmode & OP_TXRXPEND) == 0 && - ! os_queryTimeCriticalJobs(ms2osticks(1000)) && - eventPrintOne()) - ; + if ((LMIC.opmode & OP_TXRXPEND) == 0 && + !os_queryTimeCriticalJobs(ms2osticks(1000))) { + eventPrintOne(); + } } // there's a problem with running 2.5 of the MCCI STM32 BSPs; From 1e5578910addff8e82d2af5c714ac0da628f682a Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Sun, 8 Sep 2019 16:08:07 -0400 Subject: [PATCH 11/31] Parameterize fixes for MCCI BSP limitations; 2.5.0.10 fixes USB --- .../compliance-otaa-halconfig.ino | 57 +++++++++---------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino index 1de552cc..a19d9f53 100644 --- a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino +++ b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino @@ -706,53 +706,54 @@ void loop() { } } -// there's a problem with running 2.5 of the MCCI STM32 BSPs; -// hack around it. +#define NEED_USBD_LL_ConnectionState 0 +#ifdef ARDUINO_ARCH_STM32 +# ifdef _mcci_arduino_version +# if _mcci_arduino_version < _mcci_arduino_version_calc(2, 5, 0, 10) +# undef NEED_USBD_LL_ConnectionState +# define NEED_USBD_LL_ConnectionState 1 +# endif // _mcci_arduino_version < _mcci_arduino_version_calc(2, 5, 0, 10) +# endif // def _mcci_arduino_version +#endif // def ARDUINO_ARCH_STM32 + +#define NEED_STM32_ClockCalibration 0 #ifdef ARDUINO_ARCH_STM32 # ifdef _mcci_arduino_version -# if _mcci_arduino_version <= _mcci_arduino_version_calc(2, 5, 0, 0) +# if _mcci_arduino_version <= _mcci_arduino_version_calc(2, 5, 0, 10) +# undef NEED_STM32_ClockCalibration +# define NEED_STM32_ClockCalibration 1 +# endif // _mcci_arduino_version <= _mcci_arduino_version_calc(2, 5, 0, 10) +# endif // def _mcci_arduino_version +#endif // def ARDUINO_ARCH_STM32 + + +// there's a problem with running 2.5 of the MCCI STM32 BSPs; +// hack around it. +#if NEED_USBD_LL_ConnectionState uint32_t USBD_LL_ConnectionState(void) { return 1; } -# endif // _mcci_arduino_version -# endif // defined(_mcci_arduino_version) -#endif // ARDUINO_ARCH_STM32 +#endif // NEED_USBD_LL_ConnectionState -#ifdef ARDUINO_ARCH_STM32 -# if defined(_mcci_arduino_version) -# if _mcci_arduino_version >= _mcci_arduino_version_calc(2,4,0,90) +#if NEED_STM32_ClockCalibration 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"); +#if NEED_STM32_ClockCalibration Stm32_CalibrateSystemClock(); +#endif // NEED_STM32_ClockCalibration } 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) +#if NEED_STM32_ClockCalibration // RTC needs to be initialized before we calibrate the clock. bool rtcbegin() { @@ -1144,6 +1145,4 @@ MeasureMillisPerRtcSecond( /* return the delta */ return end - start; } -# endif // _mcci_arduino_version -# endif // defined(_mcci_arduino_version) -#endif // ARDUINO_ARCH_STM32 +#endif // NEED_STM32_ClockCalibration From ed69e67d810f5b052f79643b0f7f604985607644 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Sun, 8 Sep 2019 16:08:36 -0400 Subject: [PATCH 12/31] Fix error messages in STM32 clock cal code --- .../compliance-otaa-halconfig/compliance-otaa-halconfig.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino index a19d9f53..978d2fae 100644 --- a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino +++ b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino @@ -1091,7 +1091,7 @@ uint32_t Stm32_CalibrateSystemClock(void) { // Use original value Serial.println( - "?CatenaStm32L0::CalibrateSystemClock: can't calibrate" + "?CalibrateSystemClock: can't calibrate" ); } From 69501b6374a12363d288da122f23b58989d808b4 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Sun, 8 Sep 2019 16:13:33 -0400 Subject: [PATCH 13/31] Fix #249: add reentrancy protection in engineUpdate() --- src/lmic/lmic.c | 23 +++++++++++++++++++++-- src/lmic/lmic.h | 10 +++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/lmic/lmic.c b/src/lmic/lmic.c index 36e5bb4b..8c55d989 100644 --- a/src/lmic/lmic.c +++ b/src/lmic/lmic.c @@ -2453,8 +2453,9 @@ static void startRxPing (xref2osjob_t osjob) { #endif // !DISABLE_PING -// Decide what to do next for the MAC layer of a device -static void engineUpdate (void) { +// Decide what to do next for the MAC layer of a device. Inner part. +// Only called from outer part. +static void engineUpdate_inner (void) { #if LMIC_DEBUG_LEVEL > 0 LMIC_DEBUG_PRINTF("%"LMIC_PRId_ostime_t": engineUpdate, opmode=0x%x\n", os_getTime(), LMIC.opmode); #endif @@ -2637,6 +2638,24 @@ static void engineUpdate (void) { os_setTimedCallback(&LMIC.osjob, txbeg-TX_RAMPUP, FUNC_ADDR(runEngineUpdate)); } +// Decide what to do next for the MAC layer of a device. +// Outer part. Safe to call from anywhere; defers if it +// detects a recursive call. +static void engineUpdate (void) { + lmic_engine_update_state_t state; + + state = LMIC.engineUpdateState; + if (state == lmic_EngineUpdateState_idle) { + LMIC.engineUpdateState = lmic_EngineUpdateState_busy; + do { + engineUpdate_inner(); + state = LMIC.engineUpdateState - 1; + LMIC.engineUpdateState = state; + } while (state != lmic_EngineUpdateState_idle); + } else { + LMIC.engineUpdateState = lmic_EngineUpdateState_again; + } +} void LMIC_setAdrMode (bit_t enabled) { LMIC.adrEnabled = enabled ? FCT_ADREN : 0; diff --git a/src/lmic/lmic.h b/src/lmic/lmic.h index cefc57f7..fce6473c 100644 --- a/src/lmic/lmic.h +++ b/src/lmic/lmic.h @@ -360,6 +360,14 @@ enum lmic_request_time_state_e { typedef u1_t lmic_request_time_state_t; +enum lmic_engine_update_state_e { + lmic_EngineUpdateState_idle = 0, // engineUpdate is idle. + lmic_EngineUpdateState_busy = 1, // engineUpdate is busy, but has not been reentered. + lmic_EngineUpdateState_again = 2, // engineUpdate is busy, and has to be evaluated again. +}; + +typedef u1_t lmic_engine_update_state_t; + /* Structure: lmic_client_data_t @@ -480,7 +488,6 @@ struct lmic_t { #endif /* (u)int16_t things */ - rps_t rps; // radio parameter selections: SF, BW, CodingRate, NoCrc, implicit hdr u2_t opmode; // engineUpdate() operating mode flags u2_t devNonce; // last generated nonce @@ -494,6 +501,7 @@ struct lmic_t { #endif /* (u)int8_t things */ + lmic_engine_update_state_t engineUpdateState; // state of the engineUpdate() evaluator. s1_t rssi; s1_t snr; // LMIC.snr is SNR times 4 u1_t rxsyms; From 2849ceb25cd45e15cb2a77de13028ab185ed23d7 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Sun, 8 Sep 2019 21:15:32 -0400 Subject: [PATCH 14/31] Fix #434: wrong FSK detection in LMIC*_isFsk() --- src/lmic/lmic_bandplan_as923.h | 2 +- src/lmic/lmic_bandplan_eu868.h | 2 +- src/lmic/lmic_bandplan_in866.h | 2 +- src/lmic/lmic_eu868.c | 2 +- src/lmic/lmic_in866.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lmic/lmic_bandplan_as923.h b/src/lmic/lmic_bandplan_as923.h index 845541af..206d4a7d 100644 --- a/src/lmic/lmic_bandplan_as923.h +++ b/src/lmic/lmic_bandplan_as923.h @@ -72,7 +72,7 @@ void LMICas923_init(void); // override default for LMICbandplan_isFSK() #undef LMICbandplan_isFSK -#define LMICbandplan_isFSK() (/* TX datarate */LMIC.rxsyms == AS923_DR_FSK) +#define LMICbandplan_isFSK() (/* RX datarate */LMIC.dndr == AS923_DR_FSK) // txDone handling for FSK. void diff --git a/src/lmic/lmic_bandplan_eu868.h b/src/lmic/lmic_bandplan_eu868.h index 4952d3e4..13417ecd 100644 --- a/src/lmic/lmic_bandplan_eu868.h +++ b/src/lmic/lmic_bandplan_eu868.h @@ -59,7 +59,7 @@ LMICeu868_isValidBeacon1(const uint8_t *d) { // override default for LMICbandplan_isFSK() #undef LMICbandplan_isFSK -#define LMICbandplan_isFSK() (/* TX datarate */LMIC.rxsyms == EU868_DR_FSK) +#define LMICbandplan_isFSK() (/* RX datarate */LMIC.dndr == EU868_DR_FSK) // txDone handling for FSK. void diff --git a/src/lmic/lmic_bandplan_in866.h b/src/lmic/lmic_bandplan_in866.h index 39b58f15..9fc08264 100644 --- a/src/lmic/lmic_bandplan_in866.h +++ b/src/lmic/lmic_bandplan_in866.h @@ -56,7 +56,7 @@ LMICin866_isValidBeacon1(const uint8_t *d) { // override default for LMICbandplan_isFSK() #undef LMICbandplan_isFSK -#define LMICbandplan_isFSK() (/* TX datarate */LMIC.rxsyms == IN866_DR_FSK) +#define LMICbandplan_isFSK() (/* TX datarate */LMIC.dndr == IN866_DR_FSK) // txDone handling for FSK. void diff --git a/src/lmic/lmic_eu868.c b/src/lmic/lmic_eu868.c index b91e1ea8..d4b9b6b3 100644 --- a/src/lmic/lmic_eu868.c +++ b/src/lmic/lmic_eu868.c @@ -247,7 +247,7 @@ ostime_t LMICeu868_nextJoinState(void) { } #endif // !DISABLE_JOIN -// txDone handling for FSK. +// Class A txDone handling for FSK. void LMICeu868_txDoneFSK(ostime_t delay, osjobcb_t func) { LMIC.rxtime = LMIC.txend + delay - PRERX_FSK*us2osticksRound(160); diff --git a/src/lmic/lmic_in866.c b/src/lmic/lmic_in866.c index 86571bc0..78c5e81a 100644 --- a/src/lmic/lmic_in866.c +++ b/src/lmic/lmic_in866.c @@ -212,7 +212,7 @@ ostime_t LMICin866_nextJoinState(void) { } #endif // !DISABLE_JOIN -// txDone handling for FSK. +// Class A txDone handling for FSK. void LMICin866_txDoneFSK(ostime_t delay, osjobcb_t func) { LMIC.rxtime = LMIC.txend + delay - PRERX_FSK*us2osticksRound(160); From a4d2494614f13eef617e4c8aa93b085238d17450 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Sun, 8 Sep 2019 23:21:27 -0400 Subject: [PATCH 15/31] Fix #435: correct spelling error LMICbandplan_txDoneFSK --- src/lmic/lmic_bandplan_as923.h | 3 ++- src/lmic/lmic_bandplan_eu868.h | 3 ++- src/lmic/lmic_bandplan_in866.h | 3 ++- src/lmic/lmic_bandplan_kr920.h | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lmic/lmic_bandplan_as923.h b/src/lmic/lmic_bandplan_as923.h index 206d4a7d..4b4f7856 100644 --- a/src/lmic/lmic_bandplan_as923.h +++ b/src/lmic/lmic_bandplan_as923.h @@ -78,7 +78,8 @@ void LMICas923_init(void); void LMICas923_txDoneFSK(ostime_t delay, osjobcb_t func); -#define LMICbandplan_txDoneFsk(delay, func) LMICas923_txDoneFSK(delay, func) +#undef LMICbandplan_txDoneFSK +#define LMICbandplan_txDoneFSK(delay, func) LMICas923_txDoneFSK(delay, func) #define LMICbandplan_getInitialDrJoin() (AS923_DR_SF10) diff --git a/src/lmic/lmic_bandplan_eu868.h b/src/lmic/lmic_bandplan_eu868.h index 13417ecd..0770a0e1 100644 --- a/src/lmic/lmic_bandplan_eu868.h +++ b/src/lmic/lmic_bandplan_eu868.h @@ -65,7 +65,8 @@ LMICeu868_isValidBeacon1(const uint8_t *d) { void LMICeu868_txDoneFSK(ostime_t delay, osjobcb_t func); -#define LMICbandplan_txDoneFsk(delay, func) LMICeu868_txDoneFSK(delay, func) +#undef LMICbandplan_txDoneFSK +#define LMICbandplan_txDoneFSK(delay, func) LMICeu868_txDoneFSK(delay, func) #define LMICbandplan_getInitialDrJoin() (EU868_DR_SF7) diff --git a/src/lmic/lmic_bandplan_in866.h b/src/lmic/lmic_bandplan_in866.h index 9fc08264..2528dbf7 100644 --- a/src/lmic/lmic_bandplan_in866.h +++ b/src/lmic/lmic_bandplan_in866.h @@ -62,7 +62,8 @@ LMICin866_isValidBeacon1(const uint8_t *d) { void LMICin866_txDoneFSK(ostime_t delay, osjobcb_t func); -#define LMICbandplan_txDoneFsk(delay, func) LMICin866_txDoneFSK(delay, func) +#undef LMICbandplan_txDoneFSK +#define LMICbandplan_txDoneFSK(delay, func) LMICin866_txDoneFSK(delay, func) #define LMICbandplan_getInitialDrJoin() (IN866_DR_SF7) diff --git a/src/lmic/lmic_bandplan_kr920.h b/src/lmic/lmic_bandplan_kr920.h index 9a3d59a3..23a28ae3 100644 --- a/src/lmic/lmic_bandplan_kr920.h +++ b/src/lmic/lmic_bandplan_kr920.h @@ -65,7 +65,8 @@ LMICkr920_isValidBeacon1(const uint8_t *d) { void LMICkr920_txDoneFSK(ostime_t delay, osjobcb_t func); -#define LMICbandplan_txDoneFsk(delay, func) LMICkr920_txDoneFSK(delay, func) +#undef LMICbandplan_txDoneFSK +#define LMICbandplan_txDoneFSK(delay, func) LMICkr920_txDoneFSK(delay, func) #define LMICbandplan_getInitialDrJoin() (KR920_DR_SF7) From 319c686ff5f86368e0b02b13a90200815773caf1 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Sun, 8 Sep 2019 23:53:29 -0400 Subject: [PATCH 16/31] Fix #436: FSK irqs set OPMODE_STANDBY before SLEEP --- src/lmic/radio.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/lmic/radio.c b/src/lmic/radio.c index 321f633c..d6a9d7f7 100644 --- a/src/lmic/radio.c +++ b/src/lmic/radio.c @@ -1220,6 +1220,7 @@ void radio_irq_handler_v2 (u1_t dio, ostime_t now) { if( (readReg(RegOpMode) & OPMODE_LORA) != 0) { // LORA modem u1_t flags = readReg(LORARegIrqFlags); LMIC.saveIrqFlags = flags; + LMICOS_logEventUint32("radio_irq_handler_v2: LoRa", flags); LMIC_X_DEBUG_PRINTF("IRQ=%02x\n", flags); if( flags & IRQ_LORA_TXDONE_MASK ) { // save exact tx time @@ -1258,6 +1259,9 @@ void radio_irq_handler_v2 (u1_t dio, ostime_t now) { } else { // FSK modem u1_t flags1 = readReg(FSKRegIrqFlags1); u1_t flags2 = readReg(FSKRegIrqFlags2); + + LMICOS_logEventUint32("radio_irq_handler_v2: FSK", (flags2 << UINT32_C(8)) | flags1); + if( flags2 & IRQ_FSK2_PACKETSENT_MASK ) { // save exact tx time LMIC.txend = now; @@ -1275,10 +1279,15 @@ void radio_irq_handler_v2 (u1_t dio, ostime_t now) { // indicate timeout LMIC.dataLen = 0; } else { - ASSERT(0); + // ASSERT(0); + // we're not sure why we're here... treat as timeout. + LMIC.dataLen = 0; } + + // in FSK, we need to put the radio in standby first. + opmode(OPMODE_STANDBY); } - // go from stanby to sleep + // go from standby to sleep opmode(OPMODE_SLEEP); // run os job (use preset func ptr) os_setCallback(&LMIC.osjob, LMIC.osjob.func); From c6f92952f58016dee72d1fba3dbb136eeff63c91 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 9 Sep 2019 00:26:23 -0400 Subject: [PATCH 17/31] Fix #439: set RegDetectOptimize[2..0] to 3'b011 --- src/lmic/radio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lmic/radio.c b/src/lmic/radio.c index d6a9d7f7..c97e3aae 100644 --- a/src/lmic/radio.c +++ b/src/lmic/radio.c @@ -904,9 +904,9 @@ static void rxlora (u1_t rxmode) { // Errata 2.3 - receiver spurious reception of a LoRa signal bw_t const bw = getBw(LMIC.rps); - u1_t const rDetectOptimize = readReg(LORARegDetectOptimize); + u1_t const rDetectOptimize = (readReg(LORARegDetectOptimize) & 0x78) | 0x03; if (bw < BW500) { - writeReg(LORARegDetectOptimize, rDetectOptimize & 0x7F); + writeReg(LORARegDetectOptimize, rDetectOptimize); writeReg(LORARegIffReq1, 0x40); writeReg(LORARegIffReq2, 0x40); } else { From 1d1ff10ccc52e32a6e63ebb5de46f11d0680109d Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 9 Sep 2019 01:30:39 -0400 Subject: [PATCH 18/31] Add a comment --- src/lmic/lmic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lmic/lmic.c b/src/lmic/lmic.c index 8c55d989..34491299 100644 --- a/src/lmic/lmic.c +++ b/src/lmic/lmic.c @@ -2497,6 +2497,7 @@ static void engineUpdate_inner (void) { txbeg = LMIC.txend = LMICbandplan_nextTx(now); LMIC.opmode &= ~OP_NEXTCHNL; } else { + // no need to consider anything but LMIC.txend. txbeg = LMIC.txend; } // Delayed TX or waiting for duty cycle? From 59cca347f17dc0cbba3d2d42a4539158d643d59a Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 9 Sep 2019 01:34:57 -0400 Subject: [PATCH 19/31] Fix #438: use clock error in FSK rx timing --- src/lmic/lmic_as923.c | 8 -------- src/lmic/lmic_bandplan_as923.h | 7 ------- src/lmic/lmic_bandplan_eu868.h | 7 ------- src/lmic/lmic_bandplan_in866.h | 7 ------- src/lmic/lmic_bandplan_kr920.h | 7 ------- src/lmic/lmic_eu868.c | 8 -------- src/lmic/lmic_eu_like.c | 29 +++++++++++++++++++++++++++++ src/lmic/lmic_eu_like.h | 3 ++- src/lmic/lmic_in866.c | 8 -------- src/lmic/lmic_kr920.c | 8 -------- 10 files changed, 31 insertions(+), 61 deletions(-) diff --git a/src/lmic/lmic_as923.c b/src/lmic/lmic_as923.c index 70263ed4..ddff00b2 100644 --- a/src/lmic/lmic_as923.c +++ b/src/lmic/lmic_as923.c @@ -361,14 +361,6 @@ ostime_t LMICas923_nextJoinState(void) { } #endif // !DISABLE_JOIN -// txDone handling for FSK. -void -LMICas923_txDoneFSK(ostime_t delay, osjobcb_t func) { - LMIC.rxtime = LMIC.txend + delay - PRERX_FSK*us2osticksRound(160); - LMIC.rxsyms = RXLEN_FSK; - os_setTimedCallback(&LMIC.osjob, LMIC.rxtime - RX_RAMPUP, func); -} - void LMICas923_initJoinLoop(void) { // LMIC.txParam is set to 0xFF by the central code at init time. diff --git a/src/lmic/lmic_bandplan_as923.h b/src/lmic/lmic_bandplan_as923.h index 4b4f7856..16f4518d 100644 --- a/src/lmic/lmic_bandplan_as923.h +++ b/src/lmic/lmic_bandplan_as923.h @@ -74,13 +74,6 @@ void LMICas923_init(void); #undef LMICbandplan_isFSK #define LMICbandplan_isFSK() (/* RX datarate */LMIC.dndr == AS923_DR_FSK) -// txDone handling for FSK. -void -LMICas923_txDoneFSK(ostime_t delay, osjobcb_t func); - -#undef LMICbandplan_txDoneFSK -#define LMICbandplan_txDoneFSK(delay, func) LMICas923_txDoneFSK(delay, func) - #define LMICbandplan_getInitialDrJoin() (AS923_DR_SF10) void LMICas923_setBcnRxParams(void); diff --git a/src/lmic/lmic_bandplan_eu868.h b/src/lmic/lmic_bandplan_eu868.h index 0770a0e1..efff7d5c 100644 --- a/src/lmic/lmic_bandplan_eu868.h +++ b/src/lmic/lmic_bandplan_eu868.h @@ -61,13 +61,6 @@ LMICeu868_isValidBeacon1(const uint8_t *d) { #undef LMICbandplan_isFSK #define LMICbandplan_isFSK() (/* RX datarate */LMIC.dndr == EU868_DR_FSK) -// txDone handling for FSK. -void -LMICeu868_txDoneFSK(ostime_t delay, osjobcb_t func); - -#undef LMICbandplan_txDoneFSK -#define LMICbandplan_txDoneFSK(delay, func) LMICeu868_txDoneFSK(delay, func) - #define LMICbandplan_getInitialDrJoin() (EU868_DR_SF7) void LMICeu868_setBcnRxParams(void); diff --git a/src/lmic/lmic_bandplan_in866.h b/src/lmic/lmic_bandplan_in866.h index 2528dbf7..dad10cab 100644 --- a/src/lmic/lmic_bandplan_in866.h +++ b/src/lmic/lmic_bandplan_in866.h @@ -58,13 +58,6 @@ LMICin866_isValidBeacon1(const uint8_t *d) { #undef LMICbandplan_isFSK #define LMICbandplan_isFSK() (/* TX datarate */LMIC.dndr == IN866_DR_FSK) -// txDone handling for FSK. -void -LMICin866_txDoneFSK(ostime_t delay, osjobcb_t func); - -#undef LMICbandplan_txDoneFSK -#define LMICbandplan_txDoneFSK(delay, func) LMICin866_txDoneFSK(delay, func) - #define LMICbandplan_getInitialDrJoin() (IN866_DR_SF7) void LMICin866_setBcnRxParams(void); diff --git a/src/lmic/lmic_bandplan_kr920.h b/src/lmic/lmic_bandplan_kr920.h index 23a28ae3..2c22f227 100644 --- a/src/lmic/lmic_bandplan_kr920.h +++ b/src/lmic/lmic_bandplan_kr920.h @@ -61,13 +61,6 @@ LMICkr920_isValidBeacon1(const uint8_t *d) { #undef LMICbandplan_isFSK #define LMICbandplan_isFSK() (/* always false */ 0) -// txDone handling for FSK. -void -LMICkr920_txDoneFSK(ostime_t delay, osjobcb_t func); - -#undef LMICbandplan_txDoneFSK -#define LMICbandplan_txDoneFSK(delay, func) LMICkr920_txDoneFSK(delay, func) - #define LMICbandplan_getInitialDrJoin() (KR920_DR_SF7) void LMICkr920_setBcnRxParams(void); diff --git a/src/lmic/lmic_eu868.c b/src/lmic/lmic_eu868.c index d4b9b6b3..01bcd9a4 100644 --- a/src/lmic/lmic_eu868.c +++ b/src/lmic/lmic_eu868.c @@ -247,14 +247,6 @@ ostime_t LMICeu868_nextJoinState(void) { } #endif // !DISABLE_JOIN -// Class A txDone handling for FSK. -void -LMICeu868_txDoneFSK(ostime_t delay, osjobcb_t func) { - LMIC.rxtime = LMIC.txend + delay - PRERX_FSK*us2osticksRound(160); - LMIC.rxsyms = RXLEN_FSK; - os_setTimedCallback(&LMIC.osjob, LMIC.rxtime - RX_RAMPUP, func); -} - // set the Rx1 dndr, rps. void LMICeu868_setRx1Params(void) { u1_t const txdr = LMIC.dndr; diff --git a/src/lmic/lmic_eu_like.c b/src/lmic/lmic_eu_like.c index 4b72bb0d..e3f5cfbd 100644 --- a/src/lmic/lmic_eu_like.c +++ b/src/lmic/lmic_eu_like.c @@ -250,4 +250,33 @@ void LMICeulike_setRx1Freq(void) { LMIC.freq = dlFreq; #endif // !DISABLE_MCMD_DlChannelReq } + +// Class A txDone handling for FSK. +void +LMICeulike_txDoneFSK(ostime_t delay, osjobcb_t func) { + LMIC.rxsyms = RXLEN_FSK; + + // If a clock error is specified, compensate for it by extending the + // receive window + delay -= PRERX_FSK * us2osticksRound(160); + + if (LMIC.client.clockError != 0) { + // Calculate how much the clock will drift maximally after delay has + // passed. This indicates the amount of time we can be early + // _or_ late. + ostime_t drift = (int64_t)delay * LMIC.client.clockError / MAX_CLOCK_ERROR; + + // Increase the receive window by twice the maximum drift (to + // compensate for a slow or a fast clock). + // decrease the rxtime to compensate for. Note that hsym is a + // *half* symbol time, so the factor 2 is hidden. First check if + // this would overflow (which can happen if the drift is very + // high, or the symbol time is low at high datarates). + delay -= drift; + } + + LMIC.rxtime = LMIC.txend + delay; + os_setTimedCallback(&LMIC.osjob, LMIC.rxtime - RX_RAMPUP, func); +} + #endif // CFG_LMIC_EU_like diff --git a/src/lmic/lmic_eu_like.h b/src/lmic/lmic_eu_like.h index 624fa78f..c9bbeac1 100644 --- a/src/lmic/lmic_eu_like.h +++ b/src/lmic/lmic_eu_like.h @@ -56,7 +56,8 @@ LMICeulike_isValidBeacon1(const uint8_t *d) { #define LMICbandplan_isFSK() (0) // provide a default LMICbandplan_txDoneDoFSK() -#define LMICbandplan_txDoneFSK(delay, func) do { } while (0) +void LMICeulike_txDoneFSK(ostime_t delay, osjobcb_t func); +#define LMICbandplan_txDoneFSK(delay, func) LMICeulike_txDoneFSK(delay, func) #define LMICbandplan_joinAcceptChannelClear() LMICbandplan_initDefaultChannels(/* normal, not join */ 0) diff --git a/src/lmic/lmic_in866.c b/src/lmic/lmic_in866.c index 78c5e81a..15916a15 100644 --- a/src/lmic/lmic_in866.c +++ b/src/lmic/lmic_in866.c @@ -212,14 +212,6 @@ ostime_t LMICin866_nextJoinState(void) { } #endif // !DISABLE_JOIN -// Class A txDone handling for FSK. -void -LMICin866_txDoneFSK(ostime_t delay, osjobcb_t func) { - LMIC.rxtime = LMIC.txend + delay - PRERX_FSK*us2osticksRound(160); - LMIC.rxsyms = RXLEN_FSK; - os_setTimedCallback(&LMIC.osjob, LMIC.rxtime - RX_RAMPUP, func); -} - // set the Rx1 dndr, rps. void LMICin866_setRx1Params(void) { u1_t const txdr = LMIC.dndr; diff --git a/src/lmic/lmic_kr920.c b/src/lmic/lmic_kr920.c index d4e06979..9ea1dac7 100644 --- a/src/lmic/lmic_kr920.c +++ b/src/lmic/lmic_kr920.c @@ -223,14 +223,6 @@ ostime_t LMICkr920_nextJoinState(void) { } #endif // !DISABLE_JOIN -// // txDone handling for FSK. -// void -// LMICkr920_txDoneFSK(ostime_t delay, osjobcb_t func) { -// LMIC.rxtime = LMIC.txend + delay - PRERX_FSK*us2osticksRound(160); -// LMIC.rxsyms = RXLEN_FSK; -// os_setTimedCallback(&LMIC.osjob, LMIC.rxtime - RX_RAMPUP, func); -// } - // set the Rx1 dndr, rps. void LMICkr920_setRx1Params(void) { u1_t const txdr = LMIC.dndr; From 92dc08f2b59c76854ff153deda0599d6941f612c Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 9 Sep 2019 01:43:18 -0400 Subject: [PATCH 20/31] Fix comment --- src/lmic/lmic_eu868.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lmic/lmic_eu868.c b/src/lmic/lmic_eu868.c index 01bcd9a4..f8d51d15 100644 --- a/src/lmic/lmic_eu868.c +++ b/src/lmic/lmic_eu868.c @@ -82,7 +82,7 @@ static CONST_TABLE(ostime_t, DR2HSYM_osticks)[] = { us2osticksRound(128 << 3), // DR_SF8 us2osticksRound(128 << 2), // DR_SF7 us2osticksRound(128 << 1), // DR_SF7B - us2osticksRound(80) // FSK -- not used (time for 1/2 byte) + us2osticksRound(80) // FSK -- time for 1/2 byte (unused by LMIC) }; ostime_t LMICeu868_dr2hsym(uint8_t dr) { From a253285890ca6ea77db4dd2f95960c4849c3a4d4 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 9 Sep 2019 01:50:41 -0400 Subject: [PATCH 21/31] Version is v3.0.99.1 --- src/lmic/lmic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lmic/lmic.h b/src/lmic/lmic.h index fce6473c..b43b9f45 100644 --- a/src/lmic/lmic.h +++ b/src/lmic/lmic.h @@ -105,7 +105,7 @@ extern "C"{ #define ARDUINO_LMIC_VERSION_CALC(major, minor, patch, local) \ (((major) << 24u) | ((minor) << 16u) | ((patch) << 8u) | (local)) -#define ARDUINO_LMIC_VERSION ARDUINO_LMIC_VERSION_CALC(3, 0, 99, 0) /* v3.0.99.0 */ +#define ARDUINO_LMIC_VERSION ARDUINO_LMIC_VERSION_CALC(3, 0, 99, 1) /* v3.0.99.0 */ #define ARDUINO_LMIC_VERSION_GET_MAJOR(v) \ (((v) >> 24u) & 0xFFu) From 14ea892da22aa9ecc482df33714b3b6f06f3687f Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 9 Sep 2019 10:56:31 -0400 Subject: [PATCH 22/31] Fix #441: handle TX busy at FSMSTATE_TESTMODE --- src/lmic/lmic_compliance.c | 18 +++++++++++++++--- src/lmic/lmic_compliance.h | 3 ++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/lmic/lmic_compliance.c b/src/lmic/lmic_compliance.c index 6db476ac..962da45d 100644 --- a/src/lmic/lmic_compliance.c +++ b/src/lmic/lmic_compliance.c @@ -575,15 +575,26 @@ fsmDispatch( acEnterActiveMode(); acSetTimer(sec2osticks(1)); } - if (eventflags_TestAndClear(LMIC_COMPLIANCE_EVENT_TIMER_EXPIRED)) + if (eventflags_TestAndClear(LMIC_COMPLIANCE_EVENT_TIMER_EXPIRED)) { + newState = LMIC_COMPLIANCE_FSMSTATE_TESTMODE; + } + break; + } + + case LMIC_COMPLIANCE_FSMSTATE_TXBUSY: { + if (fEntry) { + acSetTimer(sec2osticks(1)); + } + if (eventflags_TestAndClear(LMIC_COMPLIANCE_EVENT_TIMER_EXPIRED)) { newState = LMIC_COMPLIANCE_FSMSTATE_TESTMODE; + } break; } case LMIC_COMPLIANCE_FSMSTATE_TESTMODE: { if (LMIC.opmode & OP_TXDATA) { - // stay here until we can do something - break; + // go back and wait some more. + newState = LMIC_COMPLIANCE_FSMSTATE_TXBUSY; } if (eventflags_TestAndClear(LMIC_COMPLIANCE_EVENT_DEACTIVATE)) { newState = LMIC_COMPLIANCE_FSMSTATE_INACTIVE; @@ -628,6 +639,7 @@ fsmDispatch( if (eventflags_TestAndClear(LMIC_COMPLIANCE_EVENT_TIMER_EXPIRED)) { newState = LMIC_COMPLIANCE_FSMSTATE_TESTMODE; } + break; } default: { diff --git a/src/lmic/lmic_compliance.h b/src/lmic/lmic_compliance.h index 52775748..8efe0e8e 100644 --- a/src/lmic/lmic_compliance.h +++ b/src/lmic/lmic_compliance.h @@ -77,11 +77,12 @@ enum lmic_compliance_fsmstate_e { LMIC_COMPLIANCE_FSMSTATE_ECHOING = 5, LMIC_COMPLIANCE_FSMSTATE_REPORTING = 6, LMIC_COMPLIANCE_FSMSTATE_RECOVERY = 7, + LMIC_COMPLIANCE_FSMSTATE_TXBUSY = 8, }; #define LMIC_COMPLIANCE_FSMSTATE__NAMES \ "INITIAL", "NOCHANGE", "ACTIVE", "INACTIVE", "TESTMODE", \ - "ECHOING", "REPORTING", "RECOVERY" + "ECHOING", "REPORTING", "RECOVERY", "TXBUSY" typedef struct lmic_compliance_eventcb_s lmic_compliance_eventcb_t; struct lmic_compliance_eventcb_s { From f99a0d1e17ef237a89502751693576967095de94 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 9 Sep 2019 12:25:44 -0400 Subject: [PATCH 23/31] Fix typo in comment --- src/lmic/lmic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lmic/lmic.h b/src/lmic/lmic.h index b43b9f45..0584c41e 100644 --- a/src/lmic/lmic.h +++ b/src/lmic/lmic.h @@ -105,7 +105,7 @@ extern "C"{ #define ARDUINO_LMIC_VERSION_CALC(major, minor, patch, local) \ (((major) << 24u) | ((minor) << 16u) | ((patch) << 8u) | (local)) -#define ARDUINO_LMIC_VERSION ARDUINO_LMIC_VERSION_CALC(3, 0, 99, 1) /* v3.0.99.0 */ +#define ARDUINO_LMIC_VERSION ARDUINO_LMIC_VERSION_CALC(3, 0, 99, 1) /* v3.0.99.1 */ #define ARDUINO_LMIC_VERSION_GET_MAJOR(v) \ (((v) >> 24u) & 0xFFu) From 76f7bd5e48c3e2113b72c6467ab3808391b447ca Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 9 Sep 2019 12:36:54 -0400 Subject: [PATCH 24/31] Silence AVR warnings on ARDUINO_LMIC_VERSION --- src/lmic/lmic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lmic/lmic.h b/src/lmic/lmic.h index 0584c41e..8a73d902 100644 --- a/src/lmic/lmic.h +++ b/src/lmic/lmic.h @@ -103,7 +103,7 @@ extern "C"{ // Arduino LMIC version #define ARDUINO_LMIC_VERSION_CALC(major, minor, patch, local) \ - (((major) << 24u) | ((minor) << 16u) | ((patch) << 8u) | (local)) + (((major) << UINT32_C(24)) | ((minor) << UINT32_C(16)) | ((patch) << UINT32_C(8)) | ((local << UINT32_C(0)))) #define ARDUINO_LMIC_VERSION ARDUINO_LMIC_VERSION_CALC(3, 0, 99, 1) /* v3.0.99.1 */ From 42da75b560c7f3fc4ec75b35da6864906dd1981c Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 9 Sep 2019 19:40:21 -0400 Subject: [PATCH 25/31] Fix #442: make RX timing closer to Semtech's --- .../compliance-otaa-halconfig.ino | 5 +- src/lmic/lmic.c | 64 ++++++++++++------- src/lmic/lmic.h | 4 +- src/lmic/lmic_bandplan.h | 34 ++++++++-- src/lmic/lmic_eu_like.c | 25 ++------ src/lmic/oslmic.h | 10 ++- 6 files changed, 90 insertions(+), 52 deletions(-) diff --git a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino index 978d2fae..dd6e40a1 100644 --- a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino +++ b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino @@ -310,8 +310,8 @@ void printAllRegisters(void) { printNl(); printHex2(i); } + Serial.print(((i % 8) == 0) ? F(" - ") : F(" ")); printHex2(regbuf[i]); - Serial.print(((i % 16) == 8) ? F(" - ") : F(" ")); } // reset the radio, just in case the register dump caused issues. @@ -630,7 +630,8 @@ void setup() { // Reset the MAC state. Session and pending data transfers will be discarded. LMIC_reset(); - LMIC_setClockError(1 * MAX_CLOCK_ERROR / 100); + // set clock rate error to 0.1% + LMIC_setClockError(1 * MAX_CLOCK_ERROR / 1000); // do the network-specific setup prior to join. setupForNetwork(false); diff --git a/src/lmic/lmic.c b/src/lmic/lmic.c index 34491299..20d467a2 100644 --- a/src/lmic/lmic.c +++ b/src/lmic/lmic.c @@ -306,11 +306,11 @@ static ostime_t calcRxWindow (u1_t secs, dr_t dr) { rxoff = (LMIC.drift * (ostime_t)secs) >> BCN_INTV_exp; err = (LMIC.lastDriftDiff * (ostime_t)secs) >> BCN_INTV_exp; } - u1_t rxsyms = MINRX_SYMS; + u1_t rxsyms = LMICbandplan_MINRX_SYMS_LoRa_ClassB; err += (ostime_t)LMIC.maxDriftDiff * LMIC.missedBcns; - LMIC.rxsyms = MINRX_SYMS + (err / dr2hsym(dr)); + LMIC.rxsyms = LMICbandplan_MINRX_SYMS_LoRa_ClassB + (err / dr2hsym(dr)); - return (rxsyms-PAMBL_SYMS) * dr2hsym(dr) + rxoff; + return (rxsyms-LMICbandplan_PAMBL_SYMS) * dr2hsym(dr) + rxoff; } @@ -323,8 +323,8 @@ static void calcBcnRxWindowFromMillis (u1_t ms, bit_t ini) { LMIC.bcninfo.flags |= BCN_NODRIFT|BCN_NODDIFF; } ostime_t hsym = dr2hsym(DR_BCN); - LMIC.bcnRxsyms = MINRX_SYMS + ms2osticksCeil(ms) / hsym; - LMIC.bcnRxtime = LMIC.bcninfo.txtime + BCN_INTV_osticks - (LMIC.bcnRxsyms-PAMBL_SYMS) * hsym; + LMIC.bcnRxsyms = LMICbandplan_MINRX_SYMS_LoRa_ClassB + ms2osticksCeil(ms) / hsym; + LMIC.bcnRxtime = LMIC.bcninfo.txtime + BCN_INTV_osticks - (LMIC.bcnRxsyms-LMICbandplan_PAMBL_SYMS) * hsym; } #endif // !DISABLE_BEACONS @@ -1421,14 +1421,7 @@ static void setupRx2 (void) { radioRx(); } - -static void schedRx12 (ostime_t delay, osjobcb_t func, u1_t dr) { - ostime_t hsym = dr2hsym(dr); - - LMIC.rxsyms = MINRX_SYMS; - - // If a clock error is specified, compensate for it by extending the - // receive window +ostime_t LMICcore_adjustForDrift (ostime_t delay, ostime_t hsym) { if (LMIC.client.clockError != 0) { // Calculate how much the clock will drift maximally after delay has // passed. This indicates the amount of time we can be early @@ -1437,20 +1430,47 @@ static void schedRx12 (ostime_t delay, osjobcb_t func, u1_t dr) { // Increase the receive window by twice the maximum drift (to // compensate for a slow or a fast clock). - // decrease the rxtime to compensate for. Note that hsym is a - // *half* symbol time, so the factor 2 is hidden. First check if - // this would overflow (which can happen if the drift is very - // high, or the symbol time is low at high datarates). - if ((255 - LMIC.rxsyms) * hsym < drift) + delay -= drift; + + // adjust rxsyms (the size of the window in syms) according to our + // uncertainty. do this in a strange order to avoid a divide if we can. + // rely on hsym = Tsym / 2 + if ((255 - LMIC.rxsyms) * hsym < drift) { LMIC.rxsyms = 255; - else - LMIC.rxsyms += drift / hsym; + } else { + LMIC.rxsyms = (u1_t) (LMIC.rxsyms + drift / hsym); + } + } + return delay; +} + +ostime_t LMICcore_RxWindowOffset (ostime_t hsym, u1_t rxsyms_in) { + ostime_t const Tsym = 2 * hsym; + ostime_t rxsyms; + ostime_t rxoffset; + rxsyms = ((2 * (int)rxsyms_in - 8) * Tsym + LMICbandplan_RX_ERROR_ABS_osticks * 2 + Tsym - 1) / Tsym; + if (rxsyms < rxsyms_in) { + rxsyms = rxsyms_in; } + LMIC.rxsyms = (u1_t) rxsyms; + + rxoffset = (8 - rxsyms) * hsym - LMICbandplan_RX_EXTRA_MARGIN_osticks; + + return rxoffset; +} - // Center the receive window on the center of the expected preamble +static void schedRx12 (ostime_t delay, osjobcb_t func, u1_t dr) { + ostime_t hsym = dr2hsym(dr); + + // Center the receive window on the center of the expected preamble and timeout. // (again note that hsym is half a sumbol time, so no /2 needed) - LMIC.rxtime = LMIC.txend + delay + PAMBL_SYMS * hsym - LMIC.rxsyms * hsym; + // we leave RX_RAMPUP unadjusted for the clock drift. The IBM LMIC generates delays + // that are too long for SF12, and too short for other SFs, so we follow the + // Semtech reference code. + // + // This also sets LMIC.rxsyms. + LMIC.rxtime = LMIC.txend + LMICcore_adjustForDrift(delay + LMICcore_RxWindowOffset(hsym, LMICbandplan_MINRX_SYMS_LoRa_ClassA), hsym); LMIC_X_DEBUG_PRINTF("%"LMIC_PRId_ostime_t": sched Rx12 %"LMIC_PRId_ostime_t"\n", os_getTime(), LMIC.rxtime - RX_RAMPUP); os_setTimedCallback(&LMIC.osjob, LMIC.rxtime - RX_RAMPUP, func); diff --git a/src/lmic/lmic.h b/src/lmic/lmic.h index 8a73d902..d31d81cd 100644 --- a/src/lmic/lmic.h +++ b/src/lmic/lmic.h @@ -103,9 +103,9 @@ extern "C"{ // Arduino LMIC version #define ARDUINO_LMIC_VERSION_CALC(major, minor, patch, local) \ - (((major) << UINT32_C(24)) | ((minor) << UINT32_C(16)) | ((patch) << UINT32_C(8)) | ((local << UINT32_C(0)))) + (((major) << 24ul) | ((minor) << 16ul) | ((patch) << 8ul) | ((local) << 0ul)) -#define ARDUINO_LMIC_VERSION ARDUINO_LMIC_VERSION_CALC(3, 0, 99, 1) /* v3.0.99.1 */ +#define ARDUINO_LMIC_VERSION ARDUINO_LMIC_VERSION_CALC(3, 0, 99, 2) /* v3.0.99.2 */ #define ARDUINO_LMIC_VERSION_GET_MAJOR(v) \ (((v) >> 24u) & 0xFFu) diff --git a/src/lmic/lmic_bandplan.h b/src/lmic/lmic_bandplan.h index 62df760b..74efc619 100644 --- a/src/lmic/lmic_bandplan.h +++ b/src/lmic/lmic_bandplan.h @@ -169,13 +169,35 @@ // // Things common to lmic.c code // +#define LMICbandplan_MINRX_SYMS_LoRa_ClassA 6 +#define LMICbandplan_RX_ERROR_ABS_osticks ms2osticks(10) + +// Semtech inherently (by calculating in ms and taking ceilings) +// rounds up to the next higher ms. It's a lot easier for us +// to just add margin for things like hardware ramp-up time +// and clock calibration when running from the LSE and HSI +// clocks on an STM32. +#define LMICbandplan_RX_EXTRA_MARGIN_osticks us2osticks(2000) + +// probably this should be the same as the Class-A value, but +// we have not the means to thoroughly test this. This is the +// number of rxsyms used in the computations for ping and beacon +// windows. +#define LMICbandplan_MINRX_SYMS_LoRa_ClassB 5 + +#define LMICbandplan_PAMBL_SYMS 8 +#define LMICbandplan_PAMBL_FSK 5 +#define LMICbandplan_PRERX_FSK 1 +#define LMICbandplan_RXLEN_FSK (1+5+2) + +// Legacy names #if !defined(MINRX_SYMS) -#define MINRX_SYMS 5 +# define MINRX_SYMS LMICbandplan_MINRX_SYMS_LoRa_ClassB #endif // !defined(MINRX_SYMS) -#define PAMBL_SYMS 8 -#define PAMBL_FSK 5 -#define PRERX_FSK 1 -#define RXLEN_FSK (1+5+2) +#define PAMBL_SYMS LMICbandplan_PAMBL_SYMS +#define PAMBL_FSK LMICbandplan_PAMBL_FSK +#define PRERX_FSK LMICbandplan_PRERX_FSK +#define RXLEN_FSK LMICbandplan_RXLEN_FSK // this is regional, but so far all regions are the same #if !defined(LMICbandplan_MAX_FCNT_GAP) @@ -204,5 +226,7 @@ // internal APIs ostime_t LMICcore_rndDelay(u1_t secSpan); void LMICcore_setDrJoin(u1_t reason, u1_t dr); +ostime_t LMICcore_adjustForDrift(ostime_t delay, ostime_t hsym); +ostime_t LMICcore_RxWindowOffset(ostime_t hsym, u1_t rxsyms_in); #endif // _lmic_bandplan_h_ diff --git a/src/lmic/lmic_eu_like.c b/src/lmic/lmic_eu_like.c index e3f5cfbd..fbaae360 100644 --- a/src/lmic/lmic_eu_like.c +++ b/src/lmic/lmic_eu_like.c @@ -254,28 +254,13 @@ void LMICeulike_setRx1Freq(void) { // Class A txDone handling for FSK. void LMICeulike_txDoneFSK(ostime_t delay, osjobcb_t func) { - LMIC.rxsyms = RXLEN_FSK; + ostime_t const hsym = us2osticksRound(80); - // If a clock error is specified, compensate for it by extending the - // receive window - delay -= PRERX_FSK * us2osticksRound(160); + // start a little earlier. + delay -= LMICbandplan_PRERX_FSK * us2osticksRound(160); - if (LMIC.client.clockError != 0) { - // Calculate how much the clock will drift maximally after delay has - // passed. This indicates the amount of time we can be early - // _or_ late. - ostime_t drift = (int64_t)delay * LMIC.client.clockError / MAX_CLOCK_ERROR; - - // Increase the receive window by twice the maximum drift (to - // compensate for a slow or a fast clock). - // decrease the rxtime to compensate for. Note that hsym is a - // *half* symbol time, so the factor 2 is hidden. First check if - // this would overflow (which can happen if the drift is very - // high, or the symbol time is low at high datarates). - delay -= drift; - } - - LMIC.rxtime = LMIC.txend + delay; + // set LMIC.rxtime and LMIC.rxsyms: + LMIC.rxtime = LMIC.txend + LMICcore_adjustForDrift(delay + LMICcore_RxWindowOffset(hsym, LMICbandplan_RXLEN_FSK), hsym); os_setTimedCallback(&LMIC.osjob, LMIC.rxtime - RX_RAMPUP, func); } diff --git a/src/lmic/oslmic.h b/src/lmic/oslmic.h index 5ede98c6..f6edae08 100644 --- a/src/lmic/oslmic.h +++ b/src/lmic/oslmic.h @@ -119,11 +119,19 @@ void radio_monitor_rssi(ostime_t n, oslmic_radio_rssi_t *pRssi); //================================================================================ - #ifndef RX_RAMPUP +// RX_RAMPUP specifies the extra time we must allow to set up an RX event due +// to platform issues. It's specified in units of ostime_t. It must reflect +// platform jitter and latency, as well as the speed of the LMIC when running +// on this plaform. #define RX_RAMPUP (us2osticks(2000)) #endif + #ifndef TX_RAMPUP +// TX_RAMPUP specifies the extra time we must allow to set up a TX event) due +// to platform issues. It's specified in units of ostime_t. It must reflect +// platform jitter and latency, as well as the speed of the LMIC when running +// on this plaform. #define TX_RAMPUP (us2osticks(2000)) #endif From 8df712a4d6b94917e40af8afc2ebfa75ebe8445d Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 9 Sep 2019 23:41:13 -0400 Subject: [PATCH 26/31] version is v3.0.99.3 --- src/lmic/lmic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lmic/lmic.h b/src/lmic/lmic.h index d31d81cd..caa7b379 100644 --- a/src/lmic/lmic.h +++ b/src/lmic/lmic.h @@ -105,7 +105,7 @@ extern "C"{ #define ARDUINO_LMIC_VERSION_CALC(major, minor, patch, local) \ (((major) << 24ul) | ((minor) << 16ul) | ((patch) << 8ul) | ((local) << 0ul)) -#define ARDUINO_LMIC_VERSION ARDUINO_LMIC_VERSION_CALC(3, 0, 99, 2) /* v3.0.99.2 */ +#define ARDUINO_LMIC_VERSION ARDUINO_LMIC_VERSION_CALC(3, 0, 99, 3) /* v3.0.99.3 */ #define ARDUINO_LMIC_VERSION_GET_MAJOR(v) \ (((v) >> 24u) & 0xFFu) From b57531ee37defdc958440c9a1cdc7e0dd209efdc Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Mon, 9 Sep 2019 23:44:56 -0400 Subject: [PATCH 27/31] Improve clock cal for STM32L0 in compliance sketch --- .../compliance-otaa-halconfig.ino | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino index dd6e40a1..d26afac4 100644 --- a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino +++ b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino @@ -631,7 +631,7 @@ void setup() { LMIC_reset(); // set clock rate error to 0.1% - LMIC_setClockError(1 * MAX_CLOCK_ERROR / 1000); + //LMIC_setClockError(1 * MAX_CLOCK_ERROR / 1000); // do the network-specific setup prior to join. setupForNetwork(false); @@ -967,20 +967,20 @@ uint32_t Stm32_CalibrateSystemClock(void) CalibLow = 0; CalibHigh = 0; mSecondLow = 0; - mSecondHigh = 2000; + mSecondHigh = 2000000; fHaveSeenLow = fHaveSeenHigh = false; /* loop until we have a new value */ do { /* meassure the # of millis per RTC second */ - mSecond = MeasureMillisPerRtcSecond(); + mSecond = MeasureMicrosPerRtcSecond(); /* invariant: */ if (Calib == CalibNew) mSecondNew = mSecond; /* if mSecond is low, this meaans we must increase the system clock */ - if (mSecond <= 1000) + if (mSecond <= 1000000) { Serial.print('-'); /* @@ -1098,6 +1098,7 @@ uint32_t Stm32_CalibrateSystemClock(void) if (CalibNew != Calib) { + Serial.print(CalibNew < Calib ? '+' : '-'); if (fCalibrateMSI) { __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(CalibNew); @@ -1109,11 +1110,13 @@ uint32_t Stm32_CalibrateSystemClock(void) delay(500); } + Serial.print(" 0x"); + Serial.println(CalibNew, HEX); return CalibNew; } uint32_t -MeasureMillisPerRtcSecond( +MeasureMicrosPerRtcSecond( void ) { @@ -1128,7 +1131,7 @@ MeasureMillisPerRtcSecond( /* wait for a new second to start, and capture millis() in start */ do { now = RTC->TR & (RTC_TR_ST | RTC_TR_SU); - start = millis(); + start = micros(); } while (second == now); /* update our second of interest */ @@ -1140,7 +1143,7 @@ MeasureMillisPerRtcSecond( /* wait for the next second to start, and capture millis() */ do { now = RTC->TR & (RTC_TR_ST | RTC_TR_SU); - end = millis(); + end = micros(); } while (second == now); /* return the delta */ From eee3933b0007e89cf49e5dd2dac87155cc3db2b0 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Tue, 10 Sep 2019 00:48:22 -0400 Subject: [PATCH 28/31] Shink compliance a little --- .../compliance-otaa-halconfig.ino | 61 ++++++++++++++----- 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino index d26afac4..530f49ae 100644 --- a/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino +++ b/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino @@ -93,6 +93,7 @@ public: uint32_t datum; ostime_t time; ostime_t txend; + ostime_t globalDutyAvail; u4_t freq; u2_t opmode; u2_t fcntDn; @@ -122,8 +123,10 @@ public: } if (i != m_head) { auto const pn = &m_queue[m_tail]; + pn->job = LMIC.osjob; pn->time = os_getTime(); pn->txend = LMIC.txend; + pn->globalDutyAvail = LMIC.globalDutyAvail; pn->event = event; pn->pMessage = pMessage; pn->datum = datum; @@ -173,17 +176,23 @@ hal_failure_handler_t log_assertion; void log_assertion(const char *pMessage, uint16_t line) { eventQueue.putEvent(ev_t(-3), pMessage, line); eventPrintAll(); - Serial.println("***HALTED BY ASSERT***"); + Serial.println(F("***HALTED BY ASSERT***")); while (true) yield(); } -uint8_t lastTxChannel; -bool lastTxStart; +bool lastWasTxStart; +uint32_t lastTxStartTime; void myEventCb(void *pUserData, ev_t ev) { eventQueue.putEvent(ev); + if (ev == EV_TXSTART) { + lastWasTxStart = true; + lastTxStartTime = millis(); + } else if (ev == EV_RXSTART) { + lastWasTxStart = false; + } if (ev == EV_JOINING) { setupForNetwork(true); } else if (ev == EV_JOINED) { @@ -193,7 +202,7 @@ void myEventCb(void *pUserData, ev_t ev) { void eventPrint(cEventQueue::eventnode_t &e); void printFcnts(cEventQueue::eventnode_t &e); - +void printTxend(cEventQueue::eventnode_t &e); void eventPrintAll(void) { while (eventPrintOne()) @@ -245,19 +254,23 @@ void printHex4(unsigned v) { printHex2(v); } +void printSpace(void) { + Serial.print(' '); +} + void printFreq(u4_t freq) { Serial.print(F(": freq=")); Serial.print(freq / 1000000); - Serial.print(F(".")); + Serial.print('.'); Serial.print((freq % 1000000) / 100000); } void printRps(rps_t rps) { Serial.print(F(" rps=0x")); printHex2(rps); Serial.print(F(" (")); Serial.print(getSfName(rps)); - Serial.print(F(" ")); Serial.print(getBwName(rps)); - Serial.print(F(" ")); Serial.print(getCrName(rps)); - Serial.print(F(" ")); Serial.print(getCrcName(rps)); + printSpace(); Serial.print(getBwName(rps)); + printSpace(); Serial.print(getCrName(rps)); + printSpace(); Serial.print(getCrcName(rps)); Serial.print(F(" IH=")); Serial.print(unsigned(getIh(rps))); Serial.print(')'); } @@ -268,8 +281,9 @@ void printOpmode(uint16_t opmode, char sep = ',') { Serial.print(F(" opmode=")); Serial.print(opmode, HEX); } -void printTxend(ostime_t txend) { - Serial.print(F(", txend=")); Serial.print(txend); +void printTxend(cEventQueue::eventnode_t &e) { + Serial.print(F(", txend=")); Serial.print(e.txend); + Serial.print(F(", avail=")); Serial.print(e.globalDutyAvail); } void printTxChnl(u1_t txChnl) { @@ -299,6 +313,7 @@ void printFcnts(cEventQueue::eventnode_t &e) { printHex4(e.fcntDn); } +#if LMIC_ENABLE_event_logging // dump all the registers. Must have printf setup. void printAllRegisters(void) { uint8_t regbuf[0x80]; @@ -324,6 +339,7 @@ void printAllRegisters(void) { const uint8_t opmode = 0x88; // LoRa and sleep. hal_spi_write(0x81, &opmode, 1); } +#endif void printNl(void) { Serial.println(); @@ -347,13 +363,15 @@ void eventPrint(cEventQueue::eventnode_t &e) { Serial.print(e.pMessage); Serial.print(F(", line ")); Serial.print(e.datum); printFreq(e.freq); - printTxend(e.txend); + printTxend(e); printTxChnl(e.txChnl); printRps(e.rps); printOpmode(e.opmode); printTxrxflags(e.txrxFlags); printSaveIrqFlags(e.saveIrqFlags); +#if LMIC_ENABLE_event_logging printAllRegisters(); +#endif } else { if (ev < sizeof(evNames) / sizeof(evNames[0])) { Serial.print(evNames[ev]); @@ -415,8 +433,9 @@ void eventPrint(cEventQueue::eventnode_t &e) { printRps(e.rps); printOpmode(e.opmode); printf(" irqLevel %u", hal_getIrqLevel()); - +#if LMIC_ENABLE_event_logging printAllRegisters(); +#endif break; case EV_REJOIN_FAILED: @@ -429,6 +448,7 @@ void eventPrint(cEventQueue::eventnode_t &e) { printRps(e.rps); printTxrxflags(e.txrxFlags); printFcnts(e); + printTxend(e); break; case EV_LOST_TSYNC: break; @@ -455,7 +475,7 @@ void eventPrint(cEventQueue::eventnode_t &e) { printRps(e.rps); printDatarate(e.datarate); printOpmode(e.opmode); - printTxend(e.txend); + printTxend(e); break; case EV_RXSTART: @@ -463,7 +483,7 @@ void eventPrint(cEventQueue::eventnode_t &e) { printRps(e.rps); printDatarate(e.datarate); printOpmode(e.opmode); - printTxend(e.txend); + printTxend(e); Serial.print(F(", delta ms ")); Serial.print(osticks2ms(e.time - e.txend)); break; @@ -701,9 +721,20 @@ void setupForNetwork(bool preJoin) { void loop() { os_runloop_once(); + + if (lastWasTxStart && millis() - lastTxStartTime > 10000) { + /* ugh. TX timed out */ + Serial.println(F("Tx timed out")); +#if LMIC_ENABLE_event_logging + printAllRegisters(); +#endif + LMIC_clrTxData(); + lastWasTxStart = false; + } + if ((LMIC.opmode & OP_TXRXPEND) == 0 && !os_queryTimeCriticalJobs(ms2osticks(1000))) { - eventPrintOne(); + eventPrintAll(); } } From 3206214623f4693880ef7abc156e7e064f72df08 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Tue, 10 Sep 2019 00:48:49 -0400 Subject: [PATCH 29/31] Don't build EU compliance sketch for now -- too big --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 62a96b60..4338c6cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -166,8 +166,9 @@ script: - _notavr || { _projcfg COMPILE_REGRESSION_TEST CFG_in866 CFG_sx1276_radio && arduino --verify --board $(_avropts) $PWD/examples/raw-feather/raw-feather.ino ; } # make sure the compliance sketch compiles on AVR in all regions. This also requires class-A only + # unfortunately EU currently is a little too large, so we don't do EU. - _notavr || { _projcfg_class_a CFG_us915 CFG_sx1276_radio && arduino --verify --board $(_avropts) $PWD/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino ; } - - _notavr || { _projcfg_class_a CFG_eu868 CFG_sx1276_radio && arduino --verify --board $(_avropts) $PWD/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino ; } + # - _notavr || { _projcfg_class_a CFG_eu868 CFG_sx1276_radio && arduino --verify --board $(_avropts) $PWD/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino ; } - _notavr || { _projcfg_class_a CFG_au921 CFG_sx1276_radio && arduino --verify --board $(_avropts) $PWD/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino ; } - _notavr || { _projcfg_class_a CFG_as923 CFG_sx1276_radio && arduino --verify --board $(_avropts) $PWD/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino ; } - _notavr || { _projcfg_class_a CFG_as923jp CFG_sx1276_radio && arduino --verify --board $(_avropts) $PWD/examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino ; } From bec1cfde34a17eca9e3bf74f6c19c135f3aa57f2 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Tue, 10 Sep 2019 01:28:19 -0400 Subject: [PATCH 30/31] Fix #383: clean up compile warnings found by CI testing --- .../ttn-otaa-feather-us915-dht22.ino | 4 ++-- .../ttn-otaa-feather-us915.ino | 4 ++-- .../ttn-otaa-halconfig-us915.ino | 4 ++-- .../ttn-otaa-network-time/ttn-otaa-network-time.ino | 4 ++-- examples/ttn-otaa/ttn-otaa.ino | 4 ++-- src/lmic/lmic.c | 3 +-- src/lmic/lmic_compliance.c | 13 +++++-------- 7 files changed, 16 insertions(+), 20 deletions(-) diff --git a/examples/ttn-otaa-feather-us915-dht22/ttn-otaa-feather-us915-dht22.ino b/examples/ttn-otaa-feather-us915-dht22/ttn-otaa-feather-us915-dht22.ino index e38a097e..40b26052 100644 --- a/examples/ttn-otaa-feather-us915-dht22/ttn-otaa-feather-us915-dht22.ino +++ b/examples/ttn-otaa-feather-us915-dht22/ttn-otaa-feather-us915-dht22.ino @@ -112,14 +112,14 @@ void onEvent (ev_t ev) { Serial.print("devaddr: "); Serial.println(devaddr, HEX); Serial.print("artKey: "); - for (int i=0; i Date: Tue, 10 Sep 2019 02:19:34 -0400 Subject: [PATCH 31/31] Update documentation / revision history --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 543c3908..56275380 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ attempt to wrap them in a higher level API that is more in the Arduino style. To find out how to use the library itself, see the examples, or see the PDF file in the doc subdirectory. -The [MCCI arduino-lorawan](https://github.com/mcci-catena/arduino-lorawan) library provides a higher level, more Arduino-like wrapper which may be useful. +The [MCCI `arduino-lorawan`](https://github.com/mcci-catena/arduino-lorawan) library provides a higher level, more Arduino-like wrapper which may be useful. This library requires Arduino IDE version 1.6.6 or above, since it requires C99 mode to be enabled by default. @@ -176,7 +176,7 @@ This function is sometimes called at time critical moments. This means that your event function should avoid doing any time-critical work. -Furthermore, the event function may be called in situations where it's not safe to call the LMIC message send APIs. Please be careful to defer all work from your event function to your `loop()` function. See the compliance example sketch for an elaborate version of how this can be done. +Furthermore, in versions of the LMIC prior to v3.0.99.3, the event function may be called in situations where it's not safe to call the general LMIC APIs. In those older LMIC versions, please be careful to defer all work from your event function to your `loop()` function. See the compliance example sketch for an elaborate version of how this can be done. ## Configuration @@ -355,7 +355,9 @@ Code to handle registered callbacks for transmit, receive, and events can be sup #### Disabling external reference to `onEvent()` -In some embedded systems, `onEvent()` may be defined for some other purpose; so the weak reference to the function `onEvent` will be satisfied, causing the LMIC to try to call that function. All reference to `onEvent()` can be suppressed by setting `LMIC_ENABLE_onEvent` to 0. This C preprocessor macro is always defined as a post-condition of `#include "config.h"`; if non-zero, a weak reference to `onEvent()` will be used; if zero, the user `onEvent()` function is not supported, and the client must register an event handler explicitly. +In V3 of the LMIC, you do not need to define a function named `onEvent`. The LMIC will notice that there's no such function, and will suppress the call. However, be cautious -- in a large software package, `onEvent()` may be defined for some other purpose. The LMIC has no way of knowing that this is not the LMIC's `onEvent`, so it will call the function, and this may cause problems. + +All reference to `onEvent()` can be suppressed by setting `LMIC_ENABLE_onEvent` to 0. This C preprocessor macro is always defined as a post-condition of `#include "config.h"`; if non-zero, a weak reference to `onEvent()` will be used; if zero, the user `onEvent()` function is not supported, and the client must register an event handler explicitly. See the PDF documentation for details on `LMIC_registerEventCb()`. #### Enabling long messages @@ -1124,9 +1126,10 @@ function uflt12f(rawUflt12) - v3.0.99 (still in pre-release) adds the following changes. (This is not an exhaustive list.) Note that the behavior of the LMIC changes in important ways, as it now enforces the LoRaWAN mandated maximum frame size for a given data rate. For Class A devices, this may cause your device to go silent after join, if you're not able to handle the frame size dictated by the parameters downloaded to the device by the network during join. The library will attempt to find a data rate that will work, but there is no guarantee that the network has provided such a data rate. + - [#443](https://github.com/mcci-catena/arduino-lmic/pull/443) addresses a number of problems found in cooperation with [RedwoodComm](https://redwoodcomm.com). They suggested a timing improvement to speed testing; this lead to the discovery of a number of problems. Some were in the compliance framework, but one corrects timing for very high spreading factors, several ([#442](https://github.com/mcci-catena/arduino-lmic/issues/442), [#436](https://github.com/mcci-catena/arduino-lmic/issues/438), [#435](https://github.com/mcci-catena/arduino-lmic/issues/435), [#434](https://github.com/mcci-catena/arduino-lmic/issues/434) fix glaring problems in FSK support; [#249](https://github.com/mcci-catena/arduino-lmic/issues/249) greatly enhances stability by making API calls much less likely to crash the LMIC if it's active. Version is v3.0.99.3. - [#388](https://github.com/mcci-catena/arduino-lmic/issues/388), [#389](https://github.com/mcci-catena/arduino-lmic/issues/390), [#390](https://github.com/mcci-catena/arduino-lmic/issues/390) change the LMIC to honor the maximum frame size for a given DR in the current region. This proves to be a breaking change for many applications, especially in the US, because DR0 in the US supports only an 11-byte payload, and many apps were ignoring this. Additional error codes were defined so that apps can detect and recover from this situation, but they must detect; otherwise they run the risk of being blocked from the network by the LMIC. Because of this change, the next version of the LMIC will be V3.1 or higher, and the LMIC version for development is bumped to 3.0.99.0. - [#401](https://github.com/mcci-catena/arduino-lmic/issues/401) adds 865 MHz through 868 MHz to the "1%" band for EU. - - [#395]((https://github.com/mcci-catena/arduino-lmic/pull/395) corrects pin-mode initialization if using `hal_interrupt_init()`. + - [#395](https://github.com/mcci-catena/arduino-lmic/pull/395) corrects pin-mode initialization if using `hal_interrupt_init()`. - [#385](https://github.com/mcci-catena/arduino-lmic/issues/385) corrects an error handling data rate selection for `TxParamSetupReq`, found in US-915 certification testing. (v2.3.2.71) - [#378](https://github.com/mcci-catena/arduino-lmic/pull/378) completely reworks MAC downlink handling. Resulting code passes the LoRaWAN V1.5 EU certification test. (v2.3.2.70) - [#360](https://github.com/mcci-catena/arduino-lmic/issues/360) adds support for the KR-920 regional plan.