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:
dudmuck
Date:
Thu Oct 05 16:11:31 2017 -0700
Revision:
0:1d8d218c5cc5
Child:
1:d95d135a4fb4
simple point-to-point, between only two units

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dudmuck 0:1d8d218c5cc5 1 #include "sx127x_lora.h"
dudmuck 0:1d8d218c5cc5 2
dudmuck 0:1d8d218c5cc5 3 DigitalOut myled(LED1);
dudmuck 0:1d8d218c5cc5 4
dudmuck 0:1d8d218c5cc5 5 SPI spi(D11, D12, D13); // mosi, miso, sclk
dudmuck 0:1d8d218c5cc5 6 // dio0, dio1, nss, spi, rst
dudmuck 0:1d8d218c5cc5 7 SX127x radio( D2, D3, D10, spi, A0); // sx1276 arduino shield
dudmuck 0:1d8d218c5cc5 8
dudmuck 0:1d8d218c5cc5 9 SX127x_lora lora(radio);
dudmuck 0:1d8d218c5cc5 10 DigitalInOut rfsw(A4); // for SX1276 arduino shield
dudmuck 0:1d8d218c5cc5 11
dudmuck 0:1d8d218c5cc5 12 InterruptIn user_button(USER_BUTTON);
dudmuck 0:1d8d218c5cc5 13 Timer t;
dudmuck 0:1d8d218c5cc5 14 Ticker ticker;
dudmuck 0:1d8d218c5cc5 15 AnalogIn a1(A1);
dudmuck 0:1d8d218c5cc5 16 DigitalOut pc6_out(PC_6);
dudmuck 0:1d8d218c5cc5 17
dudmuck 0:1d8d218c5cc5 18 DigitalOut jumper_out(PC_10);
dudmuck 0:1d8d218c5cc5 19 InterruptIn jumper_in(PC_12);
dudmuck 0:1d8d218c5cc5 20
dudmuck 0:1d8d218c5cc5 21 void rfsw_callback()
dudmuck 0:1d8d218c5cc5 22 {
dudmuck 0:1d8d218c5cc5 23 if (radio.RegOpMode.bits.Mode == RF_OPMODE_TRANSMITTER)
dudmuck 0:1d8d218c5cc5 24 rfsw = 1;
dudmuck 0:1d8d218c5cc5 25 else
dudmuck 0:1d8d218c5cc5 26 rfsw = 0;
dudmuck 0:1d8d218c5cc5 27 }
dudmuck 0:1d8d218c5cc5 28
dudmuck 0:1d8d218c5cc5 29 /**********************************************************************/
dudmuck 0:1d8d218c5cc5 30 #define CMD_OUT_PIN 0x01
dudmuck 0:1d8d218c5cc5 31 #define CMD_OUT_PIN_ACK (CMD_OUT_PIN | 0x80)
dudmuck 0:1d8d218c5cc5 32
dudmuck 0:1d8d218c5cc5 33 uint8_t out_pin_state;
dudmuck 0:1d8d218c5cc5 34
dudmuck 0:1d8d218c5cc5 35
dudmuck 0:1d8d218c5cc5 36 static uint16_t crc16( uint8_t *buffer, uint16_t length )
dudmuck 0:1d8d218c5cc5 37 {
dudmuck 0:1d8d218c5cc5 38 uint16_t i;
dudmuck 0:1d8d218c5cc5 39 // The CRC calculation follows CCITT
dudmuck 0:1d8d218c5cc5 40 const uint16_t polynom = 0x1021;
dudmuck 0:1d8d218c5cc5 41 // CRC initial value
dudmuck 0:1d8d218c5cc5 42 uint16_t crc = 0x0000;
dudmuck 0:1d8d218c5cc5 43
dudmuck 0:1d8d218c5cc5 44 if( buffer == NULL )
dudmuck 0:1d8d218c5cc5 45 {
dudmuck 0:1d8d218c5cc5 46 return 0;
dudmuck 0:1d8d218c5cc5 47 }
dudmuck 0:1d8d218c5cc5 48
dudmuck 0:1d8d218c5cc5 49 for( i = 0; i < length; ++i )
dudmuck 0:1d8d218c5cc5 50 {
dudmuck 0:1d8d218c5cc5 51 uint16_t j;
dudmuck 0:1d8d218c5cc5 52 crc ^= ( uint16_t ) buffer[i] << 8;
dudmuck 0:1d8d218c5cc5 53 for( j = 0; j < 8; ++j )
dudmuck 0:1d8d218c5cc5 54 {
dudmuck 0:1d8d218c5cc5 55 crc = ( crc & 0x8000 ) ? ( crc << 1 ) ^ polynom : ( crc << 1 );
dudmuck 0:1d8d218c5cc5 56 }
dudmuck 0:1d8d218c5cc5 57 }
dudmuck 0:1d8d218c5cc5 58
dudmuck 0:1d8d218c5cc5 59 return crc;
dudmuck 0:1d8d218c5cc5 60 }
dudmuck 0:1d8d218c5cc5 61
dudmuck 0:1d8d218c5cc5 62 void tx_ack()
dudmuck 0:1d8d218c5cc5 63 {
dudmuck 0:1d8d218c5cc5 64 uint8_t n = 0;
dudmuck 0:1d8d218c5cc5 65 uint16_t crc;
dudmuck 0:1d8d218c5cc5 66
dudmuck 0:1d8d218c5cc5 67 if (radio.rx_buf[0] == CMD_OUT_PIN) {
dudmuck 0:1d8d218c5cc5 68 uint16_t ain = a1.read_u16();
dudmuck 0:1d8d218c5cc5 69 radio.tx_buf[n++] = CMD_OUT_PIN_ACK;
dudmuck 0:1d8d218c5cc5 70 /* TODO read analog pin and digital input pin */
dudmuck 0:1d8d218c5cc5 71 radio.tx_buf[n++] = ain;
dudmuck 0:1d8d218c5cc5 72 radio.tx_buf[n++] = ain >> 8;
dudmuck 0:1d8d218c5cc5 73 } else
dudmuck 0:1d8d218c5cc5 74 radio.tx_buf[n++] = 0xff;
dudmuck 0:1d8d218c5cc5 75
dudmuck 0:1d8d218c5cc5 76 crc = crc16(radio.tx_buf, n);
dudmuck 0:1d8d218c5cc5 77 radio.tx_buf[n++] = crc;
dudmuck 0:1d8d218c5cc5 78 radio.tx_buf[n++] = crc >> 8;
dudmuck 0:1d8d218c5cc5 79
dudmuck 0:1d8d218c5cc5 80 lora.RegPayloadLength = n;
dudmuck 0:1d8d218c5cc5 81 radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
dudmuck 0:1d8d218c5cc5 82
dudmuck 0:1d8d218c5cc5 83 lora.start_tx(lora.RegPayloadLength); /* begin transmission */
dudmuck 0:1d8d218c5cc5 84
dudmuck 0:1d8d218c5cc5 85 printf("tx-ack-start\r\n");
dudmuck 0:1d8d218c5cc5 86 while (lora.service() != SERVICE_TX_DONE) /* wait for transmission to complete */
dudmuck 0:1d8d218c5cc5 87 ;
dudmuck 0:1d8d218c5cc5 88
dudmuck 0:1d8d218c5cc5 89 lora.start_rx(RF_OPMODE_RECEIVER);
dudmuck 0:1d8d218c5cc5 90 printf("tx-ack-end\r\n");
dudmuck 0:1d8d218c5cc5 91 }
dudmuck 0:1d8d218c5cc5 92
dudmuck 0:1d8d218c5cc5 93 void tx()
dudmuck 0:1d8d218c5cc5 94 {
dudmuck 0:1d8d218c5cc5 95 int i;
dudmuck 0:1d8d218c5cc5 96
dudmuck 0:1d8d218c5cc5 97 for (i = 0; i < 3; i++) {
dudmuck 0:1d8d218c5cc5 98 uint8_t n = 0;
dudmuck 0:1d8d218c5cc5 99 uint16_t crc;
dudmuck 0:1d8d218c5cc5 100 int rx_timeout_at;
dudmuck 0:1d8d218c5cc5 101
dudmuck 0:1d8d218c5cc5 102 radio.tx_buf[n++] = CMD_OUT_PIN;
dudmuck 0:1d8d218c5cc5 103 radio.tx_buf[n++] = out_pin_state;
dudmuck 0:1d8d218c5cc5 104 crc = crc16(radio.tx_buf, n);
dudmuck 0:1d8d218c5cc5 105 radio.tx_buf[n++] = crc;
dudmuck 0:1d8d218c5cc5 106 radio.tx_buf[n++] = crc >> 8;
dudmuck 0:1d8d218c5cc5 107
dudmuck 0:1d8d218c5cc5 108 lora.RegPayloadLength = n;
dudmuck 0:1d8d218c5cc5 109 radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
dudmuck 0:1d8d218c5cc5 110
dudmuck 0:1d8d218c5cc5 111 lora.start_tx(lora.RegPayloadLength); /* begin transmission */
dudmuck 0:1d8d218c5cc5 112
dudmuck 0:1d8d218c5cc5 113 while (lora.service() != SERVICE_TX_DONE) /* wait for transmission to complete */
dudmuck 0:1d8d218c5cc5 114 ;
dudmuck 0:1d8d218c5cc5 115 rx_timeout_at = t.read_us() + 200000;
dudmuck 0:1d8d218c5cc5 116
dudmuck 0:1d8d218c5cc5 117 lora.start_rx(RF_OPMODE_RECEIVER);
dudmuck 0:1d8d218c5cc5 118
dudmuck 0:1d8d218c5cc5 119 while (t.read_us() < rx_timeout_at) {
dudmuck 0:1d8d218c5cc5 120 if (lora.service() == SERVICE_READ_FIFO) {
dudmuck 0:1d8d218c5cc5 121 uint16_t rx_crc;
dudmuck 0:1d8d218c5cc5 122 rx_crc = radio.rx_buf[lora.RegRxNbBytes-2];
dudmuck 0:1d8d218c5cc5 123 rx_crc |= radio.rx_buf[lora.RegRxNbBytes-1] << 8;
dudmuck 0:1d8d218c5cc5 124 crc = crc16(radio.rx_buf, lora.RegRxNbBytes-2);
dudmuck 0:1d8d218c5cc5 125 if (crc == rx_crc) {
dudmuck 0:1d8d218c5cc5 126 printf("crcOk %u\r\n", i);
dudmuck 0:1d8d218c5cc5 127 if (radio.rx_buf[0] == CMD_OUT_PIN_ACK) {
dudmuck 0:1d8d218c5cc5 128 uint16_t ain = radio.rx_buf[0];
dudmuck 0:1d8d218c5cc5 129 ain |= radio.rx_buf[1] << 8;
dudmuck 0:1d8d218c5cc5 130 printf("ain %u\r\n", ain);
dudmuck 0:1d8d218c5cc5 131 }
dudmuck 0:1d8d218c5cc5 132 return;
dudmuck 0:1d8d218c5cc5 133 } else
dudmuck 0:1d8d218c5cc5 134 printf("crcFail %04x != %04x\r\n", crc, rx_crc);
dudmuck 0:1d8d218c5cc5 135 }
dudmuck 0:1d8d218c5cc5 136 }
dudmuck 0:1d8d218c5cc5 137 printf("rx-timeout %u\r\n", i);
dudmuck 0:1d8d218c5cc5 138 } // ..for()
dudmuck 0:1d8d218c5cc5 139 }
dudmuck 0:1d8d218c5cc5 140
dudmuck 0:1d8d218c5cc5 141 volatile bool start_tx;
dudmuck 0:1d8d218c5cc5 142
dudmuck 0:1d8d218c5cc5 143 void button_isr()
dudmuck 0:1d8d218c5cc5 144 {
dudmuck 0:1d8d218c5cc5 145 if (!jumper_in.read())
dudmuck 0:1d8d218c5cc5 146 start_tx = true;
dudmuck 0:1d8d218c5cc5 147 }
dudmuck 0:1d8d218c5cc5 148
dudmuck 0:1d8d218c5cc5 149 void auto_tx()
dudmuck 0:1d8d218c5cc5 150 {
dudmuck 0:1d8d218c5cc5 151 if (jumper_in.read())
dudmuck 0:1d8d218c5cc5 152 start_tx = true;
dudmuck 0:1d8d218c5cc5 153 else
dudmuck 0:1d8d218c5cc5 154 ticker.detach();
dudmuck 0:1d8d218c5cc5 155 }
dudmuck 0:1d8d218c5cc5 156
dudmuck 0:1d8d218c5cc5 157 int main()
dudmuck 0:1d8d218c5cc5 158 {
dudmuck 0:1d8d218c5cc5 159 bool jin = false;
dudmuck 0:1d8d218c5cc5 160 printf("\r\nreset\r\n");
dudmuck 0:1d8d218c5cc5 161
dudmuck 0:1d8d218c5cc5 162 jumper_out = 1;
dudmuck 0:1d8d218c5cc5 163 jumper_in.mode(PullDown);
dudmuck 0:1d8d218c5cc5 164
dudmuck 0:1d8d218c5cc5 165 while (!user_button) {
dudmuck 0:1d8d218c5cc5 166 printf("button-lo\r\n");
dudmuck 0:1d8d218c5cc5 167 wait(0.01);
dudmuck 0:1d8d218c5cc5 168 }
dudmuck 0:1d8d218c5cc5 169 user_button.fall(&button_isr);
dudmuck 0:1d8d218c5cc5 170 t.start();
dudmuck 0:1d8d218c5cc5 171
dudmuck 0:1d8d218c5cc5 172 radio.rf_switch = rfsw_callback;
dudmuck 0:1d8d218c5cc5 173
dudmuck 0:1d8d218c5cc5 174 radio.set_frf_MHz(917.3);
dudmuck 0:1d8d218c5cc5 175 lora.enable();
dudmuck 0:1d8d218c5cc5 176 lora.setBw_KHz(500);
dudmuck 0:1d8d218c5cc5 177 lora.setSf(9);
dudmuck 0:1d8d218c5cc5 178
dudmuck 0:1d8d218c5cc5 179 /* RFO or PABOOST choice:
dudmuck 0:1d8d218c5cc5 180 * SX1276 shield: RFO if using 900MHz, or PA_BOOST if using 433MHz
dudmuck 0:1d8d218c5cc5 181 */
dudmuck 0:1d8d218c5cc5 182 rfsw.input();
dudmuck 0:1d8d218c5cc5 183 if (rfsw.read()) {
dudmuck 0:1d8d218c5cc5 184 printf("LAS\r\n");
dudmuck 0:1d8d218c5cc5 185 /* LAS HF=PA_BOOST LF=RFO */
dudmuck 0:1d8d218c5cc5 186 if (radio.HF)
dudmuck 0:1d8d218c5cc5 187 radio.RegPaConfig.bits.PaSelect = 1;
dudmuck 0:1d8d218c5cc5 188 else
dudmuck 0:1d8d218c5cc5 189 radio.RegPaConfig.bits.PaSelect = 0;
dudmuck 0:1d8d218c5cc5 190 } else {
dudmuck 0:1d8d218c5cc5 191 /* MAS shield board, only RFO TX */
dudmuck 0:1d8d218c5cc5 192 radio.RegPaConfig.bits.PaSelect = 0;
dudmuck 0:1d8d218c5cc5 193 printf("MAS\r\n");
dudmuck 0:1d8d218c5cc5 194 }
dudmuck 0:1d8d218c5cc5 195 rfsw.output();
dudmuck 0:1d8d218c5cc5 196 radio.write_reg(REG_PACONFIG, radio.RegPaConfig.octet);
dudmuck 0:1d8d218c5cc5 197
dudmuck 0:1d8d218c5cc5 198 lora.start_rx(RF_OPMODE_RECEIVER);
dudmuck 0:1d8d218c5cc5 199
dudmuck 0:1d8d218c5cc5 200 for (;;) {
dudmuck 0:1d8d218c5cc5 201
dudmuck 0:1d8d218c5cc5 202 if (jumper_in.read()) {
dudmuck 0:1d8d218c5cc5 203 if (!jin) {
dudmuck 0:1d8d218c5cc5 204 ticker.attach(auto_tx, 0.5);
dudmuck 0:1d8d218c5cc5 205 jin = true;
dudmuck 0:1d8d218c5cc5 206 }
dudmuck 0:1d8d218c5cc5 207 } else {
dudmuck 0:1d8d218c5cc5 208 jin = false;
dudmuck 0:1d8d218c5cc5 209 }
dudmuck 0:1d8d218c5cc5 210
dudmuck 0:1d8d218c5cc5 211 if (start_tx) {
dudmuck 0:1d8d218c5cc5 212 out_pin_state ^= 1;
dudmuck 0:1d8d218c5cc5 213 tx();
dudmuck 0:1d8d218c5cc5 214 start_tx = false;
dudmuck 0:1d8d218c5cc5 215 }
dudmuck 0:1d8d218c5cc5 216 if (lora.service() == SERVICE_READ_FIFO) {
dudmuck 0:1d8d218c5cc5 217 uint16_t crc, rx_crc;
dudmuck 0:1d8d218c5cc5 218 int i;
dudmuck 0:1d8d218c5cc5 219 for (i = 0; i < lora.RegRxNbBytes; i++) {
dudmuck 0:1d8d218c5cc5 220 printf("%02x ", radio.rx_buf[i]);
dudmuck 0:1d8d218c5cc5 221 }
dudmuck 0:1d8d218c5cc5 222 printf("\r\n");
dudmuck 0:1d8d218c5cc5 223 rx_crc = radio.rx_buf[lora.RegRxNbBytes-2];
dudmuck 0:1d8d218c5cc5 224 rx_crc |= radio.rx_buf[lora.RegRxNbBytes-1] << 8;
dudmuck 0:1d8d218c5cc5 225 crc = crc16(radio.rx_buf, lora.RegRxNbBytes-2);
dudmuck 0:1d8d218c5cc5 226 if (crc == rx_crc) {
dudmuck 0:1d8d218c5cc5 227 printf("crcOk\r\n");
dudmuck 0:1d8d218c5cc5 228 if (radio.rx_buf[0] == CMD_OUT_PIN) {
dudmuck 0:1d8d218c5cc5 229 pc6_out.write(radio.rx_buf[1]);
dudmuck 0:1d8d218c5cc5 230 printf("out pin state: %u", radio.rx_buf[1]);
dudmuck 0:1d8d218c5cc5 231 }
dudmuck 0:1d8d218c5cc5 232 printf("\r\n");
dudmuck 0:1d8d218c5cc5 233 tx_ack();
dudmuck 0:1d8d218c5cc5 234 } else
dudmuck 0:1d8d218c5cc5 235 printf("crc %04x != %04x\r\n", crc, rx_crc);
dudmuck 0:1d8d218c5cc5 236 } // ..if something received
dudmuck 0:1d8d218c5cc5 237 } // ..for (;;)
dudmuck 0:1d8d218c5cc5 238 }
dudmuck 0:1d8d218c5cc5 239