Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of LMiC by
Diff: lmic.cpp
- Revision:
- 4:85b2b647cb64
- Parent:
- 3:519c71d29a06
- Parent:
- 2:974cafbfb159
diff -r 519c71d29a06 -r 85b2b647cb64 lmic.cpp --- a/lmic.cpp Thu Nov 26 12:46:56 2015 +0000 +++ b/lmic.cpp Thu Nov 26 17:17:08 2015 +0000 @@ -236,7 +236,7 @@ #elif defined(CFG_us915) // ======================================== #define maxFrameLen(dr) ((dr)<=DR_SF11CR ? maxFrameLens[(dr)] : 0xFF) -const u1_t maxFrameLens [] = { 24,66,142,255,255,255,255,255, 66,142 }; +//const u1_t maxFrameLens [] = { 24,66,142,255,255,255,255,255, 66,142 }; const u1_t _DR2RPS_CRC[] = { ILLEGAL_RPS, @@ -315,10 +315,10 @@ return (((ostime_t)tmp << sfx) * OSTICKS_PER_SEC + div/2) / div; } -extern inline s1_t rssi2s1 (int v); +/*extern inline s1_t rssi2s1 (int v); extern inline int s12rssi (s1_t v); extern inline float s12snr (s1_t v); -extern inline s1_t snr2s1 (double v); +extern inline s1_t snr2s1 (double v);*/ extern inline rps_t updr2rps (dr_t dr); extern inline rps_t dndr2rps (dr_t dr); @@ -501,8 +501,11 @@ e_.prevdr = LMIC.datarate|DR_PAGE, e_.prevtxpow = LMIC.adrTxPow)); - if( pow != KEEP_TXPOW ) - LMIC.adrTxPow = pow; + if( pow != KEEP_TXPOW ) { + LMIC.adrTxPow = pow; + if (pow < LMIC.txpow_limit) + LMIC.txpow = pow; + } if( LMIC.datarate != dr ) { LMIC.datarate = dr; DO_DEVDB(LMIC.datarate,datarate); @@ -548,7 +551,7 @@ os_clearMem(&LMIC.channelDrMap, sizeof(LMIC.channelDrMap)); os_clearMem(&LMIC.bands, sizeof(LMIC.bands)); - LMIC.channelMap = 0x1F; + LMIC.channelMap = 0x3; u1_t su = join ? 0 : 6; for( u1_t fu=0; fu<6; fu++,su++ ) { LMIC.channelFreq[fu] = iniChannelFreq[su]; @@ -680,7 +683,7 @@ #define setRx1Params() /*LMIC.freq/rps remain unchanged*/ -static void initJoinLoop (void) { +static void initJoinLoop (void) { // eu868 LMIC.txChnl = os_getRndU1() % 6; LMIC.adrTxPow = 14; setDrJoin(DRCHG_SET, DR_SF7); @@ -731,11 +734,31 @@ // BEG: US915 related stuff // - -static void initDefaultChannels (void) { +static void initDefaultChannels (void) +{ +#ifdef CHNL_HYBRID + int idx = CHNL_HYBRID >> 1; + LMIC.channelMap[0] = 0x0000; + LMIC.channelMap[1] = 0x0000; + LMIC.channelMap[2] = 0x0000; + LMIC.channelMap[3] = 0x0000; + if (CHNL_HYBRID & 1) + LMIC.channelMap[idx] = 0xff00; + else + LMIC.channelMap[idx] = 0x00ff; + + LMIC.channelMap[4] = 1 << CHNL_HYBRID; + LMIC.txpow_limit = 20; +#else for( u1_t i=0; i<4; i++ ) LMIC.channelMap[i] = 0xFFFF; LMIC.channelMap[4] = 0x00FF; + + LMIC.txpow_limit = 30; +#endif + + LMIC.txpow = LMIC.txpow_limit; + LMIC.adrTxPow = LMIC.txpow_limit; } static u4_t convFreq (xref2u1_t ptr) { @@ -777,17 +800,41 @@ static void updateTx (ostime_t txbeg) { u1_t chnl = LMIC.txChnl; +#ifdef JOIN_REQ_DEBUG + printf("chnl%d ", chnl); +#endif /* JOIN_REQ_DEBUG */ if( chnl < 64 ) { LMIC.freq = US915_125kHz_UPFBASE + chnl*US915_125kHz_UPFSTEP; - LMIC.txpow = 30; + + if (LMIC.opmode & OP_JOINING) { + /* use max allowed power for joining */ + if (LMIC.txpow < LMIC.txpow_limit) + LMIC.txpow = LMIC.txpow_limit; + } + +#ifdef JOIN_REQ_DEBUG + printf("%d (125khz)\r\n", LMIC.freq); +#endif /* JOIN_REQ_DEBUG */ return; } - LMIC.txpow = 26; + + /* using 500KHz channel */ + if (LMIC.txpow_limit >= 26) + LMIC.txpow = 26; + else + LMIC.txpow = LMIC.txpow_limit; + if( chnl < 64+8 ) { LMIC.freq = US915_500kHz_UPFBASE + (chnl-64)*US915_500kHz_UPFSTEP; +#ifdef JOIN_REQ_DEBUG + printf("%d (500k)\r\n", LMIC.freq); +#endif /* JOIN_REQ_DEBUG */ } else { ASSERT(chnl < 64+8+MAX_XCHANNELS); LMIC.freq = LMIC.xchFreq[chnl-72]; +#ifdef JOIN_REQ_DEBUG + printf("%d (x)\r\n", LMIC.freq); +#endif /* JOIN_REQ_DEBUG */ } // Update global duty cycle stats @@ -797,29 +844,72 @@ } } +int count_bits(u2_t v) +{ + int c; + + for (c = 0; v; c++) { + v &= v - 1; // clear the last significant bit set + } + + return c; +} + // US does not have duty cycling - return now as earliest TX time #define nextTx(now) (_nextTx(),(now)) static void _nextTx (void) { - if( LMIC.chRnd==0 ) - LMIC.chRnd = os_getRndU1() & 0x3F; + u1_t prev_ch = LMIC.txChnl; + u1_t tries = 0; + u1_t en_cnt; + if( LMIC.datarate >= DR_SF8C ) { // 500kHz - u1_t map = LMIC.channelMap[64/16]&0xFF; - for( u1_t i=0; i<8; i++ ) { - if( (map & (1<<(++LMIC.chRnd & 7))) != 0 ) { - LMIC.txChnl = 64 + (LMIC.chRnd & 7); - return; - } - } +#ifdef CHNL_HYBRID + LMIC.txChnl = 1 << CHNL_HYBRID; // only one channel possible +#else + en_cnt = count_bits(LMIC.channelMap[4]); + do { + do { + LMIC.chRnd = os_getRndU1() & 7; + if (++tries > 48) + return; + } while ( !(LMIC.channelMap[4] & (1 << LMIC.chRnd)) ); + LMIC.txChnl = 64 + LMIC.chRnd; + if (en_cnt < 2) + prev_ch = LMIC.txChnl + 1; // not enough enabled, skip the following test + + } while (prev_ch == LMIC.txChnl); +#endif } else { // 125kHz - for( u1_t i=0; i<64; i++ ) { - u1_t chnl = ++LMIC.chRnd & 0x3F; - if( (LMIC.channelMap[(chnl >> 4)] & (1<<(chnl & 0xF))) != 0 ) { - LMIC.txChnl = chnl; - return; - } - } +#ifdef CHNL_HYBRID + u1_t idx = CHNL_HYBRID >> 1; + en_cnt = count_bits(LMIC.channelMap[idx]); + do { + do { + LMIC.chRnd = os_getRndU1() & 15; + if (++tries > 96) + return; + } while ( !(LMIC.channelMap[idx] & (1 << LMIC.chRnd)) ); + LMIC.txChnl = (idx << 4) + LMIC.chRnd; + if (en_cnt < 2) + prev_ch = LMIC.txChnl + 1; // not enough enabled, skip the following test + + } while (prev_ch == LMIC.txChnl); +#else + en_cnt = count_bits(LMIC.channelMap[0]); + en_cnt += count_bits(LMIC.channelMap[1]); + en_cnt += count_bits(LMIC.channelMap[2]); + en_cnt += count_bits(LMIC.channelMap[3]); + do { + do { + LMIC.chRnd = os_getRndU1() & 63; + } while ( !(LMIC.channelMap[LMIC.chRnd >> 4] & (1 << (LMIC.chRnd & 15))) ); + LMIC.txChnl = LMIC.chRnd; + if (en_cnt < 2) + prev_ch = LMIC.txChnl + 1; // not enough enabled, skip the following test + + } while (prev_ch == LMIC.txChnl); +#endif } - // No feasible channel found! Keep old one. } static void setBcnRxParams (void) { @@ -839,31 +929,43 @@ static void initJoinLoop (void) { LMIC.chRnd = 0; +#ifdef CHNL_HYBRID + LMIC.joinBlockChnl = 0; + LMIC.joinBlock = CHNL_HYBRID; + LMIC.txChnl = LMIC.joinBlock << 3; +#else LMIC.txChnl = 0; - LMIC.adrTxPow = 20; + LMIC.joinBlockChnl = 0; + LMIC.joinBlock = 0; +#endif + LMIC.datarate = DR_SF10; + LMIC.adrTxPow = LMIC.txpow_limit; ASSERT((LMIC.opmode & OP_NEXTCHNL)==0); LMIC.txend = os_getTime(); setDrJoin(DRCHG_SET, DR_SF7); } static ostime_t nextJoinState (void) { - // Try the following: - // SF7/8/9/10 on a random channel 0..63 - // SF8C on a random channel 64..71 - // u1_t failed = 0; - if( LMIC.datarate != DR_SF8C ) { - LMIC.txChnl = 64+(LMIC.txChnl&7); - setDrJoin(DRCHG_SET, DR_SF8C); + + if( LMIC.datarate == DR_SF8C ) { + // attempted 500khz channel, try 125khz channel in next block + LMIC.datarate = DR_SF10; + if (++LMIC.joinBlock == 8) { + LMIC.joinBlock = 0; + if (++LMIC.joinBlockChnl == 8) + LMIC.joinBlockChnl = 0; + } + LMIC.txChnl = (LMIC.joinBlock << 3) + LMIC.joinBlockChnl; } else { - LMIC.txChnl = os_getRndU1() & 0x3F; - s1_t dr = DR_SF7 - ++LMIC.txCnt; - if( dr < DR_SF10 ) { - dr = DR_SF10; - failed = 1; // All DR exhausted - signal failed - } - setDrJoin(DRCHG_SET, dr); + // attempted 125khz channel, try 500khz channel + LMIC.datarate = DR_SF8C; + LMIC.txChnl = LMIC.joinBlock + 64; } +#ifdef JOIN_REQ_DEBUG + printf("njs blk%d, dr%d, txChnl%d ", LMIC.joinBlock, LMIC.datarate, LMIC.txChnl); // crlf in updateTx() +#endif /* JOIN_REQ_DEBUG */ + LMIC.opmode &= ~OP_NEXTCHNL; LMIC.txend = os_getTime() + (isTESTMODE() @@ -931,9 +1033,9 @@ ASSERT(LMIC.dataLen == LEN_BCN); // implicit header RX guarantees this xref2u1_t d = LMIC.frame; if( -#if CFG_eu868 +#ifdef CFG_eu868 d[OFF_BCN_CRC1] != (u1_t)os_crc16(d,OFF_BCN_CRC1) -#elif CFG_us915 +#elif defined(CFG_us915) os_rlsbf2(&d[OFF_BCN_CRC1]) != os_crc16(d,OFF_BCN_CRC1) #endif ) @@ -1322,7 +1424,7 @@ if( LMIC.dataLen == 0 ) { nojoinframe: - if( (LMIC.opmode & OP_JOINING) == 0 ) { + /* keep retrying -- if( (LMIC.opmode & OP_JOINING) == 0 ) { ASSERT((LMIC.opmode & OP_REJOIN) != 0); // REJOIN attempt for roaming LMIC.opmode &= ~(OP_REJOIN|OP_TXRXPEND); @@ -1330,7 +1432,7 @@ LMIC.rejoinCnt++; reportEvent(EV_REJOIN_FAILED); return 1; - } + }*/ LMIC.opmode &= ~OP_TXRXPEND; ostime_t delay = nextJoinState(); EV(devCond, DEBUG, (e_.reason = EV::devCond_t::NO_JACC, @@ -1860,7 +1962,7 @@ LMIC.bcnRxtime = LMIC.bcninfo.txtime + BCN_INTV_osticks - calcRxWindow(0,DR_BCN); LMIC.bcnRxsyms = LMIC.rxsyms; rev: -#if CFG_us915 +#ifdef CFG_us915 LMIC.bcnChnl = (LMIC.bcnChnl+1) & 7; #endif if( (LMIC.opmode & OP_PINGINI) != 0 ) @@ -1930,11 +2032,13 @@ if( txbeg - (now + TX_RAMPUP) < 0 ) { // We could send right now! dr_t txdr = (dr_t)LMIC.datarate; + txbeg = now; if( jacc ) { u1_t ftype; if( (LMIC.opmode & OP_REJOIN) != 0 ) { txdr = lowerDR(txdr, LMIC.rejoinCnt); - ftype = HDR_FTYPE_REJOIN; + //ftype = HDR_FTYPE_REJOIN; + ftype = HDR_FTYPE_JREQ; } else { ftype = HDR_FTYPE_JREQ; } @@ -2170,4 +2274,10 @@ LMIC.adrAckReq = enabled ? LINK_CHECK_INIT : LINK_CHECK_OFF; } - +void LMIC_reverse_memcpy(u1_t *dst, const u1_t *src, size_t n) +{ + size_t i; + + for (i=0; i < n; ++i) + dst[n-1-i] = src[i]; +}