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.

Revision:
4:b5dd459ac390
Parent:
3:cd312fc32558
Child:
5:e35b1b281466
--- a/main.cpp	Wed May 30 10:20:36 2018 -0700
+++ b/main.cpp	Tue Jul 17 14:32:29 2018 -0700
@@ -1,42 +1,51 @@
-#include "sx127x_lora.h"
+#include "radio.h"
 #include "uart_cmds.h"
 
 //#define ANALOG_TX_TRIGGER
 
+#if defined(SX127x_H) || defined(SX126x_H)
+    #define BW_KHZ              500
+    #define SPREADING_FACTOR    9
+    #define CF_HZ              917300000
+    #ifdef SX127x_H
+        AnalogIn a1(A1);
+    #else
+        /* arduino analog pins used by radio shield */
+        AnalogIn a1(PC_3);  // PC_2 and PC_4 also available
+    #endif
+#elif defined(SX128x_H)
+    #define BW_KHZ              400
+    #define SPREADING_FACTOR    9
+    #define CF_HZ              2487000000
+    /* arduino analog pins used by radio shield */
+    AnalogIn a1(PC_3);  // PC_2 and PC_4 also available
+#endif
+
 DigitalOut myled(LED1);
 
-SPI spi(D11, D12, D13); // mosi, miso, sclk
-//           dio0, dio1, nss, spi, rst
-SX127x radio(  D2,   D3, D10, spi, A0); // sx1276 arduino shield
 
-SX127x_lora lora(radio);
-DigitalInOut rfsw(A4);    // for SX1276 arduino shield
-
-InterruptIn user_button(USER_BUTTON);
 Timer t;
 Ticker ticker;
-AnalogIn a1(A1);
-#define AIN_REST_THRESHOLD      96  // 12bit left justified
+volatile bool tx_done;
+InterruptIn user_button(USER_BUTTON);
 DigitalOut pc6_out(PC_6);
 
 #ifndef ANALOG_TX_TRIGGER
-DigitalOut jumper_out(PC_10);
-InterruptIn jumper_in(PC_12);
-volatile bool start_tx;
+    #define AIN_REST_THRESHOLD      96  // 12bit left justified
+    DigitalOut jumper_out(PC_10);
+    InterruptIn jumper_in(PC_12);
+    volatile bool start_tx;
 #endif /* !ANALOG_TX_TRIGGER */
 
-void rfsw_callback()
-{
-    if (radio.RegOpMode.bits.Mode == RF_OPMODE_TRANSMITTER)
-        rfsw = 1;
-    else
-        rfsw = 0;
-}
-
+#define RX_TIMEOUT_US       200000
 /**********************************************************************/
 
 uint8_t out_pin_state;
 
+void txDoneCB()
+{
+    tx_done = true;
+}
 
 static uint16_t crc16( uint8_t *buffer, uint16_t length )
 {
@@ -69,28 +78,40 @@
     uint8_t n = 0;
     uint16_t crc;
 
-    if (radio.rx_buf[0] == CMD_OUT_PIN) {
+    if (Radio::radio.rx_buf[0] == CMD_OUT_PIN) {
         uint16_t ain = a1.read_u16();
-        radio.tx_buf[n++] = CMD_OUT_PIN_ACK;
+        Radio::radio.tx_buf[n++] = CMD_OUT_PIN_ACK;
         /* TODO read analog pin and digital input pin */
-        radio.tx_buf[n++] = ain;
-        radio.tx_buf[n++] = ain >> 8;
+        Radio::radio.tx_buf[n++] = ain;
+        Radio::radio.tx_buf[n++] = ain >> 8;
     } else
-        radio.tx_buf[n++] = 0xff;
+        Radio::radio.tx_buf[n++] = 0xff;
+
+    crc = crc16(Radio::radio.tx_buf, n);
+    Radio::radio.tx_buf[n++] = crc;
+    Radio::radio.tx_buf[n++] = crc >> 8;
 
-    crc = crc16(radio.tx_buf, n);
-    radio.tx_buf[n++] = crc;
-    radio.tx_buf[n++] = crc >> 8;
+    tx_done = false;
+    Radio::Send(n, 0, 0, 0);
+    printf("tx_ack\r\n");
+    
+    while (!tx_done)
+        Radio::service();
+
+    Radio::Rx(0);
+}
 
-    lora.RegPayloadLength = n;
-    radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
-        
-    lora.start_tx(lora.RegPayloadLength);   /* begin transmission */
-    
-    while (lora.service() != SERVICE_TX_DONE)   /* wait for transmission to complete */
-        ;
+volatile struct _rx_ {
+    uint8_t length;
+    float rssi;
+    float snr;
+} rx;
 
-    lora.start_rx(RF_OPMODE_RECEIVER);
+void rxDoneCB(uint8_t size, float Rssi, float Snr)
+{
+    rx.length = size;
+    rx.rssi = Rssi;
+    rx.snr = Snr;
 }
 
 void radio_tx(uint8_t* payload, uint8_t payload_len)
@@ -102,48 +123,53 @@
     while (payload_len > 0) {
         //printf("n%u, paylen%u\r\n", n, payload_len);
         payload_len--;
-        radio.tx_buf[payload_len] = payload[payload_len];
+        Radio::radio.tx_buf[payload_len] = payload[payload_len];
         n++;
     }
 
-    crc = crc16(radio.tx_buf, n);
-    radio.tx_buf[n++] = crc;
-    radio.tx_buf[n++] = crc >> 8;
-
-    lora.RegPayloadLength = n;
-    radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
+    crc = crc16(Radio::radio.tx_buf, n);
+    Radio::radio.tx_buf[n++] = crc;
+    Radio::radio.tx_buf[n++] = crc >> 8;
 
     for (i = 0; i < 3; i++) {
         int rx_timeout_at;
+        int rx_start_at;
 
-        lora.start_tx(lora.RegPayloadLength);   /* begin transmission */
+        tx_done = false;
+        Radio::Send(n, 0, 0, 0);
         
-        while (lora.service() != SERVICE_TX_DONE)   /* wait for transmission to complete */
-            ;
-        rx_timeout_at = t.read_us() + 200000;
+        while (!tx_done)
+            Radio::service();
 
-        lora.start_rx(RF_OPMODE_RECEIVER);
+        rx_start_at = t.read_us();
+        rx_timeout_at = rx_start_at + RX_TIMEOUT_US;
+
+        Radio::Rx(0);
+        rx.length = 0;
 
         while (t.read_us() < rx_timeout_at) {
-            if (lora.service() == SERVICE_READ_FIFO) {
+            Radio::service();
+            if (rx.length > 0) {
                 uint16_t rx_crc;
-                printf("rssi:%ddBm snr:%.1fdB ", lora.get_pkt_rssi(), lora.RegPktSnrValue / 4.0);
-                rx_crc = radio.rx_buf[lora.RegRxNbBytes-2];
-                rx_crc |= radio.rx_buf[lora.RegRxNbBytes-1] << 8;
-                crc = crc16(radio.rx_buf, lora.RegRxNbBytes-2);
+                printf(" rssi:%.1fdBm snr:%.1fdB ", rx.rssi, rx.snr);
+                rx_crc = Radio::radio.rx_buf[rx.length-2];
+                rx_crc |= Radio::radio.rx_buf[rx.length-1] << 8;
+                crc = crc16(Radio::radio.rx_buf, rx.length-2);
                 if (crc == rx_crc) {
                     printf("crcOk %u\r\n", i);
-                    if (radio.rx_buf[0] == CMD_OUT_PIN_ACK) {
-                        uint16_t ain = radio.rx_buf[1];
-                        ain |= radio.rx_buf[2] << 8;
+                    if (Radio::radio.rx_buf[0] == CMD_OUT_PIN_ACK) {
+                        uint16_t ain = Radio::radio.rx_buf[1];
+                        ain |= Radio::radio.rx_buf[2] << 8;
                         printf("ain %u\r\n", ain);
                     }
+                    rx.length = 0;
                     return;
                 } else
                     printf("crcFail %04x != %04x\r\n", crc, rx_crc);
+                rx.length = 0;
             } 
         }
-        printf("rx-timeout %u\r\n", i);
+        printf("rx-timeout %u,  %u\r\n", i, t.read_us() - rx_start_at);
     } // ..for()
 }
 
@@ -163,6 +189,19 @@
 }
 #endif /* !ANALOG_TX_TRIGGER */
 
+
+const RadioEvents_t rev = {
+    /* Dio0_top_half */     NULL,
+    /* TxDone_topHalf */    NULL,
+    /* TxDone_botHalf */    txDoneCB,
+    /* TxTimeout  */        NULL,
+    /* RxDone  */           rxDoneCB,
+    /* RxTimeout  */        NULL,
+    /* RxError  */          NULL,
+    /* FhssChangeChannel  */NULL,
+    /* CadDone  */          NULL
+};
+
 int main()
 {
 #ifdef ANALOG_TX_TRIGGER
@@ -184,33 +223,14 @@
     printf("\r\n2reset\r\n");
     t.start();
 
-    radio.rf_switch = rfsw_callback;
-    
-    radio.set_frf_MHz(917.3);
-    lora.enable();
-    lora.setBw_KHz(500);
-    lora.setSf(9);
+    Radio::Init(&rev);
+
+    Radio::Standby();
+    Radio::LoRaModemConfig(BW_KHZ, SPREADING_FACTOR, 1);
+    Radio::LoRaPacketConfig(8, false, true, false);  // preambleLen, fixLen, crcOn, invIQ
+    Radio::SetChannel(CF_HZ);
     
-    /* RFO or PABOOST choice:
-     * SX1276 shield: RFO if using 900MHz, or PA_BOOST if using 433MHz
-     */
-    rfsw.input();
-    if (rfsw.read()) {
-        printf("LAS\r\n");
-        /* LAS HF=PA_BOOST  LF=RFO */
-        if (radio.HF)
-            radio.RegPaConfig.bits.PaSelect = 1;
-        else
-            radio.RegPaConfig.bits.PaSelect = 0;
-    } else {
-        /* MAS shield board, only RFO TX */
-        radio.RegPaConfig.bits.PaSelect = 0;
-        printf("MAS\r\n");
-    }
-    rfsw.output();
-    radio.write_reg(REG_PACONFIG, radio.RegPaConfig.octet);
-                
-    lora.start_rx(RF_OPMODE_RECEIVER);
+    Radio::Rx(0);
 
 #ifdef ANALOG_TX_TRIGGER
     prev_ain = a1.read_u16();
@@ -270,33 +290,43 @@
             out_pin_state ^= 1;
             buf[0] = CMD_OUT_PIN;
             buf[1] = out_pin_state;
-            printf("start_tx...\r\n");
             radio_tx(buf, 2);
         }
 #endif /* !ANALOG_TX_TRIGGER */
-        if (lora.service() == SERVICE_READ_FIFO) {
+        if (rx.length > 0) {
             uint16_t crc, rx_crc;
             int i;
-            for (i = 0; i < lora.RegRxNbBytes; i++) {
-                printf("%02x ", radio.rx_buf[i]);
+            for (i = 0; i < rx.length; i++) {
+                printf("%02x ", Radio::radio.rx_buf[i]);
             }
-            printf(" rssi:%ddBm, snr:%.1fdB\r\n", lora.get_pkt_rssi(), lora.RegPktSnrValue / 4.0);
-            rx_crc = radio.rx_buf[lora.RegRxNbBytes-2];
-            rx_crc |= radio.rx_buf[lora.RegRxNbBytes-1] << 8;
-            crc = crc16(radio.rx_buf, lora.RegRxNbBytes-2);
+            printf(" rssi:%.1fdBm, snr:%.1fdB\r\n", rx.rssi, rx.snr);
+            rx_crc = Radio::radio.rx_buf[rx.length-2];
+            rx_crc |= Radio::radio.rx_buf[rx.length-1] << 8;
+            crc = crc16(Radio::radio.rx_buf, rx.length-2);
             if (crc == rx_crc) {
+                bool sendAck = false;
+                bool parsed = parse_radio_rx(Radio::radio.rx_buf);
                 printf("crcOk\r\n");
-                if (!parse_radio_rx(radio.rx_buf) && radio.rx_buf[0] == CMD_OUT_PIN) {
-                    pc6_out.write(radio.rx_buf[1]);
-                    printf("out pin state: %u", radio.rx_buf[1]);
-                }
+                if (!parsed && Radio::radio.rx_buf[0] == CMD_OUT_PIN) {
+                    pc6_out.write(Radio::radio.rx_buf[1]);
+                    printf("out pin state: %u", Radio::radio.rx_buf[1]);
+                    sendAck = true;
+                } else if (parsed)
+                    sendAck = true;
+
                 printf("\r\n");
-                tx_ack();
+
+                if (sendAck)
+                    tx_ack();
             } else
                 printf("crc %04x != %04x\r\n", crc, rx_crc);
+
+            rx.length = 0;
         } // ..if something received
 
         uart_service();
+
+        Radio::service();
     } // ..for (;;)
 }