LMIC lib Lora OTA device for Everynet

Fork of LMiC-10secs by Alcatel-Lucent IoT Development

Revision:
2:bebd6b2e3d18
Parent:
1:d3b7bde3995c
Child:
3:1079dc4b4c59
--- 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) {