LMiC adapted to work with SX1272MB2xAS LoRa shield.
Fork of LMiC by
Diff: lmic.cpp
- Revision:
- 2:974cafbfb159
- Parent:
- 1:d3b7bde3995c
- Child:
- 4:85b2b647cb64
diff -r d3b7bde3995c -r 974cafbfb159 lmic.cpp --- a/lmic.cpp Tue Mar 31 13:36:56 2015 +0000 +++ b/lmic.cpp Wed Nov 25 02:49:45 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); @@ -732,16 +735,36 @@ // 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) { u4_t freq = (os_rlsbf4(ptr-1) >> 8) * 100; - if( freq >= US915_FREQ_MIN && freq <= US915_FREQ_MAX ) + if( freq < US915_FREQ_MIN || freq > US915_FREQ_MAX ) freq = 0; return freq; } @@ -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]; +}