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:
Wayne Roberts
Date:
Mon Aug 20 18:13:09 2018 -0700
Revision:
1:0817a150122b
Child:
2:ea9245bb1c53
add source files

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