transfer files from mbed-os block device (i.e. SD card) over LoRa radio.
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/sec | sf12 | sf11 | sf10 | sf9 | sf8 | sf7 | sf6 | sf5 |
1600KHz | 276 | 482 | 1081 | 1887 | 3277 | 5365 | 6400 | 12000 |
800KHz | 529 | 970 | 1720 | 2800 | 4766 | 6500 | ||
400KHz | 1465 | 2265 | 4033 |
sx126x thruput
bytes/sec | sf12 | sf11 | sf10 | sf9 | sf8 | sf7 | sf6 | sf5 |
500KHz | 207 | 381 | 706 | 1257 | 2154 | 3570 | 5608 | |
250KHz | 103 | 193 | 344 | 641 | 1114 | 1887 | 3064 | |
125KHz | 97 | 173 | 324 | 547 | 972 | 1607 |
sx127x thruput
sx126x recommended at 500KHz bandwidth.
bytes/sec | sf12 | sf11 | sf10 | sf9 | sf8 | sf7 |
500KHz | 111 | 207 | 385 | 697 | 1220 | 2050 |
250KHz | 48.7 | 103 | 192 | 345 | 632 | 1115 |
125KHz | 24.2 | 44 | 97 | 151 | 313 | 552 |
62.5KHz | 12.2 | 22.1 | 39.4 | 86 | 157 | 276 |
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:
main.cpp@0:c3ecf7b252a3, 2019-05-31 (annotated)
- Committer:
- Wayne Roberts
- Date:
- Fri May 31 17:17:24 2019 -0700
- Revision:
- 0:c3ecf7b252a3
- Child:
- 1:319ef808aaa4
initial committ
Who changed what in which revision?
User | Revision | Line number | New 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 |
0:c3ecf7b252a3 | 742 | pc.printf("open %s failed\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 |
0:c3ecf7b252a3 | 805 | fd = open(pcbuf + argsAt, O_RDONLY); |
Wayne Roberts |
0:c3ecf7b252a3 | 806 | if (fd < 0) { |
Wayne Roberts |
0:c3ecf7b252a3 | 807 | pc.printf("open %s failed\n", pcbuf + argsAt); |
Wayne Roberts |
0:c3ecf7b252a3 | 808 | return; |
Wayne Roberts |
0:c3ecf7b252a3 | 809 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 810 | txlen = strlen(pcbuf + argsAt); |
Wayne Roberts |
0:c3ecf7b252a3 | 811 | |
Wayne Roberts |
0:c3ecf7b252a3 | 812 | seq = 0; |
Wayne Roberts |
0:c3ecf7b252a3 | 813 | prevRxSeq = -1; |
Wayne Roberts |
0:c3ecf7b252a3 | 814 | Radio::radio.tx_buf[0] = seq; |
Wayne Roberts |
0:c3ecf7b252a3 | 815 | Radio::radio.tx_buf[1] = 'F'; |
Wayne Roberts |
0:c3ecf7b252a3 | 816 | Radio::radio.tx_buf[2] = peerAddr; |
Wayne Roberts |
0:c3ecf7b252a3 | 817 | Radio::radio.tx_buf[3] = peerAddr >> 8; |
Wayne Roberts |
0:c3ecf7b252a3 | 818 | |
Wayne Roberts |
0:c3ecf7b252a3 | 819 | dest = (char*)(&Radio::radio.tx_buf[4]); |
Wayne Roberts |
0:c3ecf7b252a3 | 820 | strcpy(dest, pcbuf + argsAt); |
Wayne Roberts |
0:c3ecf7b252a3 | 821 | tx_buf_len = txlen + 4; |
Wayne Roberts |
0:c3ecf7b252a3 | 822 | |
Wayne Roberts |
0:c3ecf7b252a3 | 823 | crc = crc16(Radio::radio.tx_buf, tx_buf_len); |
Wayne Roberts |
0:c3ecf7b252a3 | 824 | Radio::radio.tx_buf[tx_buf_len++] = crc; |
Wayne Roberts |
0:c3ecf7b252a3 | 825 | Radio::radio.tx_buf[tx_buf_len++] = crc >> 8; |
Wayne Roberts |
0:c3ecf7b252a3 | 826 | |
Wayne Roberts |
0:c3ecf7b252a3 | 827 | byteCnt = 0; |
Wayne Roberts |
0:c3ecf7b252a3 | 828 | attemptsRemaining = MAX_ATTEMPTS; |
Wayne Roberts |
0:c3ecf7b252a3 | 829 | flags.endOfFile = false; |
Wayne Roberts |
0:c3ecf7b252a3 | 830 | state = STATE_SEND_FILE; |
Wayne Roberts |
0:c3ecf7b252a3 | 831 | |
Wayne Roberts |
0:c3ecf7b252a3 | 832 | flags.atTxDoneRxSingle = true; // receiver acks (F) |
Wayne Roberts |
0:c3ecf7b252a3 | 833 | xferStartAt = t.read_us(); |
Wayne Roberts |
0:c3ecf7b252a3 | 834 | rf_send(true, 0); |
Wayne Roberts |
0:c3ecf7b252a3 | 835 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 836 | |
Wayne Roberts |
0:c3ecf7b252a3 | 837 | void cmd_cmp(uint8_t argsAt) |
Wayne Roberts |
0:c3ecf7b252a3 | 838 | { |
Wayne Roberts |
0:c3ecf7b252a3 | 839 | char* dest; |
Wayne Roberts |
0:c3ecf7b252a3 | 840 | uint8_t txlen; |
Wayne Roberts |
0:c3ecf7b252a3 | 841 | uint16_t crc; |
Wayne Roberts |
0:c3ecf7b252a3 | 842 | |
Wayne Roberts |
0:c3ecf7b252a3 | 843 | Radio::Standby(); |
Wayne Roberts |
0:c3ecf7b252a3 | 844 | |
Wayne Roberts |
0:c3ecf7b252a3 | 845 | close(fd); |
Wayne Roberts |
0:c3ecf7b252a3 | 846 | fd = open(pcbuf + argsAt, O_RDONLY); |
Wayne Roberts |
0:c3ecf7b252a3 | 847 | if (fd < 0) { |
Wayne Roberts |
0:c3ecf7b252a3 | 848 | pc.printf("open %s failed\n", pcbuf + argsAt); |
Wayne Roberts |
0:c3ecf7b252a3 | 849 | return; |
Wayne Roberts |
0:c3ecf7b252a3 | 850 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 851 | txlen = strlen(pcbuf + argsAt); |
Wayne Roberts |
0:c3ecf7b252a3 | 852 | |
Wayne Roberts |
0:c3ecf7b252a3 | 853 | seq = 0; |
Wayne Roberts |
0:c3ecf7b252a3 | 854 | prevRxSeq = -1; |
Wayne Roberts |
0:c3ecf7b252a3 | 855 | Radio::radio.tx_buf[0] = seq; |
Wayne Roberts |
0:c3ecf7b252a3 | 856 | Radio::radio.tx_buf[1] = 'R'; |
Wayne Roberts |
0:c3ecf7b252a3 | 857 | Radio::radio.tx_buf[2] = peerAddr; |
Wayne Roberts |
0:c3ecf7b252a3 | 858 | Radio::radio.tx_buf[3] = peerAddr >> 8; |
Wayne Roberts |
0:c3ecf7b252a3 | 859 | |
Wayne Roberts |
0:c3ecf7b252a3 | 860 | dest = (char*)(&Radio::radio.tx_buf[4]); |
Wayne Roberts |
0:c3ecf7b252a3 | 861 | strcpy(dest, pcbuf + argsAt); |
Wayne Roberts |
0:c3ecf7b252a3 | 862 | tx_buf_len = txlen + 4; |
Wayne Roberts |
0:c3ecf7b252a3 | 863 | |
Wayne Roberts |
0:c3ecf7b252a3 | 864 | crc = crc16(Radio::radio.tx_buf, tx_buf_len); |
Wayne Roberts |
0:c3ecf7b252a3 | 865 | Radio::radio.tx_buf[tx_buf_len++] = crc; |
Wayne Roberts |
0:c3ecf7b252a3 | 866 | Radio::radio.tx_buf[tx_buf_len++] = crc >> 8; |
Wayne Roberts |
0:c3ecf7b252a3 | 867 | |
Wayne Roberts |
0:c3ecf7b252a3 | 868 | byteCnt = 0; |
Wayne Roberts |
0:c3ecf7b252a3 | 869 | flags.endOfFile = false; |
Wayne Roberts |
0:c3ecf7b252a3 | 870 | attemptsRemaining = MAX_ATTEMPTS; |
Wayne Roberts |
0:c3ecf7b252a3 | 871 | |
Wayne Roberts |
0:c3ecf7b252a3 | 872 | flags.atTxDoneRxSingle = false; |
Wayne Roberts |
0:c3ecf7b252a3 | 873 | xferStartAt = t.read_us(); |
Wayne Roberts |
0:c3ecf7b252a3 | 874 | rf_send(true, 0); |
Wayne Roberts |
0:c3ecf7b252a3 | 875 | state = STATE_RX_COMPARE; |
Wayne Roberts |
0:c3ecf7b252a3 | 876 | pc.printf("->STATE_RX_COMPARE\r\n"); |
Wayne Roberts |
0:c3ecf7b252a3 | 877 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 878 | |
Wayne Roberts |
0:c3ecf7b252a3 | 879 | void cmd_um(uint8_t args_at) |
Wayne Roberts |
0:c3ecf7b252a3 | 880 | { |
Wayne Roberts |
0:c3ecf7b252a3 | 881 | int err; |
Wayne Roberts |
0:c3ecf7b252a3 | 882 | |
Wayne Roberts |
0:c3ecf7b252a3 | 883 | // Tidy up |
Wayne Roberts |
0:c3ecf7b252a3 | 884 | pc.printf("Unmounting... "); |
Wayne Roberts |
0:c3ecf7b252a3 | 885 | fflush(stdout); |
Wayne Roberts |
0:c3ecf7b252a3 | 886 | err = fs.unmount(); |
Wayne Roberts |
0:c3ecf7b252a3 | 887 | pc.printf("%s\n", (err < 0 ? "Fail :(" : "OK")); |
Wayne Roberts |
0:c3ecf7b252a3 | 888 | if (err < 0) { |
Wayne Roberts |
0:c3ecf7b252a3 | 889 | error("error: %s (%d)\n", strerror(-err), err); |
Wayne Roberts |
0:c3ecf7b252a3 | 890 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 891 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 892 | |
Wayne Roberts |
0:c3ecf7b252a3 | 893 | void cmd_op(uint8_t argsAt) |
Wayne Roberts |
0:c3ecf7b252a3 | 894 | { |
Wayne Roberts |
0:c3ecf7b252a3 | 895 | int i; |
Wayne Roberts |
0:c3ecf7b252a3 | 896 | |
Wayne Roberts |
0:c3ecf7b252a3 | 897 | if (sscanf(pcbuf + argsAt, "%d", &i) == 1) |
Wayne Roberts |
0:c3ecf7b252a3 | 898 | Radio::set_tx_dbm(i); |
Wayne Roberts |
0:c3ecf7b252a3 | 899 | |
Wayne Roberts |
0:c3ecf7b252a3 | 900 | tx_dbm_print(); |
Wayne Roberts |
0:c3ecf7b252a3 | 901 | pc.printf("\r\n"); |
Wayne Roberts |
0:c3ecf7b252a3 | 902 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 903 | |
Wayne Roberts |
0:c3ecf7b252a3 | 904 | const menu_item_t menu_items[] = |
Wayne Roberts |
0:c3ecf7b252a3 | 905 | { /* after first character, command names must be [A-Za-z] */ |
Wayne Roberts |
0:c3ecf7b252a3 | 906 | { "stby", cmd_stby, "", "radio standby" }, |
Wayne Roberts |
0:c3ecf7b252a3 | 907 | { "sf", cmd_sf, "<sf>", "set sf" }, |
Wayne Roberts |
0:c3ecf7b252a3 | 908 | { "bw", cmd_bw, "<KHz>", "set bw" }, |
Wayne Roberts |
0:c3ecf7b252a3 | 909 | { "rx", cmd_rx, "", "radio rx" }, |
Wayne Roberts |
0:c3ecf7b252a3 | 910 | { "v", cmd_verbose, "", "toggle verbose printing" }, |
Wayne Roberts |
0:c3ecf7b252a3 | 911 | { "frf", cmd_frf, "<MHz>", "radio center frequency" }, |
Wayne Roberts |
0:c3ecf7b252a3 | 912 | { "op", cmd_op, "<dBm>", "tx dbm" }, |
Wayne Roberts |
0:c3ecf7b252a3 | 913 | { "ls", cmd_ls, "", "directory list" }, |
Wayne Roberts |
0:c3ecf7b252a3 | 914 | { "paddr", cmd_peerAddr, "<hex>", "get/set peer address" }, |
Wayne Roberts |
0:c3ecf7b252a3 | 915 | { "maddr", cmd_myAddr, "<hex>", "get/set my address" }, |
Wayne Roberts |
0:c3ecf7b252a3 | 916 | { "pt", cmd_pt, "", "print test" }, |
Wayne Roberts |
0:c3ecf7b252a3 | 917 | { "um", cmd_um, "", "unmount" }, |
Wayne Roberts |
0:c3ecf7b252a3 | 918 | { "md", cmd_md, "<microseconds>", "set minimum delay between rxDone and tx start" }, |
Wayne Roberts |
0:c3ecf7b252a3 | 919 | { "cat", cmd_cat, "<filename>", "print file content" }, |
Wayne Roberts |
0:c3ecf7b252a3 | 920 | { "send", cmd_send, "<filename>", "send file over radio" }, |
Wayne Roberts |
0:c3ecf7b252a3 | 921 | { "rm", cmd_rm, "<filename>", "delete local file (without directory)" }, |
Wayne Roberts |
0:c3ecf7b252a3 | 922 | { "cmp", cmd_cmp, "<filename>", "compare remote file against local" }, |
Wayne Roberts |
0:c3ecf7b252a3 | 923 | { ".", cmd_print_status, "","print status"}, |
Wayne Roberts |
0:c3ecf7b252a3 | 924 | { "?", cmd_help, "","this list of commands"}, |
Wayne Roberts |
0:c3ecf7b252a3 | 925 | { NULL, NULL, NULL, NULL } |
Wayne Roberts |
0:c3ecf7b252a3 | 926 | }; |
Wayne Roberts |
0:c3ecf7b252a3 | 927 | |
Wayne Roberts |
0:c3ecf7b252a3 | 928 | void cmd_help(uint8_t args_at) |
Wayne Roberts |
0:c3ecf7b252a3 | 929 | { |
Wayne Roberts |
0:c3ecf7b252a3 | 930 | int i; |
Wayne Roberts |
0:c3ecf7b252a3 | 931 | |
Wayne Roberts |
0:c3ecf7b252a3 | 932 | for (i = 0; menu_items[i].cmd != NULL ; i++) { |
Wayne Roberts |
0:c3ecf7b252a3 | 933 | 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 | 934 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 935 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 936 | |
Wayne Roberts |
0:c3ecf7b252a3 | 937 | void |
Wayne Roberts |
0:c3ecf7b252a3 | 938 | console() |
Wayne Roberts |
0:c3ecf7b252a3 | 939 | { |
Wayne Roberts |
0:c3ecf7b252a3 | 940 | int i; |
Wayne Roberts |
0:c3ecf7b252a3 | 941 | uint8_t user_cmd_len; |
Wayne Roberts |
0:c3ecf7b252a3 | 942 | |
Wayne Roberts |
0:c3ecf7b252a3 | 943 | if (pcbuf_len < 0) { |
Wayne Roberts |
0:c3ecf7b252a3 | 944 | pc.printf("abort\r\n"); |
Wayne Roberts |
0:c3ecf7b252a3 | 945 | Radio::Standby(); |
Wayne Roberts |
0:c3ecf7b252a3 | 946 | wait(0.02); |
Wayne Roberts |
0:c3ecf7b252a3 | 947 | rxCont(); |
Wayne Roberts |
0:c3ecf7b252a3 | 948 | pcbuf_len = 0; |
Wayne Roberts |
0:c3ecf7b252a3 | 949 | state = STATE_NONE; |
Wayne Roberts |
0:c3ecf7b252a3 | 950 | return; |
Wayne Roberts |
0:c3ecf7b252a3 | 951 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 952 | if (pcbuf_len == 0) { |
Wayne Roberts |
0:c3ecf7b252a3 | 953 | return; |
Wayne Roberts |
0:c3ecf7b252a3 | 954 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 955 | |
Wayne Roberts |
0:c3ecf7b252a3 | 956 | pc.printf("\r\n"); |
Wayne Roberts |
0:c3ecf7b252a3 | 957 | |
Wayne Roberts |
0:c3ecf7b252a3 | 958 | /* get end of user-entered command */ |
Wayne Roberts |
0:c3ecf7b252a3 | 959 | user_cmd_len = 1; // first character can be any character |
Wayne Roberts |
0:c3ecf7b252a3 | 960 | for (i = 1; i <= pcbuf_len; i++) { |
Wayne Roberts |
0:c3ecf7b252a3 | 961 | if (pcbuf[i] < 'A' || (pcbuf[i] > 'Z' && pcbuf[i] < 'a') || pcbuf[i] > 'z') { |
Wayne Roberts |
0:c3ecf7b252a3 | 962 | user_cmd_len = i; |
Wayne Roberts |
0:c3ecf7b252a3 | 963 | break; |
Wayne Roberts |
0:c3ecf7b252a3 | 964 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 965 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 966 | |
Wayne Roberts |
0:c3ecf7b252a3 | 967 | for (i = 0; menu_items[i].cmd != NULL ; i++) { |
Wayne Roberts |
0:c3ecf7b252a3 | 968 | int mi_len = strlen(menu_items[i].cmd); |
Wayne Roberts |
0:c3ecf7b252a3 | 969 | |
Wayne Roberts |
0:c3ecf7b252a3 | 970 | if (menu_items[i].handler && user_cmd_len == mi_len && (strncmp(pcbuf, menu_items[i].cmd, mi_len) == 0)) { |
Wayne Roberts |
0:c3ecf7b252a3 | 971 | while (pcbuf[mi_len] == ' ') // skip past spaces |
Wayne Roberts |
0:c3ecf7b252a3 | 972 | mi_len++; |
Wayne Roberts |
0:c3ecf7b252a3 | 973 | menu_items[i].handler(mi_len); |
Wayne Roberts |
0:c3ecf7b252a3 | 974 | break; |
Wayne Roberts |
0:c3ecf7b252a3 | 975 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 976 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 977 | |
Wayne Roberts |
0:c3ecf7b252a3 | 978 | pcbuf_len = 0; |
Wayne Roberts |
0:c3ecf7b252a3 | 979 | pc.printf("> "); |
Wayne Roberts |
0:c3ecf7b252a3 | 980 | fflush(stdout); |
Wayne Roberts |
0:c3ecf7b252a3 | 981 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 982 | |
Wayne Roberts |
0:c3ecf7b252a3 | 983 | void rx_callback() |
Wayne Roberts |
0:c3ecf7b252a3 | 984 | { |
Wayne Roberts |
0:c3ecf7b252a3 | 985 | static uint8_t prev_len = 0;; |
Wayne Roberts |
0:c3ecf7b252a3 | 986 | char c = pc.getc(); |
Wayne Roberts |
0:c3ecf7b252a3 | 987 | |
Wayne Roberts |
0:c3ecf7b252a3 | 988 | if (c == 8) { |
Wayne Roberts |
0:c3ecf7b252a3 | 989 | if (pcbuf_idx > 0) { |
Wayne Roberts |
0:c3ecf7b252a3 | 990 | pc.putc(8); |
Wayne Roberts |
0:c3ecf7b252a3 | 991 | pc.putc(' '); |
Wayne Roberts |
0:c3ecf7b252a3 | 992 | pc.putc(8); |
Wayne Roberts |
0:c3ecf7b252a3 | 993 | pcbuf_idx--; |
Wayne Roberts |
0:c3ecf7b252a3 | 994 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 995 | } else if (c == 3) { // ctrl-C |
Wayne Roberts |
0:c3ecf7b252a3 | 996 | pcbuf_len = -1; |
Wayne Roberts |
0:c3ecf7b252a3 | 997 | queue.call(console); |
Wayne Roberts |
0:c3ecf7b252a3 | 998 | } else if (c == '\r') { |
Wayne Roberts |
0:c3ecf7b252a3 | 999 | if (pcbuf_idx == 0) { |
Wayne Roberts |
0:c3ecf7b252a3 | 1000 | pcbuf_len = prev_len; |
Wayne Roberts |
0:c3ecf7b252a3 | 1001 | } else { |
Wayne Roberts |
0:c3ecf7b252a3 | 1002 | pcbuf[pcbuf_idx] = 0; // null terminate |
Wayne Roberts |
0:c3ecf7b252a3 | 1003 | prev_len = pcbuf_idx; |
Wayne Roberts |
0:c3ecf7b252a3 | 1004 | pcbuf_idx = 0; |
Wayne Roberts |
0:c3ecf7b252a3 | 1005 | pcbuf_len = prev_len; |
Wayne Roberts |
0:c3ecf7b252a3 | 1006 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 1007 | queue.call(console); |
Wayne Roberts |
0:c3ecf7b252a3 | 1008 | } else if (pcbuf_idx < sizeof(pcbuf)) { |
Wayne Roberts |
0:c3ecf7b252a3 | 1009 | pcbuf[pcbuf_idx++] = c; |
Wayne Roberts |
0:c3ecf7b252a3 | 1010 | pc.putc(c); |
Wayne Roberts |
0:c3ecf7b252a3 | 1011 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 1012 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 1013 | |
Wayne Roberts |
0:c3ecf7b252a3 | 1014 | void set_symb_timeout() |
Wayne Roberts |
0:c3ecf7b252a3 | 1015 | { |
Wayne Roberts |
0:c3ecf7b252a3 | 1016 | float symbPeriod_ms = (1 << current.sf) / (float)current.bwKHz; |
Wayne Roberts |
0:c3ecf7b252a3 | 1017 | float rxtx_turnaround_symbols = TX_RX_TURNAROUND_MS / symbPeriod_ms; |
Wayne Roberts |
0:c3ecf7b252a3 | 1018 | pc.printf("sp:%.3f, toSymbs:%.1f\r\n", symbPeriod_ms, rxtx_turnaround_symbols); |
Wayne Roberts |
0:c3ecf7b252a3 | 1019 | #if defined(SX126x_H) |
Wayne Roberts |
0:c3ecf7b252a3 | 1020 | if (rxtx_turnaround_symbols > (254-8)) { |
Wayne Roberts |
0:c3ecf7b252a3 | 1021 | rxtx_turnaround_symbols = 254-8; |
Wayne Roberts |
0:c3ecf7b252a3 | 1022 | pc.printf("\e[41msymbTo hit top\e[0m\r\n"); |
Wayne Roberts |
0:c3ecf7b252a3 | 1023 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 1024 | #endif |
Wayne Roberts |
0:c3ecf7b252a3 | 1025 | rxtx_turnaround_symbols = ceil(rxtx_turnaround_symbols); |
Wayne Roberts |
0:c3ecf7b252a3 | 1026 | pc.printf("turnSymb:%f\r\n", rxtx_turnaround_symbols); |
Wayne Roberts |
0:c3ecf7b252a3 | 1027 | Radio::SetLoRaSymbolTimeout(rxtx_turnaround_symbols + 8); |
Wayne Roberts |
0:c3ecf7b252a3 | 1028 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 1029 | |
Wayne Roberts |
0:c3ecf7b252a3 | 1030 | int main() |
Wayne Roberts |
0:c3ecf7b252a3 | 1031 | { |
Wayne Roberts |
0:c3ecf7b252a3 | 1032 | #ifdef RX_DBG_PIN |
Wayne Roberts |
0:c3ecf7b252a3 | 1033 | rx_dbg.input(); |
Wayne Roberts |
0:c3ecf7b252a3 | 1034 | rx_dbg.mode(PullUp); |
Wayne Roberts |
0:c3ecf7b252a3 | 1035 | #endif /* RX_DBG_PIN */ |
Wayne Roberts |
0:c3ecf7b252a3 | 1036 | |
Wayne Roberts |
0:c3ecf7b252a3 | 1037 | pc.attach(rx_callback); |
Wayne Roberts |
0:c3ecf7b252a3 | 1038 | pc.baud(115200); |
Wayne Roberts |
0:c3ecf7b252a3 | 1039 | pc.printf("--- Mbed OS filesystem example ---\n"); |
Wayne Roberts |
0:c3ecf7b252a3 | 1040 | |
Wayne Roberts |
0:c3ecf7b252a3 | 1041 | Radio::Init(&rev, SPI_HZ); |
Wayne Roberts |
0:c3ecf7b252a3 | 1042 | radio_readChip(); |
Wayne Roberts |
0:c3ecf7b252a3 | 1043 | |
Wayne Roberts |
0:c3ecf7b252a3 | 1044 | Radio::Standby(); |
Wayne Roberts |
0:c3ecf7b252a3 | 1045 | wait(0.05); |
Wayne Roberts |
0:c3ecf7b252a3 | 1046 | Radio::LoRaModemConfig(BW_KHZ, SPREADING_FACTOR, 1); |
Wayne Roberts |
0:c3ecf7b252a3 | 1047 | Radio::LoRaPacketConfig(8, false, true, false); // preambleLen, fixLen, crcOn, invIQ |
Wayne Roberts |
0:c3ecf7b252a3 | 1048 | Radio::SetChannel(CF_HZ); |
Wayne Roberts |
0:c3ecf7b252a3 | 1049 | |
Wayne Roberts |
0:c3ecf7b252a3 | 1050 | Radio::set_tx_dbm(TX_DBM); |
Wayne Roberts |
0:c3ecf7b252a3 | 1051 | |
Wayne Roberts |
0:c3ecf7b252a3 | 1052 | current.bwKHz = BW_KHZ; |
Wayne Roberts |
0:c3ecf7b252a3 | 1053 | current.sf = SPREADING_FACTOR; |
Wayne Roberts |
0:c3ecf7b252a3 | 1054 | set_symb_timeout(); |
Wayne Roberts |
0:c3ecf7b252a3 | 1055 | t.start(); |
Wayne Roberts |
0:c3ecf7b252a3 | 1056 | |
Wayne Roberts |
0:c3ecf7b252a3 | 1057 | wait(0.05); |
Wayne Roberts |
0:c3ecf7b252a3 | 1058 | rxCont(); |
Wayne Roberts |
0:c3ecf7b252a3 | 1059 | flags.verbose = true; |
Wayne Roberts |
0:c3ecf7b252a3 | 1060 | |
Wayne Roberts |
0:c3ecf7b252a3 | 1061 | // Try to mount the filesystem |
Wayne Roberts |
0:c3ecf7b252a3 | 1062 | pc.printf("Mounting the filesystem... "); |
Wayne Roberts |
0:c3ecf7b252a3 | 1063 | fflush(stdout); |
Wayne Roberts |
0:c3ecf7b252a3 | 1064 | int err = fs.mount(bd); |
Wayne Roberts |
0:c3ecf7b252a3 | 1065 | pc.printf("%s\r\n", (err ? "Fail :(" : "OK\r\n")); |
Wayne Roberts |
0:c3ecf7b252a3 | 1066 | if (err) { |
Wayne Roberts |
0:c3ecf7b252a3 | 1067 | // Reformat if we can't mount the filesystem |
Wayne Roberts |
0:c3ecf7b252a3 | 1068 | // this should only happen on the first boot |
Wayne Roberts |
0:c3ecf7b252a3 | 1069 | pc.printf("No filesystem found, formatting... "); |
Wayne Roberts |
0:c3ecf7b252a3 | 1070 | fflush(stdout); |
Wayne Roberts |
0:c3ecf7b252a3 | 1071 | err = fs.reformat(bd); |
Wayne Roberts |
0:c3ecf7b252a3 | 1072 | pc.printf("%s\r\n", (err ? "Fail :(" : "OK\r\n")); |
Wayne Roberts |
0:c3ecf7b252a3 | 1073 | if (err) { |
Wayne Roberts |
0:c3ecf7b252a3 | 1074 | error("error: %s (%d)\r\n", strerror(-err), err); |
Wayne Roberts |
0:c3ecf7b252a3 | 1075 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 1076 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 1077 | |
Wayne Roberts |
0:c3ecf7b252a3 | 1078 | txMinDelay_us = 2000; |
Wayne Roberts |
0:c3ecf7b252a3 | 1079 | add_txDelay_retry = 400; |
Wayne Roberts |
0:c3ecf7b252a3 | 1080 | th.start(callback(&queue, &EventQueue::dispatch_forever)); |
Wayne Roberts |
0:c3ecf7b252a3 | 1081 | |
Wayne Roberts |
0:c3ecf7b252a3 | 1082 | for (;;) { |
Wayne Roberts |
0:c3ecf7b252a3 | 1083 | Radio::service(); |
Wayne Roberts |
0:c3ecf7b252a3 | 1084 | |
Wayne Roberts |
0:c3ecf7b252a3 | 1085 | if (rxSize != 0) { |
Wayne Roberts |
0:c3ecf7b252a3 | 1086 | rxHandler(Radio::radio.rx_buf); |
Wayne Roberts |
0:c3ecf7b252a3 | 1087 | rxSize = 0; |
Wayne Roberts |
0:c3ecf7b252a3 | 1088 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 1089 | |
Wayne Roberts |
0:c3ecf7b252a3 | 1090 | if (flags.rxContStart) { |
Wayne Roberts |
0:c3ecf7b252a3 | 1091 | rxCont(); |
Wayne Roberts |
0:c3ecf7b252a3 | 1092 | flags.rxContStart = false; |
Wayne Roberts |
0:c3ecf7b252a3 | 1093 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 1094 | |
Wayne Roberts |
0:c3ecf7b252a3 | 1095 | if (flags.callRetry) { |
Wayne Roberts |
0:c3ecf7b252a3 | 1096 | retry(true); |
Wayne Roberts |
0:c3ecf7b252a3 | 1097 | flags.callRetry = false; |
Wayne Roberts |
0:c3ecf7b252a3 | 1098 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 1099 | |
Wayne Roberts |
0:c3ecf7b252a3 | 1100 | /* servicing txDone is higher priority than printing characters */ |
Wayne Roberts |
0:c3ecf7b252a3 | 1101 | while (!flags.txDonePending && printBuf_in != printBuf_out) { |
Wayne Roberts |
0:c3ecf7b252a3 | 1102 | pc.putc(printBuf[printBuf_out]); |
Wayne Roberts |
0:c3ecf7b252a3 | 1103 | if (++printBuf_out == sizeof(printBuf)) |
Wayne Roberts |
0:c3ecf7b252a3 | 1104 | printBuf_out = 0; |
Wayne Roberts |
0:c3ecf7b252a3 | 1105 | } |
Wayne Roberts |
0:c3ecf7b252a3 | 1106 | } // ..for (;;) |
Wayne Roberts |
0:c3ecf7b252a3 | 1107 | } |