operate LoRa radio over I2C

Dependencies:   TimeoutAbs lib_i2c_slave_block sx12xx_hal

radio chip selection

Radio chip driver is not included, allowing choice of radio device.
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.

This project is used as slave device with i2c_lora_master on raspberry pi. This i2c_lora_slave offloads the real-time requirements onto microcontroller. Also permits multiple slave radio devices connected to master. Radio MAC layer exists on I2C master, along with application layer.

If beacon operation is enabled, I2C functions which access radio chip are blocked while beacon is loaded and transmitted.
See lib_i2c_slave_block for wiring connections.

Revision:
0:9eb5b8bf9f7b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/device_sx127x.cpp	Fri Feb 08 11:58:09 2019 -0800
@@ -0,0 +1,297 @@
+#include "radio_device.h"
+#ifdef SX127x_H 
+void get_opmode()
+{
+    Radio::radio.RegOpMode.octet = Radio::radio.read_reg(REG_OPMODE);
+
+    switch (Radio::radio.RegOpMode.bits.Mode) {
+        case RF_OPMODE_SLEEP:
+            irq.buf[1] = OPMODE_SLEEP;
+            break;
+        case RF_OPMODE_STANDBY:
+            irq.buf[1] = OPMODE_STANDBY;
+            break;
+        case RF_OPMODE_TRANSMITTER:
+            irq.buf[1] = OPMODE_TX;
+            break;
+        case RF_OPMODE_SYNTHESIZER_TX:
+        case RF_OPMODE_SYNTHESIZER_RX:
+            irq.buf[1] = OPMODE_FS;
+            break;
+        case RF_OPMODE_RECEIVER:
+        case RF_OPMODE_RECEIVER_SINGLE:
+        case RF_OPMODE_CAD:
+            irq.buf[1] = OPMODE_RX;
+            break;
+        default:
+            irq.buf[1] = OPMODE_FAIL;
+            break;
+    }
+
+    irq.fields.flags.irq_type = IRQ_TYPE_OPMODE;
+    irqOutPin = 1;
+}
+
+void get_lora_packet()
+{
+    uint32_t val;
+    //LoRaPacketConfig(unsigned preambleLen, bool fixLen, bool crcOn, bool invIQ)
+    Radio::lora.RegPreamble = Radio::radio.read_u16(REG_LR_PREAMBLEMSB);
+    val = Radio::lora.RegPreamble;
+    irq.buf[1] = val & 0xff;
+    val >>= 8;
+    irq.buf[2] = val & 0xff;
+
+    irq.buf[3] = Radio::lora.getHeaderMode();
+
+    Radio::lora.RegTest33.octet = Radio::radio.read_reg(REG_LR_TEST33);
+    irq.buf[4] = Radio::lora.RegTest33.bits.invert_i_q;
+
+    irq.buf[5] = Radio::lora.getRxPayloadCrcOn();
+
+    irq.fields.flags.irq_type = IRQ_TYPE_LORA_PKT;
+    irqOutPin = 1;
+}
+
+static const unsigned* lora_bw_khz;
+
+void get_lora_modem()
+{
+    uint16_t khz = lora_bw_khz[Radio::lora.getBw()];
+
+    irq.buf[1] = khz & 0xff;
+    khz >>= 8;
+    irq.buf[2] = khz & 0xff;
+
+    //LoRaModemConfig(unsigned KHz, unsigned sf, unsigned cr)
+    irq.buf[3] = Radio::lora.getSf();
+    irq.buf[4] = Radio::lora.getCodingRate(false);
+    
+    irq.fields.flags.irq_type = IRQ_TYPE_LORA_MODEM;
+    irqOutPin = 1;
+}
+
+void get_tx_dbm()
+{
+    int8_t dbm;
+    RegPdsTrim1_t pds_trim;
+    uint8_t adr, pa_test_adr;
+
+    if (Radio::radio.type == SX1276) {
+        adr = REG_PDSTRIM1_SX1276;
+        pa_test_adr = REG_PATEST_SX1276;
+    } else {
+        adr = REG_PDSTRIM1_SX1272;
+        pa_test_adr = REG_PATEST_SX1272;
+    }
+
+    if (Radio::radio.read_reg(pa_test_adr) & 0x20) {
+        pds_trim.octet = Radio::radio.read_reg(adr);
+
+        Radio::radio.RegPaConfig.octet = Radio::radio.read_reg(REG_PACONFIG);
+        if (Radio::radio.RegPaConfig.bits.PaSelect) {
+            dbm = Radio::radio.RegPaConfig.bits.OutputPower + pds_trim.bits.prog_txdac - 2;
+        } else {
+            dbm = Radio::radio.RegPaConfig.bits.OutputPower - 1;
+        }
+    } else {
+        dbm = PA_OFF_DBM;
+    }
+
+    irq.buf[1] = dbm;
+    irq.fields.flags.irq_type = IRQ_TYPE_TXDBM;
+    irqOutPin = 1;
+}
+
+void get_fsk_sync()
+{
+    unsigned n, idx = 1;
+
+    Radio::fsk.RegSyncConfig.octet = Radio::radio.read_reg(REG_FSK_SYNCCONFIG);
+
+    irq.buf[idx++] = Radio::fsk.RegSyncConfig.bits.SyncSize + 1;
+    for (n = 0; n < irq.buf[2]; n++) {
+        irq.buf[idx++] = Radio::radio.read_reg(REG_FSK_SYNCVALUE1+n);
+    }
+
+    irq.fields.flags.irq_type = IRQ_TYPE_FSK_SYNC;
+    irqOutPin = 1;
+}
+
+static unsigned bw_read(uint8_t regAddr)
+{
+    RegRxBw_t reg_bw;
+
+    reg_bw.octet = Radio::radio.read_reg(regAddr);
+
+    switch (reg_bw.bits.Exponent) {
+        case 7:
+            if (reg_bw.bits.Mantissa == 2)
+                return 0;
+            if (reg_bw.bits.Mantissa == 1)
+                return 1;
+            if (reg_bw.bits.Mantissa == 0)
+                return 2;
+            break;
+        case 6:
+            if (reg_bw.bits.Mantissa == 2)
+                return 3;
+            if (reg_bw.bits.Mantissa == 1)
+                return 4;
+            if (reg_bw.bits.Mantissa == 0)
+                return 5;
+            break;
+        case 5:
+            if (reg_bw.bits.Mantissa == 2)
+                return 6;
+            if (reg_bw.bits.Mantissa == 1)
+                return 7;
+            if (reg_bw.bits.Mantissa == 0)
+                return 8;
+            break;
+        case 4:
+            if (reg_bw.bits.Mantissa == 2)
+                return 9;
+            if (reg_bw.bits.Mantissa == 1)
+                return 10;
+            if (reg_bw.bits.Mantissa == 0)
+                return 11;
+            break;
+        case 3:
+            if (reg_bw.bits.Mantissa == 2)
+                return 12;
+            if (reg_bw.bits.Mantissa == 1)
+                return 13;
+            if (reg_bw.bits.Mantissa == 0)
+                return 14;
+            break;
+        case 2:
+            if (reg_bw.bits.Mantissa == 2)
+                return 15;
+            if (reg_bw.bits.Mantissa == 1)
+                return 16;
+            if (reg_bw.bits.Mantissa == 0)
+                return 17;
+            break;
+        case 1:
+            if (reg_bw.bits.Mantissa == 2)
+                return 18;
+            if (reg_bw.bits.Mantissa == 1)
+                return 19;
+            if (reg_bw.bits.Mantissa == 0)
+                return 20;
+            break;
+    }
+
+    return 21;
+}
+
+static const unsigned rxbws[] = {
+    2600, // 0
+    3100, // 1
+    3900, // 2
+    5200, // 3
+    6300, // 4
+    7800, // 5
+    10400, // 6
+    12500, // 7
+    15600, // 8
+    20800, // 9
+    25000, // 10
+    31300, // 11
+    41700, // 12
+    50000, // 13
+    62500, // 14
+    83300, // 15
+    100000, // 16
+    125000, // 17
+    166700, // 18
+    200000, // 19
+    250000 // 20
+};
+
+void get_fsk_modem()
+{
+    uint32_t u32;
+    // GFSKModemConfig(unsigned bps, unsigned bwKHz, unsigned fdev_hz)
+
+    u32 = Radio::fsk.get_bitrate();
+    irq.buf[1] = u32 & 0xff;
+    u32 >>= 8;
+    irq.buf[2] = u32 & 0xff;
+    u32 >>= 8;
+    irq.buf[3] = u32 & 0xff;
+    u32 >>= 8;
+    irq.buf[4] = u32 & 0xff;
+
+    u32 = rxbws[bw_read(REG_FSK_RXBW)];
+    irq.buf[5] = u32 & 0xff;
+    u32 >>= 8;
+    irq.buf[6] = u32 & 0xff;
+
+    u32 = Radio::fsk.get_tx_fdev_hz();
+    irq.buf[7] = u32 & 0xff;
+    u32 >>= 8;
+    irq.buf[8] = u32 & 0xff;
+    u32 >>= 8;
+    irq.buf[9] = u32 & 0xff;
+    u32 >>= 8;
+    irq.buf[10] = u32 & 0xff;
+
+    irq.fields.flags.irq_type = IRQ_TYPE_FSK_MODEM;
+    irqOutPin = 1;
+}
+
+void get_fsk_packet()
+{
+    // GFSKPacketConfig(unsigned preambleLen, bool fixLen, bool crcOn)
+    unsigned pl = Radio::radio.read_u16(REG_FSK_PREAMBLEMSB);
+    irq.buf[1] = pl & 0xff;
+    pl >>= 8;
+    irq.buf[2] = pl & 0xff;
+
+    Radio::fsk.RegPktConfig1.octet = Radio::radio.read_reg(REG_FSK_PACKETCONFIG1);
+    irq.buf[3] = Radio::fsk.RegPktConfig1.bits.PacketFormatVariable;
+
+    Radio::fsk.RegPktConfig1.octet = Radio::radio.read_reg(REG_FSK_PACKETCONFIG1);
+    irq.buf[4] = Radio::fsk.RegPktConfig1.bits.CrcOn;
+    
+    irq.fields.flags.irq_type = IRQ_TYPE_FSK_PKT;
+    irqOutPin = 1;
+}
+
+void radio_reset()
+{
+    Radio::radio.hw_reset();
+}
+
+
+static const unsigned lora_bw_khz_1276[] = {
+      8, // 0
+     10, // 1
+     16, // 2
+     21, // 3
+     31, // 4
+     42, // 5
+     63, // 6
+    125, // 7
+    250, // 8
+    500  // 9
+};
+static const unsigned lora_bw_khz_1272[] = {
+    125, // 0
+    250, // 1
+    500  // 2
+};
+
+void radio_device_init()
+{
+    if (Radio::radio.type == SX1276) {
+        lora_bw_khz = lora_bw_khz_1276;
+    } else if (Radio::radio.type == SX1272) {
+        lora_bw_khz = lora_bw_khz_1272;
+    }
+}
+
+
+#endif /* ..SX127x_H */