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.

device_sx128x.cpp

Committer:
Wayne Roberts
Date:
2019-02-08
Revision:
0:9eb5b8bf9f7b

File content as of revision 0:9eb5b8bf9f7b:

#include "radio_device.h"
#ifdef SX128x_H 
void get_opmode()
{
    status_t status;
    Radio::radio.xfer(OPCODE_GET_STATUS, 0, 1, &status.octet);

    switch (status.bits.chipMode) {
        case 2: // STBY_RC
        case 3: // STBY_XOSC
            irq.buf[1] = OPMODE_STANDBY;
            break;
        case 4: // FS
            irq.buf[1] = OPMODE_FS;
            break;
        case 5: // RX
            irq.buf[1] = OPMODE_RX;
            break;
        case 6: // TX
            irq.buf[1] = OPMODE_TX;
            break;
        default:
            irq.buf[1] = OPMODE_FAIL;
            break;
    }

    irq.fields.flags.irq_type = IRQ_TYPE_OPMODE;
    irqOutPin = 1;
}

void get_lora_packet()
{
    LoRaLrCtl_t LoRaLrCtl;
    LoRaPktPar1_t LoRaPktPar1;
    //LoRaPacketConfig(unsigned preambleLen, bool fixLen, bool crcOn, bool invIQ)
    LoRaPreambleReg_t LoRaPreambleReg;
    LoRaPreambleReg.octet = Radio::radio.readReg(REG_ADDR_LORA_PREAMBLE, 1);
    uint32_t val = (1 << LoRaPreambleReg.bits.preamble_symb_nb_exp) * LoRaPreambleReg.bits.preamble_symb1_nb;
    irq.buf[1] = val & 0xff;
    val >>= 8;
    irq.buf[2] = val & 0xff;

    LoRaPktPar1.octet = Radio::radio.readReg(REG_ADDR_LORA_PKTPAR1, 1);
    irq.buf[3] = LoRaPktPar1.bits.implicit_header;
    irq.buf[4] = LoRaPktPar1.bits.rxinvert_iq ? 0 : 1; // std is 0

    LoRaLrCtl.octet = Radio::radio.readReg(REG_ADDR_LORA_LRCTL, 1);
    irq.buf[5] = LoRaLrCtl.bits.crc_en;

    irq.fields.flags.irq_type = IRQ_TYPE_LORA_PKT;
    irqOutPin = 1;
}

static const unsigned lora_bws[] = {
    50, // 0
    100, // 1
    200, // 2
    400, // 3
    800, // 4
    1600 // 5
};

void get_lora_modem()
{
    uint16_t khz;
    LoRaPktPar1_t LoRaPktPar1;
    LoRaPktPar0_t LoRaPktPar0;
    LoRaPktPar0.octet = Radio::radio.readReg(REG_ADDR_LORA_PKTPAR0, 1);

    khz = lora_bws[LoRaPktPar0.bits.modem_bw];
    irq.buf[1] = khz & 0xff;
    khz >>= 8;
    irq.buf[2] = khz & 0xff;

    //LoRaModemConfig(unsigned KHz, unsigned sf, unsigned cr)
    irq.buf[3] = LoRaPktPar0.bits.modem_sf;

    LoRaPktPar1.octet = Radio::radio.readReg(REG_ADDR_LORA_PKTPAR1, 1);
    irq.buf[4] = LoRaPktPar1.bits.coding_rate;
    
    irq.fields.flags.irq_type = IRQ_TYPE_LORA_MODEM;
    irqOutPin = 1;
}

#define TX_PWR_OFFSET           18
void get_tx_dbm()
{
    PaPwrCtrl_t PaPwrCtrl;

    PaPwrCtrl.octet = Radio::radio.readReg(REG_ADDR_PA_PWR_CTRL, 1);
    irq.buf[1] = PaPwrCtrl.bits.tx_pwr - TX_PWR_OFFSET;
    irq.fields.flags.irq_type = IRQ_TYPE_TXDBM;
    irqOutPin = 1;
}

void get_fsk_sync()
{
    /* TODO 3 separate sync words */

    irq.fields.flags.irq_type = IRQ_TYPE_FSK_SYNC;
    irqOutPin = 1;
}

void get_fsk_modem()
{
    uint32_t u32;
    // GFSKModemConfig(unsigned bps, unsigned bwKHz, unsigned fdev_hz)

    /* given in bitrate-bandwith combination */
    u32 = 0;    // TODO 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 = 0;    // TODO  bandwidth
    irq.buf[5] = u32 & 0xff;
    u32 >>= 8;
    irq.buf[6] = u32 & 0xff;

    u32 = 0;    // TODO fdev  mod index + bitrate
    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;
}

static const uint8_t fsk_pbl_lens[] = { 4, 8, 12, 16, 20, 24, 28, 32 };

void get_fsk_packet()
{
    PktBitStreamCtrl_t PktBitStreamCtrl;
    PktCtrl0_t PktCtrl0;
    // GFSKPacketConfig(unsigned preambleLen, bool fixLen, bool crcOn)
    PktCtrl1_t PktCtrl1;
    PktCtrl1.octet = Radio::radio.readReg(REG_ADDR_PKTCTRL1, 1);
    irq.buf[1] = fsk_pbl_lens[PktCtrl1.gfsk.preamble_len];
    irq.buf[2] = 0;

    PktCtrl0.octet = Radio::radio.readReg(REG_ADDR_PKTCTRL0, 1);
    irq.buf[3] = PktCtrl0.bits.pkt_len_format; // true = fixed

    PktBitStreamCtrl.octet = Radio::radio.readReg(REG_ADDR_PKT_BITSTREAM_CTRL, 1);
    irq.buf[4] = PktBitStreamCtrl.bits.crc_mode;
    
    irq.fields.flags.irq_type = IRQ_TYPE_FSK_PKT;
    irqOutPin = 1;
}

void radio_reset()
{
    Radio::radio.hw_reset();
}

void radio_device_init()
{
}

#endif /* ..SX128x_H */