NAMote72 Utility Application – Serial Terminal Monitor control for NAMote72 (note: this application replaces the previous na_mote1 test code application)

Dependencies:   SX127x lib_gps lib_mma8451q lib_mpl3115a2 lib_sx9500 mbed

Fork of na_mote1 by wayne roberts

See wiki Page for a detailed

This is a link to the wiki page

Revision:
2:fb41d1c4b299
Parent:
1:b13a15a34c3f
Child:
3:8924027a8933
--- a/main.cpp	Mon Oct 06 18:59:49 2014 +0000
+++ b/main.cpp	Tue Oct 07 22:16:43 2014 +0000
@@ -9,13 +9,38 @@
  *
  */
 Serial pc(USBTX, USBRX);
-DigitalInOut pb8(PB_8);
-DigitalInOut pb9(PB_9);
-//char _pb8, _pb9;
-/*I2C i2c(I2C_SDA, I2C_SCL);
-MMA8451Q mma8451q(i2c);
-MPL3115A2 mpl3115a2(i2c);
-SX9500 sx9500(i2c);*/
+#ifdef I2C_PIN_TEST
+    DigitalInOut pb8(PB_8);
+    DigitalInOut pb9(PB_9);
+#else
+    I2C i2c(I2C_SDA, I2C_SCL);
+    MMA8451Q mma8451q(i2c);
+    //MPL3115A2 mpl3115a2(i2c);
+    SX9500 sx9500(i2c);
+#endif /* I2C_PIN_TeST */
+
+DigitalOut pd2(PD_2);
+
+DigitalOut red_led(PB_1);
+DigitalOut green_led(PB_7);
+#define LED_ON  0
+#define LED_OFF 1
+
+InterruptIn dio3(PC_8);
+bool clear_valid_header;
+
+bool per_en;
+int PacketRxSequencePrev;
+//uint32_t PacketRxSequence;
+uint32_t PacketPerKoCnt;
+uint32_t PacketPerOkCnt;
+uint32_t PacketNormalCnt;
+/*Ticker per_ticker;
+float per_tx_interval = 0.1;*/
+Timeout per_timeout;
+float per_tx_delay = 0.1;
+int per_id;
+uint32_t PacketTxCnt;
 
 uint8_t tx_cnt;
 char pcbuf[64];
@@ -855,9 +880,14 @@
 void
 printPa()
 {
+    RegPdsTrim1_t pds_trim;
+    
+    pds_trim.octet = radio.read_reg(REG_PDSTRIM1);
+    printf(" txdac=%.1fuA", 2.5 + (pds_trim.bits.prog_txdac * 0.625));
     radio.RegPaConfig.octet = radio.read_reg(REG_PACONFIG);
     if (radio.RegPaConfig.bits.PaSelect) {
-        float output_dBm = 17 - (15-radio.RegPaConfig.bits.OutputPower);
+        //float output_dBm = 17 - (15-radio.RegPaConfig.bits.OutputPower);
+        float output_dBm = (pds_trim.bits.prog_txdac+13) - (15-radio.RegPaConfig.bits.OutputPower);
         printf(" PABOOST OutputPower=%.1fdBm", output_dBm);
     } else {
         float pmax = (0.6*radio.RegPaConfig.bits.MaxPower) + 10.8;
@@ -869,7 +899,7 @@
 void /* things always present, whether lora or fsk */
 common_print_status()
 {
-    printf("version:0x%02x %.3fMHz ", radio.read_reg(REG_VERSION), radio.get_frf_MHz());
+    printf("PD2:%d version:0x%02x %.3fMHz ", pd2.read(), radio.read_reg(REG_VERSION), radio.get_frf_MHz());
     printOpMode();
 
     printPa();
@@ -888,9 +918,41 @@
         printf(" OcpOFF ");
 
     printf("\r\n");
+    
+    if (per_en) {
+        printf("per_tx_delay:%f\n", per_tx_delay);
+        printf("PER device ID:%d\n", per_id);
+    }
 
 }
 
+void per_cb()
+{
+    int i;
+    
+    PacketTxCnt++;
+    
+    radio.tx_buf[0] = per_id;
+    radio.tx_buf[1] = PacketTxCnt >> 24;
+    radio.tx_buf[2] = PacketTxCnt >> 16;
+    radio.tx_buf[3] = PacketTxCnt >> 8;
+    radio.tx_buf[4] = PacketTxCnt;
+    radio.tx_buf[5] = 'P';
+    radio.tx_buf[6] = 'E';
+    radio.tx_buf[7] = 'R';
+    radio.tx_buf[8] = 0;
+    for (i = 0; i < 8; i++)
+        radio.tx_buf[8] += radio.tx_buf[i];
+    red_led = LED_ON;
+    lora.start_tx(lora.RegPayloadLength);
+}
+
+void dio3_cb()
+{
+    green_led = LED_ON;
+    clear_valid_header = true;
+}
+
 void print_rx_buf(int len)
 {
     int i;
@@ -906,6 +968,24 @@
     printf("\r\n");
 }
 
+void print_rx_verbose()
+{
+    float dbm;
+    printLoraIrqs_(false);
+    if (lora.RegHopPeriod > 0) {
+        lora.RegHopChannel.octet = radio.read_reg(REG_LR_HOPCHANNEL);
+        printf("HopCH:%d ", lora.RegHopChannel.bits.FhssPresentChannel);
+    }
+    lora_printCodingRate(true);  // true: of received packet
+    dbm = lora.get_pkt_rssi();
+    printf(" crc%s %.1fdB  %.1fdBm\r\n",
+        lora.RegHopChannel.bits.RxPayloadCrcOn ? "On" : "OFF",
+        lora.RegPktSnrValue / 4.0,
+        dbm
+    );
+    print_rx_buf(lora.RegRxNbBytes);    
+}
+    
 void
 service_radio()
 {
@@ -917,21 +997,43 @@
     
         switch (act) {
             case SERVICE_READ_FIFO:
-                float dbm;
-                if (app == APP_NONE) {     
-                    printLoraIrqs_(false);
-                    if (lora.RegHopPeriod > 0) {
-                        lora.RegHopChannel.octet = radio.read_reg(REG_LR_HOPCHANNEL);
-                        printf("HopCH:%d ", lora.RegHopChannel.bits.FhssPresentChannel);
-                    }
-                    lora_printCodingRate(true);  // true: of received packet
-                    dbm = lora.get_pkt_rssi();
-                    printf(" crc%s %.1fdB  %.1fdBm\r\n",
-                        lora.RegHopChannel.bits.RxPayloadCrcOn ? "On" : "OFF",
-                        lora.RegPktSnrValue / 4.0,
-                        dbm
-                    );
-                    print_rx_buf(lora.RegRxNbBytes);
+                green_led = LED_OFF; // ValidHeader indication
+                if (app == APP_NONE) {   
+                    if (per_en) {
+                        if (lora.RegRxNbBytes > 8 && radio.rx_buf[5] == 'P' && radio.rx_buf[6] == 'E' && radio.rx_buf[7] == 'R') {
+                            int i;
+                            float per;
+                            red_led = LED_OFF;
+                            /* this is PER packet */
+                            uint32_t PacketRxSequence = (radio.rx_buf[1] << 24) | (radio.rx_buf[2] << 16) | (radio.rx_buf[3] << 8) | radio.rx_buf[4];
+                            PacketPerOkCnt++;
+                            //IntervalPerOkCnt++;
+                            
+                            if( PacketRxSequence <= PacketRxSequencePrev )
+                            { // Sequence went back => resynchronization
+                                // dont count missed packets this time
+                                i = 0;
+                            }
+                            else
+                            {
+                                // determine number of missed packets
+                                i = PacketRxSequence - PacketRxSequencePrev - 1;
+                            }
+                            
+                            // be ready for the next
+                            PacketRxSequencePrev = PacketRxSequence;
+                            // increment 'missed' counter for the RX session
+                            PacketPerKoCnt += i;
+                            //IntervalPerKoCnt += i;
+                            printf("%d, ok=%d missed=%d normal=%d ", PacketRxSequence, PacketPerOkCnt, PacketPerKoCnt, PacketNormalCnt);
+                            per = ( 1.0 - ( float )PacketPerOkCnt / ( float )( PacketPerOkCnt + PacketPerKoCnt ) ) * 100.0;
+                            printf("per:%f\n", per);
+                        } else {
+                            PacketNormalCnt++;
+                            print_rx_verbose();
+                        }
+                    } else
+                        print_rx_verbose();
                 } else if (app == APP_CHAT) {
                     if (lora.RegHopChannel.bits.RxPayloadCrcOn) {
                         if (lora.RegIrqFlags.bits.PayloadCrcError)
@@ -952,9 +1054,11 @@
                 }
                 break;
             case SERVICE_TX_DONE:
+                red_led = LED_OFF;
                 if (app == APP_CHAT) {
                     lora.start_rx();
-                }
+                } else if (per_en)
+                    per_timeout.attach(&per_cb, per_tx_delay); // start next TX
                 break;
             case SERVICE_ERROR:
                 printf("error\r\n");
@@ -989,6 +1093,14 @@
                 break;                
          } // ...switch (act)
     }
+    
+    if (clear_valid_header) {
+        RegIrqFlags_t irqs;
+        irqs.octet = 0;
+        irqs.bits.ValidHeader = 1;
+        radio.write_reg(REG_LR_IRQFLAGS, irqs.octet);
+        clear_valid_header = false;
+    }
 }
 
 int get_kbd_str(char* buf, int size)
@@ -1015,6 +1127,7 @@
                 }
             } else if (c == 3) {
                 // ctrl-C abort
+                per_en = false;
                 return -1;
             } else if (i < size) {
                 buf[i++] = c;
@@ -1040,6 +1153,7 @@
         if (radio.RegOpMode.bits.LongRangeMode) {
             lora.RegPayloadLength = len;
             radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
+            red_led = LED_ON;
             lora.start_tx(len);
         } else {
             fsk.start_tx(len);
@@ -1187,20 +1301,26 @@
                 printf("L           toggle LongRangeMode/FSK\r\n");
                 printf("i           radio_init\r\n");
                 printf("h           hw_reset\r\n");
-                printf("tx[%%d]    transmit\r\n");
+                printf("tx[%%d]     transmit\r\n");
                 printf("rx          receive\r\n");   
                 printf("C           toggle crcOn\r\n");
-                printf("op[%%d]    get/set output power\r\n");
+                printf("op[%%d]     get/set output power\r\n");
                 printf("d[0-5]      change DIO pin assignment\r\n");
-                printf("frf[%%f}   get/set operating frequency (MHz)\r\n");
+                printf("frf[%%f]    get/set operating frequency (MHz)\r\n");
+                printf("pd2         toggle PA_High_Power\r\n");
+                printf("bgr[%%d]        get/set prog_txdac BGR bias for TXDAC (7=+20dBm)\r\n"); 
+                printf("per         toggle PER enable\n");
+                printf("pin[%%f]         get/set per_tx_delay (seconds)\n");    
+                printf("pid[%%d]        get/set PER device ID\n");
                 if (radio.RegOpMode.bits.LongRangeMode) {
-                    printf("pl[%%d]    LORA get/set RegPayloadLength\r\n");
+                    printf("pl[%%d]     LORA get/set RegPayloadLength\r\n");
                     printf("cr[1234]    LORA set coding rate \r\n");
-                    printf("bw[%%d]    LORA get/set bandwidth\r\n");
-                    printf("sf[%%d]    LORA get/set spreading factor\r\n");
+                    printf("bw[%%d]     LORA get/set bandwidth\r\n");
+                    printf("sf[%%d]     LORA get/set spreading factor\r\n");
                     printf("T           LORA toggle TxContinuousMode\r\n");
-                    printf("hp[%%d]    LORA get/set hop period\r\n");
+                    printf("hp[%%d]     LORA get/set hop period\r\n");
                     printf("hm          LORA toggle explicit/explicit header mode\r\n");
+                    printf("ld          LORA toggle LowDataRateOptimize\r\n");
                 } else {
                     printf("bw[a][%%d] FSK get-set rxbw (bwa=afcbw)\r\n");
                     printf("br[%%d]    FSK get-set bitrate\r\n");
@@ -1232,14 +1352,20 @@
     } else {
         if (pcbuf[0] == 't' && pcbuf[1] == 'x') { // TX
             if (radio.RegOpMode.bits.LongRangeMode) {
-                if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
-                    sscanf(pcbuf+2, "%d", &i);
-                    lora.RegPayloadLength = i;
+                if (per_en) {
+                    PacketTxCnt = 0;
+                    per_timeout.attach(&per_cb, per_tx_delay);
+                } else {
+                    if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
+                        sscanf(pcbuf+2, "%d", &i);
+                        lora.RegPayloadLength = i;
+                    }
+                    tx_cnt++;
+                    for (i = 0; i < lora.RegPayloadLength; i++)
+                        radio.tx_buf[i] = tx_cnt;
+                    red_led = LED_ON;
+                    lora.start_tx(lora.RegPayloadLength);
                 }
-                tx_cnt++;
-                for (i = 0; i < lora.RegPayloadLength; i++)
-                    radio.tx_buf[i] = tx_cnt;
-                lora.start_tx(lora.RegPayloadLength);
             } else {    // FSK:
                 if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
                     sscanf(pcbuf+2, "%d", &i);
@@ -1286,6 +1412,15 @@
                 }
             radio.write_reg(REG_FSK_RXCONFIG, fsk.RegRxConfig.octet);            
         } else if (pcbuf[0] == 'r' && pcbuf[1] == 'x') { // RX
+            if (per_en) {
+                red_led = LED_OFF;
+                green_led = LED_OFF;
+                PacketNormalCnt = 0;
+                PacketRxSequencePrev = -1;
+                PacketPerKoCnt = 0;
+                PacketPerOkCnt = 0;                
+                dio3.rise(&dio3_cb);
+            }
             if (radio.RegOpMode.bits.LongRangeMode)
                 lora.start_rx();
             else
@@ -1297,7 +1432,9 @@
             sscanf(pcbuf+2, "%x %x", &i, &len);
             radio.write_reg(i, len);
             printf("%02x: %02x\r\n", i, radio.read_reg(i));
-        } else if (pcbuf[0] == 'b' && pcbuf[1] == '8') {
+        }
+#ifdef I2C_PIN_TEST
+        else if (pcbuf[0] == 'b' && pcbuf[1] == '8') {
             printf("SCL:");
             switch (pcbuf[2]) {
                 case '0':
@@ -1335,13 +1472,25 @@
                     break;                    
             }
             printf("\n");                      
-        } /*else if (pcbuf[0] == 'm' && pcbuf[1] == 'm') {
-            mma8451q.try_read();
-        } else if (pcbuf[0] == 'm' && pcbuf[1] == 'p' && pcbuf[2] == 'l') {
+        }
+#else        
+        else if (pcbuf[0] == 'm' && pcbuf[1] == 'm') {
+            if (pcbuf[2] == 's')
+                mma8451q.status();
+            else if (pcbuf[2] == 'a') {
+                if (pcbuf[3] == '0' || pcbuf[3] == '1')
+                    mma8451q.set_active(pcbuf[3] - '0');
+                else  
+                    printf("active:%d\n", mma8451q.get_active());
+            } else
+                mma8451q.try_read();
+        } /*else if (pcbuf[0] == 'm' && pcbuf[1] == 'p' && pcbuf[2] == 'l') {
             mpl3115a2.try_read();
-        } else if (pcbuf[0] == '9' && pcbuf[1] == '5') {
+        }*/ else if (pcbuf[0] == '9' && pcbuf[1] == '5') {
             sx9500.try_read();
-        } */else if (pcbuf[0] == 'm' && pcbuf[1] == 'p' && !radio.RegOpMode.bits.LongRangeMode) {
+        } 
+#endif /* !I2C_PIN_TEST */
+        else if (pcbuf[0] == 'm' && pcbuf[1] == 'p' && !radio.RegOpMode.bits.LongRangeMode) {
             radio.RegDioMapping2.bits.MapPreambleDetect ^= 1;
             radio.write_reg(REG_DIOMAPPING2, radio.RegDioMapping2.octet);
             printf("MapPreambleDetect:");
@@ -1394,6 +1543,15 @@
             radio.write_reg(REG_FSK_AFCFEI, fsk.RegAfcFei.octet);
             fsk.RegAfcFei.bits.AfcClear = 0; 
             printf("%dHz\r\n", (int)(FREQ_STEP_HZ * radio.read_s16(REG_FSK_AFCMSB)));
+        } else if (pcbuf[0] == 'b' && pcbuf[1] == 'g' && pcbuf[2] == 'r') {
+            RegPdsTrim1_t pds_trim;
+            pds_trim.octet = radio.read_reg(REG_PDSTRIM1);
+            if (pcbuf[3] >= '0' && pcbuf[3] <= '9') {
+                sscanf(&pcbuf[3], "%d", &i);
+                pds_trim.bits.prog_txdac = i;
+            }
+            radio.write_reg(REG_PDSTRIM1, pds_trim.octet);
+            printf("prog_txdac:%.1fuA\r\n", 2.5 + (pds_trim.bits.prog_txdac * 0.625));
         } else if (pcbuf[0] == 'b' && pcbuf[1] == 'r' && !radio.RegOpMode.bits.LongRangeMode) {
             if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
                 sscanf(&pcbuf[2], "%d", &i);
@@ -1495,6 +1653,40 @@
                 radio.set_frf_MHz(MHz);
             }
             printf("%fMHz\r\n", radio.get_frf_MHz());
+        } else if (pcbuf[0] == 'p' && pcbuf[1] == 'i' && pcbuf[2] == 'd') {
+            if (pcbuf[3] >= '0' && pcbuf[3] <= '9') {
+                sscanf(pcbuf+3, "%d", &per_id);
+            }
+            printf("PER device ID:%d\n", per_id);
+        } else if (pcbuf[0] == 'p' && pcbuf[1] == 'i' && pcbuf[2] == 'n') {
+            if (pcbuf[3] >= '0' && pcbuf[3] <= '9') {
+                sscanf(pcbuf+2, "%f", &per_tx_delay);
+            }
+            printf("per_tx_delay:%f\n", per_tx_delay);
+        } else if (pcbuf[0] == 'p' && pcbuf[1] == 'e' && pcbuf[2] == 'r') {
+            per_en ^= 1;
+            printf("per_en:%d\n", per_en);
+            if (per_en && radio.RegOpMode.bits.LongRangeMode) {
+                if (radio.type == SX1272) {
+                    lora.RegModemConfig.sx1272bits.LowDataRateOptimize = 1;
+                    radio.write_reg(REG_LR_MODEMCONFIG, lora.RegModemConfig.octet);
+                } else if (radio.type == SX1276) {
+                    lora.RegModemConfig3.sx1276bits.LowDataRateOptimize = 1;
+                    radio.write_reg(REG_LR_MODEMCONFIG3, lora.RegModemConfig3.octet);
+                }
+                lora.RegPayloadLength = 9;
+                radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
+                radio.RegDioMapping1.bits.Dio3Mapping = 1;  // to ValidHeader
+                radio.write_reg(REG_DIOMAPPING1, radio.RegDioMapping1.octet);                                  
+            }
+            PacketRxSequencePrev = -1;
+            //PacketRxSequence = 0;
+            PacketPerKoCnt = 0;
+            PacketPerOkCnt = 0;
+            PacketNormalCnt = 0;
+            if (!per_en) {
+                per_timeout.detach();
+            }
         } else if (pcbuf[0] == 'p' && pcbuf[1] == 'r' && pcbuf[2] == 'e') {
             if (radio.RegOpMode.bits.LongRangeMode) {
                 if (pcbuf[3] >= '0' && pcbuf[3] <= '9') {
@@ -1518,6 +1710,12 @@
             }
             fsk.RegPreambleDetect.octet = radio.read_reg(REG_FSK_PREAMBLEDETECT);
             printf("PreambleDetectorTol:%d\r\n", fsk.RegPreambleDetect.bits.PreambleDetectorTol);
+        } else if (pcbuf[0] == 'p' && pcbuf[1] == 'd' && pcbuf[2] == '2') {
+            if (pd2.read())
+                pd2 = 0;
+            else 
+                pd2 = 1;
+            printf("pd2:%d\n", pd2.read());
         } else if (pcbuf[0] == 'p' && pcbuf[1] == 'd' && !radio.RegOpMode.bits.LongRangeMode) {
             fsk.RegPreambleDetect.bits.PreambleDetectorOn ^= 1;
             radio.write_reg(REG_FSK_PREAMBLEDETECT, fsk.RegPreambleDetect.octet);
@@ -1534,6 +1732,18 @@
             }
             lora.RegPayloadLength = radio.read_reg(REG_LR_PAYLOADLENGTH);
             printf("PayloadLength:%d\r\n", lora.RegPayloadLength);
+        } else if (pcbuf[0] == 'l' && pcbuf[1] == 'd' && radio.RegOpMode.bits.LongRangeMode) {
+            if (radio.type == SX1272) {
+                lora.RegModemConfig.octet = radio.read_reg(REG_LR_MODEMCONFIG);
+                lora.RegModemConfig.sx1272bits.LowDataRateOptimize ^= 1;
+                printf("LowDataRateOptimize:%d\r\n", lora.RegModemConfig.sx1272bits.LowDataRateOptimize);
+                radio.write_reg(REG_LR_MODEMCONFIG, lora.RegModemConfig.octet);
+            } else if (radio.type == SX1276) {
+                lora.RegModemConfig3.octet = radio.read_reg(REG_LR_MODEMCONFIG3);
+                lora.RegModemConfig3.sx1276bits.LowDataRateOptimize ^= 1;
+                printf("LowDataRateOptimize:%d\r\n", lora.RegModemConfig3.sx1276bits.LowDataRateOptimize); 
+                radio.write_reg(REG_LR_MODEMCONFIG3, lora.RegModemConfig3.octet);
+            }            
         } else if (pcbuf[0] == 'd' && pcbuf[1] >= '0' && pcbuf[1] <= '5') {
             switch (pcbuf[1]) {
                 case '0':
@@ -1567,8 +1777,12 @@
                 fsk_print_dio();
         } else if (pcbuf[0] == 's' && pcbuf[1] == 't' && pcbuf[2] == 'b') {
             radio.set_opmode(RF_OPMODE_STANDBY);
+            green_led = LED_OFF;
+            red_led = LED_OFF;
         } else if (pcbuf[0] == 's' && pcbuf[1] == 'l' && pcbuf[2] == 'e') {
             radio.set_opmode(RF_OPMODE_SLEEP);
+            green_led = LED_OFF;
+            red_led = LED_OFF;
         } else if (pcbuf[0] == 'c' && pcbuf[1] == 'h' && pcbuf[2] == 'a') {
             app = APP_CHAT;
             lora.start_rx();
@@ -1586,6 +1800,9 @@
     pc.baud(57600);
     
     radio.frfs = frfs;
+    
+    green_led = LED_OFF;
+    red_led = LED_OFF;
 
     while(1) {
         switch (app) {