Text menu driven ANSI/VT100 console test utility for LoRa transceivers

radio chip selection

Radio chip driver is not included, allowing choice of radio device.
If you're using SX1272 or SX1276, then import sx127x driver into your program.
if you're using SX1261 or SX1262, then import sx126x driver into your program.
if you're using SX1280, then import sx1280 driver into your program.
if you're using LR1110, then import LR1110 driver into your program.
If you're using NAmote72 or Murata discovery, then you must import only sx127x driver.
If you're using Type1SJ select target DISCO_L072CZ_LRWAN1 and import sx126x driver into your program.

This is VT100 text-based menu driven test program for SX12xx transceiver devices.
Serial console is divided into horizontally into top half and bottom half.
The bottom half serves as scrolling area to log activity.
The top half serves as menu, to configure the radio.
For all devices, the serial console operates at 115200 8N1, and requires terminal with ANSI-VT100 capability, such as putty/teraterm/minicom etc.
Use program only with keyboard up/down/left/right keys. Enter to change an item, or number for value item. Some items are single bit, requiring only enter key to toggle. Others with fixed choices give a drop-down menu.

Committer:
dudmuck
Date:
Mon Aug 05 20:07:16 2024 +0000
Revision:
15:703ca340d0fb
Parent:
14:14b9e1c08bfc
add reading of RSSI

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wayne Roberts 1:0817a150122b 1 #include "mbed.h"
Wayne Roberts 1:0817a150122b 2 #include "radio.h"
Wayne Roberts 1:0817a150122b 3
Wayne Roberts 1:0817a150122b 4 //#define MENU_DEBUG
Wayne Roberts 1:0817a150122b 5
dudmuck 15:703ca340d0fb 6 #ifdef TARGET_NUCLEO_L073RZ
dudmuck 15:703ca340d0fb 7 BufferedSerial logpc(PC_10, PC_11, 115200);
dudmuck 15:703ca340d0fb 8 #else
dudmuck 15:703ca340d0fb 9 //#error log_uart_for_target
dudmuck 15:703ca340d0fb 10 #endif
dudmuck 15:703ca340d0fb 11 void logpc_printf(const char* format, ...);
dudmuck 15:703ca340d0fb 12
dudmuck 14:14b9e1c08bfc 13 static BufferedSerial pc(USBTX, USBRX, MBED_CONF_PLATFORM_STDIO_BAUD_RATE);
dudmuck 14:14b9e1c08bfc 14 namespace mbed {
dudmuck 14:14b9e1c08bfc 15 FileHandle *mbed_override_console(int fd) {
dudmuck 14:14b9e1c08bfc 16 return &pc;
dudmuck 13:8ce61a1897ab 17 }
dudmuck 13:8ce61a1897ab 18 }
Wayne Roberts 1:0817a150122b 19
Wayne Roberts 1:0817a150122b 20 menuState_t menuState;
Wayne Roberts 1:0817a150122b 21
Wayne Roberts 1:0817a150122b 22 typedef enum {
Wayne Roberts 1:0817a150122b 23 MSG_TYPE_PACKET = 0,
Wayne Roberts 1:0817a150122b 24 MSG_TYPE_PER,
Wayne Roberts 1:0817a150122b 25 MSG_TYPE_PINGPONG
Wayne Roberts 1:0817a150122b 26 } msgType_e;
Wayne Roberts 1:0817a150122b 27
Wayne Roberts 1:0817a150122b 28 // [row][column]
Wayne Roberts 1:0817a150122b 29 const menu_t* menu_table[MAX_MENU_ROWS][MAX_MENU_COLUMNS];
Wayne Roberts 1:0817a150122b 30 int8_t StopMenuCols[MAX_MENU_ROWS];
Wayne Roberts 1:0817a150122b 31
Wayne Roberts 1:0817a150122b 32 #define SCROLLING_ROWS 20
Wayne Roberts 1:0817a150122b 33
Wayne Roberts 1:0817a150122b 34 struct _cp_ {
Wayne Roberts 1:0817a150122b 35 uint8_t row;
Wayne Roberts 1:0817a150122b 36 uint8_t tableCol;
Wayne Roberts 1:0817a150122b 37 } curpos;
Wayne Roberts 1:0817a150122b 38
Wayne Roberts 1:0817a150122b 39 uint8_t entry_buf_idx;
Wayne Roberts 1:0817a150122b 40 char entry_buf[64];
Wayne Roberts 1:0817a150122b 41
Wayne Roberts 1:0817a150122b 42 msgType_e msg_type;
Wayne Roberts 1:0817a150122b 43
Wayne Roberts 1:0817a150122b 44 const uint8_t PingMsg[] = "PING";
Wayne Roberts 1:0817a150122b 45 const uint8_t PongMsg[] = "PONG";
Wayne Roberts 1:0817a150122b 46 const uint8_t PerMsg[] = "PER";
Wayne Roberts 1:0817a150122b 47
Wayne Roberts 1:0817a150122b 48 volatile struct _flags_ {
Wayne Roberts 1:0817a150122b 49 uint8_t ping_master : 1; // 0
Wayne Roberts 1:0817a150122b 50 uint8_t send_ping : 1; // 1
Wayne Roberts 1:0817a150122b 51 uint8_t send_pong : 1; // 2
Wayne Roberts 1:0817a150122b 52 uint8_t pingpongEnable : 1; // 3
Wayne Roberts 4:fa31fdf4ec8d 53 uint8_t do_next_tx : 1; // 4
Wayne Roberts 1:0817a150122b 54 } flags;
Wayne Roberts 1:0817a150122b 55
Wayne Roberts 1:0817a150122b 56 uint8_t botRow;
Wayne Roberts 4:fa31fdf4ec8d 57 int regAddr = -1;
Wayne Roberts 1:0817a150122b 58
dudmuck 13:8ce61a1897ab 59 struct {
dudmuck 13:8ce61a1897ab 60 float start_MHz;
dudmuck 13:8ce61a1897ab 61 float step_MHz;
dudmuck 13:8ce61a1897ab 62 float stop_MHz;
dudmuck 13:8ce61a1897ab 63 unsigned dwell_ms;
dudmuck 13:8ce61a1897ab 64 float MHz;
dudmuck 13:8ce61a1897ab 65 Ticker ticker;
dudmuck 13:8ce61a1897ab 66 bool ticking;
dudmuck 13:8ce61a1897ab 67 bool tick;
dudmuck 13:8ce61a1897ab 68 } cf_sweep;
dudmuck 13:8ce61a1897ab 69
dudmuck 13:8ce61a1897ab 70
Wayne Roberts 9:295e37c38fb3 71 void Radio::cadDone(bool det)
Wayne Roberts 9:295e37c38fb3 72 {
Wayne Roberts 9:295e37c38fb3 73 log_printf("cadDone ");
Wayne Roberts 9:295e37c38fb3 74 if (det)
dudmuck 13:8ce61a1897ab 75 printf("CadDetected");
Wayne Roberts 9:295e37c38fb3 76
dudmuck 13:8ce61a1897ab 77 printf("\r\n");
Wayne Roberts 9:295e37c38fb3 78 }
Wayne Roberts 9:295e37c38fb3 79
Wayne Roberts 1:0817a150122b 80 unsigned lfsr;
Wayne Roberts 1:0817a150122b 81 #define LFSR_INIT 0x1ff
Wayne Roberts 1:0817a150122b 82
Wayne Roberts 1:0817a150122b 83 uint8_t get_pn9_byte()
Wayne Roberts 1:0817a150122b 84 {
Wayne Roberts 1:0817a150122b 85 uint8_t ret = 0;
Wayne Roberts 1:0817a150122b 86 int xor_out;
Wayne Roberts 1:0817a150122b 87
Wayne Roberts 1:0817a150122b 88 xor_out = ((lfsr >> 5) & 0xf) ^ (lfsr & 0xf); // four bits at a time
Wayne Roberts 1:0817a150122b 89 lfsr = (lfsr >> 4) | (xor_out << 5); // four bits at a time
Wayne Roberts 1:0817a150122b 90
Wayne Roberts 1:0817a150122b 91 ret |= (lfsr >> 5) & 0x0f;
Wayne Roberts 1:0817a150122b 92
Wayne Roberts 1:0817a150122b 93 xor_out = ((lfsr >> 5) & 0xf) ^ (lfsr & 0xf); // four bits at a time
Wayne Roberts 1:0817a150122b 94 lfsr = (lfsr >> 4) | (xor_out << 5); // four bits at a time
Wayne Roberts 1:0817a150122b 95
Wayne Roberts 1:0817a150122b 96 ret |= ((lfsr >> 1) & 0xf0);
Wayne Roberts 1:0817a150122b 97
Wayne Roberts 1:0817a150122b 98 return ret;
Wayne Roberts 1:0817a150122b 99 }
Wayne Roberts 1:0817a150122b 100
Wayne Roberts 1:0817a150122b 101 void hw_reset_push()
Wayne Roberts 1:0817a150122b 102 {
Wayne Roberts 1:0817a150122b 103 Radio::hw_reset();
Wayne Roberts 1:0817a150122b 104
Wayne Roberts 1:0817a150122b 105 Radio::readChip();
Wayne Roberts 1:0817a150122b 106 menuState.mode = MENUMODE_REINIT_MENU;
Wayne Roberts 1:0817a150122b 107 }
Wayne Roberts 1:0817a150122b 108
Wayne Roberts 1:0817a150122b 109 const button_item_t hw_reset_item = { _ITEM_BUTTON, "hw_reset", hw_reset_push };
Wayne Roberts 1:0817a150122b 110
Wayne Roberts 1:0817a150122b 111 void clearIrqs_push()
Wayne Roberts 1:0817a150122b 112 {
Wayne Roberts 1:0817a150122b 113 Radio::clearIrqFlags();
Wayne Roberts 1:0817a150122b 114 }
Wayne Roberts 1:0817a150122b 115
Wayne Roberts 1:0817a150122b 116 const button_item_t clearirqs_item = { _ITEM_BUTTON, "clearIrqs", clearIrqs_push };
Wayne Roberts 1:0817a150122b 117
Wayne Roberts 2:ea9245bb1c53 118 const dropdown_item_t pktType_item = { _ITEM_DROPDOWN, Radio::pktType_strs, Radio::pktType_strs, Radio::pktType_read, Radio::pktType_write};
Wayne Roberts 1:0817a150122b 119
Wayne Roberts 1:0817a150122b 120
Wayne Roberts 2:ea9245bb1c53 121 unsigned msgType_read(bool fw)
Wayne Roberts 1:0817a150122b 122 {
Wayne Roberts 1:0817a150122b 123 return msg_type;
Wayne Roberts 1:0817a150122b 124 }
Wayne Roberts 1:0817a150122b 125
Wayne Roberts 2:ea9245bb1c53 126 menuMode_e msgType_write(unsigned widx)
Wayne Roberts 1:0817a150122b 127 {
Wayne Roberts 1:0817a150122b 128 msg_type = (msgType_e)widx;
Wayne Roberts 1:0817a150122b 129
Wayne Roberts 1:0817a150122b 130 if (msg_type == MSG_TYPE_PER) {
Wayne Roberts 1:0817a150122b 131 flags.pingpongEnable = 0;
Wayne Roberts 1:0817a150122b 132 if (Radio::get_payload_length() < 7)
Wayne Roberts 1:0817a150122b 133 Radio::set_payload_length(7);
Wayne Roberts 1:0817a150122b 134 } else if (msg_type == MSG_TYPE_PINGPONG) {
Wayne Roberts 1:0817a150122b 135 if (Radio::get_payload_length() != 12)
Wayne Roberts 1:0817a150122b 136 Radio::set_payload_length(12);
Wayne Roberts 1:0817a150122b 137 } else if (msg_type == MSG_TYPE_PACKET) {
Wayne Roberts 1:0817a150122b 138 flags.pingpongEnable = 0;
Wayne Roberts 1:0817a150122b 139 }
Wayne Roberts 1:0817a150122b 140
Wayne Roberts 1:0817a150122b 141 return MENUMODE_REINIT_MENU;
Wayne Roberts 1:0817a150122b 142 }
Wayne Roberts 1:0817a150122b 143
Wayne Roberts 1:0817a150122b 144 const char* const msgType_strs[] = {
Wayne Roberts 1:0817a150122b 145 "PACKET ",
Wayne Roberts 1:0817a150122b 146 "PER ",
Wayne Roberts 1:0817a150122b 147 "PINGPONG",
Wayne Roberts 1:0817a150122b 148 NULL
Wayne Roberts 1:0817a150122b 149 };
Wayne Roberts 1:0817a150122b 150
Wayne Roberts 2:ea9245bb1c53 151 const dropdown_item_t msgType_item = { _ITEM_DROPDOWN, msgType_strs, msgType_strs, msgType_read, msgType_write};
Wayne Roberts 1:0817a150122b 152
dudmuck 13:8ce61a1897ab 153 void sweep_start_print()
dudmuck 13:8ce61a1897ab 154 {
dudmuck 13:8ce61a1897ab 155 printf("%.3fMHz", cf_sweep.start_MHz);
dudmuck 13:8ce61a1897ab 156 }
dudmuck 13:8ce61a1897ab 157
dudmuck 13:8ce61a1897ab 158 bool sweep_start_write(const char* valStr)
dudmuck 13:8ce61a1897ab 159 {
dudmuck 13:8ce61a1897ab 160 sscanf(valStr, "%f", &cf_sweep.start_MHz);
dudmuck 13:8ce61a1897ab 161 return false;
dudmuck 13:8ce61a1897ab 162 }
dudmuck 13:8ce61a1897ab 163
dudmuck 13:8ce61a1897ab 164 void sweep_step_print()
dudmuck 13:8ce61a1897ab 165 {
dudmuck 13:8ce61a1897ab 166 printf("%.3fMHz", cf_sweep.step_MHz);
dudmuck 13:8ce61a1897ab 167 }
dudmuck 13:8ce61a1897ab 168
dudmuck 13:8ce61a1897ab 169 bool sweep_step_write(const char* valStr)
dudmuck 13:8ce61a1897ab 170 {
dudmuck 13:8ce61a1897ab 171 sscanf(valStr, "%f", &cf_sweep.step_MHz);
dudmuck 13:8ce61a1897ab 172 return false;
dudmuck 13:8ce61a1897ab 173 }
dudmuck 13:8ce61a1897ab 174
dudmuck 13:8ce61a1897ab 175 void sweep_stop_print()
dudmuck 13:8ce61a1897ab 176 {
dudmuck 13:8ce61a1897ab 177 printf("%.3fMHz", cf_sweep.stop_MHz);
dudmuck 13:8ce61a1897ab 178 }
dudmuck 13:8ce61a1897ab 179
dudmuck 13:8ce61a1897ab 180 bool sweep_stop_write(const char* valStr)
dudmuck 13:8ce61a1897ab 181 {
dudmuck 13:8ce61a1897ab 182 sscanf(valStr, "%f", &cf_sweep.stop_MHz);
dudmuck 13:8ce61a1897ab 183 return false;
dudmuck 13:8ce61a1897ab 184 }
dudmuck 13:8ce61a1897ab 185
dudmuck 13:8ce61a1897ab 186 void sweep_dwell_print()
dudmuck 13:8ce61a1897ab 187 {
dudmuck 13:8ce61a1897ab 188 printf("%ums", cf_sweep.dwell_ms);
dudmuck 13:8ce61a1897ab 189 }
dudmuck 13:8ce61a1897ab 190
dudmuck 13:8ce61a1897ab 191 bool sweep_dwell_write(const char* valStr)
dudmuck 13:8ce61a1897ab 192 {
dudmuck 13:8ce61a1897ab 193 sscanf(valStr, "%u", &cf_sweep.dwell_ms);
dudmuck 13:8ce61a1897ab 194 return false;
dudmuck 13:8ce61a1897ab 195 }
dudmuck 13:8ce61a1897ab 196
Wayne Roberts 1:0817a150122b 197 const value_item_t tx_payload_length_item = { _ITEM_VALUE, 5, Radio::tx_payload_length_print, Radio::tx_payload_length_write};
Wayne Roberts 1:0817a150122b 198
Wayne Roberts 1:0817a150122b 199 void pn9_push()
Wayne Roberts 1:0817a150122b 200 {
Wayne Roberts 1:0817a150122b 201 uint8_t i, len = Radio::get_payload_length();
Wayne Roberts 1:0817a150122b 202 for (i = 0; i < len; i++)
Wayne Roberts 1:0817a150122b 203 Radio::radio.tx_buf[i] = get_pn9_byte();
Wayne Roberts 1:0817a150122b 204 }
Wayne Roberts 1:0817a150122b 205
Wayne Roberts 1:0817a150122b 206 const button_item_t tx_payload_pn9_item = { _ITEM_BUTTON, "PN9", pn9_push };
Wayne Roberts 1:0817a150122b 207
Wayne Roberts 4:fa31fdf4ec8d 208 void regAddr_print()
Wayne Roberts 4:fa31fdf4ec8d 209 {
Wayne Roberts 4:fa31fdf4ec8d 210 if (regAddr != -1)
dudmuck 13:8ce61a1897ab 211 printf("%x", regAddr);
Wayne Roberts 4:fa31fdf4ec8d 212 }
Wayne Roberts 4:fa31fdf4ec8d 213
Wayne Roberts 4:fa31fdf4ec8d 214 bool regAddr_write(const char* txt)
Wayne Roberts 4:fa31fdf4ec8d 215 {
Wayne Roberts 4:fa31fdf4ec8d 216 sscanf(txt, "%x", &regAddr);
Wayne Roberts 4:fa31fdf4ec8d 217 return false;
Wayne Roberts 4:fa31fdf4ec8d 218 }
Wayne Roberts 4:fa31fdf4ec8d 219
Wayne Roberts 4:fa31fdf4ec8d 220 const value_item_t regAddr_item = { _ITEM_VALUE, 5, regAddr_print, regAddr_write};
Wayne Roberts 4:fa31fdf4ec8d 221
Wayne Roberts 4:fa31fdf4ec8d 222 void regValue_print()
Wayne Roberts 4:fa31fdf4ec8d 223 {
Wayne Roberts 4:fa31fdf4ec8d 224 if (regAddr != -1) {
dudmuck 13:8ce61a1897ab 225 printf("%x", Radio::read_register(regAddr));
Wayne Roberts 4:fa31fdf4ec8d 226 }
Wayne Roberts 4:fa31fdf4ec8d 227 }
Wayne Roberts 4:fa31fdf4ec8d 228
Wayne Roberts 4:fa31fdf4ec8d 229 bool regValue_write(const char* txt)
Wayne Roberts 4:fa31fdf4ec8d 230 {
Wayne Roberts 4:fa31fdf4ec8d 231 unsigned val;
Wayne Roberts 4:fa31fdf4ec8d 232 sscanf(txt, "%x", &val);
Wayne Roberts 4:fa31fdf4ec8d 233 if (regAddr != -1) {
Wayne Roberts 4:fa31fdf4ec8d 234 Radio::write_register(regAddr, val);
Wayne Roberts 4:fa31fdf4ec8d 235 }
Wayne Roberts 4:fa31fdf4ec8d 236 return false;
Wayne Roberts 4:fa31fdf4ec8d 237 }
Wayne Roberts 4:fa31fdf4ec8d 238
Wayne Roberts 4:fa31fdf4ec8d 239 const value_item_t regValue_item = { _ITEM_VALUE, 5, regValue_print, regValue_write};
Wayne Roberts 4:fa31fdf4ec8d 240
Wayne Roberts 1:0817a150122b 241 void tx_payload_print()
Wayne Roberts 1:0817a150122b 242 {
Wayne Roberts 1:0817a150122b 243 uint8_t i, len = Radio::get_payload_length();
Wayne Roberts 1:0817a150122b 244 for (i = 0; i < len; i++)
dudmuck 13:8ce61a1897ab 245 printf("%02x ", Radio::radio.tx_buf[i]);
Wayne Roberts 1:0817a150122b 246 }
Wayne Roberts 1:0817a150122b 247
Wayne Roberts 1:0817a150122b 248 bool tx_payload_write(const char* txt)
Wayne Roberts 1:0817a150122b 249 {
Wayne Roberts 1:0817a150122b 250 unsigned o, i = 0, pktidx = 0;
Wayne Roberts 1:0817a150122b 251 while (i < entry_buf_idx) {
Wayne Roberts 1:0817a150122b 252 sscanf(entry_buf+i, "%02x", &o);
dudmuck 13:8ce61a1897ab 253 printf("%02x ", o);
Wayne Roberts 1:0817a150122b 254 i += 2;
Wayne Roberts 1:0817a150122b 255 Radio::radio.tx_buf[pktidx++] = o;
Wayne Roberts 1:0817a150122b 256 while (entry_buf[i] == ' ' && i < entry_buf_idx)
Wayne Roberts 1:0817a150122b 257 i++;
Wayne Roberts 1:0817a150122b 258 }
Wayne Roberts 1:0817a150122b 259 log_printf("set payload len %u\r\n", pktidx);
Wayne Roberts 1:0817a150122b 260 Radio::set_payload_length(pktidx);
Wayne Roberts 1:0817a150122b 261 return true;
Wayne Roberts 1:0817a150122b 262 }
Wayne Roberts 1:0817a150122b 263
Wayne Roberts 6:44a9df0e7855 264 const value_item_t tx_payload_item = { _ITEM_VALUE, 80, tx_payload_print, tx_payload_write};
Wayne Roberts 1:0817a150122b 265
Wayne Roberts 1:0817a150122b 266 void txpkt_push()
Wayne Roberts 1:0817a150122b 267 {
Wayne Roberts 1:0817a150122b 268 Radio::txPkt();
Wayne Roberts 1:0817a150122b 269 }
Wayne Roberts 1:0817a150122b 270
Wayne Roberts 1:0817a150122b 271 const button_item_t tx_pkt_item = { _ITEM_BUTTON, "TXPKT", txpkt_push };
Wayne Roberts 1:0817a150122b 272
Wayne Roberts 1:0817a150122b 273 void rxpkt_push()
Wayne Roberts 1:0817a150122b 274 {
Wayne Roberts 1:0817a150122b 275 Radio::Rx();
Wayne Roberts 9:295e37c38fb3 276 //yyy menuState.mode = MENUMODE_REDRAW;
Wayne Roberts 1:0817a150122b 277 }
Wayne Roberts 1:0817a150122b 278 const button_item_t rx_pkt_item = { _ITEM_BUTTON, "RXPKT", rxpkt_push };
Wayne Roberts 1:0817a150122b 279
Wayne Roberts 2:ea9245bb1c53 280 const dropdown_item_t opmode_item = { _ITEM_DROPDOWN, Radio::opmode_status_strs, Radio::opmode_select_strs, Radio::opmode_read, Radio::opmode_write };
Wayne Roberts 1:0817a150122b 281
Wayne Roberts 1:0817a150122b 282 void tx_carrier_push()
Wayne Roberts 1:0817a150122b 283 {
Wayne Roberts 1:0817a150122b 284 Radio::tx_carrier();
Wayne Roberts 1:0817a150122b 285 }
Wayne Roberts 1:0817a150122b 286 const button_item_t tx_carrier_item = { _ITEM_BUTTON, "TX_CARRIER", tx_carrier_push };
Wayne Roberts 1:0817a150122b 287
Wayne Roberts 1:0817a150122b 288 void tx_preamble_push()
Wayne Roberts 1:0817a150122b 289 {
Wayne Roberts 1:0817a150122b 290 Radio::tx_preamble();
Wayne Roberts 1:0817a150122b 291 }
Wayne Roberts 1:0817a150122b 292 const button_item_t tx_preamble_item = { _ITEM_BUTTON, "TX_PREAMBLE", tx_preamble_push };
Wayne Roberts 1:0817a150122b 293
dudmuck 15:703ca340d0fb 294 void get_rssi_push()
dudmuck 15:703ca340d0fb 295 {
dudmuck 15:703ca340d0fb 296 Radio::get_rssi();
dudmuck 15:703ca340d0fb 297 }
dudmuck 15:703ca340d0fb 298 const button_item_t get_rssi_item = { _ITEM_BUTTON, "GET_RSSI", get_rssi_push };
dudmuck 15:703ca340d0fb 299
dudmuck 13:8ce61a1897ab 300 const value_item_t sweep_start_item = { _ITEM_VALUE, 5, sweep_start_print, sweep_start_write};
dudmuck 13:8ce61a1897ab 301 const value_item_t sweep_step_item = { _ITEM_VALUE, 5, sweep_step_print, sweep_step_write};
dudmuck 13:8ce61a1897ab 302 const value_item_t sweep_stop_item = { _ITEM_VALUE, 5, sweep_stop_print, sweep_stop_write};
dudmuck 13:8ce61a1897ab 303 const value_item_t sweep_dwell_item = { _ITEM_VALUE, 5, sweep_dwell_print, sweep_dwell_write};
Wayne Roberts 1:0817a150122b 304
Wayne Roberts 1:0817a150122b 305 const menu_t msg_pkt_menu[] = {
Wayne Roberts 1:0817a150122b 306 { {LAST_CHIP_MENU_ROW+1, 1}, "tx payload length:", &tx_payload_length_item, FLAG_MSGTYPE_PKT },
Wayne Roberts 1:0817a150122b 307 { {LAST_CHIP_MENU_ROW+1, 25}, NULL, &tx_payload_pn9_item, FLAG_MSGTYPE_PKT, &tx_payload_item },
Wayne Roberts 4:fa31fdf4ec8d 308 { {LAST_CHIP_MENU_ROW+1, 40}, "regAddr:", &regAddr_item, FLAG_MSGTYPE_PKT, &regValue_item },
Wayne Roberts 4:fa31fdf4ec8d 309 { {LAST_CHIP_MENU_ROW+1, 53}, "regValue:", &regValue_item, FLAG_MSGTYPE_PKT, },
Wayne Roberts 1:0817a150122b 310 { {LAST_CHIP_MENU_ROW+2, 1}, NULL, &tx_payload_item, FLAG_MSGTYPE_PKT },
Wayne Roberts 1:0817a150122b 311 { {LAST_CHIP_MENU_ROW+3, 1}, NULL, &tx_pkt_item, FLAG_MSGTYPE_PKT, &opmode_item },
Wayne Roberts 1:0817a150122b 312 { {LAST_CHIP_MENU_ROW+3, 10}, NULL, &rx_pkt_item, FLAG_MSGTYPE_PKT },
Wayne Roberts 1:0817a150122b 313 { {LAST_CHIP_MENU_ROW+3, 20}, NULL, &tx_carrier_item, FLAG_MSGTYPE_PKT, &opmode_item },
Wayne Roberts 1:0817a150122b 314 { {LAST_CHIP_MENU_ROW+3, 45}, NULL, &tx_preamble_item, FLAG_MSGTYPE_PKT, &opmode_item },
dudmuck 15:703ca340d0fb 315 { {LAST_CHIP_MENU_ROW+3, 58}, NULL, &get_rssi_item, FLAG_MSGTYPE_PKT, &opmode_item },
dudmuck 13:8ce61a1897ab 316 { {LAST_CHIP_MENU_ROW+4, 1}, "cf sweep start:", &sweep_start_item, FLAG_MSGTYPE_PKT },
dudmuck 13:8ce61a1897ab 317 { {LAST_CHIP_MENU_ROW+4, 28}, "step:", &sweep_step_item, FLAG_MSGTYPE_PKT },
dudmuck 13:8ce61a1897ab 318 { {LAST_CHIP_MENU_ROW+4, 45}, "stop:", &sweep_stop_item, FLAG_MSGTYPE_PKT },
dudmuck 13:8ce61a1897ab 319 { {LAST_CHIP_MENU_ROW+4, 62}, "dwell_ms:", &sweep_dwell_item, FLAG_MSGTYPE_PKT },
Wayne Roberts 1:0817a150122b 320
Wayne Roberts 1:0817a150122b 321 { {0, 0}, NULL, NULL }
Wayne Roberts 1:0817a150122b 322 };
Wayne Roberts 1:0817a150122b 323
Wayne Roberts 1:0817a150122b 324 unsigned tx_ipd_ms;
Wayne Roberts 1:0817a150122b 325 Timeout mbedTimeout;
Wayne Roberts 1:0817a150122b 326 unsigned MaxNumPacket;
Wayne Roberts 1:0817a150122b 327 unsigned CntPacketTx;
Wayne Roberts 1:0817a150122b 328 unsigned PacketRxSequencePrev;
Wayne Roberts 1:0817a150122b 329 unsigned CntPacketRxKO;
Wayne Roberts 1:0817a150122b 330 unsigned CntPacketRxOK;
Wayne Roberts 1:0817a150122b 331 unsigned RxTimeOutCount;
Wayne Roberts 1:0817a150122b 332 unsigned receivedCntPacket;
Wayne Roberts 1:0817a150122b 333
Wayne Roberts 4:fa31fdf4ec8d 334 void do_next_tx ()
Wayne Roberts 1:0817a150122b 335 {
Wayne Roberts 1:0817a150122b 336 Radio::radio.tx_buf[0] = CntPacketTx >> 24;
Wayne Roberts 1:0817a150122b 337 Radio::radio.tx_buf[1] = CntPacketTx >> 16;
Wayne Roberts 1:0817a150122b 338 Radio::radio.tx_buf[2] = CntPacketTx >> 8;
Wayne Roberts 1:0817a150122b 339 Radio::radio.tx_buf[3] = CntPacketTx;
Wayne Roberts 1:0817a150122b 340
Wayne Roberts 1:0817a150122b 341 Radio::radio.tx_buf[4] = PerMsg[0];
Wayne Roberts 1:0817a150122b 342 Radio::radio.tx_buf[5] = PerMsg[1];
Wayne Roberts 1:0817a150122b 343 Radio::radio.tx_buf[6] = PerMsg[2];
Wayne Roberts 1:0817a150122b 344
Wayne Roberts 1:0817a150122b 345 Radio::txPkt();
Wayne Roberts 1:0817a150122b 346 }
Wayne Roberts 1:0817a150122b 347
Wayne Roberts 4:fa31fdf4ec8d 348 void next_tx_callback()
Wayne Roberts 4:fa31fdf4ec8d 349 {
Wayne Roberts 4:fa31fdf4ec8d 350 flags.do_next_tx = 1;
Wayne Roberts 4:fa31fdf4ec8d 351 }
Wayne Roberts 4:fa31fdf4ec8d 352
Wayne Roberts 1:0817a150122b 353
Wayne Roberts 1:0817a150122b 354 void pertx_push()
Wayne Roberts 1:0817a150122b 355 {
Wayne Roberts 1:0817a150122b 356 CntPacketTx = 1; // PacketRxSequencePrev initialized to 0 on receiver
Wayne Roberts 1:0817a150122b 357
Wayne Roberts 1:0817a150122b 358 log_printf("do perTx\r\n");
Wayne Roberts 1:0817a150122b 359
Wayne Roberts 1:0817a150122b 360 next_tx_callback();
Wayne Roberts 1:0817a150122b 361 }
Wayne Roberts 1:0817a150122b 362
Wayne Roberts 1:0817a150122b 363
Wayne Roberts 1:0817a150122b 364 const button_item_t pertx_item = { _ITEM_BUTTON, "PERTX", pertx_push };
Wayne Roberts 1:0817a150122b 365
Wayne Roberts 1:0817a150122b 366 void tx_ipd_print()
Wayne Roberts 1:0817a150122b 367 {
dudmuck 13:8ce61a1897ab 368 printf("%u", tx_ipd_ms);
Wayne Roberts 1:0817a150122b 369 }
Wayne Roberts 1:0817a150122b 370
Wayne Roberts 1:0817a150122b 371 bool tx_ipd_write(const char* valStr)
Wayne Roberts 1:0817a150122b 372 {
Wayne Roberts 1:0817a150122b 373 sscanf(valStr, "%u", &tx_ipd_ms);
Wayne Roberts 1:0817a150122b 374 return false;
Wayne Roberts 1:0817a150122b 375 }
Wayne Roberts 1:0817a150122b 376
Wayne Roberts 2:ea9245bb1c53 377 value_item_t per_ipd_item = { _ITEM_VALUE, 4, tx_ipd_print, tx_ipd_write };
Wayne Roberts 1:0817a150122b 378
Wayne Roberts 1:0817a150122b 379 void numpkts_print()
Wayne Roberts 1:0817a150122b 380 {
dudmuck 13:8ce61a1897ab 381 printf("%u", MaxNumPacket);
Wayne Roberts 1:0817a150122b 382 }
Wayne Roberts 1:0817a150122b 383
Wayne Roberts 1:0817a150122b 384 bool numpkts_write(const char* valStr)
Wayne Roberts 1:0817a150122b 385 {
Wayne Roberts 1:0817a150122b 386 sscanf(valStr, "%u", &MaxNumPacket);
Wayne Roberts 1:0817a150122b 387 return false;
Wayne Roberts 1:0817a150122b 388 }
Wayne Roberts 1:0817a150122b 389
Wayne Roberts 2:ea9245bb1c53 390 value_item_t per_numpkts_item = { _ITEM_VALUE, 6, numpkts_print, numpkts_write };
Wayne Roberts 1:0817a150122b 391
Wayne Roberts 1:0817a150122b 392 void perrx_push()
Wayne Roberts 1:0817a150122b 393 {
Wayne Roberts 1:0817a150122b 394 PacketRxSequencePrev = 0;
Wayne Roberts 1:0817a150122b 395 CntPacketRxKO = 0;
Wayne Roberts 1:0817a150122b 396 CntPacketRxOK = 0;
Wayne Roberts 1:0817a150122b 397 RxTimeOutCount = 0;
Wayne Roberts 1:0817a150122b 398
Wayne Roberts 1:0817a150122b 399 Radio::Rx();
Wayne Roberts 1:0817a150122b 400 }
Wayne Roberts 1:0817a150122b 401
Wayne Roberts 1:0817a150122b 402 const button_item_t perrx_item = { _ITEM_BUTTON, "PERRX", perrx_push };
Wayne Roberts 1:0817a150122b 403
Wayne Roberts 2:ea9245bb1c53 404 void per_reset_push()
Wayne Roberts 2:ea9245bb1c53 405 {
Wayne Roberts 2:ea9245bb1c53 406 PacketRxSequencePrev = 0;
Wayne Roberts 2:ea9245bb1c53 407 CntPacketRxKO = 0;
Wayne Roberts 2:ea9245bb1c53 408 CntPacketRxOK = 0;
Wayne Roberts 2:ea9245bb1c53 409 RxTimeOutCount = 0;
Wayne Roberts 2:ea9245bb1c53 410 }
Wayne Roberts 2:ea9245bb1c53 411
Wayne Roberts 2:ea9245bb1c53 412 const button_item_t per_clear_item = { _ITEM_BUTTON, "resetCount", per_reset_push };
Wayne Roberts 2:ea9245bb1c53 413
Wayne Roberts 1:0817a150122b 414 const menu_t msg_per_menu[] = {
Wayne Roberts 1:0817a150122b 415 { {LAST_CHIP_MENU_ROW+3, 1}, NULL, &pertx_item, FLAG_MSGTYPE_PER },
Wayne Roberts 9:295e37c38fb3 416 { {LAST_CHIP_MENU_ROW+3, 10}, "TX IPD ms:", &per_ipd_item, FLAG_MSGTYPE_PER },
Wayne Roberts 2:ea9245bb1c53 417 { {LAST_CHIP_MENU_ROW+3, 26}, "numPkts:", &per_numpkts_item, FLAG_MSGTYPE_PER },
Wayne Roberts 2:ea9245bb1c53 418 { {LAST_CHIP_MENU_ROW+3, 40}, NULL, &perrx_item, FLAG_MSGTYPE_PER, &opmode_item },
Wayne Roberts 2:ea9245bb1c53 419 { {LAST_CHIP_MENU_ROW+3, 50}, NULL, &per_clear_item, FLAG_MSGTYPE_PER, &opmode_item },
Wayne Roberts 1:0817a150122b 420 { {0, 0}, NULL, NULL }
Wayne Roberts 1:0817a150122b 421 };
Wayne Roberts 1:0817a150122b 422
Wayne Roberts 1:0817a150122b 423 void SendPong()
Wayne Roberts 1:0817a150122b 424 {
Wayne Roberts 1:0817a150122b 425 unsigned failCnt = CntPacketRxKO + RxTimeOutCount;
Wayne Roberts 1:0817a150122b 426
Wayne Roberts 1:0817a150122b 427 /* ping slave tx */
Wayne Roberts 1:0817a150122b 428 log_printf("ACK PKT%u\r\n", receivedCntPacket);
Wayne Roberts 1:0817a150122b 429
Wayne Roberts 1:0817a150122b 430 Radio::radio.tx_buf[ 0] = receivedCntPacket >> 24;
Wayne Roberts 1:0817a150122b 431 Radio::radio.tx_buf[ 1] = receivedCntPacket >> 16;
Wayne Roberts 1:0817a150122b 432 Radio::radio.tx_buf[ 2] = receivedCntPacket >> 8;
Wayne Roberts 1:0817a150122b 433 Radio::radio.tx_buf[ 3] = receivedCntPacket;
Wayne Roberts 1:0817a150122b 434 Radio::radio.tx_buf[ 4] = failCnt >> 24;
Wayne Roberts 1:0817a150122b 435 Radio::radio.tx_buf[ 5] = failCnt >> 16;
Wayne Roberts 1:0817a150122b 436 Radio::radio.tx_buf[ 6] = failCnt >> 8;
Wayne Roberts 1:0817a150122b 437 Radio::radio.tx_buf[ 7] = failCnt;
Wayne Roberts 1:0817a150122b 438 Radio::radio.tx_buf[ 8] = PongMsg[0];
Wayne Roberts 1:0817a150122b 439 Radio::radio.tx_buf[ 9] = PongMsg[1];
Wayne Roberts 1:0817a150122b 440 Radio::radio.tx_buf[10] = PongMsg[2];
Wayne Roberts 1:0817a150122b 441 Radio::radio.tx_buf[11] = PongMsg[3];
Wayne Roberts 1:0817a150122b 442
Wayne Roberts 1:0817a150122b 443 Radio::txPkt();
Wayne Roberts 1:0817a150122b 444 }
Wayne Roberts 1:0817a150122b 445
Wayne Roberts 1:0817a150122b 446 void SendPing()
Wayne Roberts 1:0817a150122b 447 {
Wayne Roberts 1:0817a150122b 448 /* ping master tx */
Wayne Roberts 1:0817a150122b 449
Wayne Roberts 1:0817a150122b 450 log_printf("MASTER > PING PKT%u\r\n", CntPacketTx);
Wayne Roberts 1:0817a150122b 451 Radio::radio.tx_buf[0] = CntPacketTx >> 24;
Wayne Roberts 1:0817a150122b 452 Radio::radio.tx_buf[1] = CntPacketTx >> 16;
Wayne Roberts 1:0817a150122b 453 Radio::radio.tx_buf[2] = CntPacketTx >> 8;
Wayne Roberts 1:0817a150122b 454 Radio::radio.tx_buf[3] = CntPacketTx;
Wayne Roberts 1:0817a150122b 455 Radio::radio.tx_buf[4] = PingMsg[0];
Wayne Roberts 1:0817a150122b 456 Radio::radio.tx_buf[5] = PingMsg[1];
Wayne Roberts 1:0817a150122b 457 Radio::radio.tx_buf[6] = PingMsg[2];
Wayne Roberts 1:0817a150122b 458 Radio::radio.tx_buf[7] = PingMsg[3];
Wayne Roberts 1:0817a150122b 459
Wayne Roberts 1:0817a150122b 460 Radio::txPkt();
Wayne Roberts 1:0817a150122b 461 }
Wayne Roberts 1:0817a150122b 462
Wayne Roberts 1:0817a150122b 463 void
Wayne Roberts 1:0817a150122b 464 pingpong_start_push()
Wayne Roberts 1:0817a150122b 465 {
Wayne Roberts 1:0817a150122b 466 CntPacketTx = 1;
Wayne Roberts 1:0817a150122b 467 CntPacketRxKO = 0;
Wayne Roberts 1:0817a150122b 468 CntPacketRxOK = 0;
Wayne Roberts 1:0817a150122b 469 RxTimeOutCount = 0;
Wayne Roberts 1:0817a150122b 470 receivedCntPacket = 0;
Wayne Roberts 1:0817a150122b 471
Wayne Roberts 1:0817a150122b 472 flags.send_ping = 1;
Wayne Roberts 1:0817a150122b 473
Wayne Roberts 1:0817a150122b 474 flags.ping_master = 1;
Wayne Roberts 1:0817a150122b 475
Wayne Roberts 1:0817a150122b 476 flags.pingpongEnable = 1;
Wayne Roberts 1:0817a150122b 477 log_printf("ping start\r\n");
Wayne Roberts 1:0817a150122b 478 }
Wayne Roberts 1:0817a150122b 479
Wayne Roberts 1:0817a150122b 480 const button_item_t pingpong_start_item = { _ITEM_BUTTON, "START", pingpong_start_push };
Wayne Roberts 1:0817a150122b 481
Wayne Roberts 1:0817a150122b 482 void
Wayne Roberts 1:0817a150122b 483 pingpong_stop_push ()
Wayne Roberts 1:0817a150122b 484 {
Wayne Roberts 1:0817a150122b 485 flags.pingpongEnable = 0;
Wayne Roberts 1:0817a150122b 486 }
Wayne Roberts 1:0817a150122b 487
Wayne Roberts 1:0817a150122b 488 const button_item_t pingpong_stop_item = { _ITEM_BUTTON, "STOP", pingpong_stop_push };
Wayne Roberts 1:0817a150122b 489
Wayne Roberts 1:0817a150122b 490 const menu_t msg_pingpong_menu[] = {
Wayne Roberts 1:0817a150122b 491 { {LAST_CHIP_MENU_ROW+3, 1}, NULL, &pingpong_start_item, FLAG_MSGTYPE_PING },
Wayne Roberts 1:0817a150122b 492 { {LAST_CHIP_MENU_ROW+3, 15}, NULL, &pingpong_stop_item, FLAG_MSGTYPE_PING },
Wayne Roberts 1:0817a150122b 493 { {0, 0}, NULL, NULL }
Wayne Roberts 1:0817a150122b 494 };
Wayne Roberts 1:0817a150122b 495
Wayne Roberts 1:0817a150122b 496 const menu_t* get_msg_menu()
Wayne Roberts 1:0817a150122b 497 {
Wayne Roberts 1:0817a150122b 498 switch (msg_type) {
Wayne Roberts 1:0817a150122b 499 case MSG_TYPE_PACKET:
Wayne Roberts 1:0817a150122b 500 return msg_pkt_menu;
Wayne Roberts 1:0817a150122b 501 case MSG_TYPE_PER:
Wayne Roberts 1:0817a150122b 502 return msg_per_menu;
Wayne Roberts 1:0817a150122b 503 case MSG_TYPE_PINGPONG:
Wayne Roberts 1:0817a150122b 504 return msg_pingpong_menu;
Wayne Roberts 1:0817a150122b 505 }
Wayne Roberts 1:0817a150122b 506 return NULL;
Wayne Roberts 1:0817a150122b 507 }
Wayne Roberts 1:0817a150122b 508
Wayne Roberts 1:0817a150122b 509 void frf_print()
Wayne Roberts 1:0817a150122b 510 {
Wayne Roberts 1:0817a150122b 511 float MHz;
Wayne Roberts 1:0817a150122b 512 #ifdef SX127x_H
Wayne Roberts 1:0817a150122b 513 MHz = Radio::radio.get_frf_MHz();
Wayne Roberts 1:0817a150122b 514 #else
Wayne Roberts 1:0817a150122b 515 MHz = Radio::radio.getMHz();
Wayne Roberts 1:0817a150122b 516 #endif
dudmuck 13:8ce61a1897ab 517 printf("%.3fMHz", MHz);
Wayne Roberts 1:0817a150122b 518 }
Wayne Roberts 1:0817a150122b 519
Wayne Roberts 1:0817a150122b 520 bool frf_write(const char* valStr)
Wayne Roberts 1:0817a150122b 521 {
Wayne Roberts 1:0817a150122b 522 float MHz;
Wayne Roberts 1:0817a150122b 523 sscanf(valStr, "%f", &MHz);
Wayne Roberts 1:0817a150122b 524 #ifdef SX127x_H
Wayne Roberts 1:0817a150122b 525 Radio::radio.set_frf_MHz(MHz);
Wayne Roberts 1:0817a150122b 526 #else
Wayne Roberts 1:0817a150122b 527 Radio::radio.setMHz(MHz);
Wayne Roberts 1:0817a150122b 528 #endif
Wayne Roberts 1:0817a150122b 529 return false;
Wayne Roberts 1:0817a150122b 530 }
Wayne Roberts 1:0817a150122b 531
Wayne Roberts 1:0817a150122b 532 const value_item_t frf_item = { _ITEM_VALUE, 14, frf_print, frf_write };
Wayne Roberts 1:0817a150122b 533
Wayne Roberts 1:0817a150122b 534 const value_item_t Radio::tx_dbm_item = { _ITEM_VALUE, 7, Radio::tx_dbm_print, Radio::tx_dbm_write };
Wayne Roberts 1:0817a150122b 535
Wayne Roberts 2:ea9245bb1c53 536 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 };
Wayne Roberts 1:0817a150122b 537
Wayne Roberts 1:0817a150122b 538 const button_item_t chipNum_item = { _ITEM_BUTTON, Radio::chipNum_str, NULL};
Wayne Roberts 1:0817a150122b 539
Wayne Roberts 1:0817a150122b 540 void botrow_print()
Wayne Roberts 1:0817a150122b 541 {
dudmuck 13:8ce61a1897ab 542 printf("%u", botRow);
Wayne Roberts 1:0817a150122b 543 }
Wayne Roberts 1:0817a150122b 544
Wayne Roberts 1:0817a150122b 545 bool botrow_write(const char* str)
Wayne Roberts 1:0817a150122b 546 {
Wayne Roberts 1:0817a150122b 547 unsigned n;
Wayne Roberts 1:0817a150122b 548 sscanf(str, "%u", &n);
Wayne Roberts 1:0817a150122b 549 botRow = n;
Wayne Roberts 1:0817a150122b 550
dudmuck 13:8ce61a1897ab 551 printf("\e[%u;%ur", MAX_MENU_ROWS, botRow); // set scrolling region
Wayne Roberts 1:0817a150122b 552
Wayne Roberts 1:0817a150122b 553 return false;
Wayne Roberts 1:0817a150122b 554 }
Wayne Roberts 1:0817a150122b 555
Wayne Roberts 1:0817a150122b 556 const value_item_t bottomRow_item = { _ITEM_VALUE, 4, botrow_print, botrow_write };
Wayne Roberts 1:0817a150122b 557
Wayne Roberts 1:0817a150122b 558 const menu_t common_menu[] = {
Wayne Roberts 5:1e5cb7139acb 559 { {1, 1}, NULL, &hw_reset_item, FLAG_MSGTYPE_ALL },
Wayne Roberts 9:295e37c38fb3 560 { {1, 13}, "packetType:", &pktType_item, FLAG_MSGTYPE_ALL },
Wayne Roberts 9:295e37c38fb3 561 { {1, 33}, NULL, &msgType_item, FLAG_MSGTYPE_ALL },
Wayne Roberts 9:295e37c38fb3 562 { {1, 43}, NULL, &chipNum_item, FLAG_MSGTYPE_ALL },
Wayne Roberts 9:295e37c38fb3 563 { {1, 61}, "bottomRow:", &bottomRow_item, FLAG_MSGTYPE_ALL },
Wayne Roberts 5:1e5cb7139acb 564 { {2, 1}, NULL, &frf_item, FLAG_MSGTYPE_ALL },
Wayne Roberts 5:1e5cb7139acb 565 { {2, 15}, "TX dBm:", &Radio::tx_dbm_item, FLAG_MSGTYPE_ALL },
Wayne Roberts 5:1e5cb7139acb 566 { {2, 30}, "ramp us:", &tx_ramp_item, FLAG_MSGTYPE_ALL },
Wayne Roberts 5:1e5cb7139acb 567 { {2, 45}, NULL, &clearirqs_item, FLAG_MSGTYPE_ALL },
Wayne Roberts 5:1e5cb7139acb 568 { {2, 55}, "opmode:", &opmode_item, FLAG_MSGTYPE_ALL },
Wayne Roberts 1:0817a150122b 569
Wayne Roberts 1:0817a150122b 570
Wayne Roberts 1:0817a150122b 571 { {0, 0}, NULL, NULL }
Wayne Roberts 1:0817a150122b 572 };
Wayne Roberts 1:0817a150122b 573
Wayne Roberts 1:0817a150122b 574 bool
Wayne Roberts 1:0817a150122b 575 is_menu_item_changable(uint8_t table_row, uint8_t table_col)
Wayne Roberts 1:0817a150122b 576 {
Wayne Roberts 1:0817a150122b 577 const menu_t* m = menu_table[table_row][table_col];
Wayne Roberts 1:0817a150122b 578 const dropdown_item_t* di = (const dropdown_item_t*)m->itemPtr;
Wayne Roberts 1:0817a150122b 579
Wayne Roberts 1:0817a150122b 580 switch (msg_type) {
Wayne Roberts 1:0817a150122b 581 case MSG_TYPE_PACKET:
Wayne Roberts 1:0817a150122b 582 if (m->flags & FLAG_MSGTYPE_PKT)
Wayne Roberts 1:0817a150122b 583 break;
Wayne Roberts 1:0817a150122b 584 else
Wayne Roberts 1:0817a150122b 585 return false;
Wayne Roberts 1:0817a150122b 586 case MSG_TYPE_PER:
Wayne Roberts 1:0817a150122b 587 if (m->flags & FLAG_MSGTYPE_PER)
Wayne Roberts 1:0817a150122b 588 break;
Wayne Roberts 1:0817a150122b 589 else
Wayne Roberts 1:0817a150122b 590 return false;
Wayne Roberts 1:0817a150122b 591 case MSG_TYPE_PINGPONG:
Wayne Roberts 1:0817a150122b 592 if (m->flags & FLAG_MSGTYPE_PING)
Wayne Roberts 1:0817a150122b 593 break;
Wayne Roberts 1:0817a150122b 594 else
Wayne Roberts 1:0817a150122b 595 return false;
Wayne Roberts 1:0817a150122b 596 }
Wayne Roberts 1:0817a150122b 597
Wayne Roberts 1:0817a150122b 598 if (di->itemType == _ITEM_DROPDOWN) {
Wayne Roberts 1:0817a150122b 599 if (di->selectable_strs == NULL || di->selectable_strs[0] == NULL) {
Wayne Roberts 1:0817a150122b 600 log_printf("NULLstrs%u,%u\r\n", table_row, table_col);
Wayne Roberts 1:0817a150122b 601 return false;
Wayne Roberts 1:0817a150122b 602 }
Wayne Roberts 1:0817a150122b 603 } else if (di->itemType == _ITEM_VALUE) {
Wayne Roberts 1:0817a150122b 604 const value_item_t* vi = (const value_item_t*)m->itemPtr;
Wayne Roberts 1:0817a150122b 605 if (vi->write == NULL)
Wayne Roberts 1:0817a150122b 606 return false;
Wayne Roberts 1:0817a150122b 607 } else if (di->itemType == _ITEM_BUTTON) {
Wayne Roberts 1:0817a150122b 608 const button_item_t* bi = (const button_item_t*)m->itemPtr;
Wayne Roberts 1:0817a150122b 609 if (bi->push == NULL)
Wayne Roberts 1:0817a150122b 610 return false;
Wayne Roberts 1:0817a150122b 611 } else if (di->itemType == _ITEM_TOGGLE) {
Wayne Roberts 1:0817a150122b 612 const toggle_item_t * ti = (const toggle_item_t *)m->itemPtr;
Wayne Roberts 1:0817a150122b 613 if (ti->push == NULL)
Wayne Roberts 1:0817a150122b 614 return false;
Wayne Roberts 1:0817a150122b 615 }
Wayne Roberts 1:0817a150122b 616
Wayne Roberts 1:0817a150122b 617 return true;
Wayne Roberts 1:0817a150122b 618 } // ..is_menu_item_changable()
Wayne Roberts 1:0817a150122b 619
Wayne Roberts 1:0817a150122b 620 void read_menu_item(const menu_t* m, bool selected)
Wayne Roberts 1:0817a150122b 621 {
Wayne Roberts 1:0817a150122b 622 uint8_t valCol;
Wayne Roberts 1:0817a150122b 623 const dropdown_item_t* di = (const dropdown_item_t*)m->itemPtr;
Wayne Roberts 1:0817a150122b 624
Wayne Roberts 1:0817a150122b 625 switch (msg_type) {
Wayne Roberts 1:0817a150122b 626 case MSG_TYPE_PACKET:
Wayne Roberts 1:0817a150122b 627 if (m->flags & FLAG_MSGTYPE_PKT)
Wayne Roberts 1:0817a150122b 628 break;
Wayne Roberts 1:0817a150122b 629 else
Wayne Roberts 1:0817a150122b 630 return;
Wayne Roberts 1:0817a150122b 631 case MSG_TYPE_PER:
Wayne Roberts 1:0817a150122b 632 if (m->flags & FLAG_MSGTYPE_PER)
Wayne Roberts 1:0817a150122b 633 break;
Wayne Roberts 1:0817a150122b 634 else
Wayne Roberts 1:0817a150122b 635 return;
Wayne Roberts 1:0817a150122b 636 case MSG_TYPE_PINGPONG:
Wayne Roberts 1:0817a150122b 637 if (m->flags & FLAG_MSGTYPE_PING)
Wayne Roberts 1:0817a150122b 638 break;
Wayne Roberts 1:0817a150122b 639 else
Wayne Roberts 1:0817a150122b 640 return;
Wayne Roberts 1:0817a150122b 641 }
Wayne Roberts 1:0817a150122b 642
dudmuck 13:8ce61a1897ab 643 printf("\e[%u;%uf", m->pos.row, m->pos.col); // set (force) cursor to row;column
Wayne Roberts 1:0817a150122b 644 valCol = m->pos.col;
Wayne Roberts 1:0817a150122b 645 if (m->label) {
dudmuck 13:8ce61a1897ab 646 printf("%s", m->label);
Wayne Roberts 1:0817a150122b 647 valCol += strlen(m->label);
Wayne Roberts 1:0817a150122b 648 }
Wayne Roberts 1:0817a150122b 649 if (di->itemType == _ITEM_DROPDOWN) {
Wayne Roberts 1:0817a150122b 650 if (di->read && di->printed_strs) {
Wayne Roberts 1:0817a150122b 651 uint8_t ridx = di->read(false);
Wayne Roberts 1:0817a150122b 652 if (selected)
dudmuck 13:8ce61a1897ab 653 printf("\e[7m");
dudmuck 13:8ce61a1897ab 654 printf("%s", di->printed_strs[ridx]);
Wayne Roberts 1:0817a150122b 655 if (selected)
dudmuck 13:8ce61a1897ab 656 printf("\e[0m");
Wayne Roberts 1:0817a150122b 657 } else if (di->printed_strs) {
dudmuck 13:8ce61a1897ab 658 printf("%s", di->printed_strs[0]);
Wayne Roberts 1:0817a150122b 659 }
Wayne Roberts 1:0817a150122b 660 } else if (di->itemType == _ITEM_VALUE) {
Wayne Roberts 1:0817a150122b 661 const value_item_t* vi = (const value_item_t*)m->itemPtr;
Wayne Roberts 1:0817a150122b 662 if (vi->print) {
Wayne Roberts 1:0817a150122b 663 for (unsigned n = 0; n < vi->width; n++)
dudmuck 13:8ce61a1897ab 664 printf(" ");
Wayne Roberts 1:0817a150122b 665
dudmuck 13:8ce61a1897ab 666 printf("\e[%u;%uf", m->pos.row, valCol); // set (force) cursor to row;column
Wayne Roberts 1:0817a150122b 667 if (selected)
dudmuck 13:8ce61a1897ab 668 printf("\e[7m");
Wayne Roberts 1:0817a150122b 669 vi->print();
Wayne Roberts 1:0817a150122b 670 if (selected)
dudmuck 13:8ce61a1897ab 671 printf("\e[0m");
Wayne Roberts 1:0817a150122b 672 }
Wayne Roberts 1:0817a150122b 673 } else if (di->itemType == _ITEM_BUTTON) {
Wayne Roberts 1:0817a150122b 674 const button_item_t* bi = (const button_item_t*)m->itemPtr;
Wayne Roberts 1:0817a150122b 675 if (bi->label) {
Wayne Roberts 1:0817a150122b 676 if (selected)
dudmuck 13:8ce61a1897ab 677 printf("\e[7m%s\e[0m", bi->label);
Wayne Roberts 1:0817a150122b 678 else
dudmuck 13:8ce61a1897ab 679 printf("%s", bi->label);
Wayne Roberts 1:0817a150122b 680 }
Wayne Roberts 1:0817a150122b 681 } else if (di->itemType == _ITEM_TOGGLE) {
Wayne Roberts 1:0817a150122b 682 const toggle_item_t* ti = (const toggle_item_t *)m->itemPtr;
Wayne Roberts 1:0817a150122b 683 bool on = ti->read();
Wayne Roberts 1:0817a150122b 684 if (ti->label1) {
Wayne Roberts 1:0817a150122b 685 const char* const cptr = on ? ti->label1 : ti->label0;
Wayne Roberts 1:0817a150122b 686 if (selected)
dudmuck 13:8ce61a1897ab 687 printf("\e[7m%s\e[0m", cptr);
Wayne Roberts 1:0817a150122b 688 else
dudmuck 13:8ce61a1897ab 689 printf("%s", cptr);
Wayne Roberts 1:0817a150122b 690 } else {
Wayne Roberts 1:0817a150122b 691 if (on)
dudmuck 13:8ce61a1897ab 692 printf("\e[1m");
Wayne Roberts 1:0817a150122b 693 if (selected)
dudmuck 13:8ce61a1897ab 694 printf("\e[7m");
Wayne Roberts 1:0817a150122b 695
dudmuck 13:8ce61a1897ab 696 printf("%s", ti->label0);
Wayne Roberts 1:0817a150122b 697
Wayne Roberts 1:0817a150122b 698 if (selected || on)
dudmuck 13:8ce61a1897ab 699 printf("\e[0m");
Wayne Roberts 1:0817a150122b 700 }
Wayne Roberts 1:0817a150122b 701 }
dudmuck 14:14b9e1c08bfc 702
Wayne Roberts 1:0817a150122b 703 } // ..read_menu_item()
Wayne Roberts 1:0817a150122b 704
Wayne Roberts 9:295e37c38fb3 705 void draw_menu()
Wayne Roberts 1:0817a150122b 706 {
Wayne Roberts 1:0817a150122b 707 unsigned table_row;
Wayne Roberts 1:0817a150122b 708
Wayne Roberts 1:0817a150122b 709 for (table_row = 0; table_row < MAX_MENU_ROWS; table_row++) {
Wayne Roberts 1:0817a150122b 710 int table_col;
Wayne Roberts 1:0817a150122b 711 for (table_col = 0; table_col < StopMenuCols[table_row]; table_col++) {
Wayne Roberts 1:0817a150122b 712 read_menu_item(menu_table[table_row][table_col], false);
Wayne Roberts 1:0817a150122b 713 } // ..table column iterator
Wayne Roberts 1:0817a150122b 714 } // ..table row iterator
Wayne Roberts 1:0817a150122b 715
Wayne Roberts 1:0817a150122b 716 read_menu_item(menu_table[curpos.row][curpos.tableCol], true);
dudmuck 14:14b9e1c08bfc 717
dudmuck 14:14b9e1c08bfc 718 fflush(stdout);
dudmuck 14:14b9e1c08bfc 719 pc.sync();
Wayne Roberts 1:0817a150122b 720 } // ..draw_menu()
Wayne Roberts 1:0817a150122b 721
Wayne Roberts 1:0817a150122b 722 typedef struct {
Wayne Roberts 1:0817a150122b 723 int row;
Wayne Roberts 1:0817a150122b 724 int col;
Wayne Roberts 1:0817a150122b 725 } tablexy_t;
Wayne Roberts 1:0817a150122b 726
Wayne Roberts 1:0817a150122b 727 void
Wayne Roberts 1:0817a150122b 728 menu_init_(const menu_t* in, tablexy_t* tc)
Wayne Roberts 1:0817a150122b 729 {
Wayne Roberts 1:0817a150122b 730 unsigned n;
Wayne Roberts 1:0817a150122b 731
Wayne Roberts 1:0817a150122b 732 for (n = 0; in[n].pos.row > 0; n++) {
Wayne Roberts 1:0817a150122b 733 const menu_t* m = &in[n];
Wayne Roberts 1:0817a150122b 734 if (tc->row != m->pos.row - 1) {
Wayne Roberts 1:0817a150122b 735 tc->row = m->pos.row - 1;
Wayne Roberts 1:0817a150122b 736 tc->col = 0;
Wayne Roberts 1:0817a150122b 737 } else
Wayne Roberts 1:0817a150122b 738 tc->col++;
Wayne Roberts 1:0817a150122b 739
Wayne Roberts 1:0817a150122b 740 menu_table[tc->row][tc->col] = m;
Wayne Roberts 1:0817a150122b 741 #ifdef MENU_DEBUG
dudmuck 13:8ce61a1897ab 742 printf("table:%u,%u ", tc->row, tc->col);
dudmuck 13:8ce61a1897ab 743 printf(" %d<%d? ", StopMenuCols[tc->row], tc->col);
Wayne Roberts 1:0817a150122b 744 #endif /* MENU_DEBUG */
Wayne Roberts 1:0817a150122b 745 if (StopMenuCols[tc->row] < tc->col)
Wayne Roberts 1:0817a150122b 746 StopMenuCols[tc->row] = tc->col;
Wayne Roberts 1:0817a150122b 747 #ifdef MENU_DEBUG
dudmuck 13:8ce61a1897ab 748 printf("{%u %u}", tc->row, tc->col);
dudmuck 13:8ce61a1897ab 749 printf("in:%p[%u] screen:%u,%u ", in, n, m->pos.row, m->pos.col);
dudmuck 13:8ce61a1897ab 750 printf("pos@%p ", &m->pos);
dudmuck 13:8ce61a1897ab 751 //printf(" loc:%p ", &in[n].itemPtr);
Wayne Roberts 1:0817a150122b 752 if (in[n].itemPtr) {
Wayne Roberts 1:0817a150122b 753 const dropdown_item_t* di = (const dropdown_item_t*)m->itemPtr;
dudmuck 13:8ce61a1897ab 754 printf(" itemPtr:%p type:%02x ", di, di->itemType);
Wayne Roberts 1:0817a150122b 755 }
dudmuck 13:8ce61a1897ab 756 printf("stopMenuCols[%u]: %d ", tc->row, StopMenuCols[tc->row]);
Wayne Roberts 1:0817a150122b 757 if (m->label)
dudmuck 13:8ce61a1897ab 758 printf("label:%s", m->label);
Wayne Roberts 1:0817a150122b 759 else
dudmuck 13:8ce61a1897ab 760 printf("noLabel");
dudmuck 13:8ce61a1897ab 761 printf("\r\n");
Wayne Roberts 1:0817a150122b 762 #endif /* MENU_DEBUG */
Wayne Roberts 1:0817a150122b 763 }
Wayne Roberts 1:0817a150122b 764 #ifdef MENU_DEBUG
dudmuck 14:14b9e1c08bfc 765 char ch;
dudmuck 13:8ce61a1897ab 766 printf("hit key:");
dudmuck 14:14b9e1c08bfc 767 pc.read(&ch, 1);
Wayne Roberts 1:0817a150122b 768 #endif /* MENU_DEBUG */
Wayne Roberts 1:0817a150122b 769
Wayne Roberts 1:0817a150122b 770 }
Wayne Roberts 1:0817a150122b 771
Wayne Roberts 1:0817a150122b 772 void navigate_dropdown(uint8_t ch)
Wayne Roberts 1:0817a150122b 773 {
Wayne Roberts 1:0817a150122b 774 unsigned n;
Wayne Roberts 1:0817a150122b 775 const menu_t* m = menuState.sm;
Wayne Roberts 1:0817a150122b 776 const dropdown_item_t* di = (const dropdown_item_t*)m->itemPtr;
Wayne Roberts 1:0817a150122b 777
Wayne Roberts 1:0817a150122b 778 switch (ch) {
Wayne Roberts 1:0817a150122b 779 case 'A': // cursor UP
Wayne Roberts 1:0817a150122b 780 if (menuState.sel_idx > 0) {
Wayne Roberts 1:0817a150122b 781 menuState.sel_idx--;
Wayne Roberts 1:0817a150122b 782 }
Wayne Roberts 1:0817a150122b 783 break;
Wayne Roberts 1:0817a150122b 784 case 'B': // cursor DOWN
Wayne Roberts 1:0817a150122b 785 if (di->selectable_strs[menuState.sel_idx+1] != NULL)
Wayne Roberts 1:0817a150122b 786 menuState.sel_idx++;
Wayne Roberts 1:0817a150122b 787 break;
Wayne Roberts 1:0817a150122b 788 } // ..switch (ch)
Wayne Roberts 1:0817a150122b 789
Wayne Roberts 1:0817a150122b 790 for (n = 0; di->selectable_strs[n] != NULL; n++) {
dudmuck 13:8ce61a1897ab 791 printf("\e[%u;%uf", m->pos.row+n, menuState.dropdown_col);
Wayne Roberts 1:0817a150122b 792 if (n == menuState.sel_idx)
dudmuck 13:8ce61a1897ab 793 printf("\e[7m");
dudmuck 13:8ce61a1897ab 794 printf("%s", di->selectable_strs[n]);
Wayne Roberts 1:0817a150122b 795 if (n == menuState.sel_idx)
dudmuck 13:8ce61a1897ab 796 printf("\e[0m");
Wayne Roberts 1:0817a150122b 797 }
dudmuck 13:8ce61a1897ab 798 printf("\e[%u;%uf", m->pos.row + menuState.sel_idx, menuState.dropdown_col + strlen(di->selectable_strs[menuState.sel_idx]));
Wayne Roberts 1:0817a150122b 799 }
Wayne Roberts 1:0817a150122b 800
Wayne Roberts 1:0817a150122b 801 bool is_item_selectable(const menu_t* m)
Wayne Roberts 1:0817a150122b 802 {
Wayne Roberts 1:0817a150122b 803 const dropdown_item_t* di = (const dropdown_item_t*)m->itemPtr;
Wayne Roberts 1:0817a150122b 804
Wayne Roberts 1:0817a150122b 805 if (di->itemType == _ITEM_BUTTON) {
Wayne Roberts 1:0817a150122b 806 const button_item_t* bi = (const button_item_t*)m->itemPtr;
Wayne Roberts 1:0817a150122b 807 if (bi->push == NULL)
Wayne Roberts 1:0817a150122b 808 return false;
Wayne Roberts 1:0817a150122b 809 } else if (di->itemType == _ITEM_TOGGLE) {
Wayne Roberts 1:0817a150122b 810 const toggle_item_t* ti = (const toggle_item_t*)m->itemPtr;
Wayne Roberts 1:0817a150122b 811 if (ti->push == NULL)
Wayne Roberts 1:0817a150122b 812 return false;
Wayne Roberts 1:0817a150122b 813 }
Wayne Roberts 1:0817a150122b 814
Wayne Roberts 1:0817a150122b 815 return true;
Wayne Roberts 1:0817a150122b 816 }
Wayne Roberts 1:0817a150122b 817
Wayne Roberts 1:0817a150122b 818 void navigate_menu(uint8_t ch)
Wayne Roberts 1:0817a150122b 819 {
dudmuck 15:703ca340d0fb 820 //logpc_printf("navigate_menu %c\r\n", ch);
Wayne Roberts 1:0817a150122b 821 read_menu_item(menu_table[curpos.row][curpos.tableCol], false);
Wayne Roberts 1:0817a150122b 822
Wayne Roberts 1:0817a150122b 823 switch (ch) {
Wayne Roberts 1:0817a150122b 824 case 'A': // cursor UP
Wayne Roberts 1:0817a150122b 825 if (curpos.row == 0)
Wayne Roberts 1:0817a150122b 826 break;
Wayne Roberts 1:0817a150122b 827
Wayne Roberts 1:0817a150122b 828 { // find previous row up with column
Wayne Roberts 1:0817a150122b 829 int8_t row;
Wayne Roberts 1:0817a150122b 830 for (row = curpos.row - 1; row >= 0; row--) {
Wayne Roberts 1:0817a150122b 831 if (StopMenuCols[row] > -1) {
Wayne Roberts 1:0817a150122b 832 curpos.row = row;
Wayne Roberts 1:0817a150122b 833 break;
Wayne Roberts 1:0817a150122b 834 }
Wayne Roberts 1:0817a150122b 835 }
Wayne Roberts 1:0817a150122b 836 if (row == 0 && StopMenuCols[0] < 0)
Wayne Roberts 1:0817a150122b 837 break; // nothing found
Wayne Roberts 1:0817a150122b 838 }
Wayne Roberts 1:0817a150122b 839
Wayne Roberts 1:0817a150122b 840 if (curpos.tableCol >= StopMenuCols[curpos.row]) {
Wayne Roberts 1:0817a150122b 841 curpos.tableCol = StopMenuCols[curpos.row]-1;
Wayne Roberts 1:0817a150122b 842 }
Wayne Roberts 1:0817a150122b 843
Wayne Roberts 1:0817a150122b 844 break;
Wayne Roberts 1:0817a150122b 845 case 'B': // cursor DOWN
Wayne Roberts 1:0817a150122b 846 if (curpos.row >= MAX_MENU_ROWS)
Wayne Roberts 1:0817a150122b 847 break;
Wayne Roberts 1:0817a150122b 848
Wayne Roberts 1:0817a150122b 849 { // find next row down with column
Wayne Roberts 1:0817a150122b 850 uint8_t row;
Wayne Roberts 1:0817a150122b 851 for (row = curpos.row + 1; row < MAX_MENU_ROWS; row++) {
Wayne Roberts 1:0817a150122b 852 if (StopMenuCols[row] != -1) {
Wayne Roberts 1:0817a150122b 853 curpos.row = row;
Wayne Roberts 1:0817a150122b 854 break;
Wayne Roberts 1:0817a150122b 855 }
Wayne Roberts 1:0817a150122b 856 }
Wayne Roberts 1:0817a150122b 857 if (row == MAX_MENU_ROWS-1 && StopMenuCols[row] == -1)
Wayne Roberts 1:0817a150122b 858 break; // nothing found
Wayne Roberts 1:0817a150122b 859 }
Wayne Roberts 1:0817a150122b 860
Wayne Roberts 1:0817a150122b 861 if (curpos.tableCol >= StopMenuCols[curpos.row]) {
Wayne Roberts 1:0817a150122b 862 curpos.tableCol = StopMenuCols[curpos.row]-1;
Wayne Roberts 1:0817a150122b 863 }
Wayne Roberts 1:0817a150122b 864
Wayne Roberts 1:0817a150122b 865
Wayne Roberts 1:0817a150122b 866 break;
Wayne Roberts 1:0817a150122b 867 case 'C': // cursor LEFT
Wayne Roberts 1:0817a150122b 868 if (curpos.tableCol >= StopMenuCols[curpos.row]-1)
Wayne Roberts 1:0817a150122b 869 break;
Wayne Roberts 1:0817a150122b 870
Wayne Roberts 1:0817a150122b 871 { // find next row left with editable
Wayne Roberts 1:0817a150122b 872 uint8_t tcol;
Wayne Roberts 1:0817a150122b 873 for (tcol = curpos.tableCol + 1; tcol < StopMenuCols[curpos.row]; tcol++) {
Wayne Roberts 1:0817a150122b 874 if (is_menu_item_changable(curpos.row, tcol)) {
Wayne Roberts 1:0817a150122b 875 curpos.tableCol = tcol;
Wayne Roberts 1:0817a150122b 876 break;
Wayne Roberts 1:0817a150122b 877 }
Wayne Roberts 1:0817a150122b 878 }
Wayne Roberts 1:0817a150122b 879 }
Wayne Roberts 1:0817a150122b 880
Wayne Roberts 1:0817a150122b 881 break;
Wayne Roberts 1:0817a150122b 882 case 'D': // cursor RIGHT
Wayne Roberts 1:0817a150122b 883 if (curpos.tableCol == 0)
Wayne Roberts 1:0817a150122b 884 break;
Wayne Roberts 1:0817a150122b 885
Wayne Roberts 1:0817a150122b 886 {
Wayne Roberts 1:0817a150122b 887 int8_t tcol;
Wayne Roberts 1:0817a150122b 888 for (tcol = curpos.tableCol - 1; tcol >= 0; tcol--) {
Wayne Roberts 1:0817a150122b 889 if (is_menu_item_changable(curpos.row, tcol)) {
Wayne Roberts 1:0817a150122b 890 curpos.tableCol = tcol;
Wayne Roberts 1:0817a150122b 891 break;
Wayne Roberts 1:0817a150122b 892 }
Wayne Roberts 1:0817a150122b 893 }
Wayne Roberts 1:0817a150122b 894 }
Wayne Roberts 1:0817a150122b 895
Wayne Roberts 1:0817a150122b 896 break;
Wayne Roberts 1:0817a150122b 897 default:
dudmuck 13:8ce61a1897ab 898 //printf("unhancled-csi:%02x\eE", ch);
Wayne Roberts 1:0817a150122b 899 break;
Wayne Roberts 1:0817a150122b 900 } // ..switch (ch)
Wayne Roberts 1:0817a150122b 901
Wayne Roberts 1:0817a150122b 902 if (!is_item_selectable(menu_table[curpos.row][curpos.tableCol])) {
Wayne Roberts 1:0817a150122b 903 int c;
Wayne Roberts 1:0817a150122b 904 for (c = 0; c < StopMenuCols[curpos.row]; c++) {
Wayne Roberts 1:0817a150122b 905 if (is_item_selectable(menu_table[curpos.row][c])) {
Wayne Roberts 1:0817a150122b 906 curpos.tableCol = c;
Wayne Roberts 1:0817a150122b 907 break;
Wayne Roberts 1:0817a150122b 908 }
Wayne Roberts 1:0817a150122b 909 }
Wayne Roberts 1:0817a150122b 910 if (c == StopMenuCols[curpos.row])
Wayne Roberts 1:0817a150122b 911 return;
Wayne Roberts 1:0817a150122b 912 }
Wayne Roberts 1:0817a150122b 913
Wayne Roberts 1:0817a150122b 914 #ifdef MENU_DEBUG
Wayne Roberts 1:0817a150122b 915 log_printf("table:%u,%u screen:%u,%u \r\n", curpos.row, curpos.tableCol,
Wayne Roberts 1:0817a150122b 916 menu_table[curpos.row][curpos.tableCol]->pos.row,
Wayne Roberts 1:0817a150122b 917 menu_table[curpos.row][curpos.tableCol]->pos.col
Wayne Roberts 1:0817a150122b 918 );
Wayne Roberts 1:0817a150122b 919 #endif /* MENU_DEBUG */
Wayne Roberts 1:0817a150122b 920
Wayne Roberts 1:0817a150122b 921 read_menu_item(menu_table[curpos.row][curpos.tableCol], true);
Wayne Roberts 1:0817a150122b 922 } // ..navigate_menu
Wayne Roberts 1:0817a150122b 923
dudmuck 13:8ce61a1897ab 924
dudmuck 13:8ce61a1897ab 925 bool is_sweep_menu_item(const void* const itemPtr)
dudmuck 13:8ce61a1897ab 926 {
dudmuck 13:8ce61a1897ab 927 if (itemPtr == &sweep_start_item ||
dudmuck 13:8ce61a1897ab 928 itemPtr == &sweep_stop_item ||
dudmuck 13:8ce61a1897ab 929 itemPtr == &sweep_dwell_item ||
dudmuck 13:8ce61a1897ab 930 itemPtr == &tx_carrier_item ||
dudmuck 13:8ce61a1897ab 931 itemPtr == &tx_preamble_item
dudmuck 13:8ce61a1897ab 932 )
dudmuck 13:8ce61a1897ab 933 return true;
dudmuck 13:8ce61a1897ab 934 else
dudmuck 13:8ce61a1897ab 935 return false;
dudmuck 13:8ce61a1897ab 936 }
dudmuck 13:8ce61a1897ab 937
Wayne Roberts 1:0817a150122b 938 void commit_menu_item_change()
Wayne Roberts 1:0817a150122b 939 {
Wayne Roberts 1:0817a150122b 940 const menu_t* m = menu_table[curpos.row][curpos.tableCol];
Wayne Roberts 1:0817a150122b 941 const dropdown_item_t* di = (const dropdown_item_t*)m->itemPtr;
Wayne Roberts 1:0817a150122b 942
Wayne Roberts 1:0817a150122b 943 if (di->itemType == _ITEM_DROPDOWN) {
Wayne Roberts 1:0817a150122b 944 menuState.mode = di->write(menuState.sel_idx);
Wayne Roberts 1:0817a150122b 945
dudmuck 13:8ce61a1897ab 946 printf("\e[%u;%uf", m->pos.row, m->pos.col-2);
Wayne Roberts 1:0817a150122b 947 } else if (di->itemType == _ITEM_VALUE) {
Wayne Roberts 1:0817a150122b 948 const value_item_t* vi = (const value_item_t*)m->itemPtr;
Wayne Roberts 1:0817a150122b 949 /* commit value entry */
Wayne Roberts 1:0817a150122b 950 if (vi->write) {
Wayne Roberts 1:0817a150122b 951 if (vi->write(entry_buf))
Wayne Roberts 1:0817a150122b 952 menuState.mode = MENUMODE_REDRAW;
Wayne Roberts 1:0817a150122b 953 else
Wayne Roberts 1:0817a150122b 954 menuState.mode = MENUMODE_NONE;
Wayne Roberts 1:0817a150122b 955 } else
Wayne Roberts 1:0817a150122b 956 menuState.mode = MENUMODE_NONE;
Wayne Roberts 1:0817a150122b 957
Wayne Roberts 1:0817a150122b 958 if (menuState.mode == MENUMODE_NONE) {
Wayne Roberts 1:0817a150122b 959 read_menu_item(menu_table[curpos.row][curpos.tableCol], true);
Wayne Roberts 1:0817a150122b 960 }
Wayne Roberts 1:0817a150122b 961 }
dudmuck 13:8ce61a1897ab 962
Wayne Roberts 1:0817a150122b 963 } // ..commit_menu_item_change()
Wayne Roberts 1:0817a150122b 964
Wayne Roberts 1:0817a150122b 965 void refresh_item_in_table(const void* item)
Wayne Roberts 1:0817a150122b 966 {
Wayne Roberts 1:0817a150122b 967 unsigned table_row;
Wayne Roberts 1:0817a150122b 968
Wayne Roberts 1:0817a150122b 969 if (item == NULL)
Wayne Roberts 1:0817a150122b 970 return;
Wayne Roberts 1:0817a150122b 971
Wayne Roberts 1:0817a150122b 972 for (table_row = 0; table_row < MAX_MENU_ROWS; table_row++) {
Wayne Roberts 1:0817a150122b 973 int table_col;
Wayne Roberts 1:0817a150122b 974 for (table_col = 0; table_col < StopMenuCols[table_row]; table_col++) {
Wayne Roberts 1:0817a150122b 975 //log_printf("%u %u %p\r\n", table_row, table_col, menu_table[table_row][table_col]->itemPtr);
Wayne Roberts 1:0817a150122b 976 if (item == menu_table[table_row][table_col]->itemPtr) {
Wayne Roberts 1:0817a150122b 977 read_menu_item(menu_table[table_row][table_col], false);
Wayne Roberts 1:0817a150122b 978 return;
Wayne Roberts 1:0817a150122b 979 }
Wayne Roberts 1:0817a150122b 980 }
Wayne Roberts 1:0817a150122b 981 }
Wayne Roberts 1:0817a150122b 982 }
Wayne Roberts 1:0817a150122b 983
Wayne Roberts 1:0817a150122b 984 void
Wayne Roberts 1:0817a150122b 985 start_value_entry(const menu_t* m)
Wayne Roberts 1:0817a150122b 986 {
Wayne Roberts 1:0817a150122b 987 const value_item_t* vi = (const value_item_t*)m->itemPtr;
Wayne Roberts 1:0817a150122b 988 uint8_t col = m->pos.col;
Wayne Roberts 1:0817a150122b 989
Wayne Roberts 1:0817a150122b 990 if (m->label)
Wayne Roberts 1:0817a150122b 991 col += strlen(m->label);
Wayne Roberts 1:0817a150122b 992
dudmuck 13:8ce61a1897ab 993 printf("\e[%u;%uf", m->pos.row, col);
Wayne Roberts 1:0817a150122b 994 for (unsigned i = 0; i < vi->width; i++)
dudmuck 13:8ce61a1897ab 995 printf(" "); // clear displayed value for user entry
Wayne Roberts 1:0817a150122b 996
dudmuck 13:8ce61a1897ab 997 printf("\e[%u;%uf", m->pos.row, col);
Wayne Roberts 1:0817a150122b 998 menuState.mode = MENUMODE_ENTRY;
Wayne Roberts 1:0817a150122b 999 entry_buf_idx = 0;
Wayne Roberts 1:0817a150122b 1000 }
Wayne Roberts 1:0817a150122b 1001
Wayne Roberts 1:0817a150122b 1002 void start_menu_item_change()
Wayne Roberts 1:0817a150122b 1003 {
Wayne Roberts 1:0817a150122b 1004 const menu_t* m = menu_table[curpos.row][curpos.tableCol];
Wayne Roberts 1:0817a150122b 1005 const dropdown_item_t* di = (const dropdown_item_t*)m->itemPtr;
Wayne Roberts 1:0817a150122b 1006 bool checkRefresh = false;
Wayne Roberts 1:0817a150122b 1007
Wayne Roberts 1:0817a150122b 1008 if (di->itemType == _ITEM_DROPDOWN && di->selectable_strs) {
Wayne Roberts 1:0817a150122b 1009 menuState.dropdown_col = m->pos.col;
Wayne Roberts 1:0817a150122b 1010 unsigned n, sidx = 0;
Wayne Roberts 1:0817a150122b 1011 /* start dropdown */
Wayne Roberts 1:0817a150122b 1012 if (di->read)
Wayne Roberts 1:0817a150122b 1013 sidx = di->read(true);
Wayne Roberts 1:0817a150122b 1014
Wayne Roberts 1:0817a150122b 1015 if (m->label)
Wayne Roberts 1:0817a150122b 1016 menuState.dropdown_col += strlen(m->label);
Wayne Roberts 1:0817a150122b 1017
Wayne Roberts 1:0817a150122b 1018 for (n = 0; di->selectable_strs[n] != NULL; n++) {
Wayne Roberts 1:0817a150122b 1019 uint8_t col = menuState.dropdown_col;
Wayne Roberts 1:0817a150122b 1020 bool leftPad = false;
Wayne Roberts 1:0817a150122b 1021 if (col > 3 && n > 0) { // dropdown left side padding
Wayne Roberts 1:0817a150122b 1022 col -= 2;
Wayne Roberts 1:0817a150122b 1023 leftPad = true;
Wayne Roberts 1:0817a150122b 1024 }
dudmuck 13:8ce61a1897ab 1025 printf("\e[%u;%uf", m->pos.row+n, col);
Wayne Roberts 1:0817a150122b 1026 if (leftPad ) {
dudmuck 13:8ce61a1897ab 1027 printf(" ");
Wayne Roberts 1:0817a150122b 1028 }
Wayne Roberts 1:0817a150122b 1029 if (n == sidx)
dudmuck 13:8ce61a1897ab 1030 printf("\e[7m");
dudmuck 13:8ce61a1897ab 1031 printf("%s", di->selectable_strs[n]);
Wayne Roberts 1:0817a150122b 1032 if (n == sidx)
dudmuck 13:8ce61a1897ab 1033 printf("\e[0m");
dudmuck 13:8ce61a1897ab 1034 printf(" "); // right side padding
Wayne Roberts 1:0817a150122b 1035 }
dudmuck 13:8ce61a1897ab 1036 printf("\e[%u;%uf", m->pos.row, menuState.dropdown_col-2);
Wayne Roberts 1:0817a150122b 1037
Wayne Roberts 1:0817a150122b 1038 menuState.mode = MENUMODE_DROPDOWN;
Wayne Roberts 1:0817a150122b 1039 menuState.sel_idx = sidx;
Wayne Roberts 1:0817a150122b 1040 menuState.sm = m;
Wayne Roberts 1:0817a150122b 1041 } else if (di->itemType == _ITEM_VALUE) {
Wayne Roberts 1:0817a150122b 1042 /* start value entry */
Wayne Roberts 1:0817a150122b 1043 start_value_entry(m);
Wayne Roberts 1:0817a150122b 1044 } else if (di->itemType == _ITEM_BUTTON) {
Wayne Roberts 1:0817a150122b 1045 const button_item_t* bi = (const button_item_t*)m->itemPtr;
Wayne Roberts 1:0817a150122b 1046 if (bi->push) {
Wayne Roberts 1:0817a150122b 1047 bi->push();
Wayne Roberts 1:0817a150122b 1048 checkRefresh = true;
Wayne Roberts 1:0817a150122b 1049 }
Wayne Roberts 1:0817a150122b 1050 } else if (di->itemType == _ITEM_TOGGLE) {
Wayne Roberts 1:0817a150122b 1051 const toggle_item_t* ti = (const toggle_item_t*)m->itemPtr;
Wayne Roberts 1:0817a150122b 1052 if (ti->push) {
Wayne Roberts 1:0817a150122b 1053 bool on = ti->push();
Wayne Roberts 1:0817a150122b 1054 uint8_t col = m->pos.col;
Wayne Roberts 1:0817a150122b 1055
Wayne Roberts 1:0817a150122b 1056 if (m->label)
Wayne Roberts 1:0817a150122b 1057 col += strlen(m->label);
Wayne Roberts 1:0817a150122b 1058
dudmuck 13:8ce61a1897ab 1059 printf("\e[%u;%uf", m->pos.row, col);
Wayne Roberts 1:0817a150122b 1060 if (ti->label1) {
dudmuck 13:8ce61a1897ab 1061 printf("\e[7m%s\e[0m", on ? ti->label1 : ti->label0);
Wayne Roberts 1:0817a150122b 1062 } else {
Wayne Roberts 1:0817a150122b 1063 if (on)
dudmuck 13:8ce61a1897ab 1064 printf("\e[1;7m%s\e[0m", ti->label0);
Wayne Roberts 1:0817a150122b 1065 else
dudmuck 13:8ce61a1897ab 1066 printf("\e[7m%s\e[0m", ti->label0);
Wayne Roberts 1:0817a150122b 1067 }
Wayne Roberts 1:0817a150122b 1068 checkRefresh = true;
Wayne Roberts 1:0817a150122b 1069 }
Wayne Roberts 1:0817a150122b 1070 }
Wayne Roberts 1:0817a150122b 1071
Wayne Roberts 1:0817a150122b 1072 if (checkRefresh) {
Wayne Roberts 1:0817a150122b 1073 if (m->refreshReadItem) {
Wayne Roberts 1:0817a150122b 1074 refresh_item_in_table(m->refreshReadItem); // read associated
Wayne Roberts 1:0817a150122b 1075 read_menu_item(m, true); // restore cursor
Wayne Roberts 1:0817a150122b 1076 }
Wayne Roberts 1:0817a150122b 1077 }
dudmuck 13:8ce61a1897ab 1078
Wayne Roberts 1:0817a150122b 1079 } // ..start_menu_item_change()
Wayne Roberts 1:0817a150122b 1080
Wayne Roberts 1:0817a150122b 1081 void full_menu_init()
Wayne Roberts 1:0817a150122b 1082 {
Wayne Roberts 1:0817a150122b 1083 unsigned n;
Wayne Roberts 1:0817a150122b 1084 const menu_t *m;
Wayne Roberts 1:0817a150122b 1085 tablexy_t txy;
Wayne Roberts 1:0817a150122b 1086
Wayne Roberts 1:0817a150122b 1087 txy.row = INT_MAX;
Wayne Roberts 1:0817a150122b 1088 txy.col = 0;
Wayne Roberts 5:1e5cb7139acb 1089
Wayne Roberts 1:0817a150122b 1090 for (n = 0; n < MAX_MENU_ROWS; n++) {
Wayne Roberts 1:0817a150122b 1091 StopMenuCols[n] = -1;
Wayne Roberts 1:0817a150122b 1092 }
Wayne Roberts 1:0817a150122b 1093
Wayne Roberts 1:0817a150122b 1094 menu_init_(common_menu, &txy);
Wayne Roberts 1:0817a150122b 1095
Wayne Roberts 1:0817a150122b 1096 menu_init_(Radio::common_menu, &txy);
Wayne Roberts 1:0817a150122b 1097
Wayne Roberts 1:0817a150122b 1098 m = Radio::get_modem_menu();
Wayne Roberts 1:0817a150122b 1099 if (m == NULL) {
Wayne Roberts 1:0817a150122b 1100 log_printf("NULL-modemMenu\r\n");
Wayne Roberts 1:0817a150122b 1101 for (;;) asm("nop");
Wayne Roberts 1:0817a150122b 1102 }
Wayne Roberts 1:0817a150122b 1103 #ifdef MENU_DEBUG
dudmuck 13:8ce61a1897ab 1104 printf("modemmenuInit\r\n");
Wayne Roberts 1:0817a150122b 1105 #endif
Wayne Roberts 1:0817a150122b 1106 menu_init_(m, &txy);
Wayne Roberts 1:0817a150122b 1107
Wayne Roberts 1:0817a150122b 1108 m = Radio::get_modem_sub_menu();
Wayne Roberts 1:0817a150122b 1109 if (m) {
Wayne Roberts 1:0817a150122b 1110 #ifdef MENU_DEBUG
dudmuck 13:8ce61a1897ab 1111 printf("modemsubmenuInit\r\n");
Wayne Roberts 1:0817a150122b 1112 #endif
Wayne Roberts 1:0817a150122b 1113 menu_init_(m, &txy);
Wayne Roberts 1:0817a150122b 1114 }
Wayne Roberts 1:0817a150122b 1115 #ifdef MENU_DEBUG
Wayne Roberts 1:0817a150122b 1116 else
dudmuck 13:8ce61a1897ab 1117 printf("no-modemsubmenu\r\n");
Wayne Roberts 1:0817a150122b 1118 #endif
Wayne Roberts 1:0817a150122b 1119
Wayne Roberts 1:0817a150122b 1120 m = get_msg_menu();
Wayne Roberts 1:0817a150122b 1121 if (m == NULL) {
Wayne Roberts 1:0817a150122b 1122 log_printf("NULL-msgMenu\r\n");
Wayne Roberts 1:0817a150122b 1123 for (;;) asm("nop");
Wayne Roberts 1:0817a150122b 1124 }
Wayne Roberts 1:0817a150122b 1125 menu_init_(m, &txy);
Wayne Roberts 1:0817a150122b 1126
Wayne Roberts 1:0817a150122b 1127 for (n = 0; n < MAX_MENU_ROWS; n++) {
Wayne Roberts 1:0817a150122b 1128 if (StopMenuCols[n] != -1)
Wayne Roberts 1:0817a150122b 1129 StopMenuCols[n]++;
Wayne Roberts 1:0817a150122b 1130 }
Wayne Roberts 1:0817a150122b 1131 }
Wayne Roberts 1:0817a150122b 1132
Wayne Roberts 1:0817a150122b 1133 bool ishexchar(char ch)
Wayne Roberts 1:0817a150122b 1134 {
Wayne Roberts 1:0817a150122b 1135 if (((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) || (ch >= '0' && ch <= '9'))
Wayne Roberts 1:0817a150122b 1136 return true;
Wayne Roberts 1:0817a150122b 1137 else
Wayne Roberts 1:0817a150122b 1138 return false;
Wayne Roberts 1:0817a150122b 1139 }
Wayne Roberts 1:0817a150122b 1140
Wayne Roberts 1:0817a150122b 1141 enum _urx_ {
Wayne Roberts 1:0817a150122b 1142 URX_STATE_NONE = 0,
Wayne Roberts 1:0817a150122b 1143 URX_STATE_ESCAPE,
Wayne Roberts 1:0817a150122b 1144 URX_STATE_CSI,
Wayne Roberts 1:0817a150122b 1145 } uart_rx_state;
Wayne Roberts 1:0817a150122b 1146
Wayne Roberts 1:0817a150122b 1147 Timeout uartRxTimeout;
Wayne Roberts 1:0817a150122b 1148
Wayne Roberts 1:0817a150122b 1149 void uart_rx_timeout()
Wayne Roberts 1:0817a150122b 1150 {
Wayne Roberts 1:0817a150122b 1151 /* escape by itself: abort change on item */
Wayne Roberts 1:0817a150122b 1152 menuState.mode = MENUMODE_REDRAW;
Wayne Roberts 1:0817a150122b 1153
Wayne Roberts 1:0817a150122b 1154 uart_rx_state = URX_STATE_NONE;
Wayne Roberts 1:0817a150122b 1155 }
Wayne Roberts 1:0817a150122b 1156
dudmuck 13:8ce61a1897ab 1157 void sweeper()
dudmuck 13:8ce61a1897ab 1158 {
dudmuck 13:8ce61a1897ab 1159 if (cf_sweep.ticking) {
dudmuck 13:8ce61a1897ab 1160 cf_sweep.tick = true;
dudmuck 13:8ce61a1897ab 1161 }
dudmuck 13:8ce61a1897ab 1162 }
dudmuck 13:8ce61a1897ab 1163
dudmuck 13:8ce61a1897ab 1164 void sweep_service()
dudmuck 13:8ce61a1897ab 1165 {
dudmuck 13:8ce61a1897ab 1166 const menu_t* m = menu_table[curpos.row][curpos.tableCol];
dudmuck 13:8ce61a1897ab 1167
dudmuck 13:8ce61a1897ab 1168 if (is_sweep_menu_item(m->itemPtr)) {
dudmuck 13:8ce61a1897ab 1169 if (cf_sweep.start_MHz != 0 && cf_sweep.stop_MHz > cf_sweep.start_MHz && cf_sweep.dwell_ms > 0) {
dudmuck 13:8ce61a1897ab 1170 std::chrono::microseconds us = std::chrono::microseconds(cf_sweep.dwell_ms * 1000);
dudmuck 13:8ce61a1897ab 1171 cf_sweep.MHz = cf_sweep.start_MHz;
dudmuck 13:8ce61a1897ab 1172 cf_sweep.ticker.attach(sweeper, us);
dudmuck 13:8ce61a1897ab 1173 cf_sweep.ticking = true;
dudmuck 13:8ce61a1897ab 1174 }
dudmuck 13:8ce61a1897ab 1175 } else {
dudmuck 13:8ce61a1897ab 1176 if (cf_sweep.ticking) {
dudmuck 13:8ce61a1897ab 1177 cf_sweep.ticker.detach();
dudmuck 13:8ce61a1897ab 1178 cf_sweep.ticking = false;
dudmuck 13:8ce61a1897ab 1179 }
dudmuck 13:8ce61a1897ab 1180 }
dudmuck 13:8ce61a1897ab 1181 }
dudmuck 13:8ce61a1897ab 1182
Wayne Roberts 1:0817a150122b 1183 void serial_callback()
Wayne Roberts 1:0817a150122b 1184 {
dudmuck 13:8ce61a1897ab 1185 char serial_write_buf[4];
dudmuck 13:8ce61a1897ab 1186 unsigned char serial_write_buf_idx = 0;
dudmuck 13:8ce61a1897ab 1187 char ch;
dudmuck 14:14b9e1c08bfc 1188 pc.read(&ch, 1);
dudmuck 14:14b9e1c08bfc 1189
Wayne Roberts 1:0817a150122b 1190 switch (uart_rx_state) {
Wayne Roberts 1:0817a150122b 1191 case URX_STATE_NONE:
Wayne Roberts 1:0817a150122b 1192 if (ch == 0x1b) {
Wayne Roberts 1:0817a150122b 1193 if (menuState.mode == MENUMODE_ENTRY) {
Wayne Roberts 1:0817a150122b 1194 /* abort entry mode */
Wayne Roberts 1:0817a150122b 1195 menuState.mode = MENUMODE_NONE;
Wayne Roberts 1:0817a150122b 1196 read_menu_item(menu_table[curpos.row][curpos.tableCol], true);
Wayne Roberts 1:0817a150122b 1197 } else {
Wayne Roberts 1:0817a150122b 1198 uart_rx_state = URX_STATE_ESCAPE;
Wayne Roberts 1:0817a150122b 1199 if (menuState.mode != MENUMODE_NONE) {
Wayne Roberts 1:0817a150122b 1200 /* is this escape by itself, user wants to abort? */
dudmuck 13:8ce61a1897ab 1201 uartRxTimeout.attach(uart_rx_timeout, 30ms);
Wayne Roberts 1:0817a150122b 1202 }
Wayne Roberts 1:0817a150122b 1203 }
Wayne Roberts 1:0817a150122b 1204 } else if (ch == 2) { // ctrl-B
Wayne Roberts 1:0817a150122b 1205 log_printf("--------------\r\n");
Wayne Roberts 1:0817a150122b 1206 } else if (ch == '\r') {
Wayne Roberts 1:0817a150122b 1207 if (menuState.mode == MENUMODE_NONE) {
Wayne Roberts 1:0817a150122b 1208 start_menu_item_change();
Wayne Roberts 1:0817a150122b 1209 } else {
Wayne Roberts 1:0817a150122b 1210 entry_buf[entry_buf_idx] = 0;
Wayne Roberts 1:0817a150122b 1211 commit_menu_item_change();
Wayne Roberts 1:0817a150122b 1212 }
dudmuck 13:8ce61a1897ab 1213 sweep_service();
Wayne Roberts 1:0817a150122b 1214 } else if (menuState.mode == MENUMODE_ENTRY) {
Wayne Roberts 1:0817a150122b 1215 if (ch == 8) {
Wayne Roberts 1:0817a150122b 1216 if (entry_buf_idx > 0) {
dudmuck 13:8ce61a1897ab 1217 serial_write_buf[serial_write_buf_idx++] = 8;
dudmuck 13:8ce61a1897ab 1218 serial_write_buf[serial_write_buf_idx++] = ' ';
dudmuck 13:8ce61a1897ab 1219 serial_write_buf[serial_write_buf_idx++] = 8;
Wayne Roberts 1:0817a150122b 1220 entry_buf_idx--;
Wayne Roberts 1:0817a150122b 1221 }
Wayne Roberts 1:0817a150122b 1222 } else if (ch == 3) { // ctrl-C
Wayne Roberts 1:0817a150122b 1223 menuState.mode = MENUMODE_NONE;
Wayne Roberts 1:0817a150122b 1224 } else if (entry_buf_idx < sizeof(entry_buf)) {
Wayne Roberts 1:0817a150122b 1225 entry_buf[entry_buf_idx++] = ch;
dudmuck 13:8ce61a1897ab 1226 serial_write_buf[serial_write_buf_idx++] = ch;
Wayne Roberts 1:0817a150122b 1227 }
Wayne Roberts 1:0817a150122b 1228 } else if (menuState.mode == MENUMODE_NONE) {
Wayne Roberts 5:1e5cb7139acb 1229 if (ishexchar(ch) || ch == '-') { // characters which start entry
Wayne Roberts 1:0817a150122b 1230 const value_item_t* vi = (const value_item_t*)menu_table[curpos.row][curpos.tableCol]->itemPtr;
Wayne Roberts 1:0817a150122b 1231 if (vi->itemType == _ITEM_VALUE) {
Wayne Roberts 1:0817a150122b 1232 start_value_entry(menu_table[curpos.row][curpos.tableCol]);
Wayne Roberts 1:0817a150122b 1233 entry_buf[entry_buf_idx++] = ch;
dudmuck 13:8ce61a1897ab 1234 serial_write_buf[serial_write_buf_idx++] = ch;
Wayne Roberts 1:0817a150122b 1235 }
Wayne Roberts 1:0817a150122b 1236 } else if (ch == 'r') {
Wayne Roberts 1:0817a150122b 1237 menuState.mode = MENUMODE_REDRAW;
Wayne Roberts 1:0817a150122b 1238 } else if (ch == '.') {
Wayne Roberts 1:0817a150122b 1239 Radio::test();
Wayne Roberts 1:0817a150122b 1240 }
Wayne Roberts 1:0817a150122b 1241
Wayne Roberts 1:0817a150122b 1242 }
Wayne Roberts 1:0817a150122b 1243 break;
Wayne Roberts 1:0817a150122b 1244 case URX_STATE_ESCAPE:
Wayne Roberts 1:0817a150122b 1245 uartRxTimeout.detach();
Wayne Roberts 1:0817a150122b 1246 if (ch == '[')
Wayne Roberts 1:0817a150122b 1247 uart_rx_state = URX_STATE_CSI;
Wayne Roberts 1:0817a150122b 1248 else {
Wayne Roberts 1:0817a150122b 1249 #ifdef MENU_DEBUG
Wayne Roberts 1:0817a150122b 1250 log_printf("unhancled-esc:%02x\r\n", ch);
Wayne Roberts 1:0817a150122b 1251 #endif /* MENU_DEBUG */
Wayne Roberts 1:0817a150122b 1252 uart_rx_state = URX_STATE_NONE;
Wayne Roberts 1:0817a150122b 1253 }
Wayne Roberts 1:0817a150122b 1254 break;
Wayne Roberts 1:0817a150122b 1255 case URX_STATE_CSI:
Wayne Roberts 1:0817a150122b 1256 if (menuState.mode == MENUMODE_NONE)
Wayne Roberts 1:0817a150122b 1257 navigate_menu(ch);
Wayne Roberts 1:0817a150122b 1258 else if (menuState.mode == MENUMODE_DROPDOWN)
Wayne Roberts 1:0817a150122b 1259 navigate_dropdown(ch);
Wayne Roberts 1:0817a150122b 1260
Wayne Roberts 1:0817a150122b 1261 uart_rx_state = URX_STATE_NONE;
dudmuck 13:8ce61a1897ab 1262 //printf("\e[18;1f"); // set (force) cursor to row;column
Wayne Roberts 1:0817a150122b 1263 break;
Wayne Roberts 1:0817a150122b 1264 } // ..switch (uart_rx_state)
dudmuck 14:14b9e1c08bfc 1265
dudmuck 14:14b9e1c08bfc 1266 fflush(stdout);
dudmuck 13:8ce61a1897ab 1267
dudmuck 13:8ce61a1897ab 1268 if (serial_write_buf_idx > 0) {
dudmuck 14:14b9e1c08bfc 1269 pc.write(serial_write_buf, serial_write_buf_idx);
dudmuck 13:8ce61a1897ab 1270 }
dudmuck 14:14b9e1c08bfc 1271
dudmuck 14:14b9e1c08bfc 1272 pc.sync();
Wayne Roberts 1:0817a150122b 1273 }
Wayne Roberts 1:0817a150122b 1274
Wayne Roberts 1:0817a150122b 1275 void txDone()
Wayne Roberts 1:0817a150122b 1276 {
Wayne Roberts 1:0817a150122b 1277
Wayne Roberts 1:0817a150122b 1278 if (msg_type == MSG_TYPE_PER) {
Wayne Roberts 1:0817a150122b 1279 log_printf("CntPacketTx%u, max:%u ipd%u\r\n", CntPacketTx, MaxNumPacket, tx_ipd_ms);
dudmuck 13:8ce61a1897ab 1280 if (++CntPacketTx <= MaxNumPacket) {
dudmuck 13:8ce61a1897ab 1281 std::chrono::microseconds us = std::chrono::microseconds(tx_ipd_ms * 1000);
dudmuck 13:8ce61a1897ab 1282 mbedTimeout.attach(next_tx_callback, us);
dudmuck 13:8ce61a1897ab 1283 }
Wayne Roberts 1:0817a150122b 1284 } else if (msg_type == MSG_TYPE_PINGPONG) {
Wayne Roberts 1:0817a150122b 1285 if (flags.ping_master) {
Wayne Roberts 1:0817a150122b 1286 ++CntPacketTx;
Wayne Roberts 1:0817a150122b 1287 }
Wayne Roberts 1:0817a150122b 1288
Wayne Roberts 1:0817a150122b 1289 Radio::Rx();
Wayne Roberts 1:0817a150122b 1290 }
Wayne Roberts 1:0817a150122b 1291 }
Wayne Roberts 1:0817a150122b 1292
Wayne Roberts 9:295e37c38fb3 1293 void
Wayne Roberts 1:0817a150122b 1294 printRxPkt(uint8_t size)
Wayne Roberts 1:0817a150122b 1295 {
Wayne Roberts 9:295e37c38fb3 1296 uint8_t col;
Wayne Roberts 1:0817a150122b 1297 char str[80];
Wayne Roberts 1:0817a150122b 1298 char *ptr, *endPtr;
Wayne Roberts 1:0817a150122b 1299 unsigned n = 0;
Wayne Roberts 1:0817a150122b 1300 endPtr = str + sizeof(str);
Wayne Roberts 1:0817a150122b 1301 ptr = str;
Wayne Roberts 9:295e37c38fb3 1302 col = 0;
Wayne Roberts 1:0817a150122b 1303 while (ptr < endPtr) {
Wayne Roberts 9:295e37c38fb3 1304 //sprintf(ptr, "%02x%c", Radio::radio.rx_buf[n], n == Radio::radio.rx_buf_offset ? '_' : ' '); // LR1110
Wayne Roberts 1:0817a150122b 1305 sprintf(ptr, "%02x ", Radio::radio.rx_buf[n]);
Wayne Roberts 1:0817a150122b 1306 ptr += 3;
Wayne Roberts 9:295e37c38fb3 1307 col += 3;
Wayne Roberts 9:295e37c38fb3 1308 if (col >= 77) {
Wayne Roberts 9:295e37c38fb3 1309 log_printf("%s\r\n", str);
Wayne Roberts 9:295e37c38fb3 1310 ptr = str;
Wayne Roberts 9:295e37c38fb3 1311 col = 0;
Wayne Roberts 9:295e37c38fb3 1312 }
Wayne Roberts 1:0817a150122b 1313 if (++n >= size)
Wayne Roberts 1:0817a150122b 1314 break;
Wayne Roberts 1:0817a150122b 1315 }
Wayne Roberts 1:0817a150122b 1316 log_printf("%s\r\n", str);
Wayne Roberts 1:0817a150122b 1317 }
Wayne Roberts 1:0817a150122b 1318
Wayne Roberts 1:0817a150122b 1319 void rxDone(uint8_t size, float rssi, float snr)
Wayne Roberts 1:0817a150122b 1320 {
Wayne Roberts 1:0817a150122b 1321 log_printf("rxDone %u, %.1fdBm %.1fdB\r\n", size, rssi, snr);
Wayne Roberts 1:0817a150122b 1322 if (msg_type == MSG_TYPE_PACKET) {
Wayne Roberts 1:0817a150122b 1323 printRxPkt(size);
Wayne Roberts 1:0817a150122b 1324 } else if (msg_type == MSG_TYPE_PER) {
Wayne Roberts 1:0817a150122b 1325 if (memcmp(Radio::radio.rx_buf+4, PerMsg, 3) == 0) {
Wayne Roberts 1:0817a150122b 1326 unsigned i, PacketRxSequence = Radio::radio.rx_buf[0];
Wayne Roberts 1:0817a150122b 1327 PacketRxSequence <<= 8;
Wayne Roberts 1:0817a150122b 1328 PacketRxSequence += Radio::radio.rx_buf[1];
Wayne Roberts 1:0817a150122b 1329 PacketRxSequence <<= 8;
Wayne Roberts 1:0817a150122b 1330 PacketRxSequence += Radio::radio.rx_buf[2];
Wayne Roberts 1:0817a150122b 1331 PacketRxSequence <<= 8;
Wayne Roberts 1:0817a150122b 1332 PacketRxSequence += Radio::radio.rx_buf[3];
Wayne Roberts 1:0817a150122b 1333
Wayne Roberts 1:0817a150122b 1334 CntPacketRxOK++;
Wayne Roberts 1:0817a150122b 1335
Wayne Roberts 1:0817a150122b 1336 if (PacketRxSequence <= PacketRxSequencePrev || PacketRxSequencePrev == 0)
Wayne Roberts 1:0817a150122b 1337 i = 0; // sequence reset to resync, dont count missed packets this time
Wayne Roberts 1:0817a150122b 1338 else
Wayne Roberts 1:0817a150122b 1339 i = PacketRxSequence - PacketRxSequencePrev - 1;
Wayne Roberts 1:0817a150122b 1340
Wayne Roberts 1:0817a150122b 1341
Wayne Roberts 1:0817a150122b 1342 CntPacketRxKO += i;
Wayne Roberts 1:0817a150122b 1343 RxTimeOutCount = 0;
Wayne Roberts 1:0817a150122b 1344 log_printf("PER rx%u ok%u ko%u\r\n", PacketRxSequence , CntPacketRxOK, CntPacketRxKO);
Wayne Roberts 1:0817a150122b 1345
Wayne Roberts 1:0817a150122b 1346 PacketRxSequencePrev = PacketRxSequence;
Wayne Roberts 1:0817a150122b 1347 } // ..if PerMsg
Wayne Roberts 1:0817a150122b 1348 else {
Wayne Roberts 1:0817a150122b 1349 log_printf("per?\r\n");
Wayne Roberts 1:0817a150122b 1350 printRxPkt(size);
Wayne Roberts 1:0817a150122b 1351 }
Wayne Roberts 1:0817a150122b 1352 } else if (msg_type == MSG_TYPE_PINGPONG) {
Wayne Roberts 1:0817a150122b 1353 if (memcmp(Radio::radio.rx_buf+4, PingMsg, 4) == 0) {
Wayne Roberts 1:0817a150122b 1354 /* ping slave rx */
Wayne Roberts 1:0817a150122b 1355 Radio::setFS();
Wayne Roberts 1:0817a150122b 1356 receivedCntPacket = Radio::radio.rx_buf[0];
Wayne Roberts 1:0817a150122b 1357 receivedCntPacket <<= 8;
Wayne Roberts 1:0817a150122b 1358 receivedCntPacket += Radio::radio.rx_buf[1];
Wayne Roberts 1:0817a150122b 1359 receivedCntPacket <<= 8;
Wayne Roberts 1:0817a150122b 1360 receivedCntPacket += Radio::radio.rx_buf[2];
Wayne Roberts 1:0817a150122b 1361 receivedCntPacket <<= 8;
Wayne Roberts 1:0817a150122b 1362 receivedCntPacket += Radio::radio.rx_buf[3];
Wayne Roberts 1:0817a150122b 1363 log_printf("%u rxPing->txPong\r\n", receivedCntPacket);
Wayne Roberts 1:0817a150122b 1364
Wayne Roberts 1:0817a150122b 1365 flags.ping_master = 0;
Wayne Roberts 1:0817a150122b 1366 flags.send_pong = 1;
Wayne Roberts 1:0817a150122b 1367
Wayne Roberts 1:0817a150122b 1368 } else if (memcmp(Radio::radio.rx_buf+8, PongMsg, 4) == 0) {
Wayne Roberts 1:0817a150122b 1369 unsigned cnt;
Wayne Roberts 1:0817a150122b 1370 /* ping master rx */
Wayne Roberts 1:0817a150122b 1371 Radio::setFS();
Wayne Roberts 1:0817a150122b 1372 cnt = Radio::radio.rx_buf[0];
Wayne Roberts 1:0817a150122b 1373 cnt <<= 8;
Wayne Roberts 1:0817a150122b 1374 cnt += Radio::radio.rx_buf[1];
Wayne Roberts 1:0817a150122b 1375 cnt <<= 8;
Wayne Roberts 1:0817a150122b 1376 cnt += Radio::radio.rx_buf[2];
Wayne Roberts 1:0817a150122b 1377 cnt <<= 8;
Wayne Roberts 1:0817a150122b 1378 cnt += Radio::radio.rx_buf[3];
Wayne Roberts 1:0817a150122b 1379 log_printf("%u rxPong->txPing\r\n", cnt);
Wayne Roberts 1:0817a150122b 1380 flags.send_ping = 1;
Wayne Roberts 1:0817a150122b 1381 } else {
Wayne Roberts 1:0817a150122b 1382 log_printf("pingpong?\r\n");
Wayne Roberts 1:0817a150122b 1383 printRxPkt(size);
Wayne Roberts 1:0817a150122b 1384 }
Wayne Roberts 1:0817a150122b 1385 } else {
Wayne Roberts 1:0817a150122b 1386 /*for (unsigned n = 0; n < size; n++)
Wayne Roberts 1:0817a150122b 1387 log_printf("%02x\r\n", Radio::radio.rx_buf[n]);*/
Wayne Roberts 1:0817a150122b 1388 log_printf("msg_type %u\r\n", msg_type);
Wayne Roberts 1:0817a150122b 1389 }
Wayne Roberts 1:0817a150122b 1390
Wayne Roberts 1:0817a150122b 1391 }
Wayne Roberts 1:0817a150122b 1392
Wayne Roberts 1:0817a150122b 1393 const RadioEvents_t rev = {
Wayne Roberts 1:0817a150122b 1394 txDone,
Wayne Roberts 1:0817a150122b 1395 rxDone
Wayne Roberts 1:0817a150122b 1396 };
Wayne Roberts 1:0817a150122b 1397
dudmuck 13:8ce61a1897ab 1398 volatile int foo;
dudmuck 13:8ce61a1897ab 1399
Wayne Roberts 1:0817a150122b 1400 int main()
Wayne Roberts 1:0817a150122b 1401 {
Wayne Roberts 1:0817a150122b 1402 lfsr = LFSR_INIT;
Wayne Roberts 1:0817a150122b 1403 msg_type = MSG_TYPE_PACKET;
Wayne Roberts 1:0817a150122b 1404
Wayne Roberts 1:0817a150122b 1405 uart_rx_state = URX_STATE_NONE;
Wayne Roberts 1:0817a150122b 1406
Wayne Roberts 1:0817a150122b 1407 Radio::boardInit(&rev);
Wayne Roberts 1:0817a150122b 1408
Wayne Roberts 1:0817a150122b 1409 {
Wayne Roberts 1:0817a150122b 1410 unsigned n;
Wayne Roberts 1:0817a150122b 1411 for (n = 0; n < MAX_MENU_ROWS; n++)
Wayne Roberts 1:0817a150122b 1412 StopMenuCols[n] = -1;
Wayne Roberts 1:0817a150122b 1413 }
Wayne Roberts 1:0817a150122b 1414
Wayne Roberts 1:0817a150122b 1415 botRow = MAX_MENU_ROWS + SCROLLING_ROWS;
Wayne Roberts 1:0817a150122b 1416
dudmuck 13:8ce61a1897ab 1417 printf("\e[7h"); // enable line wrapping
dudmuck 13:8ce61a1897ab 1418 printf("\e[%u;%ur", MAX_MENU_ROWS, botRow); // set scrolling region
dudmuck 13:8ce61a1897ab 1419 printf("\e[2J"); // erase entire screen
Wayne Roberts 1:0817a150122b 1420
Wayne Roberts 1:0817a150122b 1421 full_menu_init();
Wayne Roberts 1:0817a150122b 1422
dudmuck 13:8ce61a1897ab 1423 printf("\e[2J"); // erase entire screen
Wayne Roberts 1:0817a150122b 1424
Wayne Roberts 1:0817a150122b 1425 menuState.mode = MENUMODE_NONE;
Wayne Roberts 1:0817a150122b 1426
Wayne Roberts 9:295e37c38fb3 1427 draw_menu();
Wayne Roberts 1:0817a150122b 1428
Wayne Roberts 1:0817a150122b 1429 curpos.row = 0;
Wayne Roberts 1:0817a150122b 1430 curpos.tableCol = 0;
Wayne Roberts 1:0817a150122b 1431
Wayne Roberts 1:0817a150122b 1432 tx_ipd_ms = 100;
dudmuck 15:703ca340d0fb 1433
dudmuck 15:703ca340d0fb 1434 logpc_printf("\r\nRESET\r\n");
dudmuck 14:14b9e1c08bfc 1435
Wayne Roberts 1:0817a150122b 1436 for (;;) {
dudmuck 14:14b9e1c08bfc 1437 if (pc.readable()) {
Wayne Roberts 1:0817a150122b 1438 serial_callback();
Wayne Roberts 1:0817a150122b 1439 }
Wayne Roberts 1:0817a150122b 1440
Wayne Roberts 1:0817a150122b 1441 if (flags.send_ping) {
Wayne Roberts 1:0817a150122b 1442 if (flags.pingpongEnable)
Wayne Roberts 1:0817a150122b 1443 SendPing();
Wayne Roberts 1:0817a150122b 1444 flags.send_ping = 0;
Wayne Roberts 1:0817a150122b 1445 }
Wayne Roberts 1:0817a150122b 1446
Wayne Roberts 1:0817a150122b 1447 if (flags.send_pong) {
Wayne Roberts 1:0817a150122b 1448 if (flags.pingpongEnable)
Wayne Roberts 1:0817a150122b 1449 SendPong();
Wayne Roberts 1:0817a150122b 1450 flags.send_pong = 0;
Wayne Roberts 1:0817a150122b 1451 }
Wayne Roberts 1:0817a150122b 1452
Wayne Roberts 4:fa31fdf4ec8d 1453 if (flags.do_next_tx) {
Wayne Roberts 4:fa31fdf4ec8d 1454 do_next_tx();
Wayne Roberts 4:fa31fdf4ec8d 1455 flags.do_next_tx = 0;
Wayne Roberts 4:fa31fdf4ec8d 1456 }
Wayne Roberts 4:fa31fdf4ec8d 1457
Wayne Roberts 1:0817a150122b 1458 if (menuState.mode == MENUMODE_REINIT_MENU) {
Wayne Roberts 1:0817a150122b 1459 full_menu_init();
Wayne Roberts 1:0817a150122b 1460 menuState.mode = MENUMODE_REDRAW;
Wayne Roberts 1:0817a150122b 1461 }
Wayne Roberts 1:0817a150122b 1462
Wayne Roberts 1:0817a150122b 1463 if (menuState.mode == MENUMODE_REDRAW) {
Wayne Roberts 1:0817a150122b 1464 // erase entire screen, some dropdowns extend to scrolling area
dudmuck 13:8ce61a1897ab 1465 printf("\e[%u;%ur", MAX_MENU_ROWS, botRow); // set scrolling region, if terminal started after
dudmuck 13:8ce61a1897ab 1466 printf("\e[2J");
dudmuck 13:8ce61a1897ab 1467 //printf("\e[%u;1f\e[1J", MAX_MENU_ROWS); // erase menu area
Wayne Roberts 1:0817a150122b 1468
Wayne Roberts 1:0817a150122b 1469 menuState.mode = MENUMODE_NONE;
Wayne Roberts 9:295e37c38fb3 1470 draw_menu();
Wayne Roberts 1:0817a150122b 1471 }
Wayne Roberts 1:0817a150122b 1472
Wayne Roberts 1:0817a150122b 1473 if (Radio::service(menuState.mode == MENUMODE_NONE ? LAST_CHIP_MENU_ROW : -1)) {
Wayne Roberts 1:0817a150122b 1474 read_menu_item(menu_table[curpos.row][curpos.tableCol], true);
Wayne Roberts 1:0817a150122b 1475 }
dudmuck 13:8ce61a1897ab 1476
dudmuck 13:8ce61a1897ab 1477 if (cf_sweep.tick) {
dudmuck 13:8ce61a1897ab 1478 cf_sweep.tick = false;
dudmuck 13:8ce61a1897ab 1479 #ifdef SX127x_H
dudmuck 13:8ce61a1897ab 1480 Radio::radio.set_frf_MHz(cf_sweep.MHz);
dudmuck 13:8ce61a1897ab 1481 #else
dudmuck 13:8ce61a1897ab 1482 Radio::radio.setMHz(cf_sweep.MHz);
dudmuck 13:8ce61a1897ab 1483 #endif
dudmuck 13:8ce61a1897ab 1484 cf_sweep.MHz += cf_sweep.step_MHz;
dudmuck 13:8ce61a1897ab 1485 if (cf_sweep.MHz >= cf_sweep.stop_MHz)
dudmuck 13:8ce61a1897ab 1486 cf_sweep.MHz = cf_sweep.start_MHz;
dudmuck 13:8ce61a1897ab 1487 }
dudmuck 13:8ce61a1897ab 1488
Wayne Roberts 1:0817a150122b 1489 } // ..for (;;)
Wayne Roberts 1:0817a150122b 1490 }
Wayne Roberts 1:0817a150122b 1491
Wayne Roberts 1:0817a150122b 1492 char strbuf[255];
Wayne Roberts 1:0817a150122b 1493
Wayne Roberts 1:0817a150122b 1494 void log_printf(const char* format, ...)
Wayne Roberts 1:0817a150122b 1495 {
Wayne Roberts 1:0817a150122b 1496 va_list arglist;
Wayne Roberts 1:0817a150122b 1497
Wayne Roberts 1:0817a150122b 1498 // put cursor at last scrolling-area line
dudmuck 13:8ce61a1897ab 1499 printf("\e[%u;1f", botRow);
Wayne Roberts 1:0817a150122b 1500 va_start(arglist, format);
Wayne Roberts 1:0817a150122b 1501 vsprintf(strbuf, format, arglist);
Wayne Roberts 1:0817a150122b 1502 va_end(arglist);
Wayne Roberts 1:0817a150122b 1503
dudmuck 13:8ce61a1897ab 1504 printf("%s", strbuf);
dudmuck 14:14b9e1c08bfc 1505
dudmuck 14:14b9e1c08bfc 1506 fflush(stdout);
dudmuck 14:14b9e1c08bfc 1507 pc.sync();
Wayne Roberts 1:0817a150122b 1508 }
dudmuck 13:8ce61a1897ab 1509
dudmuck 15:703ca340d0fb 1510 void logpc_printf(const char* format, ...) /* printing on 2nd uart */
dudmuck 15:703ca340d0fb 1511 {
dudmuck 15:703ca340d0fb 1512 int len;
dudmuck 15:703ca340d0fb 1513 va_list arglist;
dudmuck 15:703ca340d0fb 1514
dudmuck 15:703ca340d0fb 1515 va_start(arglist, format);
dudmuck 15:703ca340d0fb 1516 len = vsprintf(strbuf, format, arglist);
dudmuck 15:703ca340d0fb 1517 va_end(arglist);
dudmuck 15:703ca340d0fb 1518
dudmuck 15:703ca340d0fb 1519 //logpc.write(strbuf, len);
dudmuck 15:703ca340d0fb 1520
dudmuck 15:703ca340d0fb 1521 fflush(stdout);
dudmuck 15:703ca340d0fb 1522 pc.sync();
dudmuck 15:703ca340d0fb 1523 }