transfer files from mbed-os block device (i.e. SD card) over LoRa radio.

Dependencies:   sx12xx_hal

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 NAmote72 or Murata discovery, then you must import only sx127x driver.

This program uses mbed serial terminal at 115200 8N1.
Files (on SD Card) are transferred between two LoRa devices.
Use ? question mark to see available commands on serial terminal.
Send file to other side using send /fs/somefile, then use cmp /fs/somefile to compare the file on the other side of radio link with local file with same name.
Use cmp to test radio link.

rm command to delete files must not include /fs/ directory prefix, filename only.
send and cmp require /fs/ directory.

sx1280 thruput

bytes/secsf12sf11sf10sf9sf8sf7sf6sf5
1600KHz2764821081188732775365640012000
800KHz5299701720280047666500
400KHz146522654033

sx126x thruput

bytes/secsf12sf11sf10sf9sf8sf7sf6sf5
500KHz2073817061257215435705608
250KHz103193344641111418873064
125KHz971733245479721607

sx127x thruput

sx126x recommended at 500KHz bandwidth.

bytes/secsf12sf11sf10sf9sf8sf7
500KHz11120738569712202050
250KHz48.71031923456321115
125KHz24.24497151313552
62.5KHz12.222.139.486157276

SD Card

SD card driver must be enabled in mbed_app.json with the line "target.components_add": ["SD"]
Pins for SD card connection can be overridden as shown in mbed_app.json.
The default pin configuration for SD card is found in mbed_lib.json in mbed-os/components/storage/blockdevice/COMPONENT_SD/.
If no pin configuration exists in this mbed_lib.json, or needs to be changed, the included mbed_app.json is example pin declaration for SD card.

FAT filesystem is only used in this project for demonstration purpose; for easily copying files to SD card.
However, for production projects, LittleFileSystem needs to be used instead for reliability and wear leveling.

Platforms such as K64F have SD card slot already.
See all boards with arduino shield connector and SD card here. (arduino connector needed for LoRa radio board)
...but if you want to use nucleo board: /media/uploads/dudmuck/nucleo_sdcardqtr.png

Committer:
Wayne Roberts
Date:
Wed Jun 05 09:52:27 2019 -0700
Revision:
1:319ef808aaa4
Parent:
0:c3ecf7b252a3
mbed crashes closing -1 file descriptor

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wayne Roberts 0:c3ecf7b252a3 1 #include <stdio.h>
Wayne Roberts 0:c3ecf7b252a3 2 #include <errno.h>
Wayne Roberts 0:c3ecf7b252a3 3 #include "lorachip.h"
Wayne Roberts 0:c3ecf7b252a3 4
Wayne Roberts 0:c3ecf7b252a3 5 // how long extra to keep receiver open to wait for ack/nak, due to task performed by receiver rxdone handling
Wayne Roberts 0:c3ecf7b252a3 6 #define TX_RX_TURNAROUND_MS 70
Wayne Roberts 0:c3ecf7b252a3 7
Wayne Roberts 0:c3ecf7b252a3 8 #if defined(SX127x_H)
Wayne Roberts 0:c3ecf7b252a3 9 #define BW_KHZ 500
Wayne Roberts 0:c3ecf7b252a3 10 #define SPREADING_FACTOR 7
Wayne Roberts 0:c3ecf7b252a3 11 #define CF_HZ 915000000
Wayne Roberts 0:c3ecf7b252a3 12 #define TX_DBM 20
Wayne Roberts 0:c3ecf7b252a3 13 #define SPI_HZ 5000000
Wayne Roberts 0:c3ecf7b252a3 14 #elif defined(SX126x_H)
Wayne Roberts 0:c3ecf7b252a3 15 #define BW_KHZ 500
Wayne Roberts 0:c3ecf7b252a3 16 #define SPREADING_FACTOR 5
Wayne Roberts 0:c3ecf7b252a3 17 #define CF_HZ 915000000
Wayne Roberts 0:c3ecf7b252a3 18 #define TX_DBM (Radio::chipType == CHIP_TYPE_SX1262 ? 20 : 14)
Wayne Roberts 0:c3ecf7b252a3 19 #define SPI_HZ 10000000
Wayne Roberts 0:c3ecf7b252a3 20 #elif defined(SX128x_H)
Wayne Roberts 0:c3ecf7b252a3 21 #define BW_KHZ 1600
Wayne Roberts 0:c3ecf7b252a3 22 #define SPREADING_FACTOR 5
Wayne Roberts 0:c3ecf7b252a3 23 #define CF_HZ 2487000000
Wayne Roberts 0:c3ecf7b252a3 24 #define TX_DBM 2
Wayne Roberts 0:c3ecf7b252a3 25 #define SPI_HZ 10000000
Wayne Roberts 0:c3ecf7b252a3 26 #endif
Wayne Roberts 0:c3ecf7b252a3 27 #define MAX_PKT_SIZE 250
Wayne Roberts 0:c3ecf7b252a3 28
Wayne Roberts 0:c3ecf7b252a3 29 EventQueue queue(32 * EVENTS_EVENT_SIZE);
Wayne Roberts 0:c3ecf7b252a3 30 Thread th;
Wayne Roberts 0:c3ecf7b252a3 31 Timer t;
Wayne Roberts 0:c3ecf7b252a3 32
Wayne Roberts 0:c3ecf7b252a3 33 typedef struct {
Wayne Roberts 0:c3ecf7b252a3 34 uint8_t foobar : 2; // 0,1
Wayne Roberts 0:c3ecf7b252a3 35 uint8_t rxContStart : 1; // 2
Wayne Roberts 0:c3ecf7b252a3 36 uint8_t callRetry : 1; // 3
Wayne Roberts 0:c3ecf7b252a3 37 uint8_t txDonePending : 1; // 4 txDone needs to be serviced
Wayne Roberts 0:c3ecf7b252a3 38 uint8_t endOfFile : 1; // 5
Wayne Roberts 0:c3ecf7b252a3 39 uint8_t atTxDoneRxSingle : 1; // 6
Wayne Roberts 0:c3ecf7b252a3 40 uint8_t verbose : 1; // 7
Wayne Roberts 0:c3ecf7b252a3 41 } flags_t;
Wayne Roberts 0:c3ecf7b252a3 42 volatile flags_t flags;
Wayne Roberts 0:c3ecf7b252a3 43
Wayne Roberts 0:c3ecf7b252a3 44 //#include "LittleFileSystem.h"
Wayne Roberts 0:c3ecf7b252a3 45 //LittleFileSystem fs("fs");
Wayne Roberts 0:c3ecf7b252a3 46 #include "FATFileSystem.h"
Wayne Roberts 0:c3ecf7b252a3 47 FATFileSystem fs("fs");
Wayne Roberts 0:c3ecf7b252a3 48 /* FAT FS not recommended for production */
Wayne Roberts 0:c3ecf7b252a3 49 /* use Little FS for production */
Wayne Roberts 0:c3ecf7b252a3 50
Wayne Roberts 0:c3ecf7b252a3 51 //BlockDevice *bd = BlockDevice::get_default_instance();
Wayne Roberts 0:c3ecf7b252a3 52 #include "SDBlockDevice.h"
Wayne Roberts 0:c3ecf7b252a3 53 SDBlockDevice *bd = new SDBlockDevice(MBED_CONF_SD_SPI_MOSI, MBED_CONF_SD_SPI_MISO, MBED_CONF_SD_SPI_CLK, MBED_CONF_SD_SPI_CS, 5000000);
Wayne Roberts 0:c3ecf7b252a3 54
Wayne Roberts 0:c3ecf7b252a3 55 RawSerial pc(USBTX, USBRX);
Wayne Roberts 0:c3ecf7b252a3 56
Wayne Roberts 0:c3ecf7b252a3 57 //#define RX_DBG_PIN PC_10
Wayne Roberts 0:c3ecf7b252a3 58 #ifdef RX_DBG_PIN
Wayne Roberts 0:c3ecf7b252a3 59 DigitalInOut rx_dbg(RX_DBG_PIN);
Wayne Roberts 0:c3ecf7b252a3 60 #endif /* RX_DBG_PIN */
Wayne Roberts 0:c3ecf7b252a3 61
Wayne Roberts 0:c3ecf7b252a3 62 volatile unsigned txMinDelay_us; // minimum time between RX done to TX start
Wayne Roberts 0:c3ecf7b252a3 63 volatile unsigned add_txDelay_retry; // how much extra to defer on each retry
Wayne Roberts 0:c3ecf7b252a3 64
Wayne Roberts 0:c3ecf7b252a3 65 #define MAX_ATTEMPTS 15
Wayne Roberts 0:c3ecf7b252a3 66 volatile uint8_t attemptsRemaining;
Wayne Roberts 0:c3ecf7b252a3 67 volatile int prevRxSeq;
Wayne Roberts 0:c3ecf7b252a3 68 volatile uint8_t seq;
Wayne Roberts 0:c3ecf7b252a3 69 volatile uint8_t tx_buf_len;
Wayne Roberts 0:c3ecf7b252a3 70 volatile unsigned xferStartAt;
Wayne Roberts 0:c3ecf7b252a3 71 volatile unsigned rxDoneAt;
Wayne Roberts 0:c3ecf7b252a3 72 volatile unsigned byteCnt;
Wayne Roberts 0:c3ecf7b252a3 73 int fd; // descriptor of transferring file
Wayne Roberts 0:c3ecf7b252a3 74 volatile int sendData_readLen;
Wayne Roberts 0:c3ecf7b252a3 75 lora_t current;
Wayne Roberts 0:c3ecf7b252a3 76
Wayne Roberts 0:c3ecf7b252a3 77 uint16_t myAddr;
Wayne Roberts 0:c3ecf7b252a3 78 #define BROADCAST_ADDRESS 0xffff
Wayne Roberts 0:c3ecf7b252a3 79 uint16_t peerAddr = BROADCAST_ADDRESS;
Wayne Roberts 0:c3ecf7b252a3 80
Wayne Roberts 0:c3ecf7b252a3 81 uint8_t file_buf[MAX_PKT_SIZE];
Wayne Roberts 0:c3ecf7b252a3 82
Wayne Roberts 0:c3ecf7b252a3 83 typedef enum {
Wayne Roberts 0:c3ecf7b252a3 84 /* 0 */ STATE_NONE = 0,
Wayne Roberts 0:c3ecf7b252a3 85 /* 1 */ STATE_RX_COMPARE,
Wayne Roberts 0:c3ecf7b252a3 86 /* 2 */ STATE_SEND_FILE,
Wayne Roberts 0:c3ecf7b252a3 87 /* 3 */ STATE_FILE_END,
Wayne Roberts 0:c3ecf7b252a3 88 /* 4 */ STATE_GET_FILE
Wayne Roberts 0:c3ecf7b252a3 89 } state_e;
Wayne Roberts 0:c3ecf7b252a3 90 volatile state_e state;
Wayne Roberts 0:c3ecf7b252a3 91
Wayne Roberts 0:c3ecf7b252a3 92 char printBuf[2048];
Wayne Roberts 0:c3ecf7b252a3 93 volatile uint16_t printBuf_in;
Wayne Roberts 0:c3ecf7b252a3 94 volatile uint16_t printBuf_out;
Wayne Roberts 0:c3ecf7b252a3 95
Wayne Roberts 0:c3ecf7b252a3 96 /* Prints into circular buffer to prevent impact on execution speed.
Wayne Roberts 0:c3ecf7b252a3 97 * (aka non-blocking printf)
Wayne Roberts 0:c3ecf7b252a3 98 * Characters are sent in main loop, where time is less important. */
Wayne Roberts 0:c3ecf7b252a3 99 int vspfunc(const char *format, ...)
Wayne Roberts 0:c3ecf7b252a3 100 {
Wayne Roberts 0:c3ecf7b252a3 101 va_list aptr;
Wayne Roberts 0:c3ecf7b252a3 102 int ret;
Wayne Roberts 0:c3ecf7b252a3 103 char buffer[256];
Wayne Roberts 0:c3ecf7b252a3 104
Wayne Roberts 0:c3ecf7b252a3 105 va_start(aptr, format);
Wayne Roberts 0:c3ecf7b252a3 106 ret = vsprintf(buffer, format, aptr);
Wayne Roberts 0:c3ecf7b252a3 107 va_end(aptr);
Wayne Roberts 0:c3ecf7b252a3 108 if (ret < 0) {
Wayne Roberts 0:c3ecf7b252a3 109 pc.printf("vsprintf failed\r\n");
Wayne Roberts 0:c3ecf7b252a3 110 return ret;
Wayne Roberts 0:c3ecf7b252a3 111 }
Wayne Roberts 0:c3ecf7b252a3 112
Wayne Roberts 0:c3ecf7b252a3 113 if ((printBuf_in + (unsigned)ret) >= sizeof(printBuf)) {
Wayne Roberts 0:c3ecf7b252a3 114 int len_b, len_a = sizeof(printBuf) - printBuf_in;
Wayne Roberts 0:c3ecf7b252a3 115 memcpy(printBuf + printBuf_in, buffer, len_a);
Wayne Roberts 0:c3ecf7b252a3 116 len_b = ret - len_a;
Wayne Roberts 0:c3ecf7b252a3 117 memcpy(printBuf, buffer + len_a, len_b);
Wayne Roberts 0:c3ecf7b252a3 118 printBuf_in = len_b;
Wayne Roberts 0:c3ecf7b252a3 119 } else {
Wayne Roberts 0:c3ecf7b252a3 120 memcpy(printBuf + printBuf_in, buffer, ret);
Wayne Roberts 0:c3ecf7b252a3 121 printBuf_in += ret;
Wayne Roberts 0:c3ecf7b252a3 122 }
Wayne Roberts 0:c3ecf7b252a3 123
Wayne Roberts 0:c3ecf7b252a3 124 return(ret);
Wayne Roberts 0:c3ecf7b252a3 125 }
Wayne Roberts 0:c3ecf7b252a3 126
Wayne Roberts 0:c3ecf7b252a3 127 volatile unsigned txDoneAt;
Wayne Roberts 0:c3ecf7b252a3 128
Wayne Roberts 0:c3ecf7b252a3 129 static inline void rxCont(void)
Wayne Roberts 0:c3ecf7b252a3 130 {
Wayne Roberts 0:c3ecf7b252a3 131 Radio::Rx(0);
Wayne Roberts 0:c3ecf7b252a3 132 #ifdef RX_DBG_PIN
Wayne Roberts 0:c3ecf7b252a3 133 rx_dbg.output();
Wayne Roberts 0:c3ecf7b252a3 134 rx_dbg.write(0);
Wayne Roberts 0:c3ecf7b252a3 135 #endif /* RX_DBG_PIN */
Wayne Roberts 0:c3ecf7b252a3 136 }
Wayne Roberts 0:c3ecf7b252a3 137
Wayne Roberts 0:c3ecf7b252a3 138 void txDoneCB_botHalf()
Wayne Roberts 0:c3ecf7b252a3 139 {
Wayne Roberts 0:c3ecf7b252a3 140 unsigned now;
Wayne Roberts 0:c3ecf7b252a3 141
Wayne Roberts 0:c3ecf7b252a3 142 if (flags.atTxDoneRxSingle) {
Wayne Roberts 0:c3ecf7b252a3 143 Radio::Rx(1000);
Wayne Roberts 0:c3ecf7b252a3 144 #ifdef RX_DBG_PIN
Wayne Roberts 0:c3ecf7b252a3 145 rx_dbg.output();
Wayne Roberts 0:c3ecf7b252a3 146 rx_dbg.write(0);
Wayne Roberts 0:c3ecf7b252a3 147 #endif /* RX_DBG_PIN */
Wayne Roberts 0:c3ecf7b252a3 148 now = t.read_us();
Wayne Roberts 0:c3ecf7b252a3 149 if (flags.verbose)
Wayne Roberts 0:c3ecf7b252a3 150 vspfunc("rxSingle%u ", now - txDoneAt);
Wayne Roberts 0:c3ecf7b252a3 151 } else {
Wayne Roberts 0:c3ecf7b252a3 152 rxCont();
Wayne Roberts 0:c3ecf7b252a3 153 Radio::Rx(0);
Wayne Roberts 0:c3ecf7b252a3 154 now = t.read_us();
Wayne Roberts 0:c3ecf7b252a3 155 if (flags.verbose)
Wayne Roberts 0:c3ecf7b252a3 156 vspfunc("rxCont%u ", now - txDoneAt);
Wayne Roberts 0:c3ecf7b252a3 157 }
Wayne Roberts 0:c3ecf7b252a3 158 flags.txDonePending = false;
Wayne Roberts 0:c3ecf7b252a3 159 }
Wayne Roberts 0:c3ecf7b252a3 160
Wayne Roberts 0:c3ecf7b252a3 161 void txDoneCB_topHalf()
Wayne Roberts 0:c3ecf7b252a3 162 {
Wayne Roberts 0:c3ecf7b252a3 163 txDoneAt = t.read_us();
Wayne Roberts 0:c3ecf7b252a3 164 flags.txDonePending = true;
Wayne Roberts 0:c3ecf7b252a3 165 }
Wayne Roberts 0:c3ecf7b252a3 166
Wayne Roberts 0:c3ecf7b252a3 167 static uint16_t crc16( uint8_t *buffer, uint16_t length )
Wayne Roberts 0:c3ecf7b252a3 168 {
Wayne Roberts 0:c3ecf7b252a3 169 uint16_t i;
Wayne Roberts 0:c3ecf7b252a3 170 // The CRC calculation follows CCITT
Wayne Roberts 0:c3ecf7b252a3 171 const uint16_t polynom = 0x1021;
Wayne Roberts 0:c3ecf7b252a3 172 // CRC initial value
Wayne Roberts 0:c3ecf7b252a3 173 uint16_t crc = 0x0000;
Wayne Roberts 0:c3ecf7b252a3 174
Wayne Roberts 0:c3ecf7b252a3 175 if( buffer == NULL )
Wayne Roberts 0:c3ecf7b252a3 176 {
Wayne Roberts 0:c3ecf7b252a3 177 return 0;
Wayne Roberts 0:c3ecf7b252a3 178 }
Wayne Roberts 0:c3ecf7b252a3 179
Wayne Roberts 0:c3ecf7b252a3 180 for( i = 0; i < length; ++i )
Wayne Roberts 0:c3ecf7b252a3 181 {
Wayne Roberts 0:c3ecf7b252a3 182 uint16_t j;
Wayne Roberts 0:c3ecf7b252a3 183 crc ^= ( uint16_t ) buffer[i] << 8;
Wayne Roberts 0:c3ecf7b252a3 184 for( j = 0; j < 8; ++j )
Wayne Roberts 0:c3ecf7b252a3 185 {
Wayne Roberts 0:c3ecf7b252a3 186 crc = ( crc & 0x8000 ) ? ( crc << 1 ) ^ polynom : ( crc << 1 );
Wayne Roberts 0:c3ecf7b252a3 187 }
Wayne Roberts 0:c3ecf7b252a3 188 }
Wayne Roberts 0:c3ecf7b252a3 189
Wayne Roberts 0:c3ecf7b252a3 190 return crc;
Wayne Roberts 0:c3ecf7b252a3 191 }
Wayne Roberts 0:c3ecf7b252a3 192
Wayne Roberts 0:c3ecf7b252a3 193
Wayne Roberts 0:c3ecf7b252a3 194 static inline unsigned rf_send(bool anytime, unsigned extratxdelay)
Wayne Roberts 0:c3ecf7b252a3 195 {
Wayne Roberts 0:c3ecf7b252a3 196 unsigned sinceRxDone = 0;
Wayne Roberts 0:c3ecf7b252a3 197 unsigned target = txMinDelay_us + extratxdelay;
Wayne Roberts 0:c3ecf7b252a3 198
Wayne Roberts 0:c3ecf7b252a3 199 Radio::Standby();
Wayne Roberts 0:c3ecf7b252a3 200
Wayne Roberts 0:c3ecf7b252a3 201 if (!anytime) {
Wayne Roberts 0:c3ecf7b252a3 202 do {
Wayne Roberts 0:c3ecf7b252a3 203 sinceRxDone = t.read_us() - rxDoneAt;
Wayne Roberts 0:c3ecf7b252a3 204 } while (sinceRxDone < target);
Wayne Roberts 0:c3ecf7b252a3 205 }
Wayne Roberts 0:c3ecf7b252a3 206
Wayne Roberts 0:c3ecf7b252a3 207 #ifdef RX_DBG_PIN
Wayne Roberts 0:c3ecf7b252a3 208 rx_dbg.input();
Wayne Roberts 0:c3ecf7b252a3 209 if (flags.verbose) {
Wayne Roberts 0:c3ecf7b252a3 210 if (rx_dbg.read())
Wayne Roberts 0:c3ecf7b252a3 211 vspfunc("\e[41mnotrxing\e[0m%u ", sinceRxDone);
Wayne Roberts 0:c3ecf7b252a3 212 else
Wayne Roberts 0:c3ecf7b252a3 213 vspfunc("\e[32mprxok\e[0m%u ", sinceRxDone);
Wayne Roberts 0:c3ecf7b252a3 214 }
Wayne Roberts 0:c3ecf7b252a3 215 #endif /* RX_DBG_PIN */
Wayne Roberts 0:c3ecf7b252a3 216
Wayne Roberts 0:c3ecf7b252a3 217 Radio::Send(tx_buf_len, 0, 0, 0);
Wayne Roberts 0:c3ecf7b252a3 218 return sinceRxDone;
Wayne Roberts 0:c3ecf7b252a3 219 }
Wayne Roberts 0:c3ecf7b252a3 220
Wayne Roberts 0:c3ecf7b252a3 221 static void sendAck(bool ack, unsigned addTxDelay)
Wayne Roberts 0:c3ecf7b252a3 222 {
Wayne Roberts 0:c3ecf7b252a3 223 uint16_t crc;
Wayne Roberts 0:c3ecf7b252a3 224
Wayne Roberts 0:c3ecf7b252a3 225 tx_buf_len = 0;
Wayne Roberts 0:c3ecf7b252a3 226 Radio::radio.tx_buf[tx_buf_len++] = Radio::radio.rx_buf[0];
Wayne Roberts 0:c3ecf7b252a3 227 Radio::radio.tx_buf[tx_buf_len++] = ack ? 'Y' : 'N';
Wayne Roberts 0:c3ecf7b252a3 228 crc = crc16(Radio::radio.tx_buf, tx_buf_len);
Wayne Roberts 0:c3ecf7b252a3 229 Radio::radio.tx_buf[tx_buf_len++] = crc;
Wayne Roberts 0:c3ecf7b252a3 230 Radio::radio.tx_buf[tx_buf_len++] = crc >> 8;
Wayne Roberts 0:c3ecf7b252a3 231
Wayne Roberts 0:c3ecf7b252a3 232 flags.atTxDoneRxSingle = false;
Wayne Roberts 0:c3ecf7b252a3 233 attemptsRemaining = MAX_ATTEMPTS;
Wayne Roberts 0:c3ecf7b252a3 234 /*sinceRxDone = */rf_send(false, addTxDelay);
Wayne Roberts 0:c3ecf7b252a3 235 if (flags.verbose)
Wayne Roberts 0:c3ecf7b252a3 236 vspfunc("sentAck'%c' %u ", Radio::radio.tx_buf[1], addTxDelay);
Wayne Roberts 0:c3ecf7b252a3 237 }
Wayne Roberts 0:c3ecf7b252a3 238
Wayne Roberts 0:c3ecf7b252a3 239 void retry(bool anytime)
Wayne Roberts 0:c3ecf7b252a3 240 {
Wayne Roberts 0:c3ecf7b252a3 241 if (attemptsRemaining == 0)
Wayne Roberts 0:c3ecf7b252a3 242 return;
Wayne Roberts 0:c3ecf7b252a3 243
Wayne Roberts 0:c3ecf7b252a3 244 if (--attemptsRemaining > 0) {
Wayne Roberts 0:c3ecf7b252a3 245 flags.atTxDoneRxSingle = true;
Wayne Roberts 0:c3ecf7b252a3 246 rf_send(anytime, 0);
Wayne Roberts 0:c3ecf7b252a3 247
Wayne Roberts 0:c3ecf7b252a3 248 vspfunc("retry%u '%c'\r\n", attemptsRemaining, Radio::radio.tx_buf[1]);
Wayne Roberts 0:c3ecf7b252a3 249 } else {
Wayne Roberts 0:c3ecf7b252a3 250 vspfunc("retry end\r\n");
Wayne Roberts 0:c3ecf7b252a3 251 state = STATE_NONE;
Wayne Roberts 0:c3ecf7b252a3 252 rxCont();
Wayne Roberts 0:c3ecf7b252a3 253 }
Wayne Roberts 0:c3ecf7b252a3 254 }
Wayne Roberts 0:c3ecf7b252a3 255
Wayne Roberts 0:c3ecf7b252a3 256 void sendError(const char* str)
Wayne Roberts 0:c3ecf7b252a3 257 {
Wayne Roberts 0:c3ecf7b252a3 258 uint16_t crc;
Wayne Roberts 0:c3ecf7b252a3 259 char* dest;
Wayne Roberts 0:c3ecf7b252a3 260
Wayne Roberts 0:c3ecf7b252a3 261 tx_buf_len = 0;
Wayne Roberts 0:c3ecf7b252a3 262 Radio::radio.tx_buf[tx_buf_len++] = Radio::radio.rx_buf[0];
Wayne Roberts 0:c3ecf7b252a3 263 Radio::radio.tx_buf[tx_buf_len++] = 'E';
Wayne Roberts 0:c3ecf7b252a3 264 dest = (char*)(&Radio::radio.tx_buf[tx_buf_len]);
Wayne Roberts 0:c3ecf7b252a3 265 strcpy(dest, str);
Wayne Roberts 0:c3ecf7b252a3 266 tx_buf_len += strlen(str);
Wayne Roberts 0:c3ecf7b252a3 267
Wayne Roberts 0:c3ecf7b252a3 268 crc = crc16(Radio::radio.tx_buf, tx_buf_len);
Wayne Roberts 0:c3ecf7b252a3 269 Radio::radio.tx_buf[tx_buf_len++] = crc;
Wayne Roberts 0:c3ecf7b252a3 270 Radio::radio.tx_buf[tx_buf_len++] = crc >> 8;
Wayne Roberts 0:c3ecf7b252a3 271
Wayne Roberts 0:c3ecf7b252a3 272 flags.atTxDoneRxSingle = false;
Wayne Roberts 0:c3ecf7b252a3 273
Wayne Roberts 0:c3ecf7b252a3 274 rf_send(false, 0);
Wayne Roberts 0:c3ecf7b252a3 275 }
Wayne Roberts 0:c3ecf7b252a3 276
Wayne Roberts 0:c3ecf7b252a3 277 void readData()
Wayne Roberts 0:c3ecf7b252a3 278 {
Wayne Roberts 0:c3ecf7b252a3 279 sendData_readLen = read(fd, file_buf, sizeof(file_buf));
Wayne Roberts 0:c3ecf7b252a3 280 if (sendData_readLen < (int)sizeof(file_buf)) {
Wayne Roberts 0:c3ecf7b252a3 281 /* this is last data */
Wayne Roberts 0:c3ecf7b252a3 282 flags.endOfFile = true;
Wayne Roberts 0:c3ecf7b252a3 283 }
Wayne Roberts 0:c3ecf7b252a3 284 }
Wayne Roberts 0:c3ecf7b252a3 285
Wayne Roberts 0:c3ecf7b252a3 286 void sendData()
Wayne Roberts 0:c3ecf7b252a3 287 {
Wayne Roberts 0:c3ecf7b252a3 288 uint16_t crc;
Wayne Roberts 0:c3ecf7b252a3 289 tx_buf_len = 0;
Wayne Roberts 0:c3ecf7b252a3 290 Radio::radio.tx_buf[tx_buf_len++] = ++seq;
Wayne Roberts 0:c3ecf7b252a3 291 Radio::radio.tx_buf[tx_buf_len++] = 'D';
Wayne Roberts 0:c3ecf7b252a3 292
Wayne Roberts 0:c3ecf7b252a3 293 if (sendData_readLen > 0) {
Wayne Roberts 0:c3ecf7b252a3 294 memcpy(Radio::radio.tx_buf + tx_buf_len, file_buf, sendData_readLen);
Wayne Roberts 0:c3ecf7b252a3 295 tx_buf_len += sendData_readLen;
Wayne Roberts 0:c3ecf7b252a3 296 byteCnt += sendData_readLen;
Wayne Roberts 0:c3ecf7b252a3 297 }
Wayne Roberts 0:c3ecf7b252a3 298
Wayne Roberts 0:c3ecf7b252a3 299 crc = crc16(Radio::radio.tx_buf, tx_buf_len);
Wayne Roberts 0:c3ecf7b252a3 300 Radio::radio.tx_buf[tx_buf_len++] = crc;
Wayne Roberts 0:c3ecf7b252a3 301 Radio::radio.tx_buf[tx_buf_len++] = crc >> 8;
Wayne Roberts 0:c3ecf7b252a3 302
Wayne Roberts 0:c3ecf7b252a3 303 flags.atTxDoneRxSingle = true;
Wayne Roberts 0:c3ecf7b252a3 304 attemptsRemaining = MAX_ATTEMPTS;
Wayne Roberts 0:c3ecf7b252a3 305 /*sinceRxDone = */rf_send(false, 0);
Wayne Roberts 0:c3ecf7b252a3 306
Wayne Roberts 0:c3ecf7b252a3 307 if (flags.verbose)
Wayne Roberts 0:c3ecf7b252a3 308 vspfunc("sendTotal:%u ", byteCnt);
Wayne Roberts 0:c3ecf7b252a3 309 }
Wayne Roberts 0:c3ecf7b252a3 310
Wayne Roberts 0:c3ecf7b252a3 311 volatile uint8_t rxSize;
Wayne Roberts 0:c3ecf7b252a3 312
Wayne Roberts 0:c3ecf7b252a3 313 void rxHandler(uint8_t* rxBuf)
Wayne Roberts 0:c3ecf7b252a3 314 {
Wayne Roberts 0:c3ecf7b252a3 315 static const char* pendingError = NULL;
Wayne Roberts 0:c3ecf7b252a3 316 uint16_t calc_crc, rx_crc;
Wayne Roberts 0:c3ecf7b252a3 317 static uint8_t sameCnt;
Wayne Roberts 0:c3ecf7b252a3 318
Wayne Roberts 0:c3ecf7b252a3 319 calc_crc = crc16(rxBuf, rxSize-2);
Wayne Roberts 0:c3ecf7b252a3 320 rx_crc = rxBuf[rxSize-1];
Wayne Roberts 0:c3ecf7b252a3 321 rx_crc <<= 8;
Wayne Roberts 0:c3ecf7b252a3 322 rx_crc += rxBuf[rxSize-2];
Wayne Roberts 0:c3ecf7b252a3 323 if (rx_crc != calc_crc) {
Wayne Roberts 0:c3ecf7b252a3 324 /* when received crc fails, only send NAK when this received message isnt a NAK or ACK */
Wayne Roberts 0:c3ecf7b252a3 325 if (rxBuf[1] == 'Z' || rxBuf[1] == 'D' || rxBuf[1] == 'F') {
Wayne Roberts 0:c3ecf7b252a3 326 sendAck(false, 0);
Wayne Roberts 0:c3ecf7b252a3 327 vspfunc("naking '%c' %u\r\n", rxBuf[1], rxBuf[0]);
Wayne Roberts 0:c3ecf7b252a3 328 }
Wayne Roberts 0:c3ecf7b252a3 329 vspfunc("\e[41mcalc_crc:%04x, rx_crc:%04x\e[0m\r\n", calc_crc, rx_crc);
Wayne Roberts 0:c3ecf7b252a3 330 rf_send(false, 0);
Wayne Roberts 0:c3ecf7b252a3 331 return;
Wayne Roberts 0:c3ecf7b252a3 332 }
Wayne Roberts 0:c3ecf7b252a3 333
Wayne Roberts 0:c3ecf7b252a3 334 if (flags.verbose) {
Wayne Roberts 0:c3ecf7b252a3 335 vspfunc(" rxseq%d->%u '%c' ", prevRxSeq, rxBuf[0], rxBuf[1]);
Wayne Roberts 0:c3ecf7b252a3 336 }
Wayne Roberts 0:c3ecf7b252a3 337
Wayne Roberts 0:c3ecf7b252a3 338 if (rxBuf[1] == 'E') {
Wayne Roberts 0:c3ecf7b252a3 339 rxBuf[rxSize-2] = 0; // null terminate error msg
Wayne Roberts 0:c3ecf7b252a3 340 vspfunc("from remote \"%s\" ", rxBuf + 2);
Wayne Roberts 0:c3ecf7b252a3 341 }
Wayne Roberts 0:c3ecf7b252a3 342
Wayne Roberts 0:c3ecf7b252a3 343 switch (state) {
Wayne Roberts 0:c3ecf7b252a3 344 case STATE_NONE:
Wayne Roberts 0:c3ecf7b252a3 345 if (flags.verbose)
Wayne Roberts 0:c3ecf7b252a3 346 vspfunc("STATE_NONE ");
Wayne Roberts 0:c3ecf7b252a3 347
Wayne Roberts 0:c3ecf7b252a3 348 if (rxBuf[1] == 'R') {
Wayne Roberts 0:c3ecf7b252a3 349 uint16_t rxAddr;
Wayne Roberts 0:c3ecf7b252a3 350 rxBuf[rxSize-2] = 0; // null terminate file name
Wayne Roberts 0:c3ecf7b252a3 351 rxAddr = rxBuf[3];
Wayne Roberts 0:c3ecf7b252a3 352 rxAddr <<= 8;
Wayne Roberts 0:c3ecf7b252a3 353 rxAddr += rxBuf[2];
Wayne Roberts 0:c3ecf7b252a3 354 vspfunc(" addr %04x ", rxAddr);
Wayne Roberts 0:c3ecf7b252a3 355 if (myAddr == rxAddr || BROADCAST_ADDRESS == rxAddr) {
Wayne Roberts 0:c3ecf7b252a3 356 if (flags.verbose)
Wayne Roberts 0:c3ecf7b252a3 357 vspfunc(" open-read %s, ", rxBuf + 4);
Wayne Roberts 0:c3ecf7b252a3 358 fd = open((char*)(rxBuf + 4), O_RDONLY);
Wayne Roberts 0:c3ecf7b252a3 359 if (flags.verbose)
Wayne Roberts 0:c3ecf7b252a3 360 vspfunc("fd:%d ", fd);
Wayne Roberts 0:c3ecf7b252a3 361 if (fd < 0) {
Wayne Roberts 0:c3ecf7b252a3 362 vspfunc("open %s failed\n", (char*)(rxBuf + 2));
Wayne Roberts 0:c3ecf7b252a3 363 sendError(strerror(errno));
Wayne Roberts 0:c3ecf7b252a3 364 break;
Wayne Roberts 0:c3ecf7b252a3 365 }
Wayne Roberts 0:c3ecf7b252a3 366 state = STATE_SEND_FILE;
Wayne Roberts 0:c3ecf7b252a3 367 xferStartAt = t.read_us();
Wayne Roberts 0:c3ecf7b252a3 368 byteCnt = 0;
Wayne Roberts 0:c3ecf7b252a3 369 seq = 0;
Wayne Roberts 0:c3ecf7b252a3 370 flags.endOfFile = false;
Wayne Roberts 0:c3ecf7b252a3 371 attemptsRemaining = MAX_ATTEMPTS;
Wayne Roberts 0:c3ecf7b252a3 372 readData();
Wayne Roberts 0:c3ecf7b252a3 373 sendData();
Wayne Roberts 0:c3ecf7b252a3 374 } else
Wayne Roberts 0:c3ecf7b252a3 375 vspfunc("ignore 'R'\r\n");
Wayne Roberts 0:c3ecf7b252a3 376 } else if (rxBuf[1] == 'F') {
Wayne Roberts 0:c3ecf7b252a3 377 uint16_t rxAddr;
Wayne Roberts 0:c3ecf7b252a3 378 rxBuf[rxSize-2] = 0; // null terminate file name
Wayne Roberts 0:c3ecf7b252a3 379 rxAddr = rxBuf[3];
Wayne Roberts 0:c3ecf7b252a3 380 rxAddr <<= 8;
Wayne Roberts 0:c3ecf7b252a3 381 rxAddr += rxBuf[2];
Wayne Roberts 0:c3ecf7b252a3 382 vspfunc(" addr %04x ", rxAddr);
Wayne Roberts 0:c3ecf7b252a3 383 if (myAddr == rxAddr || BROADCAST_ADDRESS == rxAddr) {
Wayne Roberts 0:c3ecf7b252a3 384 vspfunc("open-write %s ", rxBuf + 4);
Wayne Roberts 0:c3ecf7b252a3 385 fd = open((char*)(rxBuf + 4), O_WRONLY | O_CREAT | O_TRUNC);
Wayne Roberts 0:c3ecf7b252a3 386 vspfunc("fd:%d ", fd);
Wayne Roberts 0:c3ecf7b252a3 387 if (fd < 0) {
Wayne Roberts 0:c3ecf7b252a3 388 sendError(strerror(errno));
Wayne Roberts 0:c3ecf7b252a3 389 } else {
Wayne Roberts 0:c3ecf7b252a3 390 sendAck(true, 0);
Wayne Roberts 0:c3ecf7b252a3 391 xferStartAt = t.read_us();
Wayne Roberts 0:c3ecf7b252a3 392 byteCnt = 0;
Wayne Roberts 0:c3ecf7b252a3 393 state = STATE_GET_FILE;
Wayne Roberts 0:c3ecf7b252a3 394 sameCnt = 0;
Wayne Roberts 0:c3ecf7b252a3 395 }
Wayne Roberts 0:c3ecf7b252a3 396 } else
Wayne Roberts 0:c3ecf7b252a3 397 vspfunc("ignore 'F'\r\n", rxAddr);
Wayne Roberts 0:c3ecf7b252a3 398 } else if (rxBuf[1] == 'Z') {
Wayne Roberts 0:c3ecf7b252a3 399 /* probably previous ack wasnt received of just completed transfer */
Wayne Roberts 0:c3ecf7b252a3 400 sendAck(true, 0);
Wayne Roberts 0:c3ecf7b252a3 401 }
Wayne Roberts 0:c3ecf7b252a3 402 break;
Wayne Roberts 0:c3ecf7b252a3 403 case STATE_GET_FILE:
Wayne Roberts 0:c3ecf7b252a3 404 vspfunc("STATE_GET_FILE fd%d ", fd);
Wayne Roberts 0:c3ecf7b252a3 405 if (rxBuf[1] == 'D') {
Wayne Roberts 0:c3ecf7b252a3 406 if (prevRxSeq+1 == rxBuf[0]) {
Wayne Roberts 0:c3ecf7b252a3 407 uint8_t len = rxSize - 4;
Wayne Roberts 0:c3ecf7b252a3 408 int fop_len = write(fd, rxBuf + 2, len);
Wayne Roberts 0:c3ecf7b252a3 409 if (fop_len < 0) {
Wayne Roberts 0:c3ecf7b252a3 410 sendError(strerror(errno));
Wayne Roberts 0:c3ecf7b252a3 411 vspfunc(strerror(errno));
Wayne Roberts 0:c3ecf7b252a3 412 } else if (fop_len < len) {
Wayne Roberts 0:c3ecf7b252a3 413 sendError("short-write");
Wayne Roberts 0:c3ecf7b252a3 414 vspfunc("write %d vs %d", fop_len, len);
Wayne Roberts 0:c3ecf7b252a3 415 } else {
Wayne Roberts 0:c3ecf7b252a3 416 byteCnt += fop_len;
Wayne Roberts 0:c3ecf7b252a3 417 sendAck(true, 0);
Wayne Roberts 0:c3ecf7b252a3 418 vspfunc("ok total %u ", byteCnt);
Wayne Roberts 0:c3ecf7b252a3 419 }
Wayne Roberts 0:c3ecf7b252a3 420 } else if (prevRxSeq == rxBuf[0]) {
Wayne Roberts 0:c3ecf7b252a3 421 vspfunc("\e[43mrepeat %u\e[0m", rxBuf[0]);
Wayne Roberts 0:c3ecf7b252a3 422 /* ignore do nothing, ack to get next */
Wayne Roberts 0:c3ecf7b252a3 423 sendAck(true, 0);
Wayne Roberts 0:c3ecf7b252a3 424 } else {
Wayne Roberts 0:c3ecf7b252a3 425 vspfunc("\e[41msequence %u %u\e[0m", prevRxSeq, rxBuf[0]);
Wayne Roberts 0:c3ecf7b252a3 426 sendError("sequence");
Wayne Roberts 0:c3ecf7b252a3 427 state = STATE_NONE;
Wayne Roberts 0:c3ecf7b252a3 428 close(fd);
Wayne Roberts 0:c3ecf7b252a3 429 }
Wayne Roberts 0:c3ecf7b252a3 430 } else if (rxBuf[1] == 'Z') {
Wayne Roberts 0:c3ecf7b252a3 431 unsigned duration_us;
Wayne Roberts 0:c3ecf7b252a3 432 float secs;
Wayne Roberts 0:c3ecf7b252a3 433 sendAck(true, 0);
Wayne Roberts 0:c3ecf7b252a3 434 duration_us = t.read_us() - xferStartAt;
Wayne Roberts 0:c3ecf7b252a3 435 secs = duration_us / 1000000.0;
Wayne Roberts 0:c3ecf7b252a3 436 close(fd);
Wayne Roberts 0:c3ecf7b252a3 437 vspfunc("EOF total:%u = %.1f bytes/sec\r\n", byteCnt , byteCnt / secs);
Wayne Roberts 0:c3ecf7b252a3 438 state = STATE_NONE;
Wayne Roberts 0:c3ecf7b252a3 439 } else if (rxBuf[1] == 'F' && rxBuf[0] == 0) { /* check filename? */
Wayne Roberts 0:c3ecf7b252a3 440 if (prevRxSeq == rxBuf[0])
Wayne Roberts 0:c3ecf7b252a3 441 sameCnt++;
Wayne Roberts 0:c3ecf7b252a3 442 else
Wayne Roberts 0:c3ecf7b252a3 443 sameCnt = 0;
Wayne Roberts 0:c3ecf7b252a3 444
Wayne Roberts 0:c3ecf7b252a3 445 vspfunc("didnt-get-F-ack fd:%d ", fd);
Wayne Roberts 0:c3ecf7b252a3 446 sendAck(true, sameCnt * add_txDelay_retry);
Wayne Roberts 0:c3ecf7b252a3 447 }
Wayne Roberts 0:c3ecf7b252a3 448 break;
Wayne Roberts 0:c3ecf7b252a3 449 case STATE_SEND_FILE:
Wayne Roberts 0:c3ecf7b252a3 450 if (flags.verbose)
Wayne Roberts 0:c3ecf7b252a3 451 vspfunc("STATE_SEND_FILE ");
Wayne Roberts 0:c3ecf7b252a3 452
Wayne Roberts 0:c3ecf7b252a3 453 if (rxBuf[1] == 'Y') {
Wayne Roberts 0:c3ecf7b252a3 454 if (flags.endOfFile) {
Wayne Roberts 0:c3ecf7b252a3 455 uint16_t crc;
Wayne Roberts 0:c3ecf7b252a3 456 tx_buf_len = 0;
Wayne Roberts 0:c3ecf7b252a3 457 Radio::radio.tx_buf[tx_buf_len++] = ++seq;
Wayne Roberts 0:c3ecf7b252a3 458 Radio::radio.tx_buf[tx_buf_len++] = 'Z';
Wayne Roberts 0:c3ecf7b252a3 459 crc = crc16(Radio::radio.tx_buf, tx_buf_len);
Wayne Roberts 0:c3ecf7b252a3 460 Radio::radio.tx_buf[tx_buf_len++] = crc;
Wayne Roberts 0:c3ecf7b252a3 461 Radio::radio.tx_buf[tx_buf_len++] = crc >> 8;
Wayne Roberts 0:c3ecf7b252a3 462
Wayne Roberts 0:c3ecf7b252a3 463 flags.atTxDoneRxSingle = true;
Wayne Roberts 0:c3ecf7b252a3 464 attemptsRemaining = MAX_ATTEMPTS;
Wayne Roberts 0:c3ecf7b252a3 465 /*sinceRxDone = */rf_send(false, 0);
Wayne Roberts 0:c3ecf7b252a3 466 close(fd);
Wayne Roberts 0:c3ecf7b252a3 467 state = STATE_FILE_END;
Wayne Roberts 0:c3ecf7b252a3 468 } else {
Wayne Roberts 0:c3ecf7b252a3 469 readData();
Wayne Roberts 0:c3ecf7b252a3 470 sendData();
Wayne Roberts 0:c3ecf7b252a3 471 }
Wayne Roberts 0:c3ecf7b252a3 472 } else if (rxBuf[1] == 'R') {
Wayne Roberts 0:c3ecf7b252a3 473 /* peer didnt get ack for 'R' */
Wayne Roberts 0:c3ecf7b252a3 474 retry(false);
Wayne Roberts 0:c3ecf7b252a3 475 } else if (rxBuf[1] == 'N') {
Wayne Roberts 0:c3ecf7b252a3 476 /* NAK, peer crc fail */
Wayne Roberts 0:c3ecf7b252a3 477 retry(false);
Wayne Roberts 0:c3ecf7b252a3 478 } else if (rxBuf[1] == 'E') {
Wayne Roberts 0:c3ecf7b252a3 479 state = STATE_NONE;
Wayne Roberts 0:c3ecf7b252a3 480 close(fd);
Wayne Roberts 0:c3ecf7b252a3 481 rxCont();
Wayne Roberts 0:c3ecf7b252a3 482 vspfunc("xfer-ended\r\n");
Wayne Roberts 0:c3ecf7b252a3 483 }
Wayne Roberts 0:c3ecf7b252a3 484 break;
Wayne Roberts 0:c3ecf7b252a3 485 case STATE_FILE_END:
Wayne Roberts 0:c3ecf7b252a3 486 vspfunc("STATE_FILE_END ");
Wayne Roberts 0:c3ecf7b252a3 487 if (rxBuf[1] == 'Y') {
Wayne Roberts 0:c3ecf7b252a3 488 unsigned duration_us = t.read_us() - xferStartAt;
Wayne Roberts 0:c3ecf7b252a3 489 float secs = duration_us / 1000000.0;
Wayne Roberts 0:c3ecf7b252a3 490 vspfunc("total:%u = %.1f bytes/sec\r\n", byteCnt, byteCnt / secs);
Wayne Roberts 0:c3ecf7b252a3 491 state = STATE_NONE;
Wayne Roberts 0:c3ecf7b252a3 492 rxCont();
Wayne Roberts 0:c3ecf7b252a3 493 } else
Wayne Roberts 0:c3ecf7b252a3 494 vspfunc("badack:%c ", rxBuf[1]);
Wayne Roberts 0:c3ecf7b252a3 495 break;
Wayne Roberts 0:c3ecf7b252a3 496 case STATE_RX_COMPARE:
Wayne Roberts 0:c3ecf7b252a3 497 if (flags.verbose)
Wayne Roberts 0:c3ecf7b252a3 498 vspfunc("STATE_RX_COMPARE ");
Wayne Roberts 0:c3ecf7b252a3 499
Wayne Roberts 0:c3ecf7b252a3 500 if (pendingError) {
Wayne Roberts 0:c3ecf7b252a3 501 sendError(pendingError);
Wayne Roberts 0:c3ecf7b252a3 502 vspfunc("sentErr:%s ", pendingError);
Wayne Roberts 0:c3ecf7b252a3 503 pendingError = NULL;
Wayne Roberts 0:c3ecf7b252a3 504 state = STATE_NONE;
Wayne Roberts 0:c3ecf7b252a3 505 break;
Wayne Roberts 0:c3ecf7b252a3 506 }
Wayne Roberts 0:c3ecf7b252a3 507
Wayne Roberts 0:c3ecf7b252a3 508 if (rxBuf[1] == 'D') {
Wayne Roberts 0:c3ecf7b252a3 509 if (prevRxSeq == -1 || rxBuf[0] > prevRxSeq) {
Wayne Roberts 0:c3ecf7b252a3 510 int ret, rxLen = rxSize - 4;
Wayne Roberts 0:c3ecf7b252a3 511 sameCnt = 0;
Wayne Roberts 0:c3ecf7b252a3 512 ret = read(fd, file_buf, rxLen);
Wayne Roberts 0:c3ecf7b252a3 513 if (ret < 0) {
Wayne Roberts 0:c3ecf7b252a3 514 pendingError = "read fail";
Wayne Roberts 0:c3ecf7b252a3 515 vspfunc("readFail");
Wayne Roberts 0:c3ecf7b252a3 516 } else if (ret < rxLen) {
Wayne Roberts 0:c3ecf7b252a3 517 pendingError = "read short";
Wayne Roberts 0:c3ecf7b252a3 518 vspfunc("readShort");
Wayne Roberts 0:c3ecf7b252a3 519 } else if (memcmp(file_buf, rxBuf + 2, ret) == 0) {
Wayne Roberts 0:c3ecf7b252a3 520 sendAck(true, 0);
Wayne Roberts 0:c3ecf7b252a3 521 byteCnt += ret;
Wayne Roberts 0:c3ecf7b252a3 522 if (flags.verbose)
Wayne Roberts 0:c3ecf7b252a3 523 vspfunc("cmpTotal:%u ", byteCnt);
Wayne Roberts 0:c3ecf7b252a3 524 } else {
Wayne Roberts 0:c3ecf7b252a3 525 int n;
Wayne Roberts 0:c3ecf7b252a3 526 pendingError = "memcmp fail";
Wayne Roberts 0:c3ecf7b252a3 527 vspfunc("memcmp");
Wayne Roberts 0:c3ecf7b252a3 528 vspfunc("\r\nrxBuf:\r\n");
Wayne Roberts 0:c3ecf7b252a3 529 for (n = 0; n < ret; n++) {
Wayne Roberts 0:c3ecf7b252a3 530 if (rxBuf[n+2] != file_buf[n])
Wayne Roberts 0:c3ecf7b252a3 531 vspfunc("\e[41m");
Wayne Roberts 0:c3ecf7b252a3 532 vspfunc("%02x ", rxBuf[n+2]);
Wayne Roberts 0:c3ecf7b252a3 533 if (rxBuf[n+2] != file_buf[n])
Wayne Roberts 0:c3ecf7b252a3 534 vspfunc("\e[0m");
Wayne Roberts 0:c3ecf7b252a3 535 if ((n & 0xf) == 0xf)
Wayne Roberts 0:c3ecf7b252a3 536 vspfunc("\r\n");
Wayne Roberts 0:c3ecf7b252a3 537 }
Wayne Roberts 0:c3ecf7b252a3 538 vspfunc("\r\nfile_buf:\r\n");
Wayne Roberts 0:c3ecf7b252a3 539 for (n = 0; n < ret; n++) {
Wayne Roberts 0:c3ecf7b252a3 540 if (rxBuf[n+2] != file_buf[n])
Wayne Roberts 0:c3ecf7b252a3 541 vspfunc("\e[41m");
Wayne Roberts 0:c3ecf7b252a3 542 vspfunc("%02x ", file_buf[n]);
Wayne Roberts 0:c3ecf7b252a3 543 if (rxBuf[n+2] != file_buf[n])
Wayne Roberts 0:c3ecf7b252a3 544 vspfunc("\e[0m");
Wayne Roberts 0:c3ecf7b252a3 545 if ((n & 0xf) == 0xf)
Wayne Roberts 0:c3ecf7b252a3 546 vspfunc("\r\n");
Wayne Roberts 0:c3ecf7b252a3 547 }
Wayne Roberts 0:c3ecf7b252a3 548 vspfunc("\r\n");
Wayne Roberts 0:c3ecf7b252a3 549 }
Wayne Roberts 0:c3ecf7b252a3 550 } else {
Wayne Roberts 0:c3ecf7b252a3 551 if (rxBuf[0] == prevRxSeq)
Wayne Roberts 0:c3ecf7b252a3 552 sameCnt++;
Wayne Roberts 0:c3ecf7b252a3 553 else
Wayne Roberts 0:c3ecf7b252a3 554 sameCnt = 0;
Wayne Roberts 0:c3ecf7b252a3 555
Wayne Roberts 0:c3ecf7b252a3 556 sendAck(true, sameCnt * add_txDelay_retry);
Wayne Roberts 0:c3ecf7b252a3 557 vspfunc("repeat ");
Wayne Roberts 0:c3ecf7b252a3 558 }
Wayne Roberts 0:c3ecf7b252a3 559 } else if (rxBuf[1] == 'Z') {
Wayne Roberts 0:c3ecf7b252a3 560 unsigned duration_us = t.read_us() - xferStartAt;
Wayne Roberts 0:c3ecf7b252a3 561 float secs = duration_us / 1000000.0;
Wayne Roberts 0:c3ecf7b252a3 562 vspfunc("EOF total:%u = %.1f bytes/sec\r\n", byteCnt, byteCnt / secs);
Wayne Roberts 0:c3ecf7b252a3 563 close(fd);
Wayne Roberts 0:c3ecf7b252a3 564 sendAck(true, 0);
Wayne Roberts 0:c3ecf7b252a3 565 state = STATE_NONE;
Wayne Roberts 0:c3ecf7b252a3 566 } else if (rxBuf[1] == 'E') {
Wayne Roberts 0:c3ecf7b252a3 567 sendAck(true, 0);
Wayne Roberts 0:c3ecf7b252a3 568 state = STATE_NONE;
Wayne Roberts 0:c3ecf7b252a3 569 }
Wayne Roberts 0:c3ecf7b252a3 570 break;
Wayne Roberts 0:c3ecf7b252a3 571 } // ..switch (state)
Wayne Roberts 0:c3ecf7b252a3 572
Wayne Roberts 0:c3ecf7b252a3 573 prevRxSeq = rxBuf[0];
Wayne Roberts 0:c3ecf7b252a3 574 if (flags.verbose)
Wayne Roberts 0:c3ecf7b252a3 575 vspfunc("\r\n");
Wayne Roberts 0:c3ecf7b252a3 576 }
Wayne Roberts 0:c3ecf7b252a3 577
Wayne Roberts 0:c3ecf7b252a3 578 void rxDoneCB(uint8_t size, float rssi, float snr)
Wayne Roberts 0:c3ecf7b252a3 579 {
Wayne Roberts 0:c3ecf7b252a3 580 rxDoneAt = t.read_us();
Wayne Roberts 0:c3ecf7b252a3 581
Wayne Roberts 0:c3ecf7b252a3 582 if (rxSize != 0)
Wayne Roberts 0:c3ecf7b252a3 583 vspfunc("\e[41mrxoverrun\e[0m ");
Wayne Roberts 0:c3ecf7b252a3 584 else {
Wayne Roberts 0:c3ecf7b252a3 585 rxSize = size;
Wayne Roberts 0:c3ecf7b252a3 586 if (flags.verbose)
Wayne Roberts 0:c3ecf7b252a3 587 vspfunc("rxDone ");
Wayne Roberts 0:c3ecf7b252a3 588 }
Wayne Roberts 0:c3ecf7b252a3 589 /* cant TX here because irq flags cleared after returning */
Wayne Roberts 0:c3ecf7b252a3 590 }
Wayne Roberts 0:c3ecf7b252a3 591
Wayne Roberts 0:c3ecf7b252a3 592 void rxTimeoutCB()
Wayne Roberts 0:c3ecf7b252a3 593 {
Wayne Roberts 0:c3ecf7b252a3 594 vspfunc("\e[33mrxTimeout ");
Wayne Roberts 0:c3ecf7b252a3 595
Wayne Roberts 0:c3ecf7b252a3 596 if (state != STATE_NONE)
Wayne Roberts 0:c3ecf7b252a3 597 flags.callRetry = true;
Wayne Roberts 0:c3ecf7b252a3 598 else {
Wayne Roberts 0:c3ecf7b252a3 599 vspfunc("spurious");
Wayne Roberts 0:c3ecf7b252a3 600 flags.rxContStart = true;
Wayne Roberts 0:c3ecf7b252a3 601 }
Wayne Roberts 0:c3ecf7b252a3 602
Wayne Roberts 0:c3ecf7b252a3 603 vspfunc("\e[0m ");
Wayne Roberts 0:c3ecf7b252a3 604 }
Wayne Roberts 0:c3ecf7b252a3 605
Wayne Roberts 0:c3ecf7b252a3 606 const RadioEvents_t rev = {
Wayne Roberts 0:c3ecf7b252a3 607 /* Dio0_top_half */ NULL,
Wayne Roberts 0:c3ecf7b252a3 608 /* TxDone_topHalf */ txDoneCB_topHalf, // called in ISR context
Wayne Roberts 0:c3ecf7b252a3 609 /* TxDone_botHalf */ txDoneCB_botHalf, // called from service()
Wayne Roberts 0:c3ecf7b252a3 610 /* TxTimeout */ NULL,
Wayne Roberts 0:c3ecf7b252a3 611 /* RxDone */ rxDoneCB, // called from service()
Wayne Roberts 0:c3ecf7b252a3 612 /* RxTimeout */ rxTimeoutCB, // called from service()
Wayne Roberts 0:c3ecf7b252a3 613 /* RxError */ NULL,
Wayne Roberts 0:c3ecf7b252a3 614 /* FhssChangeChannel */NULL,
Wayne Roberts 0:c3ecf7b252a3 615 /* CadDone */ NULL
Wayne Roberts 0:c3ecf7b252a3 616 };
Wayne Roberts 0:c3ecf7b252a3 617
Wayne Roberts 0:c3ecf7b252a3 618 char pcbuf[64];
Wayne Roberts 0:c3ecf7b252a3 619 volatile int pcbuf_len;
Wayne Roberts 0:c3ecf7b252a3 620 volatile uint8_t pcbuf_idx;
Wayne Roberts 0:c3ecf7b252a3 621
Wayne Roberts 0:c3ecf7b252a3 622 typedef struct {
Wayne Roberts 0:c3ecf7b252a3 623 const char* const cmd;
Wayne Roberts 0:c3ecf7b252a3 624 void (*handler)(uint8_t args_at);
Wayne Roberts 0:c3ecf7b252a3 625 const char* const arg_descr;
Wayne Roberts 0:c3ecf7b252a3 626 const char* const description;
Wayne Roberts 0:c3ecf7b252a3 627 } menu_item_t;
Wayne Roberts 0:c3ecf7b252a3 628
Wayne Roberts 0:c3ecf7b252a3 629 void cmd_help(uint8_t);
Wayne Roberts 0:c3ecf7b252a3 630
Wayne Roberts 0:c3ecf7b252a3 631 void cmd_print_status(uint8_t idx)
Wayne Roberts 0:c3ecf7b252a3 632 {
Wayne Roberts 0:c3ecf7b252a3 633 pc.printf("state%u ", state);
Wayne Roberts 0:c3ecf7b252a3 634
Wayne Roberts 0:c3ecf7b252a3 635 if (flags.atTxDoneRxSingle)
Wayne Roberts 0:c3ecf7b252a3 636 pc.printf("flags.atTxDoneRxSingle ");
Wayne Roberts 0:c3ecf7b252a3 637 if (flags.endOfFile)
Wayne Roberts 0:c3ecf7b252a3 638 pc.printf("flags.endOfFile ");
Wayne Roberts 0:c3ecf7b252a3 639
Wayne Roberts 0:c3ecf7b252a3 640 print_lora_status();
Wayne Roberts 0:c3ecf7b252a3 641 }
Wayne Roberts 0:c3ecf7b252a3 642
Wayne Roberts 0:c3ecf7b252a3 643 void cmd_stby(uint8_t argsAt)
Wayne Roberts 0:c3ecf7b252a3 644 {
Wayne Roberts 0:c3ecf7b252a3 645 Radio::Standby();
Wayne Roberts 0:c3ecf7b252a3 646 #ifdef RX_DBG_PIN
Wayne Roberts 0:c3ecf7b252a3 647 rx_dbg.input();
Wayne Roberts 0:c3ecf7b252a3 648 #endif /* RX_DBG_PIN */
Wayne Roberts 0:c3ecf7b252a3 649 pc.printf("standby\r\n");
Wayne Roberts 0:c3ecf7b252a3 650 }
Wayne Roberts 0:c3ecf7b252a3 651
Wayne Roberts 0:c3ecf7b252a3 652 void cmd_verbose(uint8_t args_at)
Wayne Roberts 0:c3ecf7b252a3 653 {
Wayne Roberts 0:c3ecf7b252a3 654 flags.verbose ^= 1;
Wayne Roberts 0:c3ecf7b252a3 655 pc.printf("verbose:%u\r\n", flags.verbose);
Wayne Roberts 0:c3ecf7b252a3 656 }
Wayne Roberts 0:c3ecf7b252a3 657
Wayne Roberts 0:c3ecf7b252a3 658 void cmd_pt(uint8_t args_at)
Wayne Roberts 0:c3ecf7b252a3 659 {
Wayne Roberts 0:c3ecf7b252a3 660 char foo[32];
Wayne Roberts 0:c3ecf7b252a3 661 unsigned cnt, n;
Wayne Roberts 0:c3ecf7b252a3 662 if (sscanf(pcbuf + args_at, "%u", &cnt) == 1) {
Wayne Roberts 0:c3ecf7b252a3 663 for (n = 0; n < cnt; n++) {
Wayne Roberts 0:c3ecf7b252a3 664 foo[n] = 'a' + n;
Wayne Roberts 0:c3ecf7b252a3 665 }
Wayne Roberts 0:c3ecf7b252a3 666 for (n = 0; n < cnt; n++) {
Wayne Roberts 0:c3ecf7b252a3 667 vspfunc("in%u: test %s\r\n", printBuf_in, foo);
Wayne Roberts 0:c3ecf7b252a3 668 //vspfunc("in%u: test\r\n", printBuf_in);
Wayne Roberts 0:c3ecf7b252a3 669 }
Wayne Roberts 0:c3ecf7b252a3 670 } else
Wayne Roberts 0:c3ecf7b252a3 671 vspfunc("give count number\r\n");
Wayne Roberts 0:c3ecf7b252a3 672 }
Wayne Roberts 0:c3ecf7b252a3 673
Wayne Roberts 0:c3ecf7b252a3 674 void cmd_peerAddr(uint8_t args_at)
Wayne Roberts 0:c3ecf7b252a3 675 {
Wayne Roberts 0:c3ecf7b252a3 676 unsigned a;
Wayne Roberts 0:c3ecf7b252a3 677 if (sscanf(pcbuf + args_at, "%x", &a) == 1) {
Wayne Roberts 0:c3ecf7b252a3 678 peerAddr = a;
Wayne Roberts 0:c3ecf7b252a3 679 }
Wayne Roberts 0:c3ecf7b252a3 680 pc.printf("peerAddr:%04x\r\n", peerAddr);
Wayne Roberts 0:c3ecf7b252a3 681 }
Wayne Roberts 0:c3ecf7b252a3 682
Wayne Roberts 0:c3ecf7b252a3 683 void cmd_myAddr(uint8_t args_at)
Wayne Roberts 0:c3ecf7b252a3 684 {
Wayne Roberts 0:c3ecf7b252a3 685 unsigned a;
Wayne Roberts 0:c3ecf7b252a3 686 if (sscanf(pcbuf + args_at, "%x", &a) == 1) {
Wayne Roberts 0:c3ecf7b252a3 687 myAddr = a;
Wayne Roberts 0:c3ecf7b252a3 688 }
Wayne Roberts 0:c3ecf7b252a3 689 pc.printf("myAddr:%04x\r\n", myAddr);
Wayne Roberts 0:c3ecf7b252a3 690 }
Wayne Roberts 0:c3ecf7b252a3 691
Wayne Roberts 0:c3ecf7b252a3 692 void cmd_ls(uint8_t args_at)
Wayne Roberts 0:c3ecf7b252a3 693 {
Wayne Roberts 0:c3ecf7b252a3 694 int err;
Wayne Roberts 0:c3ecf7b252a3 695
Wayne Roberts 0:c3ecf7b252a3 696 // Display the root directory
Wayne Roberts 0:c3ecf7b252a3 697 pc.printf("Opening the root directory... ");
Wayne Roberts 0:c3ecf7b252a3 698 fflush(stdout);
Wayne Roberts 0:c3ecf7b252a3 699 DIR *d = opendir("/fs/");
Wayne Roberts 0:c3ecf7b252a3 700 pc.printf("%s\r\n", (!d ? "Fail :(" : "OK"));
Wayne Roberts 0:c3ecf7b252a3 701 if (!d) {
Wayne Roberts 0:c3ecf7b252a3 702 error("error: %s (%d)\r\n", strerror(errno), -errno);
Wayne Roberts 0:c3ecf7b252a3 703 }
Wayne Roberts 0:c3ecf7b252a3 704
Wayne Roberts 0:c3ecf7b252a3 705 pc.printf("root directory:\r\n");
Wayne Roberts 0:c3ecf7b252a3 706 while (true) {
Wayne Roberts 0:c3ecf7b252a3 707 struct stat st;
Wayne Roberts 0:c3ecf7b252a3 708 struct dirent *e = readdir(d);
Wayne Roberts 0:c3ecf7b252a3 709 if (!e) {
Wayne Roberts 0:c3ecf7b252a3 710 break;
Wayne Roberts 0:c3ecf7b252a3 711 }
Wayne Roberts 0:c3ecf7b252a3 712 fs.stat(e->d_name, &st);
Wayne Roberts 0:c3ecf7b252a3 713
Wayne Roberts 0:c3ecf7b252a3 714 pc.printf(" %s\t%lu\r\n", e->d_name, st.st_size);
Wayne Roberts 0:c3ecf7b252a3 715 }
Wayne Roberts 0:c3ecf7b252a3 716
Wayne Roberts 0:c3ecf7b252a3 717 //pc.printf("Closing the root directory... ");
Wayne Roberts 0:c3ecf7b252a3 718 fflush(stdout);
Wayne Roberts 0:c3ecf7b252a3 719 err = closedir(d);
Wayne Roberts 0:c3ecf7b252a3 720 pc.printf("%s\r\n", (err < 0 ? "Fail :(" : "OK"));
Wayne Roberts 0:c3ecf7b252a3 721 if (err < 0) {
Wayne Roberts 0:c3ecf7b252a3 722 error("error: %s (%d)\r\n", strerror(errno), -errno);
Wayne Roberts 0:c3ecf7b252a3 723 }
Wayne Roberts 0:c3ecf7b252a3 724 }
Wayne Roberts 0:c3ecf7b252a3 725
Wayne Roberts 0:c3ecf7b252a3 726 void cmd_md(uint8_t args_at)
Wayne Roberts 0:c3ecf7b252a3 727 {
Wayne Roberts 0:c3ecf7b252a3 728 unsigned us;
Wayne Roberts 0:c3ecf7b252a3 729
Wayne Roberts 0:c3ecf7b252a3 730 if (sscanf(pcbuf + args_at, "%u", &us) == 1) {
Wayne Roberts 0:c3ecf7b252a3 731 txMinDelay_us = us;
Wayne Roberts 0:c3ecf7b252a3 732 }
Wayne Roberts 0:c3ecf7b252a3 733 pc.printf("txMinDelay_us:%u\r\n", txMinDelay_us);
Wayne Roberts 0:c3ecf7b252a3 734 }
Wayne Roberts 0:c3ecf7b252a3 735
Wayne Roberts 0:c3ecf7b252a3 736 void cmd_cat(uint8_t argsAt)
Wayne Roberts 0:c3ecf7b252a3 737 {
Wayne Roberts 0:c3ecf7b252a3 738 unsigned ofs;
Wayne Roberts 0:c3ecf7b252a3 739 uint8_t buf[16];
Wayne Roberts 0:c3ecf7b252a3 740 int ret, fd = open(pcbuf + argsAt, O_RDONLY);
Wayne Roberts 0:c3ecf7b252a3 741 if (fd < 0) {
Wayne Roberts 1:319ef808aaa4 742 pc.printf("open %s failed\r\n", pcbuf + argsAt);
Wayne Roberts 0:c3ecf7b252a3 743 return;
Wayne Roberts 0:c3ecf7b252a3 744 }
Wayne Roberts 0:c3ecf7b252a3 745
Wayne Roberts 0:c3ecf7b252a3 746 ofs = 0;
Wayne Roberts 0:c3ecf7b252a3 747 do {
Wayne Roberts 0:c3ecf7b252a3 748 int n;
Wayne Roberts 0:c3ecf7b252a3 749 ret = read(fd, buf, sizeof(buf));
Wayne Roberts 0:c3ecf7b252a3 750 if (ret < 0) {
Wayne Roberts 0:c3ecf7b252a3 751 pc.printf("read failed\n");
Wayne Roberts 0:c3ecf7b252a3 752 return;
Wayne Roberts 0:c3ecf7b252a3 753 }
Wayne Roberts 0:c3ecf7b252a3 754 pc.printf("%04x: ", ofs);
Wayne Roberts 0:c3ecf7b252a3 755 for (n = 0; n < ret; n++)
Wayne Roberts 0:c3ecf7b252a3 756 pc.printf("%02x ", buf[n]);
Wayne Roberts 0:c3ecf7b252a3 757 pc.printf(" ");
Wayne Roberts 0:c3ecf7b252a3 758 for (n = 0; n < ret; n++) {
Wayne Roberts 0:c3ecf7b252a3 759 if (buf[n] >= ' ')
Wayne Roberts 0:c3ecf7b252a3 760 pc.putc(buf[n]);
Wayne Roberts 0:c3ecf7b252a3 761 else
Wayne Roberts 0:c3ecf7b252a3 762 pc.putc('.');
Wayne Roberts 0:c3ecf7b252a3 763 }
Wayne Roberts 0:c3ecf7b252a3 764 pc.putc('\r');
Wayne Roberts 0:c3ecf7b252a3 765 pc.putc('\n');
Wayne Roberts 0:c3ecf7b252a3 766
Wayne Roberts 0:c3ecf7b252a3 767 ofs += ret;
Wayne Roberts 0:c3ecf7b252a3 768 if (pcbuf_len < 0) {
Wayne Roberts 0:c3ecf7b252a3 769 pcbuf_len = 0;
Wayne Roberts 0:c3ecf7b252a3 770 break;
Wayne Roberts 0:c3ecf7b252a3 771 }
Wayne Roberts 0:c3ecf7b252a3 772 if ((ofs & 0xff) == 0) {
Wayne Roberts 0:c3ecf7b252a3 773 uint8_t x = pcbuf_idx;
Wayne Roberts 0:c3ecf7b252a3 774 pc.printf("hitkey:");
Wayne Roberts 0:c3ecf7b252a3 775 while (x == pcbuf_idx && pcbuf_len >= 0)
Wayne Roberts 0:c3ecf7b252a3 776 ;
Wayne Roberts 0:c3ecf7b252a3 777 pc.printf("\r\n");
Wayne Roberts 0:c3ecf7b252a3 778 }
Wayne Roberts 0:c3ecf7b252a3 779 } while (ret > 0);
Wayne Roberts 0:c3ecf7b252a3 780
Wayne Roberts 0:c3ecf7b252a3 781 close(fd);
Wayne Roberts 0:c3ecf7b252a3 782 }
Wayne Roberts 0:c3ecf7b252a3 783
Wayne Roberts 0:c3ecf7b252a3 784 void cmd_rm(uint8_t args_at)
Wayne Roberts 0:c3ecf7b252a3 785 {
Wayne Roberts 0:c3ecf7b252a3 786 int ret = fs.remove(pcbuf + args_at);
Wayne Roberts 0:c3ecf7b252a3 787 if (ret < 0)
Wayne Roberts 0:c3ecf7b252a3 788 perror("unlink");
Wayne Roberts 0:c3ecf7b252a3 789 else
Wayne Roberts 0:c3ecf7b252a3 790 pc.printf("delete %s ok\r\n", pcbuf + args_at);
Wayne Roberts 0:c3ecf7b252a3 791 }
Wayne Roberts 0:c3ecf7b252a3 792
Wayne Roberts 0:c3ecf7b252a3 793 void cmd_rx(uint8_t argsAt)
Wayne Roberts 0:c3ecf7b252a3 794 {
Wayne Roberts 0:c3ecf7b252a3 795 rxCont();
Wayne Roberts 0:c3ecf7b252a3 796 pc.printf("rx start\r\n");
Wayne Roberts 0:c3ecf7b252a3 797 }
Wayne Roberts 0:c3ecf7b252a3 798
Wayne Roberts 0:c3ecf7b252a3 799 void cmd_send(uint8_t argsAt)
Wayne Roberts 0:c3ecf7b252a3 800 {
Wayne Roberts 0:c3ecf7b252a3 801 char* dest;
Wayne Roberts 0:c3ecf7b252a3 802 uint8_t txlen;
Wayne Roberts 0:c3ecf7b252a3 803 uint16_t crc;
Wayne Roberts 0:c3ecf7b252a3 804
Wayne Roberts 1:319ef808aaa4 805 if (fd > 0)
Wayne Roberts 1:319ef808aaa4 806 close(fd);
Wayne Roberts 1:319ef808aaa4 807
Wayne Roberts 0:c3ecf7b252a3 808 fd = open(pcbuf + argsAt, O_RDONLY);
Wayne Roberts 0:c3ecf7b252a3 809 if (fd < 0) {
Wayne Roberts 1:319ef808aaa4 810 pc.printf("open %s failed\r\n", pcbuf + argsAt);
Wayne Roberts 0:c3ecf7b252a3 811 return;
Wayne Roberts 0:c3ecf7b252a3 812 }
Wayne Roberts 0:c3ecf7b252a3 813 txlen = strlen(pcbuf + argsAt);
Wayne Roberts 0:c3ecf7b252a3 814
Wayne Roberts 0:c3ecf7b252a3 815 seq = 0;
Wayne Roberts 0:c3ecf7b252a3 816 prevRxSeq = -1;
Wayne Roberts 0:c3ecf7b252a3 817 Radio::radio.tx_buf[0] = seq;
Wayne Roberts 0:c3ecf7b252a3 818 Radio::radio.tx_buf[1] = 'F';
Wayne Roberts 0:c3ecf7b252a3 819 Radio::radio.tx_buf[2] = peerAddr;
Wayne Roberts 0:c3ecf7b252a3 820 Radio::radio.tx_buf[3] = peerAddr >> 8;
Wayne Roberts 0:c3ecf7b252a3 821
Wayne Roberts 0:c3ecf7b252a3 822 dest = (char*)(&Radio::radio.tx_buf[4]);
Wayne Roberts 0:c3ecf7b252a3 823 strcpy(dest, pcbuf + argsAt);
Wayne Roberts 0:c3ecf7b252a3 824 tx_buf_len = txlen + 4;
Wayne Roberts 0:c3ecf7b252a3 825
Wayne Roberts 0:c3ecf7b252a3 826 crc = crc16(Radio::radio.tx_buf, tx_buf_len);
Wayne Roberts 0:c3ecf7b252a3 827 Radio::radio.tx_buf[tx_buf_len++] = crc;
Wayne Roberts 0:c3ecf7b252a3 828 Radio::radio.tx_buf[tx_buf_len++] = crc >> 8;
Wayne Roberts 0:c3ecf7b252a3 829
Wayne Roberts 0:c3ecf7b252a3 830 byteCnt = 0;
Wayne Roberts 0:c3ecf7b252a3 831 attemptsRemaining = MAX_ATTEMPTS;
Wayne Roberts 0:c3ecf7b252a3 832 flags.endOfFile = false;
Wayne Roberts 0:c3ecf7b252a3 833 state = STATE_SEND_FILE;
Wayne Roberts 0:c3ecf7b252a3 834
Wayne Roberts 0:c3ecf7b252a3 835 flags.atTxDoneRxSingle = true; // receiver acks (F)
Wayne Roberts 0:c3ecf7b252a3 836 xferStartAt = t.read_us();
Wayne Roberts 0:c3ecf7b252a3 837 rf_send(true, 0);
Wayne Roberts 0:c3ecf7b252a3 838 }
Wayne Roberts 0:c3ecf7b252a3 839
Wayne Roberts 0:c3ecf7b252a3 840 void cmd_cmp(uint8_t argsAt)
Wayne Roberts 0:c3ecf7b252a3 841 {
Wayne Roberts 0:c3ecf7b252a3 842 char* dest;
Wayne Roberts 0:c3ecf7b252a3 843 uint8_t txlen;
Wayne Roberts 0:c3ecf7b252a3 844 uint16_t crc;
Wayne Roberts 0:c3ecf7b252a3 845
Wayne Roberts 0:c3ecf7b252a3 846 Radio::Standby();
Wayne Roberts 0:c3ecf7b252a3 847
Wayne Roberts 1:319ef808aaa4 848 if (fd > 0)
Wayne Roberts 1:319ef808aaa4 849 close(fd);
Wayne Roberts 1:319ef808aaa4 850
Wayne Roberts 0:c3ecf7b252a3 851 fd = open(pcbuf + argsAt, O_RDONLY);
Wayne Roberts 0:c3ecf7b252a3 852 if (fd < 0) {
Wayne Roberts 0:c3ecf7b252a3 853 pc.printf("open %s failed\n", pcbuf + argsAt);
Wayne Roberts 0:c3ecf7b252a3 854 return;
Wayne Roberts 0:c3ecf7b252a3 855 }
Wayne Roberts 0:c3ecf7b252a3 856 txlen = strlen(pcbuf + argsAt);
Wayne Roberts 0:c3ecf7b252a3 857
Wayne Roberts 0:c3ecf7b252a3 858 seq = 0;
Wayne Roberts 0:c3ecf7b252a3 859 prevRxSeq = -1;
Wayne Roberts 0:c3ecf7b252a3 860 Radio::radio.tx_buf[0] = seq;
Wayne Roberts 0:c3ecf7b252a3 861 Radio::radio.tx_buf[1] = 'R';
Wayne Roberts 0:c3ecf7b252a3 862 Radio::radio.tx_buf[2] = peerAddr;
Wayne Roberts 0:c3ecf7b252a3 863 Radio::radio.tx_buf[3] = peerAddr >> 8;
Wayne Roberts 0:c3ecf7b252a3 864
Wayne Roberts 0:c3ecf7b252a3 865 dest = (char*)(&Radio::radio.tx_buf[4]);
Wayne Roberts 0:c3ecf7b252a3 866 strcpy(dest, pcbuf + argsAt);
Wayne Roberts 0:c3ecf7b252a3 867 tx_buf_len = txlen + 4;
Wayne Roberts 0:c3ecf7b252a3 868
Wayne Roberts 0:c3ecf7b252a3 869 crc = crc16(Radio::radio.tx_buf, tx_buf_len);
Wayne Roberts 0:c3ecf7b252a3 870 Radio::radio.tx_buf[tx_buf_len++] = crc;
Wayne Roberts 0:c3ecf7b252a3 871 Radio::radio.tx_buf[tx_buf_len++] = crc >> 8;
Wayne Roberts 0:c3ecf7b252a3 872
Wayne Roberts 0:c3ecf7b252a3 873 byteCnt = 0;
Wayne Roberts 0:c3ecf7b252a3 874 flags.endOfFile = false;
Wayne Roberts 0:c3ecf7b252a3 875 attemptsRemaining = MAX_ATTEMPTS;
Wayne Roberts 0:c3ecf7b252a3 876
Wayne Roberts 0:c3ecf7b252a3 877 flags.atTxDoneRxSingle = false;
Wayne Roberts 0:c3ecf7b252a3 878 xferStartAt = t.read_us();
Wayne Roberts 0:c3ecf7b252a3 879 rf_send(true, 0);
Wayne Roberts 0:c3ecf7b252a3 880 state = STATE_RX_COMPARE;
Wayne Roberts 0:c3ecf7b252a3 881 pc.printf("->STATE_RX_COMPARE\r\n");
Wayne Roberts 0:c3ecf7b252a3 882 }
Wayne Roberts 0:c3ecf7b252a3 883
Wayne Roberts 0:c3ecf7b252a3 884 void cmd_um(uint8_t args_at)
Wayne Roberts 0:c3ecf7b252a3 885 {
Wayne Roberts 0:c3ecf7b252a3 886 int err;
Wayne Roberts 0:c3ecf7b252a3 887
Wayne Roberts 0:c3ecf7b252a3 888 // Tidy up
Wayne Roberts 0:c3ecf7b252a3 889 pc.printf("Unmounting... ");
Wayne Roberts 0:c3ecf7b252a3 890 fflush(stdout);
Wayne Roberts 0:c3ecf7b252a3 891 err = fs.unmount();
Wayne Roberts 0:c3ecf7b252a3 892 pc.printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
Wayne Roberts 0:c3ecf7b252a3 893 if (err < 0) {
Wayne Roberts 0:c3ecf7b252a3 894 error("error: %s (%d)\n", strerror(-err), err);
Wayne Roberts 0:c3ecf7b252a3 895 }
Wayne Roberts 0:c3ecf7b252a3 896 }
Wayne Roberts 0:c3ecf7b252a3 897
Wayne Roberts 0:c3ecf7b252a3 898 void cmd_op(uint8_t argsAt)
Wayne Roberts 0:c3ecf7b252a3 899 {
Wayne Roberts 0:c3ecf7b252a3 900 int i;
Wayne Roberts 0:c3ecf7b252a3 901
Wayne Roberts 0:c3ecf7b252a3 902 if (sscanf(pcbuf + argsAt, "%d", &i) == 1)
Wayne Roberts 0:c3ecf7b252a3 903 Radio::set_tx_dbm(i);
Wayne Roberts 0:c3ecf7b252a3 904
Wayne Roberts 0:c3ecf7b252a3 905 tx_dbm_print();
Wayne Roberts 0:c3ecf7b252a3 906 pc.printf("\r\n");
Wayne Roberts 0:c3ecf7b252a3 907 }
Wayne Roberts 0:c3ecf7b252a3 908
Wayne Roberts 0:c3ecf7b252a3 909 const menu_item_t menu_items[] =
Wayne Roberts 0:c3ecf7b252a3 910 { /* after first character, command names must be [A-Za-z] */
Wayne Roberts 0:c3ecf7b252a3 911 { "stby", cmd_stby, "", "radio standby" },
Wayne Roberts 0:c3ecf7b252a3 912 { "sf", cmd_sf, "<sf>", "set sf" },
Wayne Roberts 0:c3ecf7b252a3 913 { "bw", cmd_bw, "<KHz>", "set bw" },
Wayne Roberts 0:c3ecf7b252a3 914 { "rx", cmd_rx, "", "radio rx" },
Wayne Roberts 0:c3ecf7b252a3 915 { "v", cmd_verbose, "", "toggle verbose printing" },
Wayne Roberts 0:c3ecf7b252a3 916 { "frf", cmd_frf, "<MHz>", "radio center frequency" },
Wayne Roberts 0:c3ecf7b252a3 917 { "op", cmd_op, "<dBm>", "tx dbm" },
Wayne Roberts 0:c3ecf7b252a3 918 { "ls", cmd_ls, "", "directory list" },
Wayne Roberts 0:c3ecf7b252a3 919 { "paddr", cmd_peerAddr, "<hex>", "get/set peer address" },
Wayne Roberts 0:c3ecf7b252a3 920 { "maddr", cmd_myAddr, "<hex>", "get/set my address" },
Wayne Roberts 0:c3ecf7b252a3 921 { "pt", cmd_pt, "", "print test" },
Wayne Roberts 0:c3ecf7b252a3 922 { "um", cmd_um, "", "unmount" },
Wayne Roberts 0:c3ecf7b252a3 923 { "md", cmd_md, "<microseconds>", "set minimum delay between rxDone and tx start" },
Wayne Roberts 0:c3ecf7b252a3 924 { "cat", cmd_cat, "<filename>", "print file content" },
Wayne Roberts 0:c3ecf7b252a3 925 { "send", cmd_send, "<filename>", "send file over radio" },
Wayne Roberts 0:c3ecf7b252a3 926 { "rm", cmd_rm, "<filename>", "delete local file (without directory)" },
Wayne Roberts 0:c3ecf7b252a3 927 { "cmp", cmd_cmp, "<filename>", "compare remote file against local" },
Wayne Roberts 0:c3ecf7b252a3 928 { ".", cmd_print_status, "","print status"},
Wayne Roberts 0:c3ecf7b252a3 929 { "?", cmd_help, "","this list of commands"},
Wayne Roberts 0:c3ecf7b252a3 930 { NULL, NULL, NULL, NULL }
Wayne Roberts 0:c3ecf7b252a3 931 };
Wayne Roberts 0:c3ecf7b252a3 932
Wayne Roberts 0:c3ecf7b252a3 933 void cmd_help(uint8_t args_at)
Wayne Roberts 0:c3ecf7b252a3 934 {
Wayne Roberts 0:c3ecf7b252a3 935 int i;
Wayne Roberts 0:c3ecf7b252a3 936
Wayne Roberts 0:c3ecf7b252a3 937 for (i = 0; menu_items[i].cmd != NULL ; i++) {
Wayne Roberts 0:c3ecf7b252a3 938 pc.printf("%s%s\t%s\r\n", menu_items[i].cmd, menu_items[i].arg_descr, menu_items[i].description);
Wayne Roberts 0:c3ecf7b252a3 939 }
Wayne Roberts 0:c3ecf7b252a3 940 }
Wayne Roberts 0:c3ecf7b252a3 941
Wayne Roberts 0:c3ecf7b252a3 942 void
Wayne Roberts 0:c3ecf7b252a3 943 console()
Wayne Roberts 0:c3ecf7b252a3 944 {
Wayne Roberts 0:c3ecf7b252a3 945 int i;
Wayne Roberts 0:c3ecf7b252a3 946 uint8_t user_cmd_len;
Wayne Roberts 0:c3ecf7b252a3 947
Wayne Roberts 0:c3ecf7b252a3 948 if (pcbuf_len < 0) {
Wayne Roberts 0:c3ecf7b252a3 949 pc.printf("abort\r\n");
Wayne Roberts 0:c3ecf7b252a3 950 Radio::Standby();
Wayne Roberts 0:c3ecf7b252a3 951 wait(0.02);
Wayne Roberts 0:c3ecf7b252a3 952 rxCont();
Wayne Roberts 0:c3ecf7b252a3 953 pcbuf_len = 0;
Wayne Roberts 0:c3ecf7b252a3 954 state = STATE_NONE;
Wayne Roberts 0:c3ecf7b252a3 955 return;
Wayne Roberts 0:c3ecf7b252a3 956 }
Wayne Roberts 0:c3ecf7b252a3 957 if (pcbuf_len == 0) {
Wayne Roberts 0:c3ecf7b252a3 958 return;
Wayne Roberts 0:c3ecf7b252a3 959 }
Wayne Roberts 0:c3ecf7b252a3 960
Wayne Roberts 0:c3ecf7b252a3 961 pc.printf("\r\n");
Wayne Roberts 0:c3ecf7b252a3 962
Wayne Roberts 0:c3ecf7b252a3 963 /* get end of user-entered command */
Wayne Roberts 0:c3ecf7b252a3 964 user_cmd_len = 1; // first character can be any character
Wayne Roberts 0:c3ecf7b252a3 965 for (i = 1; i <= pcbuf_len; i++) {
Wayne Roberts 0:c3ecf7b252a3 966 if (pcbuf[i] < 'A' || (pcbuf[i] > 'Z' && pcbuf[i] < 'a') || pcbuf[i] > 'z') {
Wayne Roberts 0:c3ecf7b252a3 967 user_cmd_len = i;
Wayne Roberts 0:c3ecf7b252a3 968 break;
Wayne Roberts 0:c3ecf7b252a3 969 }
Wayne Roberts 0:c3ecf7b252a3 970 }
Wayne Roberts 0:c3ecf7b252a3 971
Wayne Roberts 0:c3ecf7b252a3 972 for (i = 0; menu_items[i].cmd != NULL ; i++) {
Wayne Roberts 0:c3ecf7b252a3 973 int mi_len = strlen(menu_items[i].cmd);
Wayne Roberts 0:c3ecf7b252a3 974
Wayne Roberts 0:c3ecf7b252a3 975 if (menu_items[i].handler && user_cmd_len == mi_len && (strncmp(pcbuf, menu_items[i].cmd, mi_len) == 0)) {
Wayne Roberts 0:c3ecf7b252a3 976 while (pcbuf[mi_len] == ' ') // skip past spaces
Wayne Roberts 0:c3ecf7b252a3 977 mi_len++;
Wayne Roberts 0:c3ecf7b252a3 978 menu_items[i].handler(mi_len);
Wayne Roberts 0:c3ecf7b252a3 979 break;
Wayne Roberts 0:c3ecf7b252a3 980 }
Wayne Roberts 0:c3ecf7b252a3 981 }
Wayne Roberts 0:c3ecf7b252a3 982
Wayne Roberts 0:c3ecf7b252a3 983 pcbuf_len = 0;
Wayne Roberts 0:c3ecf7b252a3 984 pc.printf("> ");
Wayne Roberts 0:c3ecf7b252a3 985 fflush(stdout);
Wayne Roberts 0:c3ecf7b252a3 986 }
Wayne Roberts 0:c3ecf7b252a3 987
Wayne Roberts 0:c3ecf7b252a3 988 void rx_callback()
Wayne Roberts 0:c3ecf7b252a3 989 {
Wayne Roberts 0:c3ecf7b252a3 990 static uint8_t prev_len = 0;;
Wayne Roberts 0:c3ecf7b252a3 991 char c = pc.getc();
Wayne Roberts 0:c3ecf7b252a3 992
Wayne Roberts 0:c3ecf7b252a3 993 if (c == 8) {
Wayne Roberts 0:c3ecf7b252a3 994 if (pcbuf_idx > 0) {
Wayne Roberts 0:c3ecf7b252a3 995 pc.putc(8);
Wayne Roberts 0:c3ecf7b252a3 996 pc.putc(' ');
Wayne Roberts 0:c3ecf7b252a3 997 pc.putc(8);
Wayne Roberts 0:c3ecf7b252a3 998 pcbuf_idx--;
Wayne Roberts 0:c3ecf7b252a3 999 }
Wayne Roberts 0:c3ecf7b252a3 1000 } else if (c == 3) { // ctrl-C
Wayne Roberts 0:c3ecf7b252a3 1001 pcbuf_len = -1;
Wayne Roberts 0:c3ecf7b252a3 1002 queue.call(console);
Wayne Roberts 0:c3ecf7b252a3 1003 } else if (c == '\r') {
Wayne Roberts 0:c3ecf7b252a3 1004 if (pcbuf_idx == 0) {
Wayne Roberts 0:c3ecf7b252a3 1005 pcbuf_len = prev_len;
Wayne Roberts 0:c3ecf7b252a3 1006 } else {
Wayne Roberts 0:c3ecf7b252a3 1007 pcbuf[pcbuf_idx] = 0; // null terminate
Wayne Roberts 0:c3ecf7b252a3 1008 prev_len = pcbuf_idx;
Wayne Roberts 0:c3ecf7b252a3 1009 pcbuf_idx = 0;
Wayne Roberts 0:c3ecf7b252a3 1010 pcbuf_len = prev_len;
Wayne Roberts 0:c3ecf7b252a3 1011 }
Wayne Roberts 0:c3ecf7b252a3 1012 queue.call(console);
Wayne Roberts 0:c3ecf7b252a3 1013 } else if (pcbuf_idx < sizeof(pcbuf)) {
Wayne Roberts 0:c3ecf7b252a3 1014 pcbuf[pcbuf_idx++] = c;
Wayne Roberts 0:c3ecf7b252a3 1015 pc.putc(c);
Wayne Roberts 0:c3ecf7b252a3 1016 }
Wayne Roberts 0:c3ecf7b252a3 1017 }
Wayne Roberts 0:c3ecf7b252a3 1018
Wayne Roberts 0:c3ecf7b252a3 1019 void set_symb_timeout()
Wayne Roberts 0:c3ecf7b252a3 1020 {
Wayne Roberts 0:c3ecf7b252a3 1021 float symbPeriod_ms = (1 << current.sf) / (float)current.bwKHz;
Wayne Roberts 0:c3ecf7b252a3 1022 float rxtx_turnaround_symbols = TX_RX_TURNAROUND_MS / symbPeriod_ms;
Wayne Roberts 0:c3ecf7b252a3 1023 pc.printf("sp:%.3f, toSymbs:%.1f\r\n", symbPeriod_ms, rxtx_turnaround_symbols);
Wayne Roberts 0:c3ecf7b252a3 1024 #if defined(SX126x_H)
Wayne Roberts 0:c3ecf7b252a3 1025 if (rxtx_turnaround_symbols > (254-8)) {
Wayne Roberts 0:c3ecf7b252a3 1026 rxtx_turnaround_symbols = 254-8;
Wayne Roberts 0:c3ecf7b252a3 1027 pc.printf("\e[41msymbTo hit top\e[0m\r\n");
Wayne Roberts 0:c3ecf7b252a3 1028 }
Wayne Roberts 0:c3ecf7b252a3 1029 #endif
Wayne Roberts 0:c3ecf7b252a3 1030 rxtx_turnaround_symbols = ceil(rxtx_turnaround_symbols);
Wayne Roberts 0:c3ecf7b252a3 1031 pc.printf("turnSymb:%f\r\n", rxtx_turnaround_symbols);
Wayne Roberts 0:c3ecf7b252a3 1032 Radio::SetLoRaSymbolTimeout(rxtx_turnaround_symbols + 8);
Wayne Roberts 0:c3ecf7b252a3 1033 }
Wayne Roberts 0:c3ecf7b252a3 1034
Wayne Roberts 0:c3ecf7b252a3 1035 int main()
Wayne Roberts 0:c3ecf7b252a3 1036 {
Wayne Roberts 0:c3ecf7b252a3 1037 #ifdef RX_DBG_PIN
Wayne Roberts 0:c3ecf7b252a3 1038 rx_dbg.input();
Wayne Roberts 0:c3ecf7b252a3 1039 rx_dbg.mode(PullUp);
Wayne Roberts 0:c3ecf7b252a3 1040 #endif /* RX_DBG_PIN */
Wayne Roberts 0:c3ecf7b252a3 1041
Wayne Roberts 0:c3ecf7b252a3 1042 pc.attach(rx_callback);
Wayne Roberts 0:c3ecf7b252a3 1043 pc.baud(115200);
Wayne Roberts 0:c3ecf7b252a3 1044 pc.printf("--- Mbed OS filesystem example ---\n");
Wayne Roberts 0:c3ecf7b252a3 1045
Wayne Roberts 0:c3ecf7b252a3 1046 Radio::Init(&rev, SPI_HZ);
Wayne Roberts 0:c3ecf7b252a3 1047 radio_readChip();
Wayne Roberts 0:c3ecf7b252a3 1048
Wayne Roberts 0:c3ecf7b252a3 1049 Radio::Standby();
Wayne Roberts 0:c3ecf7b252a3 1050 wait(0.05);
Wayne Roberts 0:c3ecf7b252a3 1051 Radio::LoRaModemConfig(BW_KHZ, SPREADING_FACTOR, 1);
Wayne Roberts 0:c3ecf7b252a3 1052 Radio::LoRaPacketConfig(8, false, true, false); // preambleLen, fixLen, crcOn, invIQ
Wayne Roberts 0:c3ecf7b252a3 1053 Radio::SetChannel(CF_HZ);
Wayne Roberts 0:c3ecf7b252a3 1054
Wayne Roberts 0:c3ecf7b252a3 1055 Radio::set_tx_dbm(TX_DBM);
Wayne Roberts 0:c3ecf7b252a3 1056
Wayne Roberts 0:c3ecf7b252a3 1057 current.bwKHz = BW_KHZ;
Wayne Roberts 0:c3ecf7b252a3 1058 current.sf = SPREADING_FACTOR;
Wayne Roberts 0:c3ecf7b252a3 1059 set_symb_timeout();
Wayne Roberts 0:c3ecf7b252a3 1060 t.start();
Wayne Roberts 0:c3ecf7b252a3 1061
Wayne Roberts 0:c3ecf7b252a3 1062 wait(0.05);
Wayne Roberts 0:c3ecf7b252a3 1063 rxCont();
Wayne Roberts 0:c3ecf7b252a3 1064 flags.verbose = true;
Wayne Roberts 0:c3ecf7b252a3 1065
Wayne Roberts 0:c3ecf7b252a3 1066 // Try to mount the filesystem
Wayne Roberts 0:c3ecf7b252a3 1067 pc.printf("Mounting the filesystem... ");
Wayne Roberts 0:c3ecf7b252a3 1068 fflush(stdout);
Wayne Roberts 0:c3ecf7b252a3 1069 int err = fs.mount(bd);
Wayne Roberts 0:c3ecf7b252a3 1070 pc.printf("%s\r\n", (err ? "Fail :(" : "OK\r\n"));
Wayne Roberts 0:c3ecf7b252a3 1071 if (err) {
Wayne Roberts 0:c3ecf7b252a3 1072 // Reformat if we can't mount the filesystem
Wayne Roberts 0:c3ecf7b252a3 1073 // this should only happen on the first boot
Wayne Roberts 0:c3ecf7b252a3 1074 pc.printf("No filesystem found, formatting... ");
Wayne Roberts 0:c3ecf7b252a3 1075 fflush(stdout);
Wayne Roberts 0:c3ecf7b252a3 1076 err = fs.reformat(bd);
Wayne Roberts 0:c3ecf7b252a3 1077 pc.printf("%s\r\n", (err ? "Fail :(" : "OK\r\n"));
Wayne Roberts 0:c3ecf7b252a3 1078 if (err) {
Wayne Roberts 0:c3ecf7b252a3 1079 error("error: %s (%d)\r\n", strerror(-err), err);
Wayne Roberts 0:c3ecf7b252a3 1080 }
Wayne Roberts 0:c3ecf7b252a3 1081 }
Wayne Roberts 0:c3ecf7b252a3 1082
Wayne Roberts 0:c3ecf7b252a3 1083 txMinDelay_us = 2000;
Wayne Roberts 0:c3ecf7b252a3 1084 add_txDelay_retry = 400;
Wayne Roberts 0:c3ecf7b252a3 1085 th.start(callback(&queue, &EventQueue::dispatch_forever));
Wayne Roberts 0:c3ecf7b252a3 1086
Wayne Roberts 0:c3ecf7b252a3 1087 for (;;) {
Wayne Roberts 0:c3ecf7b252a3 1088 Radio::service();
Wayne Roberts 0:c3ecf7b252a3 1089
Wayne Roberts 0:c3ecf7b252a3 1090 if (rxSize != 0) {
Wayne Roberts 0:c3ecf7b252a3 1091 rxHandler(Radio::radio.rx_buf);
Wayne Roberts 0:c3ecf7b252a3 1092 rxSize = 0;
Wayne Roberts 0:c3ecf7b252a3 1093 }
Wayne Roberts 0:c3ecf7b252a3 1094
Wayne Roberts 0:c3ecf7b252a3 1095 if (flags.rxContStart) {
Wayne Roberts 0:c3ecf7b252a3 1096 rxCont();
Wayne Roberts 0:c3ecf7b252a3 1097 flags.rxContStart = false;
Wayne Roberts 0:c3ecf7b252a3 1098 }
Wayne Roberts 0:c3ecf7b252a3 1099
Wayne Roberts 0:c3ecf7b252a3 1100 if (flags.callRetry) {
Wayne Roberts 0:c3ecf7b252a3 1101 retry(true);
Wayne Roberts 0:c3ecf7b252a3 1102 flags.callRetry = false;
Wayne Roberts 0:c3ecf7b252a3 1103 }
Wayne Roberts 0:c3ecf7b252a3 1104
Wayne Roberts 0:c3ecf7b252a3 1105 /* servicing txDone is higher priority than printing characters */
Wayne Roberts 0:c3ecf7b252a3 1106 while (!flags.txDonePending && printBuf_in != printBuf_out) {
Wayne Roberts 0:c3ecf7b252a3 1107 pc.putc(printBuf[printBuf_out]);
Wayne Roberts 0:c3ecf7b252a3 1108 if (++printBuf_out == sizeof(printBuf))
Wayne Roberts 0:c3ecf7b252a3 1109 printBuf_out = 0;
Wayne Roberts 0:c3ecf7b252a3 1110 }
Wayne Roberts 0:c3ecf7b252a3 1111 } // ..for (;;)
Wayne Roberts 0:c3ecf7b252a3 1112 }