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
Revision 2:bebd6b2e3d18, committed 2015-11-20
- Comitter:
- pnysten
- Date:
- Fri Nov 20 12:30:06 2015 +0000
- Parent:
- 1:d3b7bde3995c
- Child:
- 3:1079dc4b4c59
- Commit message:
- Port 0 and Opts len = 0: commands in Payload fram
Changed in this revision
| lmic.cpp | Show annotated file Show diff for this revision Revisions of this file |
--- 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) {
