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:
Mon Oct 16 11:20:25 2017 -0700
Revision:
1:d95d135a4fb4
Parent:
0:1d8d218c5cc5
Child:
2:5131512b4eb9
add pwm

Who changed what in which revision?

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