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:
Thu Sep 16 21:57:23 2021 +0000
Revision:
14:14b9e1c08bfc
Parent:
13:8ce61a1897ab
BufferedSerial flush printf

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