point-2-point demo
radio chip selection
Radio chip driver is not included, because these options are available.
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.
TX trigger selection
Edit main.h
to define DIGITAL_TRIGGER
or ANALOG_TRIGGER
to chose whether transmit is initiated by digital pin (button/jumper) or analog pin(s) level change.
This project is intended to be used on two LoRa shields.
Each board sits in continuous RX mode, waiting for request packet.
If the received packet has good CRC, the packet is acknowledged along with read of ADC sample from the replying device.
The original request packet also contains instruction to set level of output pin.
Both sides of the link are running the same code, and each can initiate a transmission at any time.
No addressing is used, so only two nodes can operate on the radio channel.
main.cpp@5:e35b1b281466, 2018-08-01 (annotated)
- Committer:
- Wayne Roberts
- Date:
- Wed Aug 01 15:04:11 2018 -0700
- Revision:
- 5:e35b1b281466
- Parent:
- 4:b5dd459ac390
move analog to separate source file
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Wayne Roberts |
5:e35b1b281466 | 1 | #include "main.h" |
Wayne Roberts |
4:b5dd459ac390 | 2 | #include "radio.h" |
Wayne Roberts |
3:cd312fc32558 | 3 | |
Wayne Roberts |
4:b5dd459ac390 | 4 | #if defined(SX127x_H) || defined(SX126x_H) |
Wayne Roberts |
4:b5dd459ac390 | 5 | #define BW_KHZ 500 |
Wayne Roberts |
4:b5dd459ac390 | 6 | #define SPREADING_FACTOR 9 |
Wayne Roberts |
4:b5dd459ac390 | 7 | #define CF_HZ 917300000 |
Wayne Roberts |
4:b5dd459ac390 | 8 | #ifdef SX127x_H |
Wayne Roberts |
4:b5dd459ac390 | 9 | AnalogIn a1(A1); |
Wayne Roberts |
4:b5dd459ac390 | 10 | #else |
Wayne Roberts |
4:b5dd459ac390 | 11 | /* arduino analog pins used by radio shield */ |
Wayne Roberts |
4:b5dd459ac390 | 12 | AnalogIn a1(PC_3); // PC_2 and PC_4 also available |
Wayne Roberts |
4:b5dd459ac390 | 13 | #endif |
Wayne Roberts |
4:b5dd459ac390 | 14 | #elif defined(SX128x_H) |
Wayne Roberts |
4:b5dd459ac390 | 15 | #define BW_KHZ 400 |
Wayne Roberts |
4:b5dd459ac390 | 16 | #define SPREADING_FACTOR 9 |
Wayne Roberts |
4:b5dd459ac390 | 17 | #define CF_HZ 2487000000 |
Wayne Roberts |
4:b5dd459ac390 | 18 | /* arduino analog pins used by radio shield */ |
Wayne Roberts |
4:b5dd459ac390 | 19 | AnalogIn a1(PC_3); // PC_2 and PC_4 also available |
Wayne Roberts |
4:b5dd459ac390 | 20 | #endif |
Wayne Roberts |
4:b5dd459ac390 | 21 | |
dudmuck | 0:1d8d218c5cc5 | 22 | DigitalOut myled(LED1); |
dudmuck | 0:1d8d218c5cc5 | 23 | |
dudmuck | 0:1d8d218c5cc5 | 24 | Timer t; |
Wayne Roberts |
4:b5dd459ac390 | 25 | volatile bool tx_done; |
dudmuck | 0:1d8d218c5cc5 | 26 | DigitalOut pc6_out(PC_6); |
dudmuck | 0:1d8d218c5cc5 | 27 | |
Wayne Roberts |
4:b5dd459ac390 | 28 | #define RX_TIMEOUT_US 200000 |
dudmuck | 0:1d8d218c5cc5 | 29 | /**********************************************************************/ |
dudmuck | 0:1d8d218c5cc5 | 30 | |
dudmuck | 0:1d8d218c5cc5 | 31 | |
Wayne Roberts |
4:b5dd459ac390 | 32 | void txDoneCB() |
Wayne Roberts |
4:b5dd459ac390 | 33 | { |
Wayne Roberts |
4:b5dd459ac390 | 34 | tx_done = true; |
Wayne Roberts |
4:b5dd459ac390 | 35 | } |
dudmuck | 0:1d8d218c5cc5 | 36 | |
dudmuck | 0:1d8d218c5cc5 | 37 | static uint16_t crc16( uint8_t *buffer, uint16_t length ) |
dudmuck | 0:1d8d218c5cc5 | 38 | { |
dudmuck | 0:1d8d218c5cc5 | 39 | uint16_t i; |
dudmuck | 0:1d8d218c5cc5 | 40 | // The CRC calculation follows CCITT |
dudmuck | 0:1d8d218c5cc5 | 41 | const uint16_t polynom = 0x1021; |
dudmuck | 0:1d8d218c5cc5 | 42 | // CRC initial value |
dudmuck | 0:1d8d218c5cc5 | 43 | uint16_t crc = 0x0000; |
dudmuck | 0:1d8d218c5cc5 | 44 | |
dudmuck | 0:1d8d218c5cc5 | 45 | if( buffer == NULL ) |
dudmuck | 0:1d8d218c5cc5 | 46 | { |
dudmuck | 0:1d8d218c5cc5 | 47 | return 0; |
dudmuck | 0:1d8d218c5cc5 | 48 | } |
dudmuck | 0:1d8d218c5cc5 | 49 | |
dudmuck | 0:1d8d218c5cc5 | 50 | for( i = 0; i < length; ++i ) |
dudmuck | 0:1d8d218c5cc5 | 51 | { |
dudmuck | 0:1d8d218c5cc5 | 52 | uint16_t j; |
dudmuck | 0:1d8d218c5cc5 | 53 | crc ^= ( uint16_t ) buffer[i] << 8; |
dudmuck | 0:1d8d218c5cc5 | 54 | for( j = 0; j < 8; ++j ) |
dudmuck | 0:1d8d218c5cc5 | 55 | { |
dudmuck | 0:1d8d218c5cc5 | 56 | crc = ( crc & 0x8000 ) ? ( crc << 1 ) ^ polynom : ( crc << 1 ); |
dudmuck | 0:1d8d218c5cc5 | 57 | } |
dudmuck | 0:1d8d218c5cc5 | 58 | } |
dudmuck | 0:1d8d218c5cc5 | 59 | |
dudmuck | 0:1d8d218c5cc5 | 60 | return crc; |
dudmuck | 0:1d8d218c5cc5 | 61 | } |
dudmuck | 0:1d8d218c5cc5 | 62 | |
dudmuck | 0:1d8d218c5cc5 | 63 | void tx_ack() |
dudmuck | 0:1d8d218c5cc5 | 64 | { |
dudmuck | 0:1d8d218c5cc5 | 65 | uint8_t n = 0; |
dudmuck | 0:1d8d218c5cc5 | 66 | uint16_t crc; |
dudmuck | 0:1d8d218c5cc5 | 67 | |
Wayne Roberts |
4:b5dd459ac390 | 68 | if (Radio::radio.rx_buf[0] == CMD_OUT_PIN) { |
dudmuck | 0:1d8d218c5cc5 | 69 | uint16_t ain = a1.read_u16(); |
Wayne Roberts |
4:b5dd459ac390 | 70 | Radio::radio.tx_buf[n++] = CMD_OUT_PIN_ACK; |
dudmuck | 0:1d8d218c5cc5 | 71 | /* TODO read analog pin and digital input pin */ |
Wayne Roberts |
4:b5dd459ac390 | 72 | Radio::radio.tx_buf[n++] = ain; |
Wayne Roberts |
4:b5dd459ac390 | 73 | Radio::radio.tx_buf[n++] = ain >> 8; |
dudmuck | 0:1d8d218c5cc5 | 74 | } else |
Wayne Roberts |
4:b5dd459ac390 | 75 | Radio::radio.tx_buf[n++] = 0xff; |
Wayne Roberts |
4:b5dd459ac390 | 76 | |
Wayne Roberts |
4:b5dd459ac390 | 77 | crc = crc16(Radio::radio.tx_buf, n); |
Wayne Roberts |
4:b5dd459ac390 | 78 | Radio::radio.tx_buf[n++] = crc; |
Wayne Roberts |
4:b5dd459ac390 | 79 | Radio::radio.tx_buf[n++] = crc >> 8; |
dudmuck | 0:1d8d218c5cc5 | 80 | |
Wayne Roberts |
4:b5dd459ac390 | 81 | tx_done = false; |
Wayne Roberts |
4:b5dd459ac390 | 82 | Radio::Send(n, 0, 0, 0); |
Wayne Roberts |
4:b5dd459ac390 | 83 | printf("tx_ack\r\n"); |
Wayne Roberts |
4:b5dd459ac390 | 84 | |
Wayne Roberts |
4:b5dd459ac390 | 85 | while (!tx_done) |
Wayne Roberts |
4:b5dd459ac390 | 86 | Radio::service(); |
Wayne Roberts |
4:b5dd459ac390 | 87 | |
Wayne Roberts |
4:b5dd459ac390 | 88 | Radio::Rx(0); |
Wayne Roberts |
4:b5dd459ac390 | 89 | } |
dudmuck | 0:1d8d218c5cc5 | 90 | |
Wayne Roberts |
4:b5dd459ac390 | 91 | volatile struct _rx_ { |
Wayne Roberts |
4:b5dd459ac390 | 92 | uint8_t length; |
Wayne Roberts |
4:b5dd459ac390 | 93 | float rssi; |
Wayne Roberts |
4:b5dd459ac390 | 94 | float snr; |
Wayne Roberts |
4:b5dd459ac390 | 95 | } rx; |
dudmuck | 0:1d8d218c5cc5 | 96 | |
Wayne Roberts |
4:b5dd459ac390 | 97 | void rxDoneCB(uint8_t size, float Rssi, float Snr) |
Wayne Roberts |
4:b5dd459ac390 | 98 | { |
Wayne Roberts |
4:b5dd459ac390 | 99 | rx.length = size; |
Wayne Roberts |
4:b5dd459ac390 | 100 | rx.rssi = Rssi; |
Wayne Roberts |
4:b5dd459ac390 | 101 | rx.snr = Snr; |
dudmuck | 0:1d8d218c5cc5 | 102 | } |
dudmuck | 0:1d8d218c5cc5 | 103 | |
dudmuck | 1:d95d135a4fb4 | 104 | void radio_tx(uint8_t* payload, uint8_t payload_len) |
dudmuck | 0:1d8d218c5cc5 | 105 | { |
dudmuck | 0:1d8d218c5cc5 | 106 | int i; |
dudmuck | 1:d95d135a4fb4 | 107 | uint8_t n = 0; |
dudmuck | 1:d95d135a4fb4 | 108 | uint16_t crc; |
dudmuck | 1:d95d135a4fb4 | 109 | |
dudmuck | 1:d95d135a4fb4 | 110 | while (payload_len > 0) { |
dudmuck | 1:d95d135a4fb4 | 111 | //printf("n%u, paylen%u\r\n", n, payload_len); |
dudmuck | 1:d95d135a4fb4 | 112 | payload_len--; |
Wayne Roberts |
4:b5dd459ac390 | 113 | Radio::radio.tx_buf[payload_len] = payload[payload_len]; |
dudmuck | 1:d95d135a4fb4 | 114 | n++; |
dudmuck | 1:d95d135a4fb4 | 115 | } |
dudmuck | 1:d95d135a4fb4 | 116 | |
Wayne Roberts |
4:b5dd459ac390 | 117 | crc = crc16(Radio::radio.tx_buf, n); |
Wayne Roberts |
4:b5dd459ac390 | 118 | Radio::radio.tx_buf[n++] = crc; |
Wayne Roberts |
4:b5dd459ac390 | 119 | Radio::radio.tx_buf[n++] = crc >> 8; |
dudmuck | 0:1d8d218c5cc5 | 120 | |
dudmuck | 0:1d8d218c5cc5 | 121 | for (i = 0; i < 3; i++) { |
dudmuck | 0:1d8d218c5cc5 | 122 | int rx_timeout_at; |
Wayne Roberts |
4:b5dd459ac390 | 123 | int rx_start_at; |
dudmuck | 0:1d8d218c5cc5 | 124 | |
Wayne Roberts |
4:b5dd459ac390 | 125 | tx_done = false; |
Wayne Roberts |
4:b5dd459ac390 | 126 | Radio::Send(n, 0, 0, 0); |
dudmuck | 0:1d8d218c5cc5 | 127 | |
Wayne Roberts |
4:b5dd459ac390 | 128 | while (!tx_done) |
Wayne Roberts |
4:b5dd459ac390 | 129 | Radio::service(); |
dudmuck | 0:1d8d218c5cc5 | 130 | |
Wayne Roberts |
4:b5dd459ac390 | 131 | rx_start_at = t.read_us(); |
Wayne Roberts |
4:b5dd459ac390 | 132 | rx_timeout_at = rx_start_at + RX_TIMEOUT_US; |
Wayne Roberts |
4:b5dd459ac390 | 133 | |
Wayne Roberts |
4:b5dd459ac390 | 134 | Radio::Rx(0); |
Wayne Roberts |
4:b5dd459ac390 | 135 | rx.length = 0; |
dudmuck | 0:1d8d218c5cc5 | 136 | |
dudmuck | 0:1d8d218c5cc5 | 137 | while (t.read_us() < rx_timeout_at) { |
Wayne Roberts |
4:b5dd459ac390 | 138 | Radio::service(); |
Wayne Roberts |
4:b5dd459ac390 | 139 | if (rx.length > 0) { |
dudmuck | 0:1d8d218c5cc5 | 140 | uint16_t rx_crc; |
Wayne Roberts |
4:b5dd459ac390 | 141 | printf(" rssi:%.1fdBm snr:%.1fdB ", rx.rssi, rx.snr); |
Wayne Roberts |
4:b5dd459ac390 | 142 | rx_crc = Radio::radio.rx_buf[rx.length-2]; |
Wayne Roberts |
4:b5dd459ac390 | 143 | rx_crc |= Radio::radio.rx_buf[rx.length-1] << 8; |
Wayne Roberts |
4:b5dd459ac390 | 144 | crc = crc16(Radio::radio.rx_buf, rx.length-2); |
dudmuck | 0:1d8d218c5cc5 | 145 | if (crc == rx_crc) { |
dudmuck | 0:1d8d218c5cc5 | 146 | printf("crcOk %u\r\n", i); |
Wayne Roberts |
4:b5dd459ac390 | 147 | if (Radio::radio.rx_buf[0] == CMD_OUT_PIN_ACK) { |
Wayne Roberts |
4:b5dd459ac390 | 148 | uint16_t ain = Radio::radio.rx_buf[1]; |
Wayne Roberts |
4:b5dd459ac390 | 149 | ain |= Radio::radio.rx_buf[2] << 8; |
dudmuck | 0:1d8d218c5cc5 | 150 | printf("ain %u\r\n", ain); |
dudmuck | 0:1d8d218c5cc5 | 151 | } |
Wayne Roberts |
4:b5dd459ac390 | 152 | rx.length = 0; |
dudmuck | 0:1d8d218c5cc5 | 153 | return; |
dudmuck | 0:1d8d218c5cc5 | 154 | } else |
dudmuck | 0:1d8d218c5cc5 | 155 | printf("crcFail %04x != %04x\r\n", crc, rx_crc); |
Wayne Roberts |
4:b5dd459ac390 | 156 | rx.length = 0; |
dudmuck | 0:1d8d218c5cc5 | 157 | } |
dudmuck | 0:1d8d218c5cc5 | 158 | } |
Wayne Roberts |
4:b5dd459ac390 | 159 | printf("rx-timeout %u, %u\r\n", i, t.read_us() - rx_start_at); |
dudmuck | 0:1d8d218c5cc5 | 160 | } // ..for() |
dudmuck | 0:1d8d218c5cc5 | 161 | } |
dudmuck | 0:1d8d218c5cc5 | 162 | |
Wayne Roberts |
4:b5dd459ac390 | 163 | const RadioEvents_t rev = { |
Wayne Roberts |
4:b5dd459ac390 | 164 | /* Dio0_top_half */ NULL, |
Wayne Roberts |
4:b5dd459ac390 | 165 | /* TxDone_topHalf */ NULL, |
Wayne Roberts |
4:b5dd459ac390 | 166 | /* TxDone_botHalf */ txDoneCB, |
Wayne Roberts |
4:b5dd459ac390 | 167 | /* TxTimeout */ NULL, |
Wayne Roberts |
4:b5dd459ac390 | 168 | /* RxDone */ rxDoneCB, |
Wayne Roberts |
4:b5dd459ac390 | 169 | /* RxTimeout */ NULL, |
Wayne Roberts |
4:b5dd459ac390 | 170 | /* RxError */ NULL, |
Wayne Roberts |
4:b5dd459ac390 | 171 | /* FhssChangeChannel */NULL, |
Wayne Roberts |
4:b5dd459ac390 | 172 | /* CadDone */ NULL |
Wayne Roberts |
4:b5dd459ac390 | 173 | }; |
Wayne Roberts |
4:b5dd459ac390 | 174 | |
dudmuck | 0:1d8d218c5cc5 | 175 | int main() |
dudmuck | 0:1d8d218c5cc5 | 176 | { |
Wayne Roberts |
5:e35b1b281466 | 177 | printf("\r\nreset\r\n"); |
dudmuck | 0:1d8d218c5cc5 | 178 | |
Wayne Roberts |
5:e35b1b281466 | 179 | trigger_init(); |
dudmuck | 0:1d8d218c5cc5 | 180 | |
dudmuck | 0:1d8d218c5cc5 | 181 | t.start(); |
dudmuck | 0:1d8d218c5cc5 | 182 | |
Wayne Roberts |
4:b5dd459ac390 | 183 | Radio::Init(&rev); |
Wayne Roberts |
4:b5dd459ac390 | 184 | |
Wayne Roberts |
4:b5dd459ac390 | 185 | Radio::Standby(); |
Wayne Roberts |
4:b5dd459ac390 | 186 | Radio::LoRaModemConfig(BW_KHZ, SPREADING_FACTOR, 1); |
Wayne Roberts |
4:b5dd459ac390 | 187 | Radio::LoRaPacketConfig(8, false, true, false); // preambleLen, fixLen, crcOn, invIQ |
Wayne Roberts |
4:b5dd459ac390 | 188 | Radio::SetChannel(CF_HZ); |
dudmuck | 0:1d8d218c5cc5 | 189 | |
Wayne Roberts |
4:b5dd459ac390 | 190 | Radio::Rx(0); |
dudmuck | 0:1d8d218c5cc5 | 191 | |
dudmuck | 0:1d8d218c5cc5 | 192 | for (;;) { |
Wayne Roberts |
5:e35b1b281466 | 193 | trigger_mainloop(); |
Wayne Roberts |
3:cd312fc32558 | 194 | |
Wayne Roberts |
4:b5dd459ac390 | 195 | if (rx.length > 0) { |
dudmuck | 0:1d8d218c5cc5 | 196 | uint16_t crc, rx_crc; |
dudmuck | 0:1d8d218c5cc5 | 197 | int i; |
Wayne Roberts |
4:b5dd459ac390 | 198 | for (i = 0; i < rx.length; i++) { |
Wayne Roberts |
4:b5dd459ac390 | 199 | printf("%02x ", Radio::radio.rx_buf[i]); |
dudmuck | 0:1d8d218c5cc5 | 200 | } |
Wayne Roberts |
4:b5dd459ac390 | 201 | printf(" rssi:%.1fdBm, snr:%.1fdB\r\n", rx.rssi, rx.snr); |
Wayne Roberts |
4:b5dd459ac390 | 202 | rx_crc = Radio::radio.rx_buf[rx.length-2]; |
Wayne Roberts |
4:b5dd459ac390 | 203 | rx_crc |= Radio::radio.rx_buf[rx.length-1] << 8; |
Wayne Roberts |
4:b5dd459ac390 | 204 | crc = crc16(Radio::radio.rx_buf, rx.length-2); |
dudmuck | 0:1d8d218c5cc5 | 205 | if (crc == rx_crc) { |
Wayne Roberts |
4:b5dd459ac390 | 206 | bool sendAck = false; |
Wayne Roberts |
4:b5dd459ac390 | 207 | bool parsed = parse_radio_rx(Radio::radio.rx_buf); |
dudmuck | 0:1d8d218c5cc5 | 208 | printf("crcOk\r\n"); |
Wayne Roberts |
4:b5dd459ac390 | 209 | if (!parsed && Radio::radio.rx_buf[0] == CMD_OUT_PIN) { |
Wayne Roberts |
4:b5dd459ac390 | 210 | pc6_out.write(Radio::radio.rx_buf[1]); |
Wayne Roberts |
4:b5dd459ac390 | 211 | printf("out pin state: %u", Radio::radio.rx_buf[1]); |
Wayne Roberts |
4:b5dd459ac390 | 212 | sendAck = true; |
Wayne Roberts |
4:b5dd459ac390 | 213 | } else if (parsed) |
Wayne Roberts |
4:b5dd459ac390 | 214 | sendAck = true; |
Wayne Roberts |
4:b5dd459ac390 | 215 | |
dudmuck | 0:1d8d218c5cc5 | 216 | printf("\r\n"); |
Wayne Roberts |
4:b5dd459ac390 | 217 | |
Wayne Roberts |
4:b5dd459ac390 | 218 | if (sendAck) |
Wayne Roberts |
4:b5dd459ac390 | 219 | tx_ack(); |
dudmuck | 0:1d8d218c5cc5 | 220 | } else |
dudmuck | 0:1d8d218c5cc5 | 221 | printf("crc %04x != %04x\r\n", crc, rx_crc); |
Wayne Roberts |
4:b5dd459ac390 | 222 | |
Wayne Roberts |
4:b5dd459ac390 | 223 | rx.length = 0; |
dudmuck | 0:1d8d218c5cc5 | 224 | } // ..if something received |
dudmuck | 1:d95d135a4fb4 | 225 | |
dudmuck | 1:d95d135a4fb4 | 226 | uart_service(); |
Wayne Roberts |
4:b5dd459ac390 | 227 | |
Wayne Roberts |
4:b5dd459ac390 | 228 | Radio::service(); |
dudmuck | 0:1d8d218c5cc5 | 229 | } // ..for (;;) |
dudmuck | 0:1d8d218c5cc5 | 230 | } |
dudmuck | 0:1d8d218c5cc5 | 231 |