LMiC LoRa Semtech + Nucleo version sending every 10secs
Dependents: LoRaWAN-test-10secs
Fork of LMiC by
Diff: lmic.cpp
- Revision:
- 2:bebd6b2e3d18
- Parent:
- 1:d3b7bde3995c
- Child:
- 3:1079dc4b4c59
diff -r d3b7bde3995c -r bebd6b2e3d18 lmic.cpp --- a/lmic.cpp Tue Mar 31 13:36:56 2015 +0000 +++ b/lmic.cpp Fri Nov 20 12:30:06 2015 +0000 @@ -10,7 +10,10 @@ *******************************************************************************/ //! \file + + #include "lmic.h" +#include "debug.h" #if !defined(MINRX_SYMS) #define MINRX_SYMS 5 @@ -964,6 +967,8 @@ static bit_t decodeFrame (void) { + debug_str("decodeFrame: "); + debug_buf(LMIC.frame, LMIC.dataLen); xref2u1_t d = LMIC.frame; u1_t hdr = d[0]; u1_t ftype = hdr & HDR_FTYPE; @@ -989,6 +994,9 @@ int ackup = (fct & FCT_ACK) != 0 ? 1 : 0; // ACK last up frame int poff = OFF_DAT_OPTS+olen; int pend = dlen-4; // MIC + + debug_val("fct: ", fct); + debug_val("olen: ", olen); if( addr != LMIC.devaddr ) { EV(specCond, WARN, (e_.reason = EV::specCond_t::ALIEN_ADDRESS, @@ -1009,7 +1017,6 @@ if( pend > poff ) port = d[poff++]; - seqno = LMIC.seqnoDn + (u2_t)(seqno - LMIC.seqnoDn); if( !aes_verifyMic(LMIC.nwkKey, LMIC.devaddr, seqno, /*dn*/1, d, pend) ) { @@ -1066,15 +1073,22 @@ xref2u1_t opts = &d[OFF_DAT_OPTS]; int oidx = 0; + debug_val("Port: ", port); while( oidx < olen ) { +// debug_str("Port: "); + debug_str("Process OPTS..."); + debug_hex(opts[oidx]); + debug_str("\r\n"); switch( opts[oidx] ) { case MCMD_LCHK_ANS: { + debug_str("MCMD_LCHK_ANS\r\n"); //int gwmargin = opts[oidx+1]; //int ngws = opts[oidx+2]; oidx += 3; continue; } case MCMD_LADR_REQ: { + debug_str("MCMD_LADR_REQ\r\n"); u1_t p1 = opts[oidx+1]; // txpow + DR u2_t chmap = os_rlsbf2(&opts[oidx+2]);// list of enabled channels u1_t chpage = opts[oidx+4] & MCMD_LADR_CHPAGE_MASK; // channel page @@ -1099,14 +1113,20 @@ setDrTxpow(DRCHG_NWKCMD, dr, pow2dBm(p1)); } LMIC.adrChanged = 1; // Trigger an ACK to NWK + + debug_str("decodeFrame: "); + debug_buf(LMIC.frame, LMIC.dataLen); + continue; } case MCMD_DEVS_REQ: { + debug_str("DEVS_REQ\r\n"); LMIC.devsAns = 1; oidx += 1; continue; } case MCMD_DN2P_SET: { + debug_str("MCMD_DN2P_SET\r\n"); dr_t dr = (dr_t)(opts[oidx+1] & 0x0F); u4_t freq = convFreq(&opts[oidx+2]); oidx += 5; @@ -1124,6 +1144,7 @@ continue; } case MCMD_DCAP_REQ: { + debug_str("MCMD_DCAP_REQ\r\n"); u1_t cap = opts[oidx+1]; oidx += 2; // A value cap=0xFF means device is OFF unless enabled again manually. @@ -1136,6 +1157,7 @@ continue; } case MCMD_SNCH_REQ: { + debug_str("MCMD_SNCH_REQ\r\n"); u1_t chidx = opts[oidx+1]; // channel u4_t freq = convFreq(&opts[oidx+2]); // freq u1_t drs = opts[oidx+5]; // datarate span @@ -1146,6 +1168,7 @@ continue; } case MCMD_PING_SET: { + debug_str("MCMD_PING_SET\r\n"); u4_t freq = convFreq(&opts[oidx+1]); oidx += 4; u1_t flags = 0x80; @@ -1160,6 +1183,7 @@ continue; } case MCMD_BCNI_ANS: { + debug_str("MCMD_BCNI_ANS\r\n"); // Ignore if tracking already enabled if( (LMIC.opmode & OP_TRACK) == 0 ) { LMIC.bcnChnl = opts[oidx+3]; @@ -1193,6 +1217,7 @@ e_.info2 = Base::msbf4(&opts[oidx]))); break; } + if( oidx != olen ) { EV(specCond, ERR, (e_.reason = EV::specCond_t::CORRUPTED_FRAME, e_.eui = MAIN::CDEV->getEui(), @@ -1247,6 +1272,164 @@ LMIC.dataBeg = poff; LMIC.dataLen = pend-poff; } + debug_str("decodeFrame End: "); + debug_buf(LMIC.frame, LMIC.dataLen); + +// PANY + if ((port == 0) && (olen == 0)) + { + oidx = 0; + olen = LMIC.dataLen; + debug_str("Port 0!!!\r\n"); + opts = LMIC.frame + LMIC.dataBeg; + + debug_val("Data Len: ", LMIC.dataLen); + while( oidx < olen ) { + // debug_str("Port: "); + debug_str("Process OPTS..."); + debug_hex(opts[oidx]); + debug_str("\r\n"); + switch( opts[oidx] ) { + case MCMD_LCHK_ANS: { + debug_str("MCMD_LCHK_ANS\r\n"); + //int gwmargin = opts[oidx+1]; + //int ngws = opts[oidx+2]; + oidx += 3; + continue; + } + case MCMD_LADR_REQ: { + debug_str("MCMD_LADR_REQ\r\n"); + u1_t p1 = opts[oidx+1]; // txpow + DR + u2_t chmap = os_rlsbf2(&opts[oidx+2]);// list of enabled channels + u1_t chpage = opts[oidx+4] & MCMD_LADR_CHPAGE_MASK; // channel page + u1_t uprpt = opts[oidx+4] & MCMD_LADR_REPEAT_MASK; // up repeat count + oidx += 5; + + LMIC.ladrAns = 0x80 | // Include an answer into next frame up + MCMD_LADR_ANS_POWACK | MCMD_LADR_ANS_CHACK | MCMD_LADR_ANS_DRACK; + if( !mapChannels(chpage, chmap) ) + LMIC.ladrAns &= ~MCMD_LADR_ANS_CHACK; + dr_t dr = (dr_t)(p1>>MCMD_LADR_DR_SHIFT); + if( !validDR(dr) ) { + LMIC.ladrAns &= ~MCMD_LADR_ANS_DRACK; + EV(specCond, ERR, (e_.reason = EV::specCond_t::BAD_MAC_CMD, + e_.eui = MAIN::CDEV->getEui(), + e_.info = Base::lsbf4(&d[pend]), + e_.info2 = Base::msbf4(&opts[oidx-4]))); + } + if( (LMIC.ladrAns & 0x7F) == (MCMD_LADR_ANS_POWACK | MCMD_LADR_ANS_CHACK | MCMD_LADR_ANS_DRACK) ) { + // Nothing went wrong - use settings + LMIC.upRepeat = uprpt; + setDrTxpow(DRCHG_NWKCMD, dr, pow2dBm(p1)); + } + LMIC.adrChanged = 1; // Trigger an ACK to NWK + + debug_str("decodeFrame: "); + debug_buf(LMIC.frame, LMIC.dataLen); + + continue; + } + case MCMD_DEVS_REQ: { + debug_str("DEVS_REQ\r\n"); + LMIC.devsAns = 1; + oidx += 1; + continue; + } + case MCMD_DN2P_SET: { + debug_str("MCMD_DN2P_SET\r\n"); + dr_t dr = (dr_t)(opts[oidx+1] & 0x0F); + u4_t freq = convFreq(&opts[oidx+2]); + oidx += 5; + LMIC.dn2Ans = 0x80; // answer pending + if( validDR(dr) ) + LMIC.dn2Ans |= MCMD_DN2P_ANS_DRACK; + if( freq != 0 ) + LMIC.dn2Ans |= MCMD_DN2P_ANS_CHACK; + if( LMIC.dn2Ans == (0x80|MCMD_DN2P_ANS_DRACK|MCMD_DN2P_ANS_CHACK) ) { + LMIC.dn2Dr = dr; + LMIC.dn2Freq = freq; + DO_DEVDB(LMIC.dn2Dr,dn2Dr); + DO_DEVDB(LMIC.dn2Freq,dn2Freq); + } + continue; + } + case MCMD_DCAP_REQ: { + debug_str("MCMD_DCAP_REQ\r\n"); + u1_t cap = opts[oidx+1]; + oidx += 2; + // A value cap=0xFF means device is OFF unless enabled again manually. + if( cap==0xFF ) + LMIC.opmode |= OP_SHUTDOWN; // stop any sending + LMIC.globalDutyRate = cap & 0xF; + LMIC.globalDutyAvail = os_getTime(); + DO_DEVDB(cap,dutyCap); + LMIC.dutyCapAns = 1; + continue; + } + case MCMD_SNCH_REQ: { + debug_str("MCMD_SNCH_REQ\r\n"); + u1_t chidx = opts[oidx+1]; // channel + u4_t freq = convFreq(&opts[oidx+2]); // freq + u1_t drs = opts[oidx+5]; // datarate span + LMIC.snchAns = 0x80; + if( freq != 0 && LMIC_setupChannel(chidx, freq, DR_RANGE_MAP(drs&0xF,drs>>4), -1) ) + LMIC.snchAns |= MCMD_SNCH_ANS_DRACK|MCMD_SNCH_ANS_FQACK; + oidx += 6; + continue; + } + case MCMD_PING_SET: { + debug_str("MCMD_PING_SET\r\n"); + u4_t freq = convFreq(&opts[oidx+1]); + oidx += 4; + u1_t flags = 0x80; + if( freq != 0 ) { + flags |= MCMD_PING_ANS_FQACK; + LMIC.ping.freq = freq; + DO_DEVDB(LMIC.ping.intvExp, pingIntvExp); + DO_DEVDB(LMIC.ping.freq, pingFreq); + DO_DEVDB(LMIC.ping.dr, pingDr); + } + LMIC.pingSetAns = flags; + continue; + } + case MCMD_BCNI_ANS: { + debug_str("MCMD_BCNI_ANS\r\n"); + // Ignore if tracking already enabled + if( (LMIC.opmode & OP_TRACK) == 0 ) { + LMIC.bcnChnl = opts[oidx+3]; + // Enable tracking - bcninfoTries + LMIC.opmode |= OP_TRACK; + // Cleared later in txComplete handling - triggers EV_BEACON_FOUND + ASSERT(LMIC.bcninfoTries!=0); + // Setup RX parameters + LMIC.bcninfo.txtime = (LMIC.rxtime + + ms2osticks(os_rlsbf2(&opts[oidx+1]) * MCMD_BCNI_TUNIT) + + ms2osticksCeil(MCMD_BCNI_TUNIT/2) + - BCN_INTV_osticks); + LMIC.bcninfo.flags = 0; // txtime above cannot be used as reference (BCN_PARTIAL|BCN_FULL cleared) + calcBcnRxWindowFromMillis(MCMD_BCNI_TUNIT,1); // error of +/-N ms + + EV(lostFrame, INFO, (e_.reason = EV::lostFrame_t::MCMD_BCNI_ANS, + e_.eui = MAIN::CDEV->getEui(), + e_.lostmic = Base::lsbf4(&d[pend]), + e_.info = (LMIC.missedBcns | + (osticks2us(LMIC.bcninfo.txtime + BCN_INTV_osticks + - LMIC.bcnRxtime) << 8)), + e_.time = MAIN::CDEV->ostime2ustime(LMIC.bcninfo.txtime + BCN_INTV_osticks))); + } + oidx += 4; + continue; + } + } + EV(specCond, ERR, (e_.reason = EV::specCond_t::BAD_MAC_CMD, + e_.eui = MAIN::CDEV->getEui(), + e_.info = Base::lsbf4(&d[pend]), + e_.info2 = Base::msbf4(&opts[oidx]))); + break; + } + } +// PANY + return 1; } @@ -1490,6 +1673,7 @@ static void buildDataFrame (void) { + debug_str("buildDataFrame\r\n"); bit_t txdata = ((LMIC.opmode & (OP_TXDATA|OP_POLL)) != OP_POLL); u1_t dlen = txdata ? LMIC.pendTxLen : 0; @@ -1514,6 +1698,7 @@ LMIC.dn2Ans = 0; } if( LMIC.devsAns ) { // answer to device status + debug_str("Send Device Status\r\n"); LMIC.frame[end+0] = MCMD_DEVS_ANS; LMIC.frame[end+1] = LMIC.margin; LMIC.frame[end+2] = os_getBattLevel(); @@ -2112,6 +2297,10 @@ return 0; } +/*u1_t* LMIC_getEui() { + return MAIN::CDEV->getEui(); +}*/ + // Send a payload-less message to signal device is alive void LMIC_sendAlive (void) {