From 4a1839cbd1a59125f8b902714346710b2a4c302f Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Sat, 17 Aug 2019 02:01:29 -0400 Subject: [PATCH] Pass KR920 tests (individually) --- src/lmic/lmic.c | 75 ++++++++++++++++++++++++++++------------ src/lmic/lmic.h | 2 ++ src/lmic/lmic_bandplan.h | 4 +++ src/lmic/lmic_eu868.c | 2 +- src/lmic/lmic_eu_like.c | 46 ++++++++++++++---------- src/lmic/lmic_eu_like.h | 3 ++ src/lmic/lmic_in866.c | 2 +- src/lmic/lmic_kr920.c | 2 +- src/lmic/lmic_us_like.c | 33 ++++++++++++------ src/lmic/lmic_us_like.h | 3 ++ 10 files changed, 117 insertions(+), 55 deletions(-) diff --git a/src/lmic/lmic.c b/src/lmic/lmic.c index 067cafd4..1e67fe88 100644 --- a/src/lmic/lmic.c +++ b/src/lmic/lmic.c @@ -38,7 +38,7 @@ DEFINE_LMIC; -#define LMIC_ENABLE_TRACE 1 +//#define LMIC_ENABLE_TRACE 1 #ifndef LMIC_ENABLE_TRACE # define LMIC_ENABLE_TRACE 0 @@ -750,37 +750,60 @@ applyAdrRequests( u1_t p1 = 0; u1_t p4 = 0; bit_t response_fit = 1; + bit_t map_ok = 1; LMICbandplan_saveAdrState(&initialState); - for (oidx = 0; oidx < olen && response_fit; ) { - if (adrAns == MCMD_LinkADRAns_PowerACK | MCMD_LinkADRAns_DataRateACK | MCMD_LinkADRAns_ChannelACK) { + // compute the changes + if (adrAns == MCMD_LinkADRAns_PowerACK | MCMD_LinkADRAns_DataRateACK | MCMD_LinkADRAns_ChannelACK) { + for (oidx = 0; oidx < olen; oidx += kAdrReqSize) { + // can we advance? + if (olen - oidx < kAdrReqSize) { + // ignore the malformed one at the end + break; + } u2_t chmap = os_rlsbf2(&opts[oidx+2]);// list of enabled channels p1 = opts[oidx+1]; // txpow + DR, in case last p4 = opts[oidx+4]; // ChMaskCtl, NbTrans u1_t chpage = p4 & MCMD_LinkADRReq_Redundancy_ChMaskCntl_MASK; // channel page - LMICbandplan_mapChannels(chpage, chmap); + map_ok = LMICbandplan_mapChannels(chpage, chmap); + ArduinoLMIC_putEventDatum("applyAdrRequests: mapChannels", (chpage << 16)|(chmap << 0)); } + } - oidx += kAdrReqSize; + if (! map_ok) { + adrAns &= ~MCMD_LinkADRAns_ChannelACK; + LMICbandplan_restoreAdrState(&initialState); + } + + // now put all the options + for (oidx = 0; oidx < olen && response_fit; oidx += kAdrReqSize) { + // can we advance? + if (olen - oidx < kAdrReqSize) { + // ignore the malformed one at the end + break; + } response_fit = put_mac_uplink_byte2(MCMD_LinkADRAns, adrAns); } // all done scanning options bit_t changes = LMICbandplan_compareAdrState(&initialState); - // handle uplink repeat count - u1_t uprpt = p4 & MCMD_LinkADRReq_Redundancy_NbTrans_MASK; // up repeat count - if (LMIC.upRepeat != uprpt) { - LMIC.upRepeat = uprpt; - changes = 1; - } + // handle the final options + if (adrAns == (MCMD_LinkADRAns_PowerACK | MCMD_LinkADRAns_DataRateACK | MCMD_LinkADRAns_ChannelACK)) { + // handle uplink repeat count + u1_t uprpt = p4 & MCMD_LinkADRReq_Redundancy_NbTrans_MASK; // up repeat count + if (LMIC.upRepeat != uprpt) { + LMIC.upRepeat = uprpt; + changes = 1; + } - if (adrAns & MCMD_LinkADRAns_DataRateACK) { dr_t dr = (dr_t)(p1>>MCMD_LinkADRReq_DR_SHIFT); + ArduinoLMIC_putEventDatum("applyAdrRequests: setDrTxPow", (adrAns << 16)|(dr << 8)|(p1 << 0)); + // handle power changes here, too. changes |= setDrTxpow(DRCHG_NWKCMD, dr, pow2dBm(p1)); } @@ -798,6 +821,8 @@ scan_mac_cmds_link_adr( bit_t *presponse_fit ) { + ArduinoLMIC_putEventDatum("scan_mac_cmds_link_adr", olen); + if (olen == 0) return 0; @@ -867,6 +892,15 @@ scan_mac_cmds( response_fit = 1; cmd = opts[oidx]; + + /* compute length, and exit for illegal commands */ + int const cmdlen = getMacCmdSize(cmd); + if (cmdlen > olen - oidx) { + // "the first unknown command terminates processing" + olen = oidx; + break; + } + switch( cmd ) { case MCMD_LinkCheckAns: { // TODO(tmm@mcci.com) capture these, reliably.. @@ -1119,17 +1153,12 @@ scan_mac_cmds( } /* end case */ } /* end switch */ - /* compute length, and exit for illegal commands */ - int const cmdlen = getMacCmdSize(cmd); - if (cmdlen == 0) { - // "the first unknown command terminates processing" - // force olen to current oidx so we'll exit the while(). - olen = oidx; - } else if (! response_fit) { - olen = oidx; - } - - oidx += cmdlen; + /* if we're out of spce for responses, skip to end. */ + if (! response_fit) { + olen = oidx; + } else { + oidx += cmdlen; + } } /* end while */ return oidx; diff --git a/src/lmic/lmic.h b/src/lmic/lmic.h index 350457e4..1f23a54c 100644 --- a/src/lmic/lmic.h +++ b/src/lmic/lmic.h @@ -168,6 +168,8 @@ enum { MAX_XCHANNELS = 2 }; // extra channels in RAM, channels 0-71 are imm struct lmic_saved_adr_state_s { u2_t channelMap[(72+MAX_XCHANNELS+15)/16]; // enabled bits + u2_t activeChannels125khz; + u2_t activeChannels500khz; }; #endif // ========================================================================== diff --git a/src/lmic/lmic_bandplan.h b/src/lmic/lmic_bandplan.h index 87475e9f..b4c552c6 100644 --- a/src/lmic/lmic_bandplan.h +++ b/src/lmic/lmic_bandplan.h @@ -158,6 +158,10 @@ # error "LMICbandplan_compareAdrState() not defined by bandplan" #endif +#if !defined(LMICbandplan_restoreAdrState) +# error "LMICbandplan_restoreAdrState() not defined by bandplan" +#endif + // // Things common to lmic.c code // diff --git a/src/lmic/lmic_eu868.c b/src/lmic/lmic_eu868.c index 3b6ee353..de700ecb 100644 --- a/src/lmic/lmic_eu868.c +++ b/src/lmic/lmic_eu868.c @@ -64,7 +64,7 @@ static CONST_TABLE(s1_t, TXPOWLEVELS)[] = { int8_t LMICeu868_pow2dBm(uint8_t mcmd_ladr_p1) { uint8_t const pindex = (mcmd_ladr_p1&MCMD_LinkADRReq_POW_MASK)>>MCMD_LinkADRReq_POW_SHIFT; - if (pindex < sizeof(constant_table_TXPOWLEVELS)) { + if (pindex < LENOF_TABLE(TXPOWLEVELS)) { return TABLE_GET_S1(TXPOWLEVELS, pindex); } else { return -128; diff --git a/src/lmic/lmic_eu_like.c b/src/lmic/lmic_eu_like.c index b25f1f4e..00acbe92 100644 --- a/src/lmic/lmic_eu_like.c +++ b/src/lmic/lmic_eu_like.c @@ -80,12 +80,11 @@ bit_t LMICeulike_canMapChannels(u1_t chpage, u2_t chmap) { } } -// assumes that LMICeulike_canMapChannels passed. Return true if something changed. -// chpage is 0 or 6; 6 turns all on; 0 selects channels 0..15 via mask. +// assumes that LMICeulike_canMapChannels passed. Return true if this would +// be a valid final configuration. +// chpage is 0 or 0x60; 0x60 turns all on; 0 selects channels 0..15 via mask. // Assumes canMapChannels has already approved this change. bit_t LMICeulike_mapChannels(u1_t chpage, u2_t chmap) { - u2_t const old_chmap = LMIC.channelMap; - switch (chpage) { case MCMD_LinkADRReq_ChMaskCntl_EULIKE_DIRECT: LMIC.channelMap = chmap; @@ -106,7 +105,7 @@ bit_t LMICeulike_mapChannels(u1_t chpage, u2_t chmap) { // do nothing. break; } - return old_chmap != chmap; + return LMIC.channelMap != 0; } #if !defined(DISABLE_JOIN) @@ -159,12 +158,12 @@ ostime_t LMICeulike_nextJoinState(uint8_t nDefaultChannels) { LMIC.txChnl = 0; if ((++LMIC.txCnt % nDefaultChannels) == 0) { // Lower DR every nth try (having all default channels with same DR) - // - // TODO(tmm@mcci.com) add new DR_REGIN_JOIN_MIN instead of LORAWAN_DR0; - // then we can eliminate the LMIC_REGION_as923 below because we'll set - // the failed flag here. This will cause the outer caller to take the - // appropriate join path. Or add new LMICeulike_GetLowestJoinDR() - // + // + // TODO(tmm@mcci.com) add new DR_REGIN_JOIN_MIN instead of LORAWAN_DR0; + // then we can eliminate the LMIC_REGION_as923 below because we'll set + // the failed flag here. This will cause the outer caller to take the + // appropriate join path. Or add new LMICeulike_GetLowestJoinDR() + // if (LMIC.datarate == LORAWAN_DR0) failed = 1; // we have tried all DR - signal EV_JOIN_FAILED else @@ -185,12 +184,12 @@ ostime_t LMICeulike_nextJoinState(uint8_t nDefaultChannels) { // Duty cycle is based on txend. ostime_t const time = LMICbandplan_nextJoinTime(os_getTime()); - // TODO(tmm@mcci.com): change delay to (0:1) secs + a known t0, but randomized; + // TODO(tmm@mcci.com): change delay to (0:1) secs + a known t0, but randomized; // starting adding a bias after 1 hour, 25 hours, etc.; and limit the duty // cycle on power up. For testability, add a way to set the join start time // externally (a test API) so we can check this feature. // See https://github.com/mcci-catena/arduino-lmic/issues/2 - // Current code doesn't match LoRaWAN 1.0.2 requirements. + // Current code doesn't match LoRaWAN 1.0.2 requirements. LMIC.txend = time + (isTESTMODE() @@ -206,12 +205,12 @@ ostime_t LMICeulike_nextJoinState(uint8_t nDefaultChannels) { #endif // !DISABLE_JOIN void LMICeulike_saveAdrState(lmic_saved_adr_state_t *pStateBuffer) { - memcpy( - pStateBuffer->channelFreq, - LMIC.channelFreq, - sizeof(LMIC.channelFreq) - ); - pStateBuffer->channelMap = LMIC.channelMap; + os_copyMem( + pStateBuffer->channelFreq, + LMIC.channelFreq, + sizeof(LMIC.channelFreq) + ); + pStateBuffer->channelMap = LMIC.channelMap; } bit_t LMICeulike_compareAdrState(const lmic_saved_adr_state_t *pStateBuffer) { @@ -220,6 +219,15 @@ bit_t LMICeulike_compareAdrState(const lmic_saved_adr_state_t *pStateBuffer) { return pStateBuffer->channelMap != LMIC.channelMap; } +void LMICeulike_restoreAdrState(const lmic_saved_adr_state_t *pStateBuffer) { + os_copyMem( + LMIC.channelFreq, + pStateBuffer->channelFreq, + sizeof(LMIC.channelFreq) + ); + LMIC.channelMap = pStateBuffer->channelMap; +} + void LMICeulike_setRx1Freq(void) { #if !defined(DISABLE_MCMD_DlChannelReq) uint32_t dlFreq = LMIC.channelDlFreq[LMIC.txChnl]; diff --git a/src/lmic/lmic_eu_like.h b/src/lmic/lmic_eu_like.h index 8d869734..16f2679e 100644 --- a/src/lmic/lmic_eu_like.h +++ b/src/lmic/lmic_eu_like.h @@ -101,6 +101,9 @@ void LMICeulike_saveAdrState(lmic_saved_adr_state_t *pStateBuffer); bit_t LMICeulike_compareAdrState(const lmic_saved_adr_state_t *pStateBuffer); #define LMICbandplan_compareAdrState(pState) LMICeulike_compareAdrState(pState) +void LMICeulike_restoreAdrState(const lmic_saved_adr_state_t *pStateBuffer); +#define LMICbandplan_restoreAdrState(pState) LMICeulike_restoreAdrState(pState) + // set Rx1 frequency (might be different than uplink). void LMICeulike_setRx1Freq(void); diff --git a/src/lmic/lmic_in866.c b/src/lmic/lmic_in866.c index 8ca14fd2..b99e9686 100644 --- a/src/lmic/lmic_in866.c +++ b/src/lmic/lmic_in866.c @@ -64,7 +64,7 @@ static CONST_TABLE(s1_t, TXPOWLEVELS)[] = { int8_t LMICin866_pow2dBm(uint8_t mcmd_ladr_p1) { uint8_t const pindex = (mcmd_ladr_p1&MCMD_LinkADRReq_POW_MASK)>>MCMD_LinkADRReq_POW_SHIFT; - if (pindex < sizeof(constant_table_TXPOWLEVELS)) { + if (pindex < LENOF_TABLE(TXPOWLEVELS)) { return TABLE_GET_S1(TXPOWLEVELS, pindex); } else { return -128; diff --git a/src/lmic/lmic_kr920.c b/src/lmic/lmic_kr920.c index 4877c20c..cb07b2a8 100644 --- a/src/lmic/lmic_kr920.c +++ b/src/lmic/lmic_kr920.c @@ -62,7 +62,7 @@ static CONST_TABLE(s1_t, TXPOWLEVELS)[] = { int8_t LMICkr920_pow2dBm(uint8_t mcmd_ladr_p1) { uint8_t const pindex = (mcmd_ladr_p1&MCMD_LinkADRReq_POW_MASK)>>MCMD_LinkADRReq_POW_SHIFT; - if (pindex < sizeof(constant_table_TXPOWLEVELS)) { + if (pindex < LENOF_TABLE(TXPOWLEVELS)) { return TABLE_GET_S1(TXPOWLEVELS, pindex); } else { return -128; diff --git a/src/lmic/lmic_us_like.c b/src/lmic/lmic_us_like.c index f0581d51..90d8c92b 100644 --- a/src/lmic/lmic_us_like.c +++ b/src/lmic/lmic_us_like.c @@ -130,6 +130,7 @@ bit_t LMICuslike_canMapChannels(u1_t chpage, u2_t chmap) { return 1; } +// map channels. return true if configuration looks valid. bit_t LMICuslike_mapChannels(u1_t chpage, u2_t chmap) { /* || MCMD_LinkADRReq_ChMaskCntl_USLIKE_125ON and MCMD_LinkADRReq_ChMaskCntl_USLIKE_125OFF are special. The @@ -138,19 +139,18 @@ bit_t LMICuslike_mapChannels(u1_t chpage, u2_t chmap) { || is also special, in that it enables subbands. */ u1_t base, top; - bit_t result = 0; if (chpage == MCMD_LinkADRReq_ChMaskCntl_USLIKE_BANK) { // each bit enables a bank of channels for (u1_t subband = 0; subband < 8; ++subband, chmap >>= 1) { if (chmap & 1) { - result |= LMIC_enableSubBand(subband); + LMIC_enableSubBand(subband); } else { - result |= LMIC_disableSubBand(subband); + LMIC_disableSubBand(subband); } } - return result; + return LMIC.activeChannels125khz || LMIC.activeChannels500khz; } if (chpage < MCMD_LinkADRReq_ChMaskCntl_USLIKE_SPECIAL) { @@ -167,9 +167,9 @@ bit_t LMICuslike_mapChannels(u1_t chpage, u2_t chmap) { // enable or disable all 125kHz channels for (u1_t chnl = 0; chnl < 64; ++chnl) { if (en125) - result |= LMIC_enableChannel(chnl); + LMIC_enableChannel(chnl); else - result |= LMIC_disableChannel(chnl); + LMIC_disableChannel(chnl); } // then apply mask to top 8 channels. @@ -181,11 +181,11 @@ bit_t LMICuslike_mapChannels(u1_t chpage, u2_t chmap) { // Use enable/disable channel to keep activeChannel counts in sync. for (u1_t chnl = base; chnl < top; ++chnl, chmap >>= 1) { if (chmap & 0x0001) - result |= LMIC_enableChannel(chnl); + LMIC_enableChannel(chnl); else - result |= LMIC_disableChannel(chnl); + LMIC_disableChannel(chnl); } - return result; + return LMIC.activeChannels125khz || LMIC.activeChannels500khz; } // US does not have duty cycling - return now as earliest TX time @@ -288,13 +288,26 @@ ostime_t LMICuslike_nextJoinState(void) { #endif void LMICuslike_saveAdrState(lmic_saved_adr_state_t *pStateBuffer) { - memcpy( + os_copyMem( pStateBuffer->channelMap, LMIC.channelMap, sizeof(LMIC.channelMap) ); + pStateBuffer->activeChannels125khz = LMIC.activeChannels125khz; + pStateBuffer->activeChannels500khz = LMIC.activeChannels500khz; } +void LMICuslike_restoreAdrState(const lmic_saved_adr_state_t *pStateBuffer) { + os_copyMem( + LMIC.channelMap, + pStateBuffer->channelMap, + sizeof(LMIC.channelMap) + ); + LMIC.activeChannels125khz = pStateBuffer->activeChannels125khz; + LMIC.activeChannels500khz = pStateBuffer->activeChannels500khz; +} + + bit_t LMICuslike_compareAdrState(const lmic_saved_adr_state_t *pStateBuffer) { return memcmp(pStateBuffer->channelMap, LMIC.channelMap, sizeof(LMIC.channelMap)) != 0; } diff --git a/src/lmic/lmic_us_like.h b/src/lmic/lmic_us_like.h index ba6dc89d..316a12c8 100644 --- a/src/lmic/lmic_us_like.h +++ b/src/lmic/lmic_us_like.h @@ -106,4 +106,7 @@ void LMICuslike_saveAdrState(lmic_saved_adr_state_t *pStateBuffer); bit_t LMICuslike_compareAdrState(const lmic_saved_adr_state_t *pStateBuffer); #define LMICbandplan_compareAdrState(pState) LMICuslike_compareAdrState(pState) +void LMICuslike_restoreAdrState(const lmic_saved_adr_state_t *pStateBuffer); +#define LMICbandplan_restoreAdrState(pState) LMICuslike_restoreAdrState(pState) + #endif // _lmic_us_like_h_