UART console application for testing SX1272/SX1276

Dependencies:   SX127x mbed

/media/uploads/dudmuck/lora.png

This is a UART console test application for using SX127x library driver for SX1272/SX1276 radio transceivers. Serial console is provided at 57600bps. Refer to Serial Communication with a PC for information about using the serial port with your PC.

Using this command interface, you can exercise the functionality of radio chip without needing specialized software application for your PC.

Commands which can be used include ? to list available commands, or . to query status from radio chip, for example. The serial console allows you to configure the radio chip, such as setting spreading factor, bandwidth, operating frequency, etc.

A simple chat application is provided to try communications between two boards. The SX127x library object is instantiated with pin assignments generic arduino headers, but can be easily reassigned for any mbed board.

The same driver library can operate for both SX1272 and SX1276. Upon starting, the driver auto-detects whether SX1272 or SX1276 transceiver chip is connected by attempting to change the LowFrequencyModeOn bit in RegOpMode register. If this bit can be changed, then the radio device is SX1276. This bit is not implemented in SX1272. A few of the radio driver functions select behavior based on this detection. The differences between these two devices is small, from a software perspective.

Using with SX1276MB1xAS Shield

This component plugs into any board with arduino uno headers.

There are two different version of this shield. European version (MAS), and North American (LAS). The LAS shield uses PA_BOOST transmit pin to permit +20dBm power. The MAS version uses RFO transmit pin in Europe. This software reads RF switch pin (A4 pin) pulling resistor to determine which type of shield is installed.


Using with your own production board

This software is useful for validating RF performance your own LoRa board design, because only two external pins needs to be provided to PC (UART TX/RX). You can select an mbed platform which matches the CPU on your own board. If the memory size doesnt match exactly, you can export the program to an offline toolchain and edit the target type or linker file there.

Transmitter Test Guidelines

FSK mode is used for transmitter testing, because an unmodulated carrier can be sent, permitting easy measurement of TX power and frequency error.

commands used for transmitter testing:

  • frf915.0 change to your desired RF center frequency (in this case 915MHz)
  • L to toggle the radio chip into FSK mode.
  • fdev0 to configure TX frequency deviation to zero, to put the transmitted carrier on the center frequency.
  • pas to select which TX pin is connected to antenna matching (RFO vs PA_BOOST).
  • op<dBm> to configure TX power.
  • If you desire to test higher power PA_BOOST, use ocp<mA>
  • w 01 03 put radio chip into transmit mode (skips writing to FIFO). This will cause radio to transmit preamble, because the FIFO is empty in TX mode. Since Fdev is zero, an unmodulated carrier is sent.
  • Spectrum analyzer can now be used to to observe TX power, harmonics, power consumption, or frequency error.
  • stby to end transmission, or use h to reset radio chip to default condition.
  • Use period . command at any time to review current radio configuration.

LoRa transmitter testing

  • use L command to toggle radio into LoRa, if necessary.
  • Normally the tx command is used to manually send single packets.
  • txc will toggle TxContinuousMode in LoRa modem to send continuous modulated transmission.
  • Useful for checking adjacent channel power.
  • enter txc again to end transmission.

Receiver Test Guidelines

FSK mode is used for receiver sensitivity testing, allowing the use of a BERT signal generator (such as R/S SMIQ03B). Using this method provides real-time indication of receiver sensitivity, useful for tuning and impedance matching. The radio chip outputs DCLK and DATA digital signals which are connected back to BERT signal generator.

commands used for receiver testing:

  • L to toggle the radio chip into FSK mode.
  • datam to toggle FSK modem into continuous mode. This disables packet engine and gives direct access to demodulator.
  • configure DIO1 pin to DCLK function, and DIO2 pin to DATA function:
    • dio command to list current DIO pin asignments
    • d1 to cycle DIO1 function until Dclk is selected
    • d2 for DIO2, only Data function is available in FSK continuous mode
  • frf915.0 change to your desired RF center frequency (in this case 915MHz)
  • rx to start receiver
  • stby to disable receiver

Full command list

Arguments shown in square brackets [] indicate required. <> are optional, where leaving off the argument usually causes a read of the item, and providing the value causes a write operation. You should always have the radio chip datasheet on-hand when using these commands.

Hitting <enter> key by itself will repeat last command.
<Ctrl-C> will cancel an operation in progress.

command list: common commands (both LoRa and FSK)

commanddescription
. (period)print current radio status
?list available commands
Ltoggle active radio modem (LoRa vs FSK)
hhardware reset, put radio into default power-on condition
frf<MHz>get/set RF operating frequency
rxstart radio receiver (any received packets are printed onto your serial terminal)
rssiread instantaneous RSSI (level read at the time command is issued)
tx<%d>transmit test packet. Packet length value can be provided as argument, or uses last value if not provided
payl<%d>get/set payload length
bw<KHz>get/set bandwidth. In LoRa mode, both receive and transmit bandwidth are changed. For FSK, only receive bandwidth is affected. bwa accesses AFC bandwidth in FSK
pastoggle RFO / PA_BOOST transmit pin output selection
op<dBm>get/set TX output power. Value is provided in dBm. Special case is value of 20dBm (on PA_BOOST), which causes increase in TX DAC voltage
ocp<mA>get/set TX current limit, in milliamps. Necessary adjustment when +20dBm is used
dioshow DIO pin assignments
d<0-5>change DIO pin assignment, the pin number is given as arguement. Each pin has up to 4 possible functions
pres<%d>set preamble length. LoRa: number of symbols. FSK: number of bytes
crcontoggle crcOn
lnabcycle LNA-boost setting (receiver performance adjustment)
Rread all radio registers (use only while reading chip datasheet)
r[%x]read single radio register (use only while reading chip datasheet)
w[%x %x]write single radio register (use only while reading chip datasheet)
pllbwchange PLL bandwidth
stbyset chip mode to standby
sleepset chip mode to sleep
fstxset chip mode to fstx
fsrxset chip mode to fsrx
Eiger range test commandsdescription
pid<%d>get set ID number in range test payload
pertx<%d>start Eiger PER transmit. The count of packets to send is provided as arguement
perrxstart Eiger PER receive
txpd<%d>get/set tx delay between PER packets transmitted

command list: LoRa modem commands

LoRa commandLoRa description
iqinvtoggle RX IQ invert
cintoggle TX IQ invert
lhp<%d>(RX) get/set hop period
sync<%x>get/set sync (post-preamble gap, single byte)
cr<1-4>get/set codingRate
lhmtoggle explicit/implicit (explicit mode sends payload length with each packet)
sf<%d>get/set spreadingFactor (SF7 to SF12)
ldrtoggle LowDataRateOptimize (changes payload encoding, for long packets)
txctoggle TxContinuousMode
rxt<%d>get/set SymbTimeout
rxsstart RX_SINGLE (receives only for SymbTimeout symbols)
cad<%d num tries>run channel activity detection

command list: FSK modem commands

FSK commandFSK description
c<%d>get/set test cases. Several FSK bitrates/bandwidths pre-configured to give optimal performance.
fdev<kHz>(TX) get/set frequency deviation
mods(TX) increment modulation shaping
par(TX) increment paRamp
datamtoggle DataMode (packet/continuous)
fifottoggle TxStartCondition (FifoThreshold level vs FifoNotEmpty)
br<%f kbps>get/set bitrate
dcfincrement DcFree (manchester / whitening)
pktftoggle PacketFormat fixed/variable length
syncontoggle SyncOn (frame sync, SFD enable)
bitsynctoggle BitSyncOn (continuous mode only)
syncw<hex bytes>get/set syncword. Sync bytes are provided by hex octects separated by spaces.
fei(RX) read FEI
rxt(RX) increment RxTrigger (RX start on rssi vs. preamble detect)
rssit<-dBm>(RX) get/set rssi threshold (trigger level for RSSI interrupt)
rssis<%d>(RX) get/set rssi smoothing
rssio<%d>(RX) get/set rssi offset
agcauto(RX) toggle AgcAutoOn (true = LNA gain set automatically)
afcauto(RX) toggle AfcAutoOn
ac(RX) AfcClear
ar(RX) increment AutoRestartRxMode
alc(RX) toggle AfcAutoClearOn (only if AfcAutoOn is set)
prep(RX) toggle PreamblePolarity (0xAA vs 0x55)
pde(RX) toggle PreambleDetectorOn
pds<%d>(RX) get/set PreambleDetectorSize
pdt<%d>(RX) get/set PreambleDetectorTol
mp(RX) toggle MapPreambleDetect (DIO function RSSI vs PreambleDetect)
thr<%d>get/set FifoThreshold (triggers FifoLevel interrupt)
polltoggle poll_irq_en. Radio events read from DIO pins vs polling of IrqFlags register
Eempty out FIFO
clkoutincrement ClkOut divider
ookenter OOK mode
ooktincrement OokThreshType
ooksincrement OokPeakTheshStep
sqlch<%d>get/set OokFixedThresh
Committer:
Wayne Roberts
Date:
Tue May 22 15:55:15 2018 -0700
Revision:
24:9ba45aa15b53
Parent:
18:9530d682fd9a
remove TYPE_ABZ: use discovery-l073rz target.   updated to latest sx127x library.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dudmuck 18:9530d682fd9a 1 #if 0
dudmuck 18:9530d682fd9a 2
dudmuck 18:9530d682fd9a 3 #include "kermit.h"
dudmuck 18:9530d682fd9a 4
dudmuck 18:9530d682fd9a 5
dudmuck 18:9530d682fd9a 6 #ifdef RADIO_FILE_XFER
dudmuck 18:9530d682fd9a 7 typedef enum {
dudmuck 18:9530d682fd9a 8 XFER_STATE__NONE = 0,
dudmuck 18:9530d682fd9a 9 XFER_STATE_WAIT_S, // 1
dudmuck 18:9530d682fd9a 10 XFER_STATE_S_ACKED, // 2
dudmuck 18:9530d682fd9a 11 XFER_STATE_WAIT_F, // 3
dudmuck 18:9530d682fd9a 12 XFER_STATE_F_ACKED, // 4
dudmuck 18:9530d682fd9a 13 XFER_STATE_WAIT_DATA_ACK, // 5
dudmuck 18:9530d682fd9a 14 XFER_STATE_D_ACKED, // 6
dudmuck 18:9530d682fd9a 15 XFER_STATE_WAIT_Z, // 7
dudmuck 18:9530d682fd9a 16 XFER_STATE_Z_ACKED, // 8
dudmuck 18:9530d682fd9a 17 XFER_STATE_WAIT_B, // 9
dudmuck 18:9530d682fd9a 18 XFER_STATE_B_ACKED // 10
dudmuck 18:9530d682fd9a 19 } xfer_state_e;
dudmuck 18:9530d682fd9a 20
dudmuck 18:9530d682fd9a 21 typedef struct {
dudmuck 18:9530d682fd9a 22 bool radio_initialized;
dudmuck 18:9530d682fd9a 23 bool do_tx;
dudmuck 18:9530d682fd9a 24 xfer_state_e state;
dudmuck 18:9530d682fd9a 25 int fail_length;
dudmuck 18:9530d682fd9a 26 float tx_sleep;
dudmuck 18:9530d682fd9a 27 char seq_from_rx;
dudmuck 18:9530d682fd9a 28 float data_tx_delay;
dudmuck 18:9530d682fd9a 29 char data_ack_char; // tmp debug
dudmuck 18:9530d682fd9a 30 } radio_xfer_t;
dudmuck 18:9530d682fd9a 31 radio_xfer_t radio_xfer;
dudmuck 18:9530d682fd9a 32
dudmuck 18:9530d682fd9a 33 #endif /* RADIO_FILE_XFER */
dudmuck 18:9530d682fd9a 34
dudmuck 18:9530d682fd9a 35 #ifdef TARGET_NUCLEO_F103RB
dudmuck 18:9530d682fd9a 36 /* NUCLEO-F103RB UARTs:
dudmuck 18:9530d682fd9a 37 * # TX RX use
dudmuck 18:9530d682fd9a 38 * 2 PA_2 PA_3 mbed default
dudmuck 18:9530d682fd9a 39 * 1 PA_9 PA_10 PA_9=D8=DIO4a PA_10=D2=DIO0
dudmuck 18:9530d682fd9a 40 * 3 PB_10 PB_11 PB_10=D6=nothing PB11=C26=4.7uF
dudmuck 18:9530d682fd9a 41 * 1 PB_6 PB_7 remap PB_6=D10=SX1276_NSS PB7=CN7-21
dudmuck 18:9530d682fd9a 42 * 3 PC_10 PC_11 partial remap
dudmuck 18:9530d682fd9a 43 * SX127x radio(D11, D12, D13, D10, A0, D2, D3);
dudmuck 18:9530d682fd9a 44 */
dudmuck 18:9530d682fd9a 45 Serial pc_b(PB_10, PB_11); //PB_10=D6=nothing PB11=C26=4.7uF
dudmuck 18:9530d682fd9a 46 CRC_HandleTypeDef CrcHandle;
dudmuck 18:9530d682fd9a 47 #endif /* TARGET_NUCLEO_F103RB */
dudmuck 18:9530d682fd9a 48
dudmuck 18:9530d682fd9a 49 #ifdef TARGET_LPC11U6X
dudmuck 18:9530d682fd9a 50 /* U1_RXD: PIO0_13=A2, PIO1_2=P2-24
dudmuck 18:9530d682fd9a 51 * U1_TXD: PIO0_14=A1, PIO1_8=P2-50
dudmuck 18:9530d682fd9a 52 * U0_RXD: PIO0_18=mbed, PIO1_26=D5, PIO1_17=J4-4
dudmuck 18:9530d682fd9a 53 * U0_TXD: PIO0_19=mbed, PIO1_18=D2, PIO1_27=D6
dudmuck 18:9530d682fd9a 54 * U2_RXD: PIO0_20=P2-14, PIO1_6=P2-53
dudmuck 18:9530d682fd9a 55 * U2_TXD: PIO1_0=P2-13, PIO1_23=J4-1
dudmuck 18:9530d682fd9a 56 * PIO2_3: U3_RXD=D9
dudmuck 18:9530d682fd9a 57 * PIO2_4: U3_TXD=J8-3
dudmuck 18:9530d682fd9a 58 * PIO2_11: U4_RXD
dudmuck 18:9530d682fd9a 59 */
dudmuck 18:9530d682fd9a 60 Serial pc_b(P1_8, P1_2); // TX=PIO1_8=P2-50, RX=PIO1_2=P2-24
dudmuck 18:9530d682fd9a 61 #endif
dudmuck 18:9530d682fd9a 62
dudmuck 18:9530d682fd9a 63 #define MAX_LEN_FRAME 130 /* */
dudmuck 18:9530d682fd9a 64
dudmuck 18:9530d682fd9a 65 Kermit::Kermit(SX127x_lora& _lora) : lora(_lora)
dudmuck 18:9530d682fd9a 66 {
dudmuck 18:9530d682fd9a 67 uart_rx_enabled = false;
dudmuck 18:9530d682fd9a 68 }
dudmuck 18:9530d682fd9a 69
dudmuck 18:9530d682fd9a 70 Kermit::~Kermit()
dudmuck 18:9530d682fd9a 71 {
dudmuck 18:9530d682fd9a 72 }
dudmuck 18:9530d682fd9a 73
dudmuck 18:9530d682fd9a 74 uint8_t Kermit::tochar(uint8_t c) { return c + 32; }
dudmuck 18:9530d682fd9a 75 uint8_t Kermit::unchar(uint8_t c) { return c - 32; }
dudmuck 18:9530d682fd9a 76 uint8_t Kermit::ctl(uint8_t c) { return c ^ 64; }
dudmuck 18:9530d682fd9a 77
dudmuck 18:9530d682fd9a 78 void Kermit::rx_callback(uint8_t c)
dudmuck 18:9530d682fd9a 79 {
dudmuck 18:9530d682fd9a 80 static uint8_t ctrl_c_cnt = 0;
dudmuck 18:9530d682fd9a 81
dudmuck 18:9530d682fd9a 82 if (c == 3) {
dudmuck 18:9530d682fd9a 83 if (++ctrl_c_cnt > 3) {
dudmuck 18:9530d682fd9a 84 uart_rx_enabled = false;
dudmuck 18:9530d682fd9a 85 end_cause = 3;
dudmuck 18:9530d682fd9a 86 end = true;
dudmuck 18:9530d682fd9a 87 return;
dudmuck 18:9530d682fd9a 88 }
dudmuck 18:9530d682fd9a 89 } else
dudmuck 18:9530d682fd9a 90 ctrl_c_cnt = 0;
dudmuck 18:9530d682fd9a 91
dudmuck 18:9530d682fd9a 92 switch (state) {
dudmuck 18:9530d682fd9a 93 case KERMIT_STATE_WAIT_SOH:
dudmuck 18:9530d682fd9a 94 if (c == SOH) {
dudmuck 18:9530d682fd9a 95 state = KERMIT_STATE_WAIT_LEN;
dudmuck 18:9530d682fd9a 96 }
dudmuck 18:9530d682fd9a 97 break;
dudmuck 18:9530d682fd9a 98 case KERMIT_STATE_WAIT_LEN:
dudmuck 18:9530d682fd9a 99 uart_rx_sum = c;
dudmuck 18:9530d682fd9a 100 uart_rx_length = unchar(c) - 2;
dudmuck 18:9530d682fd9a 101 state = KERMIT_STATE_WAIT_SEQ;
dudmuck 18:9530d682fd9a 102 break;
dudmuck 18:9530d682fd9a 103 case KERMIT_STATE_WAIT_SEQ:
dudmuck 18:9530d682fd9a 104 uart_rx_sum += c;
dudmuck 18:9530d682fd9a 105 uart_rx_seq = unchar(c);
dudmuck 18:9530d682fd9a 106 state = KERMIT_STATE_WAIT_TYPE;
dudmuck 18:9530d682fd9a 107 break;
dudmuck 18:9530d682fd9a 108 case KERMIT_STATE_WAIT_TYPE:
dudmuck 18:9530d682fd9a 109 uart_rx_sum += c;
dudmuck 18:9530d682fd9a 110 uart_rx_type = c;
dudmuck 18:9530d682fd9a 111 state = KERMIT_STATE_DATA;
dudmuck 18:9530d682fd9a 112 uart_rx_data_idx = 0;
dudmuck 18:9530d682fd9a 113 break;
dudmuck 18:9530d682fd9a 114 case KERMIT_STATE_DATA:
dudmuck 18:9530d682fd9a 115 uart_rx_data[uart_rx_data_idx++] = c;
dudmuck 18:9530d682fd9a 116 if (uart_rx_data_idx == uart_rx_length) {
dudmuck 18:9530d682fd9a 117 char check = tochar((uart_rx_sum + ((uart_rx_sum & 192)/64)) & 63);
dudmuck 18:9530d682fd9a 118 if (check == c) {
dudmuck 18:9530d682fd9a 119 if (parse_rx()) {
dudmuck 18:9530d682fd9a 120 //kermit_state = KERMIT_STATE_GET_EOL;
dudmuck 18:9530d682fd9a 121 end_cause = 4;
dudmuck 18:9530d682fd9a 122 /////////////////////////
dudmuck 18:9530d682fd9a 123 uart_tx_data_idx = 0;
dudmuck 18:9530d682fd9a 124 uart_tx_data[uart_tx_data_idx++] = 'E';
dudmuck 18:9530d682fd9a 125 uart_tx_data[uart_tx_data_idx++] = uart_rx_type;
dudmuck 18:9530d682fd9a 126 uart_do_tx = true;
dudmuck 18:9530d682fd9a 127 end_after_tx = true;
dudmuck 18:9530d682fd9a 128 /////////////////////////
dudmuck 18:9530d682fd9a 129 break;
dudmuck 18:9530d682fd9a 130 }
dudmuck 18:9530d682fd9a 131 }
dudmuck 18:9530d682fd9a 132 if (uart_rx_type == 'E') {
dudmuck 18:9530d682fd9a 133 state = KERMIT_STATE_GET_EOL;
dudmuck 18:9530d682fd9a 134 end_cause = 2;
dudmuck 18:9530d682fd9a 135 } else
dudmuck 18:9530d682fd9a 136 state = KERMIT_STATE_WAIT_SOH;
dudmuck 18:9530d682fd9a 137 } else
dudmuck 18:9530d682fd9a 138 uart_rx_sum += c;
dudmuck 18:9530d682fd9a 139 break;
dudmuck 18:9530d682fd9a 140 case KERMIT_STATE_GET_EOL:
dudmuck 18:9530d682fd9a 141 uart_rx_enabled = false;
dudmuck 18:9530d682fd9a 142 end = true;
dudmuck 18:9530d682fd9a 143 if (uart_rx_type == 'E')
dudmuck 18:9530d682fd9a 144 show_error = true;
dudmuck 18:9530d682fd9a 145 uart_rx_data[uart_rx_data_idx-1] = 0; //null terminate, this is ascii text string
dudmuck 18:9530d682fd9a 146 state = KERMIT_STATE_OFF;
dudmuck 18:9530d682fd9a 147 break;
dudmuck 18:9530d682fd9a 148 } // ..switch (state)
dudmuck 18:9530d682fd9a 149 }
dudmuck 18:9530d682fd9a 150
dudmuck 18:9530d682fd9a 151 #ifdef RADIO_FILE_XFER
dudmuck 18:9530d682fd9a 152 void Kermit::radio_xfer_rx()
dudmuck 18:9530d682fd9a 153 {
dudmuck 18:9530d682fd9a 154 radio_xfer.seq_from_rx = lora.m_xcvr.rx_buf[0];
dudmuck 18:9530d682fd9a 155 pc_b.printf("rfrx:%02x,%c\r\n", radio_xfer.seq_from_rx, lora.m_xcvr.rx_buf[1]);
dudmuck 18:9530d682fd9a 156
dudmuck 18:9530d682fd9a 157 switch (radio_xfer.state) {
dudmuck 18:9530d682fd9a 158 case XFER_STATE_WAIT_S: // 'S' response
dudmuck 18:9530d682fd9a 159 end_cause = 0;
dudmuck 18:9530d682fd9a 160 filename[0] = 0;
dudmuck 18:9530d682fd9a 161 uart_tx_data_idx = 0;
dudmuck 18:9530d682fd9a 162 if (lora.m_xcvr.rx_buf[1] == 'S') {
dudmuck 18:9530d682fd9a 163 uart_tx_data[uart_tx_data_idx++] = 'Y';
dudmuck 18:9530d682fd9a 164 uart_tx_data[uart_tx_data_idx++] = tochar(94); // MAXL
dudmuck 18:9530d682fd9a 165 //uart_tx_data[uart_tx_data_idx++] = tochar(kermit.time-1);//TIME
dudmuck 18:9530d682fd9a 166 uart_tx_data[uart_tx_data_idx++] = tochar(1);//TIME (when reply from other radio is bad)
dudmuck 18:9530d682fd9a 167 uart_tx_data[uart_tx_data_idx++] = tochar(0); //NPAD
dudmuck 18:9530d682fd9a 168 uart_tx_data[uart_tx_data_idx++] = tochar(32); //PADC
dudmuck 18:9530d682fd9a 169 uart_tx_data[uart_tx_data_idx++] = tochar('\r'); //EOL
dudmuck 18:9530d682fd9a 170 uart_tx_data[uart_tx_data_idx++] = '#'; //QCTL
dudmuck 18:9530d682fd9a 171 uart_tx_data[uart_tx_data_idx++] = 'Y'; //QBIN
dudmuck 18:9530d682fd9a 172 uart_tx_data[uart_tx_data_idx++] = '1'; //CHKT
dudmuck 18:9530d682fd9a 173 uart_tx_data[uart_tx_data_idx++] = '~'; //REPT
dudmuck 18:9530d682fd9a 174 } else
dudmuck 18:9530d682fd9a 175 uart_tx_data[uart_tx_data_idx++] = 'E';
dudmuck 18:9530d682fd9a 176
dudmuck 18:9530d682fd9a 177 uart_do_tx = true;
dudmuck 18:9530d682fd9a 178 radio_xfer.state = XFER_STATE_S_ACKED;
dudmuck 18:9530d682fd9a 179 break;
dudmuck 18:9530d682fd9a 180 case XFER_STATE_WAIT_F: // 'F' response
dudmuck 18:9530d682fd9a 181 uart_tx_data_idx = 0;
dudmuck 18:9530d682fd9a 182 if (lora.m_xcvr.rx_buf[1] == 'F') {
dudmuck 18:9530d682fd9a 183 uart_tx_data[uart_tx_data_idx++] = 'Y';
dudmuck 18:9530d682fd9a 184 } else
dudmuck 18:9530d682fd9a 185 uart_tx_data[uart_tx_data_idx++] = 'E';
dudmuck 18:9530d682fd9a 186
dudmuck 18:9530d682fd9a 187 uart_do_tx = true;
dudmuck 18:9530d682fd9a 188 radio_xfer.state = XFER_STATE_F_ACKED;
dudmuck 18:9530d682fd9a 189 break;
dudmuck 18:9530d682fd9a 190 case XFER_STATE_WAIT_DATA_ACK:
dudmuck 18:9530d682fd9a 191 if (lora.m_xcvr.rx_buf[1] == 'E' || lora.m_xcvr.rx_buf[1] == 'Y' || lora.m_xcvr.rx_buf[1] == 'N') {
dudmuck 18:9530d682fd9a 192 uart_tx_data_idx = 0;
dudmuck 18:9530d682fd9a 193 radio_xfer.data_ack_char = lora.m_xcvr.rx_buf[1];
dudmuck 18:9530d682fd9a 194 uart_tx_data[uart_tx_data_idx++] = lora.m_xcvr.rx_buf[1];
dudmuck 18:9530d682fd9a 195 uart_do_tx = true;
dudmuck 18:9530d682fd9a 196 radio_xfer.state = XFER_STATE_D_ACKED;
dudmuck 18:9530d682fd9a 197 }
dudmuck 18:9530d682fd9a 198 break;
dudmuck 18:9530d682fd9a 199 case XFER_STATE_WAIT_Z:
dudmuck 18:9530d682fd9a 200 uart_tx_data_idx = 0;
dudmuck 18:9530d682fd9a 201 uart_tx_data[uart_tx_data_idx++] = lora.m_xcvr.rx_buf[1];
dudmuck 18:9530d682fd9a 202 uart_do_tx = true;
dudmuck 18:9530d682fd9a 203 radio_xfer.state = XFER_STATE_Z_ACKED;
dudmuck 18:9530d682fd9a 204 break;
dudmuck 18:9530d682fd9a 205 case XFER_STATE_WAIT_B:
dudmuck 18:9530d682fd9a 206 uart_tx_data_idx = 0;
dudmuck 18:9530d682fd9a 207 uart_tx_data[uart_tx_data_idx++] = lora.m_xcvr.rx_buf[1];
dudmuck 18:9530d682fd9a 208 uart_do_tx = true;
dudmuck 18:9530d682fd9a 209 end_after_tx = true;
dudmuck 18:9530d682fd9a 210 radio_xfer.state = XFER_STATE_B_ACKED;
dudmuck 18:9530d682fd9a 211 break;
dudmuck 18:9530d682fd9a 212 } // ..switch (radio_xfer.state)
dudmuck 18:9530d682fd9a 213 //radio_xfer.ack_waiting = false;
dudmuck 18:9530d682fd9a 214 }
dudmuck 18:9530d682fd9a 215 #endif /* RADIO_FILE_XFER */
dudmuck 18:9530d682fd9a 216
dudmuck 18:9530d682fd9a 217
dudmuck 18:9530d682fd9a 218 #ifdef TARGET_STM
dudmuck 18:9530d682fd9a 219 uint32_t Kermit::_HAL_CRC_Calculate(uint32_t pBuffer[], uint32_t BufferLength)
dudmuck 18:9530d682fd9a 220 {
dudmuck 18:9530d682fd9a 221 uint32_t index = 0;
dudmuck 18:9530d682fd9a 222
dudmuck 18:9530d682fd9a 223 /* Reset CRC Calculation Unit */
dudmuck 18:9530d682fd9a 224 __HAL_CRC_DR_RESET(&CrcHandle);
dudmuck 18:9530d682fd9a 225 __nop();
dudmuck 18:9530d682fd9a 226 __nop();
dudmuck 18:9530d682fd9a 227 __nop();
dudmuck 18:9530d682fd9a 228 __nop();
dudmuck 18:9530d682fd9a 229 __nop();
dudmuck 18:9530d682fd9a 230
dudmuck 18:9530d682fd9a 231 /* Enter Data to the CRC calculator */
dudmuck 18:9530d682fd9a 232 for(index = 0; index < BufferLength; index++)
dudmuck 18:9530d682fd9a 233 {
dudmuck 18:9530d682fd9a 234 CrcHandle.Instance->DR = pBuffer[index];
dudmuck 18:9530d682fd9a 235 //printf("Calc %08x\r\n", CrcHandle.Instance->DR);
dudmuck 18:9530d682fd9a 236 __nop();
dudmuck 18:9530d682fd9a 237 __nop();
dudmuck 18:9530d682fd9a 238 __nop();
dudmuck 18:9530d682fd9a 239 }
dudmuck 18:9530d682fd9a 240
dudmuck 18:9530d682fd9a 241 /* Return the CRC computed value */
dudmuck 18:9530d682fd9a 242 return CrcHandle.Instance->DR;
dudmuck 18:9530d682fd9a 243 }
dudmuck 18:9530d682fd9a 244
dudmuck 18:9530d682fd9a 245
dudmuck 18:9530d682fd9a 246 // 20000788 08003101 08007e35 08007e37 08007e39 08007e3b 08007e3d 00000000 00000000 00000000 00000000 08007e3f 08007e41 00000000 08007e43 08007e45 0000311b
dudmuck 18:9530d682fd9a 247 void Kermit::test_crc()
dudmuck 18:9530d682fd9a 248 {
dudmuck 18:9530d682fd9a 249 uint32_t tbuf[17] = { 0x20000788, 0x08003101, 0x08007e35, 0x08007e37, 0x08007e39, 0x08007e3b, 0x08007e3d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x08007e3f, 0x08007e41, 0x00000000, 0x08007e43, 0x08007e45, 0x0000311b };
dudmuck 18:9530d682fd9a 250 uint32_t crc;
dudmuck 18:9530d682fd9a 251 int i;
dudmuck 18:9530d682fd9a 252 crc = _HAL_CRC_Calculate(tbuf, 17);
dudmuck 18:9530d682fd9a 253 printf("Crc:%08x\r\n", crc);
dudmuck 18:9530d682fd9a 254 __HAL_CRC_DR_RESET(&CrcHandle);
dudmuck 18:9530d682fd9a 255 __nop();
dudmuck 18:9530d682fd9a 256 __nop();
dudmuck 18:9530d682fd9a 257 __nop();
dudmuck 18:9530d682fd9a 258 __nop();
dudmuck 18:9530d682fd9a 259 __nop();
dudmuck 18:9530d682fd9a 260 for (i = 0; i < 17; i++) {
dudmuck 18:9530d682fd9a 261 CrcHandle.Instance->DR = tbuf[i];
dudmuck 18:9530d682fd9a 262 printf("%08x: %08x\r\n", tbuf[i], CrcHandle.Instance->DR);
dudmuck 18:9530d682fd9a 263 __nop();
dudmuck 18:9530d682fd9a 264 __nop();
dudmuck 18:9530d682fd9a 265 __nop();
dudmuck 18:9530d682fd9a 266
dudmuck 18:9530d682fd9a 267 }
dudmuck 18:9530d682fd9a 268 printf(": %08x\r\n", CrcHandle.Instance->DR);
dudmuck 18:9530d682fd9a 269
dudmuck 18:9530d682fd9a 270 }
dudmuck 18:9530d682fd9a 271 #else // !STM...
dudmuck 18:9530d682fd9a 272 const uint32_t CrcTable[16] = { // Nibble lookup table for 0x04C11DB7 polynomial
dudmuck 18:9530d682fd9a 273 0x00000000,0x04C11DB7,0x09823B6E,0x0D4326D9,0x130476DC,0x17C56B6B,0x1A864DB2,0x1E475005,
dudmuck 18:9530d682fd9a 274 0x2608EDB8,0x22C9F00F,0x2F8AD6D6,0x2B4BCB61,0x350C9B64,0x31CD86D3,0x3C8EA00A,0x384FBDBD };
dudmuck 18:9530d682fd9a 275 uint32_t Kermit::_HAL_CRC_Calculate(uint32_t u32_buf[], uint32_t Size)
dudmuck 18:9530d682fd9a 276 {
dudmuck 18:9530d682fd9a 277 int i = 0;
dudmuck 18:9530d682fd9a 278 uint32_t Crc = 0xffffffff;
dudmuck 18:9530d682fd9a 279
dudmuck 18:9530d682fd9a 280 while(Size--)
dudmuck 18:9530d682fd9a 281 {
dudmuck 18:9530d682fd9a 282 Crc = Crc ^ u32_buf[i++];
dudmuck 18:9530d682fd9a 283
dudmuck 18:9530d682fd9a 284 // Process 32-bits, 4 at a time, or 8 rounds
dudmuck 18:9530d682fd9a 285 Crc = (Crc << 4) ^ CrcTable[Crc >> 28]; // Assumes 32-bit reg, masking index to 4-bits
dudmuck 18:9530d682fd9a 286 Crc = (Crc << 4) ^ CrcTable[Crc >> 28]; // 0x04C11DB7 Polynomial used in STM32
dudmuck 18:9530d682fd9a 287 Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
dudmuck 18:9530d682fd9a 288 Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
dudmuck 18:9530d682fd9a 289 Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
dudmuck 18:9530d682fd9a 290 Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
dudmuck 18:9530d682fd9a 291 Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
dudmuck 18:9530d682fd9a 292 Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
dudmuck 18:9530d682fd9a 293 }
dudmuck 18:9530d682fd9a 294
dudmuck 18:9530d682fd9a 295 return(Crc);
dudmuck 18:9530d682fd9a 296 }
dudmuck 18:9530d682fd9a 297 uint32_t g_tbuf[17] = { 0x20000788, 0x08003101, 0x08007e35, 0x08007e37, 0x08007e39, 0x08007e3b, 0x08007e3d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x08007e3f, 0x08007e41, 0x00000000, 0x08007e43, 0x08007e45, 0x0000311b };
dudmuck 18:9530d682fd9a 298
dudmuck 18:9530d682fd9a 299 // 20000788 08003101 08007e35 08007e37 08007e39 08007e3b 08007e3d 00000000 00000000 00000000 00000000 08007e3f 08007e41 00000000 08007e43 08007e45 0000311b
dudmuck 18:9530d682fd9a 300 void Kermit::test_crc()
dudmuck 18:9530d682fd9a 301 {
dudmuck 18:9530d682fd9a 302 //uint32_t tbuf[17] = { 0x20000788, 0x08003101, 0x08007e35, 0x08007e37, 0x08007e39, 0x08007e3b, 0x08007e3d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x08007e3f, 0x08007e41, 0x00000000, 0x08007e43, 0x08007e45, 0x0000311b };
dudmuck 18:9530d682fd9a 303 uint32_t crc;
dudmuck 18:9530d682fd9a 304 //uint32_t *u32_ptr;
dudmuck 18:9530d682fd9a 305 //u32_ptr = (uint32_t*)bin_data;
dudmuck 18:9530d682fd9a 306
dudmuck 18:9530d682fd9a 307 printf("test_crc...%p\r\n", g_tbuf);
dudmuck 18:9530d682fd9a 308 //u32_ptr[0] = 0x20000788;
dudmuck 18:9530d682fd9a 309 //u32_ptr[1] = 0x08003101;
dudmuck 18:9530d682fd9a 310
dudmuck 18:9530d682fd9a 311 //crc = _HAL_CRC_Calculate((uint32_t*)bin_data, 17);
dudmuck 18:9530d682fd9a 312 crc = _HAL_CRC_Calculate(g_tbuf, 17);
dudmuck 18:9530d682fd9a 313 printf("crc:%08x\r\n", crc);
dudmuck 18:9530d682fd9a 314 }
dudmuck 18:9530d682fd9a 315 #endif /* !TARGET_STM */
dudmuck 18:9530d682fd9a 316
dudmuck 18:9530d682fd9a 317
dudmuck 18:9530d682fd9a 318 int Kermit::parse_rx()
dudmuck 18:9530d682fd9a 319 {
dudmuck 18:9530d682fd9a 320 static char prev_uart_rx_seq;
dudmuck 18:9530d682fd9a 321 static uint32_t prev_bin_data_idx;
dudmuck 18:9530d682fd9a 322
dudmuck 18:9530d682fd9a 323 //pc_b.printf("kermit_parse_rx %02x '%c'\r\n", uart_rx_seq, uartrx_type);
dudmuck 18:9530d682fd9a 324 #ifdef RADIO_FILE_XFER
dudmuck 18:9530d682fd9a 325 lora.m_xcvr.tx_buf[0] = uart_rx_seq;
dudmuck 18:9530d682fd9a 326 lora.m_xcvr.tx_buf[1] = uart_rx_type;
dudmuck 18:9530d682fd9a 327 #endif /* RADIO_FILE_XFER */
dudmuck 18:9530d682fd9a 328
dudmuck 18:9530d682fd9a 329 if (uart_rx_type == 'S') {
dudmuck 18:9530d682fd9a 330 got_send_init = true;
dudmuck 18:9530d682fd9a 331
dudmuck 18:9530d682fd9a 332 if (uart_rx_data_idx > 0)
dudmuck 18:9530d682fd9a 333 maxl = unchar(uart_rx_data[0]);
dudmuck 18:9530d682fd9a 334 if (uart_rx_data_idx > 1)
dudmuck 18:9530d682fd9a 335 time = unchar(uart_rx_data[1]);
dudmuck 18:9530d682fd9a 336 if (uart_rx_data_idx > 2)
dudmuck 18:9530d682fd9a 337 npad = unchar(uart_rx_data[2]);
dudmuck 18:9530d682fd9a 338 if (uart_rx_data_idx > 3)
dudmuck 18:9530d682fd9a 339 padc = unchar(uart_rx_data[3]);
dudmuck 18:9530d682fd9a 340 if (uart_rx_data_idx > 4)
dudmuck 18:9530d682fd9a 341 eol = unchar(uart_rx_data[4]);
dudmuck 18:9530d682fd9a 342 if (uart_rx_data_idx > 5)
dudmuck 18:9530d682fd9a 343 qctl = uart_rx_data[5]; // verbatim
dudmuck 18:9530d682fd9a 344 if (uart_rx_data_idx > 6)
dudmuck 18:9530d682fd9a 345 qbin = uart_rx_data[6]; // verbatim 'Y'==agree-to-8bit, 'N'=no-8bit '&'==I need this char to do 8bit quoting
dudmuck 18:9530d682fd9a 346 if (uart_rx_data_idx > 7)
dudmuck 18:9530d682fd9a 347 chkt = uart_rx_data[7]; // verbatim
dudmuck 18:9530d682fd9a 348 if (uart_rx_data_idx > 8)
dudmuck 18:9530d682fd9a 349 rept = uart_rx_data[8];
dudmuck 18:9530d682fd9a 350
dudmuck 18:9530d682fd9a 351 #ifdef RADIO_FILE_XFER
dudmuck 18:9530d682fd9a 352 lora.RegPayloadLength = 2;
dudmuck 18:9530d682fd9a 353 lora.m_xcvr.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
dudmuck 18:9530d682fd9a 354 radio_xfer.do_tx = true;
dudmuck 18:9530d682fd9a 355 radio_xfer.state = XFER_STATE_WAIT_S;
dudmuck 18:9530d682fd9a 356 #else
dudmuck 18:9530d682fd9a 357 uart_tx_data_idx = 0;
dudmuck 18:9530d682fd9a 358 uart_tx_data[uart_tx_data_idx++] = 'Y';
dudmuck 18:9530d682fd9a 359 uart_tx_data[uart_tx_data_idx++] = tochar(94); // MAXL
dudmuck 18:9530d682fd9a 360 uart_tx_data[uart_tx_data_idx++] = tochar(kermit.time-1);//TIME
dudmuck 18:9530d682fd9a 361 uart_tx_data[uart_tx_data_idx++] = tochar(0); //NPAD
dudmuck 18:9530d682fd9a 362 uart_tx_data[uart_tx_data_idx++] = tochar(32); //PADC
dudmuck 18:9530d682fd9a 363 uart_tx_data[uart_tx_data_idx++] = tochar('\r'); //EOL
dudmuck 18:9530d682fd9a 364 uart_tx_data[uart_tx_data_idx++] = '#'; //QCTL
dudmuck 18:9530d682fd9a 365 uart_tx_data[uart_tx_data_idx++] = 'Y'; //QBIN
dudmuck 18:9530d682fd9a 366 uart_tx_data[uart_tx_data_idx++] = '1'; //CHKT
dudmuck 18:9530d682fd9a 367 uart_tx_data[uart_tx_data_idx++] = '~'; //REPT
dudmuck 18:9530d682fd9a 368 uart_do_tx = true;
dudmuck 18:9530d682fd9a 369 #endif /* !RADIO_FILE_XFER */
dudmuck 18:9530d682fd9a 370 pc_b.printf("S\r\n");
dudmuck 18:9530d682fd9a 371 } else if (uart_rx_type == 'F') {
dudmuck 18:9530d682fd9a 372 /* keep filename if desired */
dudmuck 18:9530d682fd9a 373 memcpy(filename, uart_rx_data, uart_rx_data_idx-1);
dudmuck 18:9530d682fd9a 374 filename[uart_rx_data_idx-1] = 0;
dudmuck 18:9530d682fd9a 375
dudmuck 18:9530d682fd9a 376 total_file_bytes = 0;
dudmuck 18:9530d682fd9a 377 prev_uart_rx_seq = uart_rx_seq;
dudmuck 18:9530d682fd9a 378 prev_bin_data_idx = 0;
dudmuck 18:9530d682fd9a 379 #ifdef XXD_PRINT
dudmuck 18:9530d682fd9a 380 xxd_total_file_bytes_so_far = 0;
dudmuck 18:9530d682fd9a 381 xxd_remainder = 0;
dudmuck 18:9530d682fd9a 382 #endif /* XXD_PRINT */
dudmuck 18:9530d682fd9a 383
dudmuck 18:9530d682fd9a 384 #ifdef RADIO_FILE_XFER
dudmuck 18:9530d682fd9a 385 lora.RegPayloadLength = 2;
dudmuck 18:9530d682fd9a 386 lora.m_xcvr.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
dudmuck 18:9530d682fd9a 387 radio_xfer.do_tx = true;
dudmuck 18:9530d682fd9a 388 radio_xfer.tx_sleep = radio_xfer.data_tx_delay;
dudmuck 18:9530d682fd9a 389 radio_xfer.state = XFER_STATE_WAIT_F;
dudmuck 18:9530d682fd9a 390 #else
dudmuck 18:9530d682fd9a 391 uart_tx_data_idx = 0;
dudmuck 18:9530d682fd9a 392 uart_tx_data[uart_tx_data_idx++] = 'Y';
dudmuck 18:9530d682fd9a 393 /*memcpy(uart_tx_data+1, uart_rx_data, uart_rx_data_idx-1);
dudmuck 18:9530d682fd9a 394 uart_tx_data_idx += uart_rx_data_idx-1;*/
dudmuck 18:9530d682fd9a 395 uart_do_tx = true;
dudmuck 18:9530d682fd9a 396 #endif /* !RADIO_FILE_XFER */
dudmuck 18:9530d682fd9a 397 bin_data = (uint8_t*)bin_data_u32;
dudmuck 18:9530d682fd9a 398 pc_b.printf("F\r\n");
dudmuck 18:9530d682fd9a 399 } else if (uart_rx_type == 'D') {
dudmuck 18:9530d682fd9a 400 int i;
dudmuck 18:9530d682fd9a 401 #ifdef RADIO_FILE_XFER
dudmuck 18:9530d682fd9a 402 uint8_t len_for_crc;
dudmuck 18:9530d682fd9a 403 //uint32_t* u32_ptr;
dudmuck 18:9530d682fd9a 404 uint32_t uwCRCValue;
dudmuck 18:9530d682fd9a 405 #endif /* RADIO_FILE_XFER */
dudmuck 18:9530d682fd9a 406
dudmuck 18:9530d682fd9a 407 bin_data_idx = 0;
dudmuck 18:9530d682fd9a 408
dudmuck 18:9530d682fd9a 409 #ifdef KERMIT_DATA_PRINT
dudmuck 18:9530d682fd9a 410 pc_b.printf("%04x: ", kermit.total_file_bytes);
dudmuck 18:9530d682fd9a 411 #endif /* */
dudmuck 18:9530d682fd9a 412
dudmuck 18:9530d682fd9a 413 uart_rx_data_idx--; // cut off trailing sum byte
dudmuck 18:9530d682fd9a 414 for (i = 0; i < uart_rx_data_idx; i++) {
dudmuck 18:9530d682fd9a 415 if (uart_rx_data[i] == qctl) { // escaped..
dudmuck 18:9530d682fd9a 416 uint8_t in = uart_rx_data[++i];
dudmuck 18:9530d682fd9a 417 #ifdef KERMIT_DATA_PRINT
dudmuck 18:9530d682fd9a 418 pc_b.printf("#");
dudmuck 18:9530d682fd9a 419 #endif /* */
dudmuck 18:9530d682fd9a 420 if ((in & 0x7f) == rept || (in & 0x7f) == qctl) {
dudmuck 18:9530d682fd9a 421 #ifdef KERMIT_DATA_PRINT
dudmuck 18:9530d682fd9a 422 pc_b.printf(":%02x ", in);
dudmuck 18:9530d682fd9a 423 #endif /* */
dudmuck 18:9530d682fd9a 424 bin_data[bin_data_idx++] = in;
dudmuck 18:9530d682fd9a 425 } else {
dudmuck 18:9530d682fd9a 426 #ifdef KERMIT_DATA_PRINT
dudmuck 18:9530d682fd9a 427 pc_b.printf("ctl:%02x ", ctl(in));
dudmuck 18:9530d682fd9a 428 #endif /* */
dudmuck 18:9530d682fd9a 429 bin_data[bin_data_idx++] = ctl(in);
dudmuck 18:9530d682fd9a 430 }
dudmuck 18:9530d682fd9a 431 } else if (uart_rx_data[i] == rept) { //repeat..
dudmuck 18:9530d682fd9a 432 uint8_t octet, cnt = unchar(uart_rx_data[++i]);
dudmuck 18:9530d682fd9a 433 i++; // step past count
dudmuck 18:9530d682fd9a 434 if (uart_rx_data[i] == qctl) {
dudmuck 18:9530d682fd9a 435 uint8_t raw = uart_rx_data[++i];
dudmuck 18:9530d682fd9a 436 octet = ctl(raw);
dudmuck 18:9530d682fd9a 437 } else {
dudmuck 18:9530d682fd9a 438 octet = uart_rx_data[i];
dudmuck 18:9530d682fd9a 439 }
dudmuck 18:9530d682fd9a 440 for (int n = 0; n < cnt; n++) {
dudmuck 18:9530d682fd9a 441 #ifdef KERMIT_DATA_PRINT
dudmuck 18:9530d682fd9a 442 pc_b.printf("rep%02x ", octet);
dudmuck 18:9530d682fd9a 443 #endif /* */
dudmuck 18:9530d682fd9a 444 bin_data[bin_data_idx++] = octet;
dudmuck 18:9530d682fd9a 445 }
dudmuck 18:9530d682fd9a 446 } else {
dudmuck 18:9530d682fd9a 447 #ifdef KERMIT_DATA_PRINT
dudmuck 18:9530d682fd9a 448 pc_b.printf("%02x ", uart_rx_data[i]);
dudmuck 18:9530d682fd9a 449 #endif /* */
dudmuck 18:9530d682fd9a 450 bin_data[bin_data_idx++] = uart_rx_data[i];
dudmuck 18:9530d682fd9a 451 }
dudmuck 18:9530d682fd9a 452 } // ..for()
dudmuck 18:9530d682fd9a 453 #ifdef KERMIT_DATA_PRINT
dudmuck 18:9530d682fd9a 454 pc_b.printf("\r\n");
dudmuck 18:9530d682fd9a 455 #endif /* */
dudmuck 18:9530d682fd9a 456
dudmuck 18:9530d682fd9a 457 if (prev_uart_rx_seq == uart_rx_seq) {
dudmuck 18:9530d682fd9a 458 // resend of previous 'D' packet
dudmuck 18:9530d682fd9a 459 total_file_bytes -= prev_bin_data_idx;
dudmuck 18:9530d682fd9a 460 } else {
dudmuck 18:9530d682fd9a 461 #ifdef XXD_PRINT
dudmuck 18:9530d682fd9a 462 xxd_print(0);
dudmuck 18:9530d682fd9a 463 #endif /* XXD_PRINT */
dudmuck 18:9530d682fd9a 464 }
dudmuck 18:9530d682fd9a 465
dudmuck 18:9530d682fd9a 466 total_file_bytes += bin_data_idx;
dudmuck 18:9530d682fd9a 467 prev_bin_data_idx = bin_data_idx;
dudmuck 18:9530d682fd9a 468 prev_uart_rx_seq = uart_rx_seq;
dudmuck 18:9530d682fd9a 469
dudmuck 18:9530d682fd9a 470 #ifdef RADIO_FILE_XFER
dudmuck 18:9530d682fd9a 471 // zero-pad to 4byte size alignment
dudmuck 18:9530d682fd9a 472 len_for_crc = bin_data_idx;
dudmuck 18:9530d682fd9a 473 while (len_for_crc & 3) {
dudmuck 18:9530d682fd9a 474 bin_data[len_for_crc++] = 0;
dudmuck 18:9530d682fd9a 475 }
dudmuck 18:9530d682fd9a 476 uwCRCValue = _HAL_CRC_Calculate((uint32_t *)bin_data, len_for_crc >> 2);
dudmuck 18:9530d682fd9a 477 //kermit.crc32 = uwCRCValue;
dudmuck 18:9530d682fd9a 478 //memcpy(crc_buf, bin_data, len_for_crc);
dudmuck 18:9530d682fd9a 479 //kermit.len_for_crc = len_for_crc;
dudmuck 18:9530d682fd9a 480
dudmuck 18:9530d682fd9a 481
dudmuck 18:9530d682fd9a 482 if (bin_data_idx > MAX_LEN_FRAME) { // oversized
dudmuck 18:9530d682fd9a 483 radio_xfer.fail_length = bin_data_idx;
dudmuck 18:9530d682fd9a 484 return 1; // fail
dudmuck 18:9530d682fd9a 485 }
dudmuck 18:9530d682fd9a 486
dudmuck 18:9530d682fd9a 487 //u32_ptr = (uint32_t *)&lora.m_xcvr.tx_buf[2];
dudmuck 18:9530d682fd9a 488 //pc_b.printf("D-hhh %p\r\n", u32_ptr);
dudmuck 18:9530d682fd9a 489 //*u32_ptr = uwCRCValue;
dudmuck 18:9530d682fd9a 490 memcpy(&lora.m_xcvr.tx_buf[2], &uwCRCValue, 4);
dudmuck 18:9530d682fd9a 491 /*
dudmuck 18:9530d682fd9a 492 if (prev_rx_seq == kermit.rx_seq) {
dudmuck 18:9530d682fd9a 493 // resend of previous 'D' packet
dudmuck 18:9530d682fd9a 494 radio_xfer.total_file_bytes -= prev_bin_data_idx;
dudmuck 18:9530d682fd9a 495 }
dudmuck 18:9530d682fd9a 496 radio_xfer.total_file_bytes += bin_data_idx;
dudmuck 18:9530d682fd9a 497 prev_bin_data_idx = bin_data_idx;
dudmuck 18:9530d682fd9a 498 prev_rx_seq = kermit.rx_seq;
dudmuck 18:9530d682fd9a 499 */
dudmuck 18:9530d682fd9a 500
dudmuck 18:9530d682fd9a 501 memcpy(lora.m_xcvr.tx_buf+6, bin_data, bin_data_idx);
dudmuck 18:9530d682fd9a 502 lora.RegPayloadLength = bin_data_idx+6;
dudmuck 18:9530d682fd9a 503 lora.m_xcvr.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
dudmuck 18:9530d682fd9a 504 radio_xfer.do_tx = true;
dudmuck 18:9530d682fd9a 505 radio_xfer.state = XFER_STATE_WAIT_DATA_ACK;
dudmuck 18:9530d682fd9a 506 radio_xfer.tx_sleep = radio_xfer.data_tx_delay;
dudmuck 18:9530d682fd9a 507 #else
dudmuck 18:9530d682fd9a 508 /* send ACK.. */
dudmuck 18:9530d682fd9a 509 while (uart_do_tx);
dudmuck 18:9530d682fd9a 510 uart_tx_data_idx = 0;
dudmuck 18:9530d682fd9a 511 uart_tx_data[uart_tx_data_idx++] = 'Y';
dudmuck 18:9530d682fd9a 512 uart_do_tx = true;
dudmuck 18:9530d682fd9a 513 #endif /* !RADIO_FILE_XFER */
dudmuck 18:9530d682fd9a 514 return 0;
dudmuck 18:9530d682fd9a 515 } else if (uart_rx_type == 'Z') {
dudmuck 18:9530d682fd9a 516 #ifdef RADIO_FILE_XFER
dudmuck 18:9530d682fd9a 517 lora.RegPayloadLength = 2;
dudmuck 18:9530d682fd9a 518 lora.m_xcvr.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
dudmuck 18:9530d682fd9a 519 radio_xfer.do_tx = true;
dudmuck 18:9530d682fd9a 520 radio_xfer.tx_sleep = radio_xfer.data_tx_delay;
dudmuck 18:9530d682fd9a 521 radio_xfer.state = XFER_STATE_WAIT_Z;
dudmuck 18:9530d682fd9a 522 #else
dudmuck 18:9530d682fd9a 523 /* send ACK.. */
dudmuck 18:9530d682fd9a 524 while (uart_do_tx);
dudmuck 18:9530d682fd9a 525 uart_tx_data_idx = 0;
dudmuck 18:9530d682fd9a 526 uart_tx_data[uart_tx_data_idx++] = 'Y';
dudmuck 18:9530d682fd9a 527 uart_do_tx = true;
dudmuck 18:9530d682fd9a 528 uart_tx_sleep = 0.1;
dudmuck 18:9530d682fd9a 529 #endif /* !RADIO_FILE_XFER */
dudmuck 18:9530d682fd9a 530 pc_b.printf("Z\r\n");
dudmuck 18:9530d682fd9a 531 return 0;
dudmuck 18:9530d682fd9a 532 } else if (uart_rx_type == 'B') {
dudmuck 18:9530d682fd9a 533 #ifdef RADIO_FILE_XFER
dudmuck 18:9530d682fd9a 534 lora.RegPayloadLength = 2;
dudmuck 18:9530d682fd9a 535 lora.m_xcvr.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
dudmuck 18:9530d682fd9a 536 radio_xfer.do_tx = true;
dudmuck 18:9530d682fd9a 537 radio_xfer.tx_sleep = radio_xfer.data_tx_delay;
dudmuck 18:9530d682fd9a 538 radio_xfer.state = XFER_STATE_WAIT_B;
dudmuck 18:9530d682fd9a 539 #else
dudmuck 18:9530d682fd9a 540 uart_tx_data_idx = 0;
dudmuck 18:9530d682fd9a 541 uart_tx_data[uart_tx_data_idx++] = 'Y';
dudmuck 18:9530d682fd9a 542 uart_do_tx = true;
dudmuck 18:9530d682fd9a 543 uart_tx_sleep = 0.1;
dudmuck 18:9530d682fd9a 544 #endif /* RADIO_FILE_XFER */
dudmuck 18:9530d682fd9a 545 #ifdef XXD_PRINT
dudmuck 18:9530d682fd9a 546 xxd_print(1);
dudmuck 18:9530d682fd9a 547 #endif /* XXD_PRINT */
dudmuck 18:9530d682fd9a 548 pc_b.printf("B\r\n");
dudmuck 18:9530d682fd9a 549 return 0;
dudmuck 18:9530d682fd9a 550 } else {
dudmuck 18:9530d682fd9a 551 // unknown packet, prevent further packets from overwriting
dudmuck 18:9530d682fd9a 552 return 1;
dudmuck 18:9530d682fd9a 553 }
dudmuck 18:9530d682fd9a 554
dudmuck 18:9530d682fd9a 555 return 0;
dudmuck 18:9530d682fd9a 556 }
dudmuck 18:9530d682fd9a 557
dudmuck 18:9530d682fd9a 558 void Kermit::kermit_uart_tx()
dudmuck 18:9530d682fd9a 559 {
dudmuck 18:9530d682fd9a 560 uint8_t buf[128];
dudmuck 18:9530d682fd9a 561 uint8_t idx = 0;
dudmuck 18:9530d682fd9a 562 int i;
dudmuck 18:9530d682fd9a 563 uint32_t sum;
dudmuck 18:9530d682fd9a 564
dudmuck 18:9530d682fd9a 565 buf[idx++] = SOH; // MARK
dudmuck 18:9530d682fd9a 566 buf[idx++] = 0; // length to be inserted later
dudmuck 18:9530d682fd9a 567 #ifdef RADIO_FILE_XFER
dudmuck 18:9530d682fd9a 568 buf[idx++] = tochar(radio_xfer.seq_from_rx); // SEQ
dudmuck 18:9530d682fd9a 569 #else
dudmuck 18:9530d682fd9a 570 buf[idx++] = tochar(uart_rx_seq); // SEQ
dudmuck 18:9530d682fd9a 571 #endif
dudmuck 18:9530d682fd9a 572 // TYPE is uart_tx_data[0]
dudmuck 18:9530d682fd9a 573 for (i = 0; i < uart_tx_data_idx; i++) {
dudmuck 18:9530d682fd9a 574 buf[idx++] = uart_tx_data[i];
dudmuck 18:9530d682fd9a 575 }
dudmuck 18:9530d682fd9a 576
dudmuck 18:9530d682fd9a 577 buf[1] = tochar(idx - 1); // LEN (-1 because block check hasnt been included in idx yet)
dudmuck 18:9530d682fd9a 578
dudmuck 18:9530d682fd9a 579 sum = 0;
dudmuck 18:9530d682fd9a 580 for (i = 1; i < idx; i++) {
dudmuck 18:9530d682fd9a 581 sum += buf[i];
dudmuck 18:9530d682fd9a 582 }
dudmuck 18:9530d682fd9a 583 buf[idx++] = tochar((sum + ((sum & 192)/64)) & 63);
dudmuck 18:9530d682fd9a 584 buf[idx++] = eol;
dudmuck 18:9530d682fd9a 585
dudmuck 18:9530d682fd9a 586 for (i = 0; i < idx; i++)
dudmuck 18:9530d682fd9a 587 putc(buf[i], stdout);
dudmuck 18:9530d682fd9a 588 //pc.putc(buf[i]);
dudmuck 18:9530d682fd9a 589
dudmuck 18:9530d682fd9a 590 }
dudmuck 18:9530d682fd9a 591
dudmuck 18:9530d682fd9a 592 void Kermit::service()
dudmuck 18:9530d682fd9a 593 {
dudmuck 18:9530d682fd9a 594 if (end) {
dudmuck 18:9530d682fd9a 595 if (show_error) {
dudmuck 18:9530d682fd9a 596 printf("kermit error:\"%s\"\r\n", uart_rx_data);
dudmuck 18:9530d682fd9a 597 show_error = false;
dudmuck 18:9530d682fd9a 598 }
dudmuck 18:9530d682fd9a 599 printf("kermit_end\r\n");
dudmuck 18:9530d682fd9a 600 printf("total_file_bytes:%d\r\n", total_file_bytes);
dudmuck 18:9530d682fd9a 601 end = false;
dudmuck 18:9530d682fd9a 602 }
dudmuck 18:9530d682fd9a 603
dudmuck 18:9530d682fd9a 604 if (uart_do_tx) {
dudmuck 18:9530d682fd9a 605 if (uart_tx_sleep > 0.001) {
dudmuck 18:9530d682fd9a 606 wait(uart_tx_sleep);
dudmuck 18:9530d682fd9a 607 uart_tx_sleep = 0;
dudmuck 18:9530d682fd9a 608 }
dudmuck 18:9530d682fd9a 609 kermit_uart_tx();
dudmuck 18:9530d682fd9a 610 uart_do_tx = false;
dudmuck 18:9530d682fd9a 611 if (end_after_tx) {
dudmuck 18:9530d682fd9a 612 //know this cause -- end_cause = 1;
dudmuck 18:9530d682fd9a 613 uart_rx_enabled = false;
dudmuck 18:9530d682fd9a 614 end = true;
dudmuck 18:9530d682fd9a 615 state = KERMIT_STATE_OFF;
dudmuck 18:9530d682fd9a 616 end_after_tx = false;
dudmuck 18:9530d682fd9a 617 }
dudmuck 18:9530d682fd9a 618 } // ...if (uart_do_tx)
dudmuck 18:9530d682fd9a 619
dudmuck 18:9530d682fd9a 620 #ifdef RADIO_FILE_XFER
dudmuck 18:9530d682fd9a 621 if (!radio_xfer.radio_initialized) {
dudmuck 18:9530d682fd9a 622 lora.m_xcvr.set_opmode(RF_OPMODE_STANDBY);
dudmuck 18:9530d682fd9a 623 lora.m_xcvr.write_reg(REG_LR_SYNC_BYTE, 0x34);
dudmuck 18:9530d682fd9a 624 lora.setBw_KHz(500);
dudmuck 18:9530d682fd9a 625 lora.setSf(7);
dudmuck 18:9530d682fd9a 626 lora.m_xcvr.set_frf_MHz(915.0);
dudmuck 18:9530d682fd9a 627 lora.invert_tx(true);
dudmuck 18:9530d682fd9a 628 radio_xfer.fail_length = -1;
dudmuck 18:9530d682fd9a 629 radio_xfer.radio_initialized = true;
dudmuck 18:9530d682fd9a 630 }
dudmuck 18:9530d682fd9a 631
dudmuck 18:9530d682fd9a 632 if (radio_xfer.do_tx) {
dudmuck 18:9530d682fd9a 633 pc_b.printf("rfTX:%02x\r\n", lora.m_xcvr.tx_buf[0]);
dudmuck 18:9530d682fd9a 634 if (radio_xfer.tx_sleep > 0.001) {
dudmuck 18:9530d682fd9a 635 wait(radio_xfer.tx_sleep);
dudmuck 18:9530d682fd9a 636 radio_xfer.tx_sleep = 0;
dudmuck 18:9530d682fd9a 637 }
dudmuck 18:9530d682fd9a 638 lora.start_tx(lora.RegPayloadLength);
dudmuck 18:9530d682fd9a 639 radio_xfer.do_tx = false;
dudmuck 18:9530d682fd9a 640 }
dudmuck 18:9530d682fd9a 641 #endif /* RADIO_FILE_XFER */
dudmuck 18:9530d682fd9a 642 }
dudmuck 18:9530d682fd9a 643
dudmuck 18:9530d682fd9a 644 void Kermit::uart_rx_enable()
dudmuck 18:9530d682fd9a 645 {
dudmuck 18:9530d682fd9a 646 got_send_init = false;
dudmuck 18:9530d682fd9a 647 uart_rx_enabled = true;
dudmuck 18:9530d682fd9a 648 state = KERMIT_STATE_WAIT_LEN;
dudmuck 18:9530d682fd9a 649 #ifdef RADIO_FILE_XFER
dudmuck 18:9530d682fd9a 650 radio_xfer.radio_initialized = false; // causes radio initialization for transfer
dudmuck 18:9530d682fd9a 651 #endif /* RADIO_FILE_XFER */
dudmuck 18:9530d682fd9a 652 }
dudmuck 18:9530d682fd9a 653 #endif /* #if 0 */