point-2-point demo

Dependencies:   sx12xx_hal

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.

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?

UserRevisionLine numberNew 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