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.
main.cpp
00001 #include "mbed.h" 00002 #include "radio.h" 00003 00004 //#define MENU_DEBUG 00005 00006 #ifdef TARGET_NUCLEO_L073RZ 00007 BufferedSerial logpc(PC_10, PC_11, 115200); 00008 #else 00009 //#error log_uart_for_target 00010 #endif 00011 void logpc_printf(const char* format, ...); 00012 00013 static BufferedSerial pc(USBTX, USBRX, MBED_CONF_PLATFORM_STDIO_BAUD_RATE); 00014 namespace mbed { 00015 FileHandle *mbed_override_console(int fd) { 00016 return &pc; 00017 } 00018 } 00019 00020 menuState_t menuState; 00021 00022 typedef enum { 00023 MSG_TYPE_PACKET = 0, 00024 MSG_TYPE_PER, 00025 MSG_TYPE_PINGPONG 00026 } msgType_e; 00027 00028 // [row][column] 00029 const menu_t* menu_table[MAX_MENU_ROWS][MAX_MENU_COLUMNS]; 00030 int8_t StopMenuCols[MAX_MENU_ROWS]; 00031 00032 #define SCROLLING_ROWS 20 00033 00034 struct _cp_ { 00035 uint8_t row; 00036 uint8_t tableCol; 00037 } curpos; 00038 00039 uint8_t entry_buf_idx; 00040 char entry_buf[64]; 00041 00042 msgType_e msg_type; 00043 00044 const uint8_t PingMsg[] = "PING"; 00045 const uint8_t PongMsg[] = "PONG"; 00046 const uint8_t PerMsg[] = "PER"; 00047 00048 volatile struct _flags_ { 00049 uint8_t ping_master : 1; // 0 00050 uint8_t send_ping : 1; // 1 00051 uint8_t send_pong : 1; // 2 00052 uint8_t pingpongEnable : 1; // 3 00053 uint8_t do_next_tx : 1; // 4 00054 } flags; 00055 00056 uint8_t botRow; 00057 int regAddr = -1; 00058 00059 struct { 00060 float start_MHz; 00061 float step_MHz; 00062 float stop_MHz; 00063 unsigned dwell_ms; 00064 float MHz; 00065 Ticker ticker; 00066 bool ticking; 00067 bool tick; 00068 } cf_sweep; 00069 00070 00071 void Radio::cadDone(bool det) 00072 { 00073 log_printf("cadDone "); 00074 if (det) 00075 printf("CadDetected"); 00076 00077 printf("\r\n"); 00078 } 00079 00080 unsigned lfsr; 00081 #define LFSR_INIT 0x1ff 00082 00083 uint8_t get_pn9_byte() 00084 { 00085 uint8_t ret = 0; 00086 int xor_out; 00087 00088 xor_out = ((lfsr >> 5) & 0xf) ^ (lfsr & 0xf); // four bits at a time 00089 lfsr = (lfsr >> 4) | (xor_out << 5); // four bits at a time 00090 00091 ret |= (lfsr >> 5) & 0x0f; 00092 00093 xor_out = ((lfsr >> 5) & 0xf) ^ (lfsr & 0xf); // four bits at a time 00094 lfsr = (lfsr >> 4) | (xor_out << 5); // four bits at a time 00095 00096 ret |= ((lfsr >> 1) & 0xf0); 00097 00098 return ret; 00099 } 00100 00101 void hw_reset_push() 00102 { 00103 Radio::hw_reset(); 00104 00105 Radio::readChip(); 00106 menuState.mode = MENUMODE_REINIT_MENU; 00107 } 00108 00109 const button_item_t hw_reset_item = { _ITEM_BUTTON, "hw_reset", hw_reset_push }; 00110 00111 void clearIrqs_push() 00112 { 00113 Radio::clearIrqFlags(); 00114 } 00115 00116 const button_item_t clearirqs_item = { _ITEM_BUTTON, "clearIrqs", clearIrqs_push }; 00117 00118 const dropdown_item_t pktType_item = { _ITEM_DROPDOWN, Radio::pktType_strs, Radio::pktType_strs, Radio::pktType_read, Radio::pktType_write}; 00119 00120 00121 unsigned msgType_read(bool fw) 00122 { 00123 return msg_type; 00124 } 00125 00126 menuMode_e msgType_write(unsigned widx) 00127 { 00128 msg_type = (msgType_e)widx; 00129 00130 if (msg_type == MSG_TYPE_PER) { 00131 flags.pingpongEnable = 0; 00132 if (Radio::get_payload_length() < 7) 00133 Radio::set_payload_length(7); 00134 } else if (msg_type == MSG_TYPE_PINGPONG) { 00135 if (Radio::get_payload_length() != 12) 00136 Radio::set_payload_length(12); 00137 } else if (msg_type == MSG_TYPE_PACKET) { 00138 flags.pingpongEnable = 0; 00139 } 00140 00141 return MENUMODE_REINIT_MENU; 00142 } 00143 00144 const char* const msgType_strs[] = { 00145 "PACKET ", 00146 "PER ", 00147 "PINGPONG", 00148 NULL 00149 }; 00150 00151 const dropdown_item_t msgType_item = { _ITEM_DROPDOWN, msgType_strs, msgType_strs, msgType_read, msgType_write}; 00152 00153 void sweep_start_print() 00154 { 00155 printf("%.3fMHz", cf_sweep.start_MHz); 00156 } 00157 00158 bool sweep_start_write(const char* valStr) 00159 { 00160 sscanf(valStr, "%f", &cf_sweep.start_MHz); 00161 return false; 00162 } 00163 00164 void sweep_step_print() 00165 { 00166 printf("%.3fMHz", cf_sweep.step_MHz); 00167 } 00168 00169 bool sweep_step_write(const char* valStr) 00170 { 00171 sscanf(valStr, "%f", &cf_sweep.step_MHz); 00172 return false; 00173 } 00174 00175 void sweep_stop_print() 00176 { 00177 printf("%.3fMHz", cf_sweep.stop_MHz); 00178 } 00179 00180 bool sweep_stop_write(const char* valStr) 00181 { 00182 sscanf(valStr, "%f", &cf_sweep.stop_MHz); 00183 return false; 00184 } 00185 00186 void sweep_dwell_print() 00187 { 00188 printf("%ums", cf_sweep.dwell_ms); 00189 } 00190 00191 bool sweep_dwell_write(const char* valStr) 00192 { 00193 sscanf(valStr, "%u", &cf_sweep.dwell_ms); 00194 return false; 00195 } 00196 00197 const value_item_t tx_payload_length_item = { _ITEM_VALUE, 5, Radio::tx_payload_length_print, Radio::tx_payload_length_write}; 00198 00199 void pn9_push() 00200 { 00201 uint8_t i, len = Radio::get_payload_length(); 00202 for (i = 0; i < len; i++) 00203 Radio::radio.tx_buf[i] = get_pn9_byte(); 00204 } 00205 00206 const button_item_t tx_payload_pn9_item = { _ITEM_BUTTON, "PN9", pn9_push }; 00207 00208 void regAddr_print() 00209 { 00210 if (regAddr != -1) 00211 printf("%x", regAddr); 00212 } 00213 00214 bool regAddr_write(const char* txt) 00215 { 00216 sscanf(txt, "%x", ®Addr); 00217 return false; 00218 } 00219 00220 const value_item_t regAddr_item = { _ITEM_VALUE, 5, regAddr_print, regAddr_write}; 00221 00222 void regValue_print() 00223 { 00224 if (regAddr != -1) { 00225 printf("%x", Radio::read_register(regAddr)); 00226 } 00227 } 00228 00229 bool regValue_write(const char* txt) 00230 { 00231 unsigned val; 00232 sscanf(txt, "%x", &val); 00233 if (regAddr != -1) { 00234 Radio::write_register(regAddr, val); 00235 } 00236 return false; 00237 } 00238 00239 const value_item_t regValue_item = { _ITEM_VALUE, 5, regValue_print, regValue_write}; 00240 00241 void tx_payload_print() 00242 { 00243 uint8_t i, len = Radio::get_payload_length(); 00244 for (i = 0; i < len; i++) 00245 printf("%02x ", Radio::radio.tx_buf[i]); 00246 } 00247 00248 bool tx_payload_write(const char* txt) 00249 { 00250 unsigned o, i = 0, pktidx = 0; 00251 while (i < entry_buf_idx) { 00252 sscanf(entry_buf+i, "%02x", &o); 00253 printf("%02x ", o); 00254 i += 2; 00255 Radio::radio.tx_buf[pktidx++] = o; 00256 while (entry_buf[i] == ' ' && i < entry_buf_idx) 00257 i++; 00258 } 00259 log_printf("set payload len %u\r\n", pktidx); 00260 Radio::set_payload_length(pktidx); 00261 return true; 00262 } 00263 00264 const value_item_t tx_payload_item = { _ITEM_VALUE, 80, tx_payload_print, tx_payload_write}; 00265 00266 void txpkt_push() 00267 { 00268 Radio::txPkt(); 00269 } 00270 00271 const button_item_t tx_pkt_item = { _ITEM_BUTTON, "TXPKT", txpkt_push }; 00272 00273 void rxpkt_push() 00274 { 00275 Radio::Rx(); 00276 //yyy menuState.mode = MENUMODE_REDRAW; 00277 } 00278 const button_item_t rx_pkt_item = { _ITEM_BUTTON, "RXPKT", rxpkt_push }; 00279 00280 const dropdown_item_t opmode_item = { _ITEM_DROPDOWN, Radio::opmode_status_strs, Radio::opmode_select_strs, Radio::opmode_read, Radio::opmode_write }; 00281 00282 void tx_carrier_push() 00283 { 00284 Radio::tx_carrier(); 00285 } 00286 const button_item_t tx_carrier_item = { _ITEM_BUTTON, "TX_CARRIER", tx_carrier_push }; 00287 00288 void tx_preamble_push() 00289 { 00290 Radio::tx_preamble(); 00291 } 00292 const button_item_t tx_preamble_item = { _ITEM_BUTTON, "TX_PREAMBLE", tx_preamble_push }; 00293 00294 void get_rssi_push() 00295 { 00296 Radio::get_rssi(); 00297 } 00298 const button_item_t get_rssi_item = { _ITEM_BUTTON, "GET_RSSI", get_rssi_push }; 00299 00300 const value_item_t sweep_start_item = { _ITEM_VALUE, 5, sweep_start_print, sweep_start_write}; 00301 const value_item_t sweep_step_item = { _ITEM_VALUE, 5, sweep_step_print, sweep_step_write}; 00302 const value_item_t sweep_stop_item = { _ITEM_VALUE, 5, sweep_stop_print, sweep_stop_write}; 00303 const value_item_t sweep_dwell_item = { _ITEM_VALUE, 5, sweep_dwell_print, sweep_dwell_write}; 00304 00305 const menu_t msg_pkt_menu[] = { 00306 { {LAST_CHIP_MENU_ROW+1, 1}, "tx payload length:", &tx_payload_length_item, FLAG_MSGTYPE_PKT }, 00307 { {LAST_CHIP_MENU_ROW+1, 25}, NULL, &tx_payload_pn9_item, FLAG_MSGTYPE_PKT, &tx_payload_item }, 00308 { {LAST_CHIP_MENU_ROW+1, 40}, "regAddr:", ®Addr_item, FLAG_MSGTYPE_PKT, ®Value_item }, 00309 { {LAST_CHIP_MENU_ROW+1, 53}, "regValue:", ®Value_item, FLAG_MSGTYPE_PKT, }, 00310 { {LAST_CHIP_MENU_ROW+2, 1}, NULL, &tx_payload_item, FLAG_MSGTYPE_PKT }, 00311 { {LAST_CHIP_MENU_ROW+3, 1}, NULL, &tx_pkt_item, FLAG_MSGTYPE_PKT, &opmode_item }, 00312 { {LAST_CHIP_MENU_ROW+3, 10}, NULL, &rx_pkt_item, FLAG_MSGTYPE_PKT }, 00313 { {LAST_CHIP_MENU_ROW+3, 20}, NULL, &tx_carrier_item, FLAG_MSGTYPE_PKT, &opmode_item }, 00314 { {LAST_CHIP_MENU_ROW+3, 45}, NULL, &tx_preamble_item, FLAG_MSGTYPE_PKT, &opmode_item }, 00315 { {LAST_CHIP_MENU_ROW+3, 58}, NULL, &get_rssi_item, FLAG_MSGTYPE_PKT, &opmode_item }, 00316 { {LAST_CHIP_MENU_ROW+4, 1}, "cf sweep start:", &sweep_start_item, FLAG_MSGTYPE_PKT }, 00317 { {LAST_CHIP_MENU_ROW+4, 28}, "step:", &sweep_step_item, FLAG_MSGTYPE_PKT }, 00318 { {LAST_CHIP_MENU_ROW+4, 45}, "stop:", &sweep_stop_item, FLAG_MSGTYPE_PKT }, 00319 { {LAST_CHIP_MENU_ROW+4, 62}, "dwell_ms:", &sweep_dwell_item, FLAG_MSGTYPE_PKT }, 00320 00321 { {0, 0}, NULL, NULL } 00322 }; 00323 00324 unsigned tx_ipd_ms; 00325 Timeout mbedTimeout; 00326 unsigned MaxNumPacket; 00327 unsigned CntPacketTx; 00328 unsigned PacketRxSequencePrev; 00329 unsigned CntPacketRxKO; 00330 unsigned CntPacketRxOK; 00331 unsigned RxTimeOutCount; 00332 unsigned receivedCntPacket; 00333 00334 void do_next_tx () 00335 { 00336 Radio::radio.tx_buf[0] = CntPacketTx >> 24; 00337 Radio::radio.tx_buf[1] = CntPacketTx >> 16; 00338 Radio::radio.tx_buf[2] = CntPacketTx >> 8; 00339 Radio::radio.tx_buf[3] = CntPacketTx; 00340 00341 Radio::radio.tx_buf[4] = PerMsg[0]; 00342 Radio::radio.tx_buf[5] = PerMsg[1]; 00343 Radio::radio.tx_buf[6] = PerMsg[2]; 00344 00345 Radio::txPkt(); 00346 } 00347 00348 void next_tx_callback() 00349 { 00350 flags.do_next_tx = 1; 00351 } 00352 00353 00354 void pertx_push() 00355 { 00356 CntPacketTx = 1; // PacketRxSequencePrev initialized to 0 on receiver 00357 00358 log_printf("do perTx\r\n"); 00359 00360 next_tx_callback(); 00361 } 00362 00363 00364 const button_item_t pertx_item = { _ITEM_BUTTON, "PERTX", pertx_push }; 00365 00366 void tx_ipd_print() 00367 { 00368 printf("%u", tx_ipd_ms); 00369 } 00370 00371 bool tx_ipd_write(const char* valStr) 00372 { 00373 sscanf(valStr, "%u", &tx_ipd_ms); 00374 return false; 00375 } 00376 00377 value_item_t per_ipd_item = { _ITEM_VALUE, 4, tx_ipd_print, tx_ipd_write }; 00378 00379 void numpkts_print() 00380 { 00381 printf("%u", MaxNumPacket); 00382 } 00383 00384 bool numpkts_write(const char* valStr) 00385 { 00386 sscanf(valStr, "%u", &MaxNumPacket); 00387 return false; 00388 } 00389 00390 value_item_t per_numpkts_item = { _ITEM_VALUE, 6, numpkts_print, numpkts_write }; 00391 00392 void perrx_push() 00393 { 00394 PacketRxSequencePrev = 0; 00395 CntPacketRxKO = 0; 00396 CntPacketRxOK = 0; 00397 RxTimeOutCount = 0; 00398 00399 Radio::Rx(); 00400 } 00401 00402 const button_item_t perrx_item = { _ITEM_BUTTON, "PERRX", perrx_push }; 00403 00404 void per_reset_push() 00405 { 00406 PacketRxSequencePrev = 0; 00407 CntPacketRxKO = 0; 00408 CntPacketRxOK = 0; 00409 RxTimeOutCount = 0; 00410 } 00411 00412 const button_item_t per_clear_item = { _ITEM_BUTTON, "resetCount", per_reset_push }; 00413 00414 const menu_t msg_per_menu[] = { 00415 { {LAST_CHIP_MENU_ROW+3, 1}, NULL, &pertx_item, FLAG_MSGTYPE_PER }, 00416 { {LAST_CHIP_MENU_ROW+3, 10}, "TX IPD ms:", &per_ipd_item, FLAG_MSGTYPE_PER }, 00417 { {LAST_CHIP_MENU_ROW+3, 26}, "numPkts:", &per_numpkts_item, FLAG_MSGTYPE_PER }, 00418 { {LAST_CHIP_MENU_ROW+3, 40}, NULL, &perrx_item, FLAG_MSGTYPE_PER, &opmode_item }, 00419 { {LAST_CHIP_MENU_ROW+3, 50}, NULL, &per_clear_item, FLAG_MSGTYPE_PER, &opmode_item }, 00420 { {0, 0}, NULL, NULL } 00421 }; 00422 00423 void SendPong() 00424 { 00425 unsigned failCnt = CntPacketRxKO + RxTimeOutCount; 00426 00427 /* ping slave tx */ 00428 log_printf("ACK PKT%u\r\n", receivedCntPacket); 00429 00430 Radio::radio.tx_buf[ 0] = receivedCntPacket >> 24; 00431 Radio::radio.tx_buf[ 1] = receivedCntPacket >> 16; 00432 Radio::radio.tx_buf[ 2] = receivedCntPacket >> 8; 00433 Radio::radio.tx_buf[ 3] = receivedCntPacket; 00434 Radio::radio.tx_buf[ 4] = failCnt >> 24; 00435 Radio::radio.tx_buf[ 5] = failCnt >> 16; 00436 Radio::radio.tx_buf[ 6] = failCnt >> 8; 00437 Radio::radio.tx_buf[ 7] = failCnt; 00438 Radio::radio.tx_buf[ 8] = PongMsg[0]; 00439 Radio::radio.tx_buf[ 9] = PongMsg[1]; 00440 Radio::radio.tx_buf[10] = PongMsg[2]; 00441 Radio::radio.tx_buf[11] = PongMsg[3]; 00442 00443 Radio::txPkt(); 00444 } 00445 00446 void SendPing() 00447 { 00448 /* ping master tx */ 00449 00450 log_printf("MASTER > PING PKT%u\r\n", CntPacketTx); 00451 Radio::radio.tx_buf[0] = CntPacketTx >> 24; 00452 Radio::radio.tx_buf[1] = CntPacketTx >> 16; 00453 Radio::radio.tx_buf[2] = CntPacketTx >> 8; 00454 Radio::radio.tx_buf[3] = CntPacketTx; 00455 Radio::radio.tx_buf[4] = PingMsg[0]; 00456 Radio::radio.tx_buf[5] = PingMsg[1]; 00457 Radio::radio.tx_buf[6] = PingMsg[2]; 00458 Radio::radio.tx_buf[7] = PingMsg[3]; 00459 00460 Radio::txPkt(); 00461 } 00462 00463 void 00464 pingpong_start_push() 00465 { 00466 CntPacketTx = 1; 00467 CntPacketRxKO = 0; 00468 CntPacketRxOK = 0; 00469 RxTimeOutCount = 0; 00470 receivedCntPacket = 0; 00471 00472 flags.send_ping = 1; 00473 00474 flags.ping_master = 1; 00475 00476 flags.pingpongEnable = 1; 00477 log_printf("ping start\r\n"); 00478 } 00479 00480 const button_item_t pingpong_start_item = { _ITEM_BUTTON, "START", pingpong_start_push }; 00481 00482 void 00483 pingpong_stop_push () 00484 { 00485 flags.pingpongEnable = 0; 00486 } 00487 00488 const button_item_t pingpong_stop_item = { _ITEM_BUTTON, "STOP", pingpong_stop_push }; 00489 00490 const menu_t msg_pingpong_menu[] = { 00491 { {LAST_CHIP_MENU_ROW+3, 1}, NULL, &pingpong_start_item, FLAG_MSGTYPE_PING }, 00492 { {LAST_CHIP_MENU_ROW+3, 15}, NULL, &pingpong_stop_item, FLAG_MSGTYPE_PING }, 00493 { {0, 0}, NULL, NULL } 00494 }; 00495 00496 const menu_t* get_msg_menu() 00497 { 00498 switch (msg_type) { 00499 case MSG_TYPE_PACKET: 00500 return msg_pkt_menu; 00501 case MSG_TYPE_PER: 00502 return msg_per_menu; 00503 case MSG_TYPE_PINGPONG: 00504 return msg_pingpong_menu; 00505 } 00506 return NULL; 00507 } 00508 00509 void frf_print() 00510 { 00511 float MHz; 00512 #ifdef SX127x_H 00513 MHz = Radio::radio.get_frf_MHz(); 00514 #else 00515 MHz = Radio::radio.getMHz(); 00516 #endif 00517 printf("%.3fMHz", MHz); 00518 } 00519 00520 bool frf_write(const char* valStr) 00521 { 00522 float MHz; 00523 sscanf(valStr, "%f", &MHz); 00524 #ifdef SX127x_H 00525 Radio::radio.set_frf_MHz(MHz); 00526 #else 00527 Radio::radio.setMHz(MHz); 00528 #endif 00529 return false; 00530 } 00531 00532 const value_item_t frf_item = { _ITEM_VALUE, 14, frf_print, frf_write }; 00533 00534 const value_item_t Radio::tx_dbm_item = { _ITEM_VALUE, 7, Radio::tx_dbm_print, Radio::tx_dbm_write }; 00535 00536 const dropdown_item_t tx_ramp_item = { _ITEM_DROPDOWN, Radio::tx_ramp_strs, Radio::tx_ramp_strs, Radio::tx_ramp_read, Radio::tx_ramp_write }; 00537 00538 const button_item_t chipNum_item = { _ITEM_BUTTON, Radio::chipNum_str, NULL}; 00539 00540 void botrow_print() 00541 { 00542 printf("%u", botRow); 00543 } 00544 00545 bool botrow_write(const char* str) 00546 { 00547 unsigned n; 00548 sscanf(str, "%u", &n); 00549 botRow = n; 00550 00551 printf("\e[%u;%ur", MAX_MENU_ROWS, botRow); // set scrolling region 00552 00553 return false; 00554 } 00555 00556 const value_item_t bottomRow_item = { _ITEM_VALUE, 4, botrow_print, botrow_write }; 00557 00558 const menu_t common_menu[] = { 00559 { {1, 1}, NULL, &hw_reset_item, FLAG_MSGTYPE_ALL }, 00560 { {1, 13}, "packetType:", &pktType_item, FLAG_MSGTYPE_ALL }, 00561 { {1, 33}, NULL, &msgType_item, FLAG_MSGTYPE_ALL }, 00562 { {1, 43}, NULL, &chipNum_item, FLAG_MSGTYPE_ALL }, 00563 { {1, 61}, "bottomRow:", &bottomRow_item, FLAG_MSGTYPE_ALL }, 00564 { {2, 1}, NULL, &frf_item, FLAG_MSGTYPE_ALL }, 00565 { {2, 15}, "TX dBm:", &Radio::tx_dbm_item, FLAG_MSGTYPE_ALL }, 00566 { {2, 30}, "ramp us:", &tx_ramp_item, FLAG_MSGTYPE_ALL }, 00567 { {2, 45}, NULL, &clearirqs_item, FLAG_MSGTYPE_ALL }, 00568 { {2, 55}, "opmode:", &opmode_item, FLAG_MSGTYPE_ALL }, 00569 00570 00571 { {0, 0}, NULL, NULL } 00572 }; 00573 00574 bool 00575 is_menu_item_changable(uint8_t table_row, uint8_t table_col) 00576 { 00577 const menu_t* m = menu_table[table_row][table_col]; 00578 const dropdown_item_t* di = (const dropdown_item_t*)m->itemPtr; 00579 00580 switch (msg_type) { 00581 case MSG_TYPE_PACKET: 00582 if (m->flags & FLAG_MSGTYPE_PKT) 00583 break; 00584 else 00585 return false; 00586 case MSG_TYPE_PER: 00587 if (m->flags & FLAG_MSGTYPE_PER) 00588 break; 00589 else 00590 return false; 00591 case MSG_TYPE_PINGPONG: 00592 if (m->flags & FLAG_MSGTYPE_PING) 00593 break; 00594 else 00595 return false; 00596 } 00597 00598 if (di->itemType == _ITEM_DROPDOWN) { 00599 if (di->selectable_strs == NULL || di->selectable_strs[0] == NULL) { 00600 log_printf("NULLstrs%u,%u\r\n", table_row, table_col); 00601 return false; 00602 } 00603 } else if (di->itemType == _ITEM_VALUE) { 00604 const value_item_t* vi = (const value_item_t*)m->itemPtr; 00605 if (vi->write == NULL) 00606 return false; 00607 } else if (di->itemType == _ITEM_BUTTON) { 00608 const button_item_t* bi = (const button_item_t*)m->itemPtr; 00609 if (bi->push == NULL) 00610 return false; 00611 } else if (di->itemType == _ITEM_TOGGLE) { 00612 const toggle_item_t * ti = (const toggle_item_t *)m->itemPtr; 00613 if (ti->push == NULL) 00614 return false; 00615 } 00616 00617 return true; 00618 } // ..is_menu_item_changable() 00619 00620 void read_menu_item(const menu_t* m, bool selected) 00621 { 00622 uint8_t valCol; 00623 const dropdown_item_t* di = (const dropdown_item_t*)m->itemPtr; 00624 00625 switch (msg_type) { 00626 case MSG_TYPE_PACKET: 00627 if (m->flags & FLAG_MSGTYPE_PKT) 00628 break; 00629 else 00630 return; 00631 case MSG_TYPE_PER: 00632 if (m->flags & FLAG_MSGTYPE_PER) 00633 break; 00634 else 00635 return; 00636 case MSG_TYPE_PINGPONG: 00637 if (m->flags & FLAG_MSGTYPE_PING) 00638 break; 00639 else 00640 return; 00641 } 00642 00643 printf("\e[%u;%uf", m->pos.row, m->pos.col); // set (force) cursor to row;column 00644 valCol = m->pos.col; 00645 if (m->label) { 00646 printf("%s", m->label); 00647 valCol += strlen(m->label); 00648 } 00649 if (di->itemType == _ITEM_DROPDOWN) { 00650 if (di->read && di->printed_strs) { 00651 uint8_t ridx = di->read(false); 00652 if (selected) 00653 printf("\e[7m"); 00654 printf("%s", di->printed_strs[ridx]); 00655 if (selected) 00656 printf("\e[0m"); 00657 } else if (di->printed_strs) { 00658 printf("%s", di->printed_strs[0]); 00659 } 00660 } else if (di->itemType == _ITEM_VALUE) { 00661 const value_item_t* vi = (const value_item_t*)m->itemPtr; 00662 if (vi->print) { 00663 for (unsigned n = 0; n < vi->width; n++) 00664 printf(" "); 00665 00666 printf("\e[%u;%uf", m->pos.row, valCol); // set (force) cursor to row;column 00667 if (selected) 00668 printf("\e[7m"); 00669 vi->print(); 00670 if (selected) 00671 printf("\e[0m"); 00672 } 00673 } else if (di->itemType == _ITEM_BUTTON) { 00674 const button_item_t* bi = (const button_item_t*)m->itemPtr; 00675 if (bi->label) { 00676 if (selected) 00677 printf("\e[7m%s\e[0m", bi->label); 00678 else 00679 printf("%s", bi->label); 00680 } 00681 } else if (di->itemType == _ITEM_TOGGLE) { 00682 const toggle_item_t* ti = (const toggle_item_t *)m->itemPtr; 00683 bool on = ti->read(); 00684 if (ti->label1) { 00685 const char* const cptr = on ? ti->label1 : ti->label0; 00686 if (selected) 00687 printf("\e[7m%s\e[0m", cptr); 00688 else 00689 printf("%s", cptr); 00690 } else { 00691 if (on) 00692 printf("\e[1m"); 00693 if (selected) 00694 printf("\e[7m"); 00695 00696 printf("%s", ti->label0); 00697 00698 if (selected || on) 00699 printf("\e[0m"); 00700 } 00701 } 00702 00703 } // ..read_menu_item() 00704 00705 void draw_menu() 00706 { 00707 unsigned table_row; 00708 00709 for (table_row = 0; table_row < MAX_MENU_ROWS; table_row++) { 00710 int table_col; 00711 for (table_col = 0; table_col < StopMenuCols[table_row]; table_col++) { 00712 read_menu_item(menu_table[table_row][table_col], false); 00713 } // ..table column iterator 00714 } // ..table row iterator 00715 00716 read_menu_item(menu_table[curpos.row][curpos.tableCol], true); 00717 00718 fflush(stdout); 00719 pc.sync(); 00720 } // ..draw_menu() 00721 00722 typedef struct { 00723 int row; 00724 int col; 00725 } tablexy_t; 00726 00727 void 00728 menu_init_(const menu_t* in, tablexy_t* tc) 00729 { 00730 unsigned n; 00731 00732 for (n = 0; in[n].pos.row > 0; n++) { 00733 const menu_t* m = &in[n]; 00734 if (tc->row != m->pos.row - 1) { 00735 tc->row = m->pos.row - 1; 00736 tc->col = 0; 00737 } else 00738 tc->col++; 00739 00740 menu_table[tc->row][tc->col] = m; 00741 #ifdef MENU_DEBUG 00742 printf("table:%u,%u ", tc->row, tc->col); 00743 printf(" %d<%d? ", StopMenuCols[tc->row], tc->col); 00744 #endif /* MENU_DEBUG */ 00745 if (StopMenuCols[tc->row] < tc->col) 00746 StopMenuCols[tc->row] = tc->col; 00747 #ifdef MENU_DEBUG 00748 printf("{%u %u}", tc->row, tc->col); 00749 printf("in:%p[%u] screen:%u,%u ", in, n, m->pos.row, m->pos.col); 00750 printf("pos@%p ", &m->pos); 00751 //printf(" loc:%p ", &in[n].itemPtr); 00752 if (in[n].itemPtr) { 00753 const dropdown_item_t* di = (const dropdown_item_t*)m->itemPtr; 00754 printf(" itemPtr:%p type:%02x ", di, di->itemType); 00755 } 00756 printf("stopMenuCols[%u]: %d ", tc->row, StopMenuCols[tc->row]); 00757 if (m->label) 00758 printf("label:%s", m->label); 00759 else 00760 printf("noLabel"); 00761 printf("\r\n"); 00762 #endif /* MENU_DEBUG */ 00763 } 00764 #ifdef MENU_DEBUG 00765 char ch; 00766 printf("hit key:"); 00767 pc.read(&ch, 1); 00768 #endif /* MENU_DEBUG */ 00769 00770 } 00771 00772 void navigate_dropdown(uint8_t ch) 00773 { 00774 unsigned n; 00775 const menu_t* m = menuState.sm; 00776 const dropdown_item_t* di = (const dropdown_item_t*)m->itemPtr; 00777 00778 switch (ch) { 00779 case 'A': // cursor UP 00780 if (menuState.sel_idx > 0) { 00781 menuState.sel_idx--; 00782 } 00783 break; 00784 case 'B': // cursor DOWN 00785 if (di->selectable_strs[menuState.sel_idx+1] != NULL) 00786 menuState.sel_idx++; 00787 break; 00788 } // ..switch (ch) 00789 00790 for (n = 0; di->selectable_strs[n] != NULL; n++) { 00791 printf("\e[%u;%uf", m->pos.row+n, menuState.dropdown_col); 00792 if (n == menuState.sel_idx) 00793 printf("\e[7m"); 00794 printf("%s", di->selectable_strs[n]); 00795 if (n == menuState.sel_idx) 00796 printf("\e[0m"); 00797 } 00798 printf("\e[%u;%uf", m->pos.row + menuState.sel_idx, menuState.dropdown_col + strlen(di->selectable_strs[menuState.sel_idx])); 00799 } 00800 00801 bool is_item_selectable(const menu_t* m) 00802 { 00803 const dropdown_item_t* di = (const dropdown_item_t*)m->itemPtr; 00804 00805 if (di->itemType == _ITEM_BUTTON) { 00806 const button_item_t* bi = (const button_item_t*)m->itemPtr; 00807 if (bi->push == NULL) 00808 return false; 00809 } else if (di->itemType == _ITEM_TOGGLE) { 00810 const toggle_item_t* ti = (const toggle_item_t*)m->itemPtr; 00811 if (ti->push == NULL) 00812 return false; 00813 } 00814 00815 return true; 00816 } 00817 00818 void navigate_menu(uint8_t ch) 00819 { 00820 //logpc_printf("navigate_menu %c\r\n", ch); 00821 read_menu_item(menu_table[curpos.row][curpos.tableCol], false); 00822 00823 switch (ch) { 00824 case 'A': // cursor UP 00825 if (curpos.row == 0) 00826 break; 00827 00828 { // find previous row up with column 00829 int8_t row; 00830 for (row = curpos.row - 1; row >= 0; row--) { 00831 if (StopMenuCols[row] > -1) { 00832 curpos.row = row; 00833 break; 00834 } 00835 } 00836 if (row == 0 && StopMenuCols[0] < 0) 00837 break; // nothing found 00838 } 00839 00840 if (curpos.tableCol >= StopMenuCols[curpos.row]) { 00841 curpos.tableCol = StopMenuCols[curpos.row]-1; 00842 } 00843 00844 break; 00845 case 'B': // cursor DOWN 00846 if (curpos.row >= MAX_MENU_ROWS) 00847 break; 00848 00849 { // find next row down with column 00850 uint8_t row; 00851 for (row = curpos.row + 1; row < MAX_MENU_ROWS; row++) { 00852 if (StopMenuCols[row] != -1) { 00853 curpos.row = row; 00854 break; 00855 } 00856 } 00857 if (row == MAX_MENU_ROWS-1 && StopMenuCols[row] == -1) 00858 break; // nothing found 00859 } 00860 00861 if (curpos.tableCol >= StopMenuCols[curpos.row]) { 00862 curpos.tableCol = StopMenuCols[curpos.row]-1; 00863 } 00864 00865 00866 break; 00867 case 'C': // cursor LEFT 00868 if (curpos.tableCol >= StopMenuCols[curpos.row]-1) 00869 break; 00870 00871 { // find next row left with editable 00872 uint8_t tcol; 00873 for (tcol = curpos.tableCol + 1; tcol < StopMenuCols[curpos.row]; tcol++) { 00874 if (is_menu_item_changable(curpos.row, tcol)) { 00875 curpos.tableCol = tcol; 00876 break; 00877 } 00878 } 00879 } 00880 00881 break; 00882 case 'D': // cursor RIGHT 00883 if (curpos.tableCol == 0) 00884 break; 00885 00886 { 00887 int8_t tcol; 00888 for (tcol = curpos.tableCol - 1; tcol >= 0; tcol--) { 00889 if (is_menu_item_changable(curpos.row, tcol)) { 00890 curpos.tableCol = tcol; 00891 break; 00892 } 00893 } 00894 } 00895 00896 break; 00897 default: 00898 //printf("unhancled-csi:%02x\eE", ch); 00899 break; 00900 } // ..switch (ch) 00901 00902 if (!is_item_selectable(menu_table[curpos.row][curpos.tableCol])) { 00903 int c; 00904 for (c = 0; c < StopMenuCols[curpos.row]; c++) { 00905 if (is_item_selectable(menu_table[curpos.row][c])) { 00906 curpos.tableCol = c; 00907 break; 00908 } 00909 } 00910 if (c == StopMenuCols[curpos.row]) 00911 return; 00912 } 00913 00914 #ifdef MENU_DEBUG 00915 log_printf("table:%u,%u screen:%u,%u \r\n", curpos.row, curpos.tableCol, 00916 menu_table[curpos.row][curpos.tableCol]->pos.row, 00917 menu_table[curpos.row][curpos.tableCol]->pos.col 00918 ); 00919 #endif /* MENU_DEBUG */ 00920 00921 read_menu_item(menu_table[curpos.row][curpos.tableCol], true); 00922 } // ..navigate_menu 00923 00924 00925 bool is_sweep_menu_item(const void* const itemPtr) 00926 { 00927 if (itemPtr == &sweep_start_item || 00928 itemPtr == &sweep_stop_item || 00929 itemPtr == &sweep_dwell_item || 00930 itemPtr == &tx_carrier_item || 00931 itemPtr == &tx_preamble_item 00932 ) 00933 return true; 00934 else 00935 return false; 00936 } 00937 00938 void commit_menu_item_change() 00939 { 00940 const menu_t* m = menu_table[curpos.row][curpos.tableCol]; 00941 const dropdown_item_t* di = (const dropdown_item_t*)m->itemPtr; 00942 00943 if (di->itemType == _ITEM_DROPDOWN) { 00944 menuState.mode = di->write(menuState.sel_idx); 00945 00946 printf("\e[%u;%uf", m->pos.row, m->pos.col-2); 00947 } else if (di->itemType == _ITEM_VALUE) { 00948 const value_item_t* vi = (const value_item_t*)m->itemPtr; 00949 /* commit value entry */ 00950 if (vi->write) { 00951 if (vi->write(entry_buf)) 00952 menuState.mode = MENUMODE_REDRAW; 00953 else 00954 menuState.mode = MENUMODE_NONE; 00955 } else 00956 menuState.mode = MENUMODE_NONE; 00957 00958 if (menuState.mode == MENUMODE_NONE) { 00959 read_menu_item(menu_table[curpos.row][curpos.tableCol], true); 00960 } 00961 } 00962 00963 } // ..commit_menu_item_change() 00964 00965 void refresh_item_in_table(const void* item) 00966 { 00967 unsigned table_row; 00968 00969 if (item == NULL) 00970 return; 00971 00972 for (table_row = 0; table_row < MAX_MENU_ROWS; table_row++) { 00973 int table_col; 00974 for (table_col = 0; table_col < StopMenuCols[table_row]; table_col++) { 00975 //log_printf("%u %u %p\r\n", table_row, table_col, menu_table[table_row][table_col]->itemPtr); 00976 if (item == menu_table[table_row][table_col]->itemPtr) { 00977 read_menu_item(menu_table[table_row][table_col], false); 00978 return; 00979 } 00980 } 00981 } 00982 } 00983 00984 void 00985 start_value_entry(const menu_t* m) 00986 { 00987 const value_item_t* vi = (const value_item_t*)m->itemPtr; 00988 uint8_t col = m->pos.col; 00989 00990 if (m->label) 00991 col += strlen(m->label); 00992 00993 printf("\e[%u;%uf", m->pos.row, col); 00994 for (unsigned i = 0; i < vi->width; i++) 00995 printf(" "); // clear displayed value for user entry 00996 00997 printf("\e[%u;%uf", m->pos.row, col); 00998 menuState.mode = MENUMODE_ENTRY; 00999 entry_buf_idx = 0; 01000 } 01001 01002 void start_menu_item_change() 01003 { 01004 const menu_t* m = menu_table[curpos.row][curpos.tableCol]; 01005 const dropdown_item_t* di = (const dropdown_item_t*)m->itemPtr; 01006 bool checkRefresh = false; 01007 01008 if (di->itemType == _ITEM_DROPDOWN && di->selectable_strs) { 01009 menuState.dropdown_col = m->pos.col; 01010 unsigned n, sidx = 0; 01011 /* start dropdown */ 01012 if (di->read) 01013 sidx = di->read(true); 01014 01015 if (m->label) 01016 menuState.dropdown_col += strlen(m->label); 01017 01018 for (n = 0; di->selectable_strs[n] != NULL; n++) { 01019 uint8_t col = menuState.dropdown_col; 01020 bool leftPad = false; 01021 if (col > 3 && n > 0) { // dropdown left side padding 01022 col -= 2; 01023 leftPad = true; 01024 } 01025 printf("\e[%u;%uf", m->pos.row+n, col); 01026 if (leftPad ) { 01027 printf(" "); 01028 } 01029 if (n == sidx) 01030 printf("\e[7m"); 01031 printf("%s", di->selectable_strs[n]); 01032 if (n == sidx) 01033 printf("\e[0m"); 01034 printf(" "); // right side padding 01035 } 01036 printf("\e[%u;%uf", m->pos.row, menuState.dropdown_col-2); 01037 01038 menuState.mode = MENUMODE_DROPDOWN; 01039 menuState.sel_idx = sidx; 01040 menuState.sm = m; 01041 } else if (di->itemType == _ITEM_VALUE) { 01042 /* start value entry */ 01043 start_value_entry(m); 01044 } else if (di->itemType == _ITEM_BUTTON) { 01045 const button_item_t* bi = (const button_item_t*)m->itemPtr; 01046 if (bi->push) { 01047 bi->push(); 01048 checkRefresh = true; 01049 } 01050 } else if (di->itemType == _ITEM_TOGGLE) { 01051 const toggle_item_t* ti = (const toggle_item_t*)m->itemPtr; 01052 if (ti->push) { 01053 bool on = ti->push(); 01054 uint8_t col = m->pos.col; 01055 01056 if (m->label) 01057 col += strlen(m->label); 01058 01059 printf("\e[%u;%uf", m->pos.row, col); 01060 if (ti->label1) { 01061 printf("\e[7m%s\e[0m", on ? ti->label1 : ti->label0); 01062 } else { 01063 if (on) 01064 printf("\e[1;7m%s\e[0m", ti->label0); 01065 else 01066 printf("\e[7m%s\e[0m", ti->label0); 01067 } 01068 checkRefresh = true; 01069 } 01070 } 01071 01072 if (checkRefresh) { 01073 if (m->refreshReadItem) { 01074 refresh_item_in_table(m->refreshReadItem); // read associated 01075 read_menu_item(m, true); // restore cursor 01076 } 01077 } 01078 01079 } // ..start_menu_item_change() 01080 01081 void full_menu_init() 01082 { 01083 unsigned n; 01084 const menu_t *m; 01085 tablexy_t txy; 01086 01087 txy.row = INT_MAX; 01088 txy.col = 0; 01089 01090 for (n = 0; n < MAX_MENU_ROWS; n++) { 01091 StopMenuCols[n] = -1; 01092 } 01093 01094 menu_init_(common_menu, &txy); 01095 01096 menu_init_(Radio::common_menu, &txy); 01097 01098 m = Radio::get_modem_menu(); 01099 if (m == NULL) { 01100 log_printf("NULL-modemMenu\r\n"); 01101 for (;;) asm("nop"); 01102 } 01103 #ifdef MENU_DEBUG 01104 printf("modemmenuInit\r\n"); 01105 #endif 01106 menu_init_(m, &txy); 01107 01108 m = Radio::get_modem_sub_menu(); 01109 if (m) { 01110 #ifdef MENU_DEBUG 01111 printf("modemsubmenuInit\r\n"); 01112 #endif 01113 menu_init_(m, &txy); 01114 } 01115 #ifdef MENU_DEBUG 01116 else 01117 printf("no-modemsubmenu\r\n"); 01118 #endif 01119 01120 m = get_msg_menu(); 01121 if (m == NULL) { 01122 log_printf("NULL-msgMenu\r\n"); 01123 for (;;) asm("nop"); 01124 } 01125 menu_init_(m, &txy); 01126 01127 for (n = 0; n < MAX_MENU_ROWS; n++) { 01128 if (StopMenuCols[n] != -1) 01129 StopMenuCols[n]++; 01130 } 01131 } 01132 01133 bool ishexchar(char ch) 01134 { 01135 if (((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) || (ch >= '0' && ch <= '9')) 01136 return true; 01137 else 01138 return false; 01139 } 01140 01141 enum _urx_ { 01142 URX_STATE_NONE = 0, 01143 URX_STATE_ESCAPE, 01144 URX_STATE_CSI, 01145 } uart_rx_state; 01146 01147 Timeout uartRxTimeout; 01148 01149 void uart_rx_timeout() 01150 { 01151 /* escape by itself: abort change on item */ 01152 menuState.mode = MENUMODE_REDRAW; 01153 01154 uart_rx_state = URX_STATE_NONE; 01155 } 01156 01157 void sweeper() 01158 { 01159 if (cf_sweep.ticking) { 01160 cf_sweep.tick = true; 01161 } 01162 } 01163 01164 void sweep_service() 01165 { 01166 const menu_t* m = menu_table[curpos.row][curpos.tableCol]; 01167 01168 if (is_sweep_menu_item(m->itemPtr)) { 01169 if (cf_sweep.start_MHz != 0 && cf_sweep.stop_MHz > cf_sweep.start_MHz && cf_sweep.dwell_ms > 0) { 01170 std::chrono::microseconds us = std::chrono::microseconds(cf_sweep.dwell_ms * 1000); 01171 cf_sweep.MHz = cf_sweep.start_MHz; 01172 cf_sweep.ticker.attach(sweeper, us); 01173 cf_sweep.ticking = true; 01174 } 01175 } else { 01176 if (cf_sweep.ticking) { 01177 cf_sweep.ticker.detach(); 01178 cf_sweep.ticking = false; 01179 } 01180 } 01181 } 01182 01183 void serial_callback() 01184 { 01185 char serial_write_buf[4]; 01186 unsigned char serial_write_buf_idx = 0; 01187 char ch; 01188 pc.read(&ch, 1); 01189 01190 switch (uart_rx_state) { 01191 case URX_STATE_NONE: 01192 if (ch == 0x1b) { 01193 if (menuState.mode == MENUMODE_ENTRY) { 01194 /* abort entry mode */ 01195 menuState.mode = MENUMODE_NONE; 01196 read_menu_item(menu_table[curpos.row][curpos.tableCol], true); 01197 } else { 01198 uart_rx_state = URX_STATE_ESCAPE; 01199 if (menuState.mode != MENUMODE_NONE) { 01200 /* is this escape by itself, user wants to abort? */ 01201 uartRxTimeout.attach(uart_rx_timeout, 30ms); 01202 } 01203 } 01204 } else if (ch == 2) { // ctrl-B 01205 log_printf("--------------\r\n"); 01206 } else if (ch == '\r') { 01207 if (menuState.mode == MENUMODE_NONE) { 01208 start_menu_item_change(); 01209 } else { 01210 entry_buf[entry_buf_idx] = 0; 01211 commit_menu_item_change(); 01212 } 01213 sweep_service(); 01214 } else if (menuState.mode == MENUMODE_ENTRY) { 01215 if (ch == 8) { 01216 if (entry_buf_idx > 0) { 01217 serial_write_buf[serial_write_buf_idx++] = 8; 01218 serial_write_buf[serial_write_buf_idx++] = ' '; 01219 serial_write_buf[serial_write_buf_idx++] = 8; 01220 entry_buf_idx--; 01221 } 01222 } else if (ch == 3) { // ctrl-C 01223 menuState.mode = MENUMODE_NONE; 01224 } else if (entry_buf_idx < sizeof(entry_buf)) { 01225 entry_buf[entry_buf_idx++] = ch; 01226 serial_write_buf[serial_write_buf_idx++] = ch; 01227 } 01228 } else if (menuState.mode == MENUMODE_NONE) { 01229 if (ishexchar(ch) || ch == '-') { // characters which start entry 01230 const value_item_t* vi = (const value_item_t*)menu_table[curpos.row][curpos.tableCol]->itemPtr; 01231 if (vi->itemType == _ITEM_VALUE) { 01232 start_value_entry(menu_table[curpos.row][curpos.tableCol]); 01233 entry_buf[entry_buf_idx++] = ch; 01234 serial_write_buf[serial_write_buf_idx++] = ch; 01235 } 01236 } else if (ch == 'r') { 01237 menuState.mode = MENUMODE_REDRAW; 01238 } else if (ch == '.') { 01239 Radio::test(); 01240 } 01241 01242 } 01243 break; 01244 case URX_STATE_ESCAPE: 01245 uartRxTimeout.detach(); 01246 if (ch == '[') 01247 uart_rx_state = URX_STATE_CSI; 01248 else { 01249 #ifdef MENU_DEBUG 01250 log_printf("unhancled-esc:%02x\r\n", ch); 01251 #endif /* MENU_DEBUG */ 01252 uart_rx_state = URX_STATE_NONE; 01253 } 01254 break; 01255 case URX_STATE_CSI: 01256 if (menuState.mode == MENUMODE_NONE) 01257 navigate_menu(ch); 01258 else if (menuState.mode == MENUMODE_DROPDOWN) 01259 navigate_dropdown(ch); 01260 01261 uart_rx_state = URX_STATE_NONE; 01262 //printf("\e[18;1f"); // set (force) cursor to row;column 01263 break; 01264 } // ..switch (uart_rx_state) 01265 01266 fflush(stdout); 01267 01268 if (serial_write_buf_idx > 0) { 01269 pc.write(serial_write_buf, serial_write_buf_idx); 01270 } 01271 01272 pc.sync(); 01273 } 01274 01275 void txDone() 01276 { 01277 01278 if (msg_type == MSG_TYPE_PER) { 01279 log_printf("CntPacketTx%u, max:%u ipd%u\r\n", CntPacketTx, MaxNumPacket, tx_ipd_ms); 01280 if (++CntPacketTx <= MaxNumPacket) { 01281 std::chrono::microseconds us = std::chrono::microseconds(tx_ipd_ms * 1000); 01282 mbedTimeout.attach(next_tx_callback, us); 01283 } 01284 } else if (msg_type == MSG_TYPE_PINGPONG) { 01285 if (flags.ping_master) { 01286 ++CntPacketTx; 01287 } 01288 01289 Radio::Rx(); 01290 } 01291 } 01292 01293 void 01294 printRxPkt(uint8_t size) 01295 { 01296 uint8_t col; 01297 char str[80]; 01298 char *ptr, *endPtr; 01299 unsigned n = 0; 01300 endPtr = str + sizeof(str); 01301 ptr = str; 01302 col = 0; 01303 while (ptr < endPtr) { 01304 //sprintf(ptr, "%02x%c", Radio::radio.rx_buf[n], n == Radio::radio.rx_buf_offset ? '_' : ' '); // LR1110 01305 sprintf(ptr, "%02x ", Radio::radio.rx_buf[n]); 01306 ptr += 3; 01307 col += 3; 01308 if (col >= 77) { 01309 log_printf("%s\r\n", str); 01310 ptr = str; 01311 col = 0; 01312 } 01313 if (++n >= size) 01314 break; 01315 } 01316 log_printf("%s\r\n", str); 01317 } 01318 01319 void rxDone(uint8_t size, float rssi, float snr) 01320 { 01321 log_printf("rxDone %u, %.1fdBm %.1fdB\r\n", size, rssi, snr); 01322 if (msg_type == MSG_TYPE_PACKET) { 01323 printRxPkt(size); 01324 } else if (msg_type == MSG_TYPE_PER) { 01325 if (memcmp(Radio::radio.rx_buf+4, PerMsg, 3) == 0) { 01326 unsigned i, PacketRxSequence = Radio::radio.rx_buf[0]; 01327 PacketRxSequence <<= 8; 01328 PacketRxSequence += Radio::radio.rx_buf[1]; 01329 PacketRxSequence <<= 8; 01330 PacketRxSequence += Radio::radio.rx_buf[2]; 01331 PacketRxSequence <<= 8; 01332 PacketRxSequence += Radio::radio.rx_buf[3]; 01333 01334 CntPacketRxOK++; 01335 01336 if (PacketRxSequence <= PacketRxSequencePrev || PacketRxSequencePrev == 0) 01337 i = 0; // sequence reset to resync, dont count missed packets this time 01338 else 01339 i = PacketRxSequence - PacketRxSequencePrev - 1; 01340 01341 01342 CntPacketRxKO += i; 01343 RxTimeOutCount = 0; 01344 log_printf("PER rx%u ok%u ko%u\r\n", PacketRxSequence , CntPacketRxOK, CntPacketRxKO); 01345 01346 PacketRxSequencePrev = PacketRxSequence; 01347 } // ..if PerMsg 01348 else { 01349 log_printf("per?\r\n"); 01350 printRxPkt(size); 01351 } 01352 } else if (msg_type == MSG_TYPE_PINGPONG) { 01353 if (memcmp(Radio::radio.rx_buf+4, PingMsg, 4) == 0) { 01354 /* ping slave rx */ 01355 Radio::setFS(); 01356 receivedCntPacket = Radio::radio.rx_buf[0]; 01357 receivedCntPacket <<= 8; 01358 receivedCntPacket += Radio::radio.rx_buf[1]; 01359 receivedCntPacket <<= 8; 01360 receivedCntPacket += Radio::radio.rx_buf[2]; 01361 receivedCntPacket <<= 8; 01362 receivedCntPacket += Radio::radio.rx_buf[3]; 01363 log_printf("%u rxPing->txPong\r\n", receivedCntPacket); 01364 01365 flags.ping_master = 0; 01366 flags.send_pong = 1; 01367 01368 } else if (memcmp(Radio::radio.rx_buf+8, PongMsg, 4) == 0) { 01369 unsigned cnt; 01370 /* ping master rx */ 01371 Radio::setFS(); 01372 cnt = Radio::radio.rx_buf[0]; 01373 cnt <<= 8; 01374 cnt += Radio::radio.rx_buf[1]; 01375 cnt <<= 8; 01376 cnt += Radio::radio.rx_buf[2]; 01377 cnt <<= 8; 01378 cnt += Radio::radio.rx_buf[3]; 01379 log_printf("%u rxPong->txPing\r\n", cnt); 01380 flags.send_ping = 1; 01381 } else { 01382 log_printf("pingpong?\r\n"); 01383 printRxPkt(size); 01384 } 01385 } else { 01386 /*for (unsigned n = 0; n < size; n++) 01387 log_printf("%02x\r\n", Radio::radio.rx_buf[n]);*/ 01388 log_printf("msg_type %u\r\n", msg_type); 01389 } 01390 01391 } 01392 01393 const RadioEvents_t rev = { 01394 txDone, 01395 rxDone 01396 }; 01397 01398 volatile int foo; 01399 01400 int main() 01401 { 01402 lfsr = LFSR_INIT; 01403 msg_type = MSG_TYPE_PACKET; 01404 01405 uart_rx_state = URX_STATE_NONE; 01406 01407 Radio::boardInit(&rev); 01408 01409 { 01410 unsigned n; 01411 for (n = 0; n < MAX_MENU_ROWS; n++) 01412 StopMenuCols[n] = -1; 01413 } 01414 01415 botRow = MAX_MENU_ROWS + SCROLLING_ROWS; 01416 01417 printf("\e[7h"); // enable line wrapping 01418 printf("\e[%u;%ur", MAX_MENU_ROWS, botRow); // set scrolling region 01419 printf("\e[2J"); // erase entire screen 01420 01421 full_menu_init(); 01422 01423 printf("\e[2J"); // erase entire screen 01424 01425 menuState.mode = MENUMODE_NONE; 01426 01427 draw_menu(); 01428 01429 curpos.row = 0; 01430 curpos.tableCol = 0; 01431 01432 tx_ipd_ms = 100; 01433 01434 logpc_printf("\r\nRESET\r\n"); 01435 01436 for (;;) { 01437 if (pc.readable()) { 01438 serial_callback(); 01439 } 01440 01441 if (flags.send_ping) { 01442 if (flags.pingpongEnable) 01443 SendPing(); 01444 flags.send_ping = 0; 01445 } 01446 01447 if (flags.send_pong) { 01448 if (flags.pingpongEnable) 01449 SendPong(); 01450 flags.send_pong = 0; 01451 } 01452 01453 if (flags.do_next_tx) { 01454 do_next_tx(); 01455 flags.do_next_tx = 0; 01456 } 01457 01458 if (menuState.mode == MENUMODE_REINIT_MENU) { 01459 full_menu_init(); 01460 menuState.mode = MENUMODE_REDRAW; 01461 } 01462 01463 if (menuState.mode == MENUMODE_REDRAW) { 01464 // erase entire screen, some dropdowns extend to scrolling area 01465 printf("\e[%u;%ur", MAX_MENU_ROWS, botRow); // set scrolling region, if terminal started after 01466 printf("\e[2J"); 01467 //printf("\e[%u;1f\e[1J", MAX_MENU_ROWS); // erase menu area 01468 01469 menuState.mode = MENUMODE_NONE; 01470 draw_menu(); 01471 } 01472 01473 if (Radio::service(menuState.mode == MENUMODE_NONE ? LAST_CHIP_MENU_ROW : -1)) { 01474 read_menu_item(menu_table[curpos.row][curpos.tableCol], true); 01475 } 01476 01477 if (cf_sweep.tick) { 01478 cf_sweep.tick = false; 01479 #ifdef SX127x_H 01480 Radio::radio.set_frf_MHz(cf_sweep.MHz); 01481 #else 01482 Radio::radio.setMHz(cf_sweep.MHz); 01483 #endif 01484 cf_sweep.MHz += cf_sweep.step_MHz; 01485 if (cf_sweep.MHz >= cf_sweep.stop_MHz) 01486 cf_sweep.MHz = cf_sweep.start_MHz; 01487 } 01488 01489 } // ..for (;;) 01490 } 01491 01492 char strbuf[255]; 01493 01494 void log_printf(const char* format, ...) 01495 { 01496 va_list arglist; 01497 01498 // put cursor at last scrolling-area line 01499 printf("\e[%u;1f", botRow); 01500 va_start(arglist, format); 01501 vsprintf(strbuf, format, arglist); 01502 va_end(arglist); 01503 01504 printf("%s", strbuf); 01505 01506 fflush(stdout); 01507 pc.sync(); 01508 } 01509 01510 void logpc_printf(const char* format, ...) /* printing on 2nd uart */ 01511 { 01512 int len; 01513 va_list arglist; 01514 01515 va_start(arglist, format); 01516 len = vsprintf(strbuf, format, arglist); 01517 va_end(arglist); 01518 01519 //logpc.write(strbuf, len); 01520 01521 fflush(stdout); 01522 pc.sync(); 01523 }
Generated on Mon Aug 5 2024 20:07:26 by
1.7.2