wayne roberts / Mbed OS lr1110_wifi_geolocation_device

Dependencies:   lr1110 sx12xx_hal

Files at this revision

API Documentation at this revision

Comitter:
Wayne Roberts
Date:
Tue Feb 09 10:47:25 2021 -0800
Parent:
0:d8a6a7dfa435
Commit message:
add source file

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r d8a6a7dfa435 -r 416ed16806fc main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Feb 09 10:47:25 2021 -0800
@@ -0,0 +1,323 @@
+#include "radio.h"
+
+#define TX_DBM              20
+#define BW_KHZ              500
+#define SPREADING_FACTOR    11
+#define CF_HZ               919000000
+
+#define HEADER_LENGTH           10  /* for chipEUI and extra reserved */
+#define WIFI_MAX_RESULTS        20
+#define LORA_RX_TIME_MS         20000       /* how long for cloud to reply with resolved location? */
+
+/**********************************************************************/
+bool wifiResultFormatBasic; /* false, TODO get basic results functional */
+EventQueue queue(4 * EVENTS_EVENT_SIZE);
+
+unsigned packet_len;
+uint8_t chip_eui[8];
+
+InterruptIn ub(USER_BUTTON);  /* released = hi, pressed = lo */
+void button_released(void);
+int wifi_scan_id, long_press_id;
+bool long_pressed;
+
+uint64_t wifi_start_at, wifi_scan_dur;
+
+static void cfg_lora()
+{
+    /* after wifi scan, lora is gone */
+    Radio::LoRaModemConfig(BW_KHZ, SPREADING_FACTOR, 1);
+    Radio::SetChannel(CF_HZ);
+
+    Radio::set_tx_dbm(TX_DBM);
+
+               // preambleLen, fixLen, crcOn, invIQ
+    Radio::LoRaPacketConfig(8, false, true, false);
+}
+
+void wifi_scan()
+{
+    uint8_t wifiScan_buf[9];
+
+    {   /* wifi scan defaults, see LR1110 user manual section 10.2 */
+        unsigned chanmask = 0x0421; // ch1, ch6, ch11
+        unsigned timeout = 105; // in milliseconds, 100 wifi TUs (beacon interval)
+
+        wifiScan_buf[0] = 0x01; // wifi type
+        wifiScan_buf[2] = chanmask; // chanmask-lo
+        chanmask >>= 8;
+        wifiScan_buf[1] = chanmask; // chanmask-hi
+        wifiScan_buf[3] = 0x02; // acqMode
+        wifiScan_buf[4] = WIFI_MAX_RESULTS; // NbMaxRes
+        wifiScan_buf[5] = 0x10; // NbScanPerChan
+        wifiScan_buf[7] = timeout; // Timeout-lo
+        timeout >>= 8;
+        wifiScan_buf[6] = timeout; // Timeout-hi
+        wifiScan_buf[8] = 0x00; // AbortOnTimeout
+    }
+
+    Radio::radio.xfer(OPCODE_WIFI_SCAN, 9, 0, wifiScan_buf);
+    wifi_start_at = Kernel::get_ms_count();
+    printf("wifiScan...\r\n");
+}
+
+void long_press()
+{
+    long_pressed = true;
+    wifi_scan();
+}
+
+void button_pressed()
+{
+    ub.rise(button_released);
+    queue.cancel(wifi_scan_id);
+    long_pressed = false;
+    long_press_id = queue.call_in(500, long_press);
+}
+
+void button_released()
+{
+    ub.fall(button_pressed);
+    if (!long_pressed) {
+        wifi_scan_id = queue.call_in(20, wifi_scan);
+        queue.cancel(long_press_id);
+    }
+}
+
+void txDoneCB()
+{
+    Radio::Rx(0);
+    queue.call_in(LORA_RX_TIME_MS, Radio::Standby);
+}
+
+void rxDoneCB(uint8_t size, float rssi, float snr)
+{
+    unsigned i;
+    printf("%.1fdBm  snr:%.1fdB\t", rssi, snr);
+
+    /*
+    for (i = 0; i < size; i++) {
+        printf("%02x ", Radio::radio.rx_buf[i]);
+    }
+    printf("\r\n");*/
+
+    if (memcmp(Radio::radio.rx_buf, chip_eui, 8) == 0) {
+        /* print resolved coordinates from cloud */
+        printf(">> %s\r\n", Radio::radio.rx_buf + HEADER_LENGTH);
+    }
+}
+
+struct wifidr {
+    const char *txt;
+    float Mbps;
+};
+
+const struct wifidr wifiDatarates[] = {
+    /*   0 */ { NULL, 0},
+    /*   1 */ { "DBPSK", 1},
+    /*   2 */ { "DQPSK", 2},
+    /*   3 */ { "BPSK", 6},
+    /*   4 */ { "BPSK", 9},
+    /*   5 */ { "QPSK", 12},
+    /*   6 */ { "QPSK", 18},
+    /*   7 */ { "16-QAM", 24},
+    /*   8 */ { "16-QAM", 36},
+    /*   9 */ { "(9)", 0},
+    /*  10 */ { "(10)", 0},
+    /*  11 */ { "BPSK", 6.5},
+    /*  12 */ { "QPSK", 13},
+    /*  13 */ { "QPSK", 19.5},
+    /*  14 */ { "16-QAM", 26},
+    /*  15 */ { "16-QAM", 39},
+    /*  16 */ { "(16)", 0},
+    /*  17 */ { "(17)", 0},
+    /*  18 */ { "(18)", 0},
+    /*  19 */ { "BPSK", 7.2},
+    /*  20 */ { "QPSK", 14.4},
+    /*  21 */ { "QPSK", 21.7},
+    /*  22 */ { "16-QAM", 28.9},
+    /*  23 */ { "16-QAM", 43.3},
+};
+
+void print_wifi_result(const uint8_t *result)
+{
+    char out[96];
+    char str[24];
+    unsigned n, macStart;
+    wifiType_t wt;
+    wifiChanInfo_t ci;
+    wt.octet = result[0];
+    ci.octet = result[1];
+    out[0] = 0;
+    strcat(out, "802.11");
+    switch (wt.bits.signal) {
+        case 1: strcat(out, "b"); break;
+        case 2: strcat(out, "g"); break;
+        case 3: strcat(out, "n"); break;
+    }
+    sprintf(str, " %s %.1fMbps", wifiDatarates[wt.bits.datarate].txt, wifiDatarates[wt.bits.datarate].Mbps);
+    strcat(out, str);
+    strcat(out, " ");
+
+    sprintf(str, "ch%u ", ci.bits.channelID);
+    strcat(out, str);
+    switch (ci.bits.channelID) {
+        // table 10-5
+    }
+    strcat(out, " ");
+    sprintf(str, "mv:%u ", ci.bits.macValidationID);
+    strcat(out, str);
+    switch (ci.bits.macValidationID) {
+        case 1: strcat(out, "gateway"); break;
+        case 2: strcat(out, "phone"); break;
+        case 3: strcat(out, "?"); break;
+        // table 10.8
+    }
+
+    strcat(out, " ");
+
+    if (wifiResultFormatBasic) {
+        macStart = 3;
+    } else {
+        macStart = 4;
+    }
+    for (n = 0; n < 6; n++) {
+        sprintf(str, "%02x", result[n+macStart]);
+        strcat(out, str);
+        if (n < 5)
+            strcat(out, ":");
+    }
+
+    sprintf(str, " rssi:%d ", (int8_t)result[2]);
+    strcat(out, str);
+
+    if (!wifiResultFormatBasic) {
+        sprintf(str, "frameCtrl:%02x ", result[3]);
+        strcat(out, str);
+    }
+    printf("%s\r\n", out);
+}
+
+static void service()
+{
+    irq_t irq;
+    irq.dword = Radio::radio.service();
+    if (irq.bits.WifiDone) {
+        unsigned n;
+        stat_t stat;
+        uint8_t nbResults;
+        stat.word = Radio::radio.xfer(OPCODE_GET_WIFI_NB_RESULTS, 0, 0, NULL);
+        stat.word = Radio::radio.xfer(0x0000, 0, 1, &nbResults);
+        if (stat.bits.cmdStatus != CMD_DAT) {
+            printf("get-nbResult-fail\r\n");
+            return;
+        }
+        packet_len = HEADER_LENGTH;
+        printf("%ums nbResults:%u\r\n", (unsigned)wifi_scan_dur, nbResults);
+        for (n = 0; n < nbResults; n++) {
+            uint8_t buf[3];
+            uint8_t resultBuf[22];
+            buf[0] = n;
+            buf[1] = 1; // number of results in this read
+            buf[2] = wifiResultFormatBasic ? 4 : 1;
+            stat.word = Radio::radio.xfer(OPCODE_WIFI_READ_RESULTS, 3, 0, buf);
+            // basic =  9byte length
+            // full  = 22byte length
+            stat.word = Radio::radio.xfer(0x0000, 0, wifiResultFormatBasic ? 9 : 22, resultBuf);
+
+            if (stat.bits.cmdStatus == CMD_DAT) {
+                unsigned n, macStart;
+                wifiChanInfo_t ci;
+                ci.octet = resultBuf[1];
+                if (ci.bits.macValidationID == 1) { // gateway (AP)
+                    macStart = wifiResultFormatBasic ? 3 : 4;
+                    for (n = 0; n < 6; n++) {
+                        Radio::radio.tx_buf[packet_len++] = resultBuf[n+macStart];
+                        printf("%02x", resultBuf[n+macStart]);
+                        if (n < 5)
+                            printf(":");
+                    }
+                    printf(" rssi:%d\r\n", (int8_t)resultBuf[2]);
+                    Radio::radio.tx_buf[packet_len++] = resultBuf[2];
+                }
+            } else
+                printf("readResult:%s\r\n", Radio::radio.cmdStatus_toString(stat.bits.cmdStatus));
+        }
+
+        if (!long_pressed) {
+            unsigned n;
+            cfg_lora();
+            for (n = 0; n < 8; n++)
+                Radio::radio.tx_buf[n] = chip_eui[n];
+
+            Radio::radio.tx_buf[n++] = 0;    // rfu
+            Radio::radio.tx_buf[n++] = 0;    // rfu
+            printf("pktLen:%u\r\n", packet_len);
+            Radio::Send(packet_len, 0, 0, 0);   /* begin transmission */
+        }
+    } // ..if (irq.bits.WifiDone)
+
+    if (irq.bits.TxDone) {
+        printf("main-TxDone\r\n");
+    }
+}
+
+void radio_irq_callback()
+{
+    wifi_scan_dur = Kernel::get_ms_count() - wifi_start_at;
+    queue.call(service);
+}
+
+const RadioEvents_t rev = {
+    /* DioPin_top_half */   radio_irq_callback,
+    /* TxDone_topHalf */    NULL,
+    /* TxDone_botHalf */    txDoneCB,
+    /* TxTimeout  */        NULL,
+    /* RxDone  */           rxDoneCB,
+    /* RxTimeout  */        NULL,
+    /* RxError  */          NULL,
+    /* FhssChangeChannel  */NULL,
+    /* CadDone  */          NULL
+};
+
+int main()
+{
+    Radio::Init(&rev);
+
+    Radio::Standby();
+    cfg_lora();
+
+    {
+        uint8_t buf[9];
+        stat_t stat;
+        stat.word = Radio::radio.xfer(OPCODE_GET_VERSION, 0, 0, NULL);
+        stat.word = Radio::radio.xfer(0x0000, 0, 4, buf);
+        if (stat.bits.cmdStatus == CMD_DAT) {
+            printf("LR1110 chip:%02x use:%02x fw-v%u.%u\r\n",
+                buf[0], /* silicon rev */
+                buf[1], /* use case */
+                buf[2], /* firmware major */
+                buf[3]  /* firmware minor */
+            );
+        }
+
+        stat.word = Radio::radio.xfer(OPCODE_GET_DEVEUI, 0, 0, NULL);
+        stat.word = Radio::radio.xfer(0x0000, 0, 9, buf);
+        memcpy(chip_eui, buf+1, 8);
+        for (unsigned i = 0; i < 9; i++)
+            printf("%02x ", buf[i]);
+        printf("\r\n");
+    }
+
+#ifdef AUTO_TX
+    queue.call_in(500, tx_test);
+#endif /* AUTO_TX */
+
+    if (ub.read())
+        ub.fall(button_pressed);
+    else
+        ub.rise(button_released);
+
+    queue.dispatch();
+}
+