simple example of wifi AP scanning, sending scan-results over radio link

Dependencies:   lr1110 sx12xx_hal

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "radio.h"
00002 
00003 #define TX_DBM              20
00004 #define BW_KHZ              500
00005 #define SPREADING_FACTOR    11
00006 #define CF_HZ               919000000
00007 
00008 #define HEADER_LENGTH           10  /* for chipEUI and extra reserved */
00009 #define WIFI_MAX_RESULTS        20
00010 #define LORA_RX_TIME_MS         20000       /* how long for cloud to reply with resolved location? */
00011 
00012 /**********************************************************************/
00013 bool wifiResultFormatBasic; /* false, TODO get basic results functional */
00014 EventQueue queue(4 * EVENTS_EVENT_SIZE);
00015 
00016 unsigned packet_len;
00017 uint8_t chip_eui[8];
00018 
00019 InterruptIn ub(USER_BUTTON);  /* released = hi, pressed = lo */
00020 void button_released(void);
00021 int wifi_scan_id, long_press_id;
00022 bool long_pressed;
00023 
00024 uint64_t wifi_start_at, wifi_scan_dur;
00025 
00026 static void cfg_lora()
00027 {
00028     /* after wifi scan, lora is gone */
00029     Radio::LoRaModemConfig(BW_KHZ, SPREADING_FACTOR, 1);
00030     Radio::SetChannel(CF_HZ);
00031 
00032     Radio::set_tx_dbm(TX_DBM);
00033 
00034                // preambleLen, fixLen, crcOn, invIQ
00035     Radio::LoRaPacketConfig(8, false, true, false);
00036 }
00037 
00038 void wifi_scan()
00039 {
00040     uint8_t wifiScan_buf[9];
00041 
00042     {   /* wifi scan defaults, see LR1110 user manual section 10.2 */
00043         unsigned chanmask = 0x0421; // ch1, ch6, ch11
00044         unsigned timeout = 105; // in milliseconds, 100 wifi TUs (beacon interval)
00045 
00046         wifiScan_buf[0] = 0x01; // wifi type
00047         wifiScan_buf[2] = chanmask; // chanmask-lo
00048         chanmask >>= 8;
00049         wifiScan_buf[1] = chanmask; // chanmask-hi
00050         wifiScan_buf[3] = 0x02; // acqMode
00051         wifiScan_buf[4] = WIFI_MAX_RESULTS; // NbMaxRes
00052         wifiScan_buf[5] = 0x10; // NbScanPerChan
00053         wifiScan_buf[7] = timeout; // Timeout-lo
00054         timeout >>= 8;
00055         wifiScan_buf[6] = timeout; // Timeout-hi
00056         wifiScan_buf[8] = 0x00; // AbortOnTimeout
00057     }
00058 
00059     Radio::radio.xfer(OPCODE_WIFI_SCAN, 9, 0, wifiScan_buf);
00060     wifi_start_at = Kernel::get_ms_count();
00061     printf("wifiScan...\r\n");
00062 }
00063 
00064 void long_press()
00065 {
00066     long_pressed = true;
00067     wifi_scan();
00068 }
00069 
00070 void button_pressed()
00071 {
00072     ub.rise(button_released);
00073     queue.cancel(wifi_scan_id);
00074     long_pressed = false;
00075     long_press_id = queue.call_in(500, long_press);
00076 }
00077 
00078 void button_released()
00079 {
00080     ub.fall(button_pressed);
00081     if (!long_pressed) {
00082         wifi_scan_id = queue.call_in(20, wifi_scan);
00083         queue.cancel(long_press_id);
00084     }
00085 }
00086 
00087 void txDoneCB()
00088 {
00089     Radio::Rx(0);
00090     queue.call_in(LORA_RX_TIME_MS, Radio::Standby);
00091 }
00092 
00093 void rxDoneCB(uint8_t size, float rssi, float snr)
00094 {
00095     unsigned i;
00096     printf("%.1fdBm  snr:%.1fdB\t", rssi, snr);
00097 
00098     /*
00099     for (i = 0; i < size; i++) {
00100         printf("%02x ", Radio::radio.rx_buf[i]);
00101     }
00102     printf("\r\n");*/
00103 
00104     if (memcmp(Radio::radio.rx_buf, chip_eui, 8) == 0) {
00105         /* print resolved coordinates from cloud */
00106         printf(">> %s\r\n", Radio::radio.rx_buf + HEADER_LENGTH);
00107     }
00108 }
00109 
00110 struct wifidr {
00111     const char *txt;
00112     float Mbps;
00113 };
00114 
00115 const struct wifidr wifiDatarates[] = {
00116     /*   0 */ { NULL, 0},
00117     /*   1 */ { "DBPSK", 1},
00118     /*   2 */ { "DQPSK", 2},
00119     /*   3 */ { "BPSK", 6},
00120     /*   4 */ { "BPSK", 9},
00121     /*   5 */ { "QPSK", 12},
00122     /*   6 */ { "QPSK", 18},
00123     /*   7 */ { "16-QAM", 24},
00124     /*   8 */ { "16-QAM", 36},
00125     /*   9 */ { "(9)", 0},
00126     /*  10 */ { "(10)", 0},
00127     /*  11 */ { "BPSK", 6.5},
00128     /*  12 */ { "QPSK", 13},
00129     /*  13 */ { "QPSK", 19.5},
00130     /*  14 */ { "16-QAM", 26},
00131     /*  15 */ { "16-QAM", 39},
00132     /*  16 */ { "(16)", 0},
00133     /*  17 */ { "(17)", 0},
00134     /*  18 */ { "(18)", 0},
00135     /*  19 */ { "BPSK", 7.2},
00136     /*  20 */ { "QPSK", 14.4},
00137     /*  21 */ { "QPSK", 21.7},
00138     /*  22 */ { "16-QAM", 28.9},
00139     /*  23 */ { "16-QAM", 43.3},
00140 };
00141 
00142 void print_wifi_result(const uint8_t *result)
00143 {
00144     char out[96];
00145     char str[24];
00146     unsigned n, macStart;
00147     wifiType_t wt;
00148     wifiChanInfo_t ci;
00149     wt.octet = result[0];
00150     ci.octet = result[1];
00151     out[0] = 0;
00152     strcat(out, "802.11");
00153     switch (wt.bits.signal) {
00154         case 1: strcat(out, "b"); break;
00155         case 2: strcat(out, "g"); break;
00156         case 3: strcat(out, "n"); break;
00157     }
00158     sprintf(str, " %s %.1fMbps", wifiDatarates[wt.bits.datarate].txt, wifiDatarates[wt.bits.datarate].Mbps);
00159     strcat(out, str);
00160     strcat(out, " ");
00161 
00162     sprintf(str, "ch%u ", ci.bits.channelID);
00163     strcat(out, str);
00164     switch (ci.bits.channelID) {
00165         // table 10-5
00166     }
00167     strcat(out, " ");
00168     sprintf(str, "mv:%u ", ci.bits.macValidationID);
00169     strcat(out, str);
00170     switch (ci.bits.macValidationID) {
00171         case 1: strcat(out, "gateway"); break;
00172         case 2: strcat(out, "phone"); break;
00173         case 3: strcat(out, "?"); break;
00174         // table 10.8
00175     }
00176 
00177     strcat(out, " ");
00178 
00179     if (wifiResultFormatBasic) {
00180         macStart = 3;
00181     } else {
00182         macStart = 4;
00183     }
00184     for (n = 0; n < 6; n++) {
00185         sprintf(str, "%02x", result[n+macStart]);
00186         strcat(out, str);
00187         if (n < 5)
00188             strcat(out, ":");
00189     }
00190 
00191     sprintf(str, " rssi:%d ", (int8_t)result[2]);
00192     strcat(out, str);
00193 
00194     if (!wifiResultFormatBasic) {
00195         sprintf(str, "frameCtrl:%02x ", result[3]);
00196         strcat(out, str);
00197     }
00198     printf("%s\r\n", out);
00199 }
00200 
00201 static void service()
00202 {
00203     irq_t irq;
00204     irq.dword = Radio::radio.service();
00205     if (irq.bits.WifiDone) {
00206         unsigned n;
00207         stat_t stat;
00208         uint8_t nbResults;
00209         stat.word = Radio::radio.xfer(OPCODE_GET_WIFI_NB_RESULTS, 0, 0, NULL);
00210         stat.word = Radio::radio.xfer(0x0000, 0, 1, &nbResults);
00211         if (stat.bits.cmdStatus != CMD_DAT) {
00212             printf("get-nbResult-fail\r\n");
00213             return;
00214         }
00215         packet_len = HEADER_LENGTH;
00216         printf("%ums nbResults:%u\r\n", (unsigned)wifi_scan_dur, nbResults);
00217         for (n = 0; n < nbResults; n++) {
00218             uint8_t buf[3];
00219             uint8_t resultBuf[22];
00220             buf[0] = n;
00221             buf[1] = 1; // number of results in this read
00222             buf[2] = wifiResultFormatBasic ? 4 : 1;
00223             stat.word = Radio::radio.xfer(OPCODE_WIFI_READ_RESULTS, 3, 0, buf);
00224             // basic =  9byte length
00225             // full  = 22byte length
00226             stat.word = Radio::radio.xfer(0x0000, 0, wifiResultFormatBasic ? 9 : 22, resultBuf);
00227 
00228             if (stat.bits.cmdStatus == CMD_DAT) {
00229                 unsigned n, macStart;
00230                 wifiChanInfo_t ci;
00231                 ci.octet = resultBuf[1];
00232                 if (ci.bits.macValidationID == 1) { // gateway (AP)
00233                     macStart = wifiResultFormatBasic ? 3 : 4;
00234                     for (n = 0; n < 6; n++) {
00235                         Radio::radio.tx_buf[packet_len++] = resultBuf[n+macStart];
00236                         printf("%02x", resultBuf[n+macStart]);
00237                         if (n < 5)
00238                             printf(":");
00239                     }
00240                     printf(" rssi:%d\r\n", (int8_t)resultBuf[2]);
00241                     Radio::radio.tx_buf[packet_len++] = resultBuf[2];
00242                 }
00243             } else
00244                 printf("readResult:%s\r\n", Radio::radio.cmdStatus_toString(stat.bits.cmdStatus));
00245         }
00246 
00247         if (!long_pressed) {
00248             unsigned n;
00249             cfg_lora();
00250             for (n = 0; n < 8; n++)
00251                 Radio::radio.tx_buf[n] = chip_eui[n];
00252 
00253             Radio::radio.tx_buf[n++] = 0;    // rfu
00254             Radio::radio.tx_buf[n++] = 0;    // rfu
00255             printf("pktLen:%u\r\n", packet_len);
00256             Radio::Send(packet_len, 0, 0, 0);   /* begin transmission */
00257         }
00258     } // ..if (irq.bits.WifiDone)
00259 
00260     if (irq.bits.TxDone) {
00261         printf("main-TxDone\r\n");
00262     }
00263 }
00264 
00265 void radio_irq_callback()
00266 {
00267     wifi_scan_dur = Kernel::get_ms_count() - wifi_start_at;
00268     queue.call(service);
00269 }
00270 
00271 const RadioEvents_t rev = {
00272     /* DioPin_top_half */   radio_irq_callback,
00273     /* TxDone_topHalf */    NULL,
00274     /* TxDone_botHalf */    txDoneCB,
00275     /* TxTimeout  */        NULL,
00276     /* RxDone  */           rxDoneCB,
00277     /* RxTimeout  */        NULL,
00278     /* RxError  */          NULL,
00279     /* FhssChangeChannel  */NULL,
00280     /* CadDone  */          NULL
00281 };
00282 
00283 int main()
00284 {
00285     Radio::Init(&rev);
00286 
00287     Radio::Standby();
00288     cfg_lora();
00289 
00290     {
00291         uint8_t buf[9];
00292         stat_t stat;
00293         stat.word = Radio::radio.xfer(OPCODE_GET_VERSION, 0, 0, NULL);
00294         stat.word = Radio::radio.xfer(0x0000, 0, 4, buf);
00295         if (stat.bits.cmdStatus == CMD_DAT) {
00296             printf("LR1110 chip:%02x use:%02x fw-v%u.%u\r\n",
00297                 buf[0], /* silicon rev */
00298                 buf[1], /* use case */
00299                 buf[2], /* firmware major */
00300                 buf[3]  /* firmware minor */
00301             );
00302         }
00303 
00304         stat.word = Radio::radio.xfer(OPCODE_GET_DEVEUI, 0, 0, NULL);
00305         stat.word = Radio::radio.xfer(0x0000, 0, 9, buf);
00306         memcpy(chip_eui, buf+1, 8);
00307         for (unsigned i = 0; i < 9; i++)
00308             printf("%02x ", buf[i]);
00309         printf("\r\n");
00310     }
00311 
00312 #ifdef AUTO_TX
00313     queue.call_in(500, tx_test);
00314 #endif /* AUTO_TX */
00315 
00316     if (ub.read())
00317         ub.fall(button_pressed);
00318     else
00319         ub.rise(button_released);
00320 
00321     queue.dispatch();
00322 }
00323