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:
Wed Aug 22 09:50:32 2018 -0700
Revision:
2:ea9245bb1c53
Parent:
1:0817a150122b
Child:
3:56fc764dee0a
add LoRa CAD function

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