Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: alarm_slave_extended_SX1280 alarm_master_extended_Vance_SX1280
Revision 0:abb827c65ff5, committed 2018-06-28
- Comitter:
- Wayne Roberts
- Date:
- Thu Jun 28 17:52:22 2018 -0700
- Child:
- 1:70ef46fa6fc6
- Commit message:
- initial commit
Changed in this revision
| sx1280.cpp | Show annotated file Show diff for this revision Revisions of this file |
| sx12xx.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sx1280.cpp Thu Jun 28 17:52:22 2018 -0700
@@ -0,0 +1,395 @@
+#include "sx12xx.h"
+
+Callback<void()> SX128x::diox_topHalf; // low latency ISR context
+
+const float SX128x::timeOutStep[] = { 0.015625, 0.0625, 1, 4 };
+
+void SX128x::dioxisr()
+{
+ if (diox_topHalf)
+ diox_topHalf.call();
+}
+
+SX128x::SX128x(SPI& _spi, PinName _nss, PinName _busy, PinName _diox)
+ : spi(_spi), nss(_nss), busy(_busy), diox(_diox)
+{
+ nss = 1;
+
+ diox.rise(dioxisr);
+
+ if (busy) {
+ /*status_t status;
+ status.octet =*/ xfer(OPCODE_GET_STATUS, 0, 0, NULL);
+ while (busy)
+ ;
+ }
+
+ periodBase = 3;
+}
+
+uint8_t SX128x::xfer(uint8_t opcode, uint8_t wlen, uint8_t rlen, uint8_t* ptr)
+{
+ const uint8_t* stopPtr;
+ const uint8_t* wstop;
+ const uint8_t* rstop;
+ uint8_t nop = 0;
+ uint8_t ret;
+
+ if (opcode != OPCODE_GET_STATUS) {
+ if (sleeping) {
+ nss = 0;
+ while (busy)
+ ;
+ sleeping = false;
+ } else {
+ while (busy)
+ ;
+
+ nss = 0;
+ }
+ } else
+ nss = 0;
+
+ ret = spi.write(opcode);
+
+ wstop = ptr + wlen;
+ rstop = ptr + rlen;
+ if (rlen > wlen)
+ stopPtr = rstop;
+ else
+ stopPtr = wstop;
+
+ for (; ptr < stopPtr; ptr++) {
+ if (ptr < wstop && ptr < rstop)
+ *ptr = spi.write(*ptr);
+ else if (ptr < wstop)
+ spi.write(*ptr);
+ else
+ *ptr = spi.write(nop); // n >= write length: send NOP
+ }
+
+ nss = 1;
+
+ if (opcode == OPCODE_SET_SLEEP)
+ sleeping = true;
+
+ return ret;
+}
+
+uint32_t SX128x::readReg(uint16_t addr, uint8_t len)
+{
+ uint32_t ret = 0;
+ unsigned i;
+
+ uint8_t buf[7];
+ buf[0] = addr >> 8;
+ buf[1] = (uint8_t)addr;
+ xfer(OPCODE_READ_REGISTER, 2, 3+len, buf);
+ for (i = 0; i < len; i++) {
+ ret <<= 8;
+ ret |= buf[i+3];
+ }
+ return ret;
+}
+
+void SX128x::start_tx(uint8_t pktLen, float timeout_ms)
+{
+ IrqFlags_t irqEnable;
+ uint8_t buf[8];
+
+ irqEnable.word = 0;
+ irqEnable.bits.TxDone = 1;
+ irqEnable.bits.RxTxTimeout = 1;
+
+ buf[0] = irqEnable.word >> 8; // enable bits
+ buf[1] = irqEnable.word; // enable bits
+ buf[2] = irqEnable.word >> 8; // dio1
+ buf[3] = irqEnable.word; // dio1
+ buf[4] = 0; // dio2
+ buf[5] = 0; // dio2
+ buf[6] = 0; // dio3
+ buf[7] = 0; // dio3
+ xfer(OPCODE_SET_DIO_IRQ_PARAMS, 8, 0, buf);
+
+ {
+ uint8_t i;
+
+ while (busy)
+ ;
+
+ nss = 0;
+ spi.write(OPCODE_WRITE_BUFFER);
+ spi.write(0); // offset
+ i = 0;
+ for (i = 0; i < pktLen; i++) {
+ spi.write(tx_buf[i]);
+ }
+ nss = 1;
+ }
+
+ buf[0] = 3;
+ if (timeout_ms > 0) {
+ unsigned t_o = timeout_ms / timeOutStep[periodBase];
+ buf[1] = t_o >> 8;
+ buf[2] = t_o;
+ } else {
+ /* no timeout */
+ buf[1] = 0;
+ buf[2] = 0;
+ }
+ xfer(OPCODE_SET_TX, 3, 0, buf);
+
+ chipMode = CHIPMODE_TX;
+ if (chipModeChange)
+ chipModeChange.call();
+}
+
+void SX128x::hw_reset(PinName pin)
+{
+ DigitalInOut nrst(pin);
+ nrst.output();
+ nrst = 0;
+ wait_us(100);
+ nrst = 1;
+ nrst.mode(PullUp);
+ nrst.input();
+
+ while (busy)
+ ;
+}
+
+uint64_t SX128x::getSyncAddr(uint8_t num)
+{
+ uint64_t ret;
+ unsigned regAdr = REG_ADDR_PKT_SYNC_ADRS_1 + ((num-1) * 5);
+ ret = readReg(regAdr, 1);
+ ret <<= 32;
+ ret |= readReg(regAdr+1, 4);
+ return ret;
+}
+
+void SX128x::setSyncAddr(uint8_t num, uint64_t sa)
+{
+ unsigned regAdr = REG_ADDR_PKT_SYNC_ADRS_1 + ((num-1) * 5);
+ writeReg(regAdr+1, sa & 0xffffffff, 4);
+ sa >>= 32;
+ writeReg(regAdr, sa & 0xff, 1);
+}
+
+void SX128x::set_tx_dbm(int8_t dbm)
+{
+ uint8_t buf[2];
+
+ buf[0] = dbm;
+ buf[1] = RADIO_RAMP_20_US;
+ xfer(OPCODE_SET_TX_PARAMS, 2, 0, buf);
+}
+
+void SX128x::setMHz(float MHz)
+{
+ unsigned frf = MHz / PLL_STEP_MHZ;
+ uint8_t buf[3];
+
+ buf[0] = frf >> 16;
+ buf[1] = frf >> 8;
+ buf[2] = frf;
+ xfer(OPCODE_SET_RF_FREQUENCY, 3, 0, buf);
+}
+
+float SX128x::getMHz()
+{
+ uint32_t frf = readReg(REG_ADDR_RFFREQ, 3);
+ return frf * PLL_STEP_MHZ;
+}
+
+void SX128x::setStandby(stby_t stby)
+{
+ uint8_t octet = stby;
+ xfer(OPCODE_SET_STANDBY, 1, 0, &octet);
+
+ chipMode = CHIPMODE_NONE;
+ if (chipModeChange)
+ chipModeChange.call();
+}
+
+void SX128x::setFS()
+{
+ xfer(OPCODE_SET_FS, 0, 0, NULL);
+
+ chipMode = CHIPMODE_NONE;
+ if (chipModeChange)
+ chipModeChange.call();
+}
+
+void SX128x::setSleep(bool warmStart)
+{
+ sleepConfig_t sc;
+
+ sc.octet = 0;
+ sc.retentionBits.dataRAM = warmStart;
+ sc.retentionBits.dataBuffer = warmStart;
+ sc.retentionBits.instructionRAM = warmStart;
+ xfer(OPCODE_SET_SLEEP, 1, 0, &sc.octet);
+
+ chipMode = CHIPMODE_NONE;
+ if (chipModeChange)
+ chipModeChange.call();
+}
+
+uint8_t SX128x::getPacketType()
+{
+ uint8_t buf[2];
+
+ xfer(OPCODE_GET_PACKET_TYPE, 0, 2, buf);
+
+ return buf[1];
+}
+
+void SX128x::setPacketType(uint8_t type)
+{
+ xfer(OPCODE_SET_PACKET_TYPE, 1, 0, &type);
+}
+
+void SX128x::setBufferBase(uint8_t txAddr, uint8_t rxAddr)
+{
+ uint8_t buf[2];
+
+ buf[0] = txAddr; // TX base address
+ buf[1] = rxAddr; // RX base address
+ xfer(OPCODE_SET_BUFFER_BASE_ADDR, 2, 0, buf);
+}
+
+void SX128x::setRegulator(uint8_t rmp)
+{
+ xfer(OPCODE_SET_REGULATOR_MODE, 1, 0, &rmp);
+}
+
+void SX128x::start_rx(float timeout_ms)
+{
+ IrqFlags_t irqEnable;
+ uint8_t buf[8];
+ unsigned t_o;
+
+ irqEnable.word = 0;
+ irqEnable.bits.RxDone = 1;
+ irqEnable.bits.RxTxTimeout = 1;
+
+ buf[0] = irqEnable.word >> 8; // enable bits
+ buf[1] = irqEnable.word; // enable bits
+ buf[2] = irqEnable.word >> 8; // dio1
+ buf[3] = irqEnable.word; // dio1
+ buf[4] = 0; // dio2
+ buf[5] = 0; // dio2
+ buf[6] = 0; // dio3
+ buf[7] = 0; // dio3
+ xfer(OPCODE_SET_DIO_IRQ_PARAMS, 8, 0, buf);
+
+ buf[0] = periodBase;
+ if (timeout_ms > 0) {
+ t_o = timeout_ms / timeOutStep[periodBase];
+ buf[1] = t_o >> 8;
+ buf[2] = t_o;
+ } else {
+ /* receive packets forever */
+ buf[1] = 0xff;
+ buf[2] = 0xff;
+ }
+ xfer(OPCODE_SET_RX, 3, 0, buf);
+
+ chipMode = CHIPMODE_RX;
+ if (chipModeChange) {
+ chipModeChange.call();
+ }
+}
+
+void SX128x::service()
+{
+ IrqFlags_t irqFlags, clearIrqFlags;
+ uint8_t buf[6];
+ pktStatus_t pktStatus;
+
+ if (busy) {
+ return;
+ }
+
+ while (diox) {
+ xfer(OPCODE_GET_IRQ_STATUS, 0, 3, buf);
+ irqFlags.word = buf[1] << 8;
+ irqFlags.word |= buf[2];
+ clearIrqFlags.word = 0;
+ if (irqFlags.bits.TxDone) {
+ if (txDone)
+ txDone.call();
+ clearIrqFlags.bits.TxDone = 1;
+ chipMode = CHIPMODE_NONE;
+ if (chipModeChange)
+ chipModeChange.call();
+ }
+ if (irqFlags.bits.RxDone) {
+ if (rxDone) {
+ uint8_t len;
+ xfer(OPCODE_GET_RX_BUFFER_STATUS, 0, 3, buf);
+ if (buf[1] == 0)
+ len = readReg(REG_ADDR_LORA_TX_PAYLOAD_LENGTH, 1); // lora implicit
+ else
+ len = buf[1];
+
+ ReadBuffer(len, buf[2]);
+ xfer(OPCODE_GET_PACKET_STATUS, 0, 6, pktStatus.buf);
+ rxDone(len, &pktStatus);
+ }
+ clearIrqFlags.bits.RxDone = 1;
+ }
+ if (irqFlags.bits.RxTxTimeout) {
+ if (chipMode != CHIPMODE_NONE) {
+ if (timeout)
+ timeout(chipMode == CHIPMODE_TX);
+ }
+ chipMode = CHIPMODE_NONE;
+ if (chipModeChange)
+ chipModeChange.call();
+ clearIrqFlags.bits.RxTxTimeout = 1;
+ }
+
+ if (clearIrqFlags.word != 0) {
+ buf[0] = clearIrqFlags.word >> 8;
+ buf[1] = (uint8_t)clearIrqFlags.word;
+ xfer(OPCODE_CLEAR_IRQ_STATUS, 2, 0, buf);
+ }
+
+ } // ...while (diox)
+
+} // ..service()
+
+void SX128x::writeReg(uint16_t addr, uint32_t data, uint8_t len)
+{
+ uint8_t buf[6];
+ uint8_t n;
+ buf[0] = addr >> 8;
+ buf[1] = (uint8_t)addr;
+ for (n = len; n > 0; n--) {
+ buf[n+1] = (uint8_t)data;
+ data >>= 8;
+ }
+ xfer(OPCODE_WRITE_REGISTER, 2+len, 2+len, buf);
+}
+
+void SX128x::ReadBuffer(uint8_t size, uint8_t offset)
+{
+ unsigned i;
+ while (busy)
+ ;
+
+ nss = 0;
+
+ spi.write(OPCODE_READ_BUFFER);
+ spi.write(offset);
+ spi.write(0); // NOP
+ i = 0;
+ for (i = 0; i < size; i++) {
+ rx_buf[i] = spi.write(0);
+ }
+
+ nss = 1;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sx12xx.h Thu Jun 28 17:52:22 2018 -0700
@@ -0,0 +1,651 @@
+#include "mbed.h"
+#ifndef SX128x_H
+#define SX128x_H
+
+/***************************************************************/
+#define OPCODE_GET_PACKET_TYPE 0x03
+#define OPCODE_CLEAR_DEVICE_ERRORS 0x07
+#define OPCODE_GET_IRQ_STATUS 0x15
+#define OPCODE_GET_RX_BUFFER_STATUS 0x17
+#define OPCODE_WRITE_REGISTER 0x18
+#define OPCODE_READ_REGISTER 0x19
+#define OPCODE_WRITE_BUFFER 0x1a
+#define OPCODE_READ_BUFFER 0x1b
+#define OPCODE_GET_PACKET_STATUS 0x1d
+#define OPCODE_GET_RSSIINST 0x1f
+#define OPCODE_SET_STANDBY 0x80
+#define OPCODE_SET_RX 0x82
+#define OPCODE_SET_TX 0x83
+#define OPCODE_SET_SLEEP 0x84
+#define OPCODE_SET_RF_FREQUENCY 0x86
+#define OPCODE_SET_CAD_PARAM 0x88
+#define OPCODE_CALIBRATE 0x89
+#define OPCODE_SET_PACKET_TYPE 0x8a
+#define OPCODE_SET_MODULATION_PARAMS 0x8b
+#define OPCODE_SET_PACKET_PARAMS 0x8c
+#define OPCODE_SET_DIO_IRQ_PARAMS 0x8d
+#define OPCODE_SET_TX_PARAMS 0x8e
+#define OPCODE_SET_BUFFER_BASE_ADDR 0x8f
+#define OPCODE_SET_PA_CONFIG 0x95
+#define OPCODE_SET_REGULATOR_MODE 0x96
+#define OPCODE_CLEAR_IRQ_STATUS 0x97
+#define OPCODE_SET_LORA_SYMBOL_TIMEOUT 0xa0
+#define OPCODE_GET_STATUS 0xc0
+#define OPCODE_SET_FS 0xc1
+#define OPCODE_SET_CAD 0xc5
+#define OPCODE_SET_TX_CARRIER 0xd1
+#define OPCODE_SET_TX_PREAMBLE 0xd2
+/***************************************************************/
+#define REG_ADDR_AFIRQ 0x053 // 7bit
+#define REG_ADDR_RXBW 0x881 // 7bit
+#define REG_ADDR_GFSK_DEMODSTATUS 0x8cb // 5bit
+#define REG_ADDR_LORA_TX_PAYLOAD_LENGTH 0x901 // 8bit
+#define REG_ADDR_LORA_PKTPAR0 0x902 // 8bit
+#define REG_ADDR_LORA_PKTPAR1 0x902 // 8bit
+#define REG_ADDR_LORA_LRCTL 0x904 // 8bit
+#define REG_ADDR_LORA_IRQMASK 0x90f // 24bit
+#define REG_ADDR_LORA_PREAMBLE 0x93f // 8bit
+#define REG_ADDR_LORA_MODEMSTAT 0x95c // 8bit
+
+#define REG_ADDR_FSK_CFG 0x9a0 // 8bit
+#define REG_ADDR_FSK_MODDFH 0x9a1 // 8bit
+#define REG_ADDR_FSK_MODDFL 0x9a2 // 8bit
+#define REG_ADDR_RFFREQ 0x9a3 // 24bit
+
+#define REG_ADDR_PKTCTRL0 0x9c0 // 8bit
+#define REG_ADDR_PKTCTRL1 0x9c1 // 8bit
+#define REG_ADDR_PKT_TX_HEADER 0x9c2 // 8bit
+#define REG_ADDR_PAYLOAD_LEN 0x9c3 // 8bit
+#define REG_ADDR_PKT_BITSTREAM_CTRL 0x9c4 // 8bit
+#define REG_ADDR_FLORA_PREAMBLE_HI 0x9ca // 8bit contains data rate
+#define REG_ADDR_PKT_SYNC_ADRS_CTRL 0x9cd // 8bit
+#define REG_ADDR_PKT_SYNC_ADRS_1 0x9ce // 40bit / 5bytes
+#define REG_ADDR_PKT_SYNC_ADRS_2 0x9d2 // 40bit / 5bytes
+#define REG_ADDR_PKT_SYNC_ADRS_3 0x9d8 // 40bit / 5bytes
+
+#define REG_ADDR_FLRC_SYNCWORDCTRL 0x98b // 5bit
+#define REG_ADDR_FLRC_IRQSTATUS 0x990 // 3bit
+
+#define REG_ADDR_PA_PWR_CTRL 0xa53 // 8bit
+/***************************************************************/
+#define PLL_STEP_HZ 198.364257812 // 52MHz / 2^18
+#define PLL_STEP_MHZ 0.000198364257812 // 52 / 2^18
+
+#define RX_CONTINUOUS_TIMEOUT 0xffff // receive forever
+#define RX_SINGLE_TIMEOUT 0x0000 // receive until packet received
+
+#define PACKET_TYPE_GFSK 0
+#define PACKET_TYPE_LORA 1
+#define PACKET_TYPE_RANGING 2
+#define PACKET_TYPE_FLRC 3
+#define PACKET_TYPE_BLE 4
+
+
+#define RADIO_PACKET_FIXED_LENGTH 0x00
+#define RADIO_PACKET_VARIABLE_LENGTH 0x20
+
+// birate & bandwidth modParam1:
+#define GFSK_BLE_BR_2_000_BW_2_4 0x04 // Mbps:2 bw:2.4MHz 0000 0100
+#define GFSK_BLE_BR_1_600_BW_2_4 0x28 // Mbps:1.6 bw:2.4MHz 0010 1000
+#define GFSK_BLE_BR_1_000_BW_2_4 0x4C // Mbps:1 bw:2.4MHz 0100 1100
+#define GFSK_BLE_BR_1_000_BW_1_2 0x45 // Mbps:1 bw:1.2MHz 0100 0101
+#define GFSK_BLE_BR_0_800_BW_2_4 0x70 // Mbps:0.8 bw:2.4MHz 0111 0000
+#define GFSK_BLE_BR_0_800_BW_1_2 0x69 // Mbps:0.8 bw:1.2MHz 0110 1001
+#define GFSK_BLE_BR_0_500_BW_1_2 0x8D // Mbps:0.5 bw:1.2MHz 1000 1101
+#define GFSK_BLE_BR_0_500_BW_0_6 0x86 // Mbps:0.5 bw:0.6MHz 1000 0110
+#define GFSK_BLE_BR_0_400_BW_1_2 0xB1 // Mbps:0.4 bw:1.2MHz 1011 0001
+#define GFSK_BLE_BR_0_400_BW_0_6 0xAA // Mbps:0.4 bw:0.6MHz 1010 1010
+#define GFSK_BLE_BR_0_250_BW_0_6 0xCE // Mbps:0.25 bw:0.6MHz 1100 1110
+#define GFSK_BLE_BR_0_250_BW_0_3 0xC7 // Mbps:0.25 bw:0.3MHz 1100 0111
+#define GFSK_BLE_BR_0_125_BW_0_3 0xEF // Mbps:0.125 bw:0.3MHz 1110 1111
+
+// modulationIndex modParam2
+#define MOD_IND_0_35 0x00 // 0.35
+#define MOD_IND_0_5 0x01 // 0.5
+#define MOD_IND_0_75 0x02 // 0.75
+#define MOD_IND_1_00 0x03 // 1
+#define MOD_IND_1_25 0x04 // 1.25
+#define MOD_IND_1_50 0x05 // 1.5
+#define MOD_IND_1_75 0x06 // 1.75
+#define MOD_IND_2_00 0x07 // 2
+#define MOD_IND_2_25 0x08 // 2.25
+#define MOD_IND_2_50 0x09 // 2.5
+#define MOD_IND_2_75 0x0A // 2.75
+#define MOD_IND_3_00 0x0B // 3
+#define MOD_IND_3_25 0x0C // 3.25
+#define MOD_IND_3_50 0x0D // 3.5
+#define MOD_IND_3_75 0x0E // 3.75
+#define MOD_IND_4_00 0x0F // 4
+
+// modulationShaping modParam3:
+#define BT_OFF 0x00 // No filtering
+#define BT_1_0 0x10 // BT1
+#define BT_0_5 0x20 // BT0.5
+
+// packetParam6:
+#define RADIO_CRC_OFF 0x00 // CRC off
+#define RADIO_CRC_1_BYTES 0x10 // CRC field used 1 byte
+#define RADIO_CRC_2_BYTES 0x20 // CRC field uses 2 bytes
+#define RADIO_CRC_3_BYTES 0x30 // ??? CRC field uses 3 bytes FLRC ????
+
+// GFSK packetParam7:
+#define WHITENING_ENABLE 0x00
+#define WHITENING_DISABLE 0x08
+
+// LoRa spreadingFactor modParam1:
+#define LORA_SF_5 0x50
+#define LORA_SF_6 0x60
+#define LORA_SF_7 0x70
+#define LORA_SF_8 0x80
+#define LORA_SF_9 0x90
+#define LORA_SF_10 0xA0
+#define LORA_SF_11 0xB0
+#define LORA_SF_12 0xC0
+
+// LoRa modParam2
+#define LORA_BW_1600 0x0A // 1625.0KHz
+#define LORA_BW_800 0x18 // 812.5KHz
+#define LORA_BW_400 0x26 // 406.25KHz
+#define LORA_BW_200 0x34 // 203.125KHz
+
+// LoRa modParam3
+#define LORA_CR_4_5 0x01 // 4/5
+#define LORA_CR_4_6 0x02 // 4/6
+#define LORA_CR_4_7 0x03 // 4/7
+#define LORA_CR_4_8 0x04 // 4/8
+#define LORA_CR_LI_4_5 0x05 // 4/5*
+#define LORA_CR_LI_4_6 0x06 // 4/6*
+#define LORA_CR_LI_4_7 0x07 // 4/8*
+
+// LoRa packetParam2:
+#define EXPLICIT_HEADER 0x00 // var length
+#define IMPLICIT_HEADER 0x80 // fixed Length
+
+// LoRa packetParam4:
+#define LORA_CRC_ENABLE 0x20
+#define LORA_CRC_DISABLE 0x00
+
+// LoRa packetParam5
+#define LORA_IQ_STD 0x40 // IQ as defined
+#define LORA_IQ_INVERTED 0x00 // IQ swapped
+
+// transmitter power ramping
+#define RADIO_RAMP_02_US 0x00 // 2 microseconds
+#define RADIO_RAMP_04_US 0x20 // 4 microseconds
+#define RADIO_RAMP_06_US 0x40 // 6 microseconds
+#define RADIO_RAMP_08_US 0x60 // 8 microseconds
+#define RADIO_RAMP_10_US 0x80 // 10 microseconds
+#define RADIO_RAMP_12_US 0xA0 // 12 microseconds
+#define RADIO_RAMP_16_US 0xC0 // 16 microseconds
+#define RADIO_RAMP_20_US 0xE0 // 20 microseconds
+
+// BLE packetParam1
+#define BLE_PAYLOAD_LENGTH_MAX_31_BYTES 0x00 // maxlen:31 Bluetooth® 4.1 and above
+#define BLE_PAYLOAD_LENGTH_MAX_37_BYTES 0x20 // maxlen:37 Bluetooth® 4.1 and above
+#define BLE_TX_TEST_MODE 0x40 // maxlen:63 Bluetooth® 4.1 and above
+#define BLE_PAYLOAD_LENGTH_MAX_255_BYTES 0x80 // maxlen:255 Bluetooth® 4.2 and above
+
+// BLE packetParam2
+#define BLE_CRC_OFF 0x00 // No CRC No
+#define BLE_CRC_3B 0x10 // CRC field used 3bytes Yes
+
+// BLE packetParam3 ignored in BLE_TX_TEST_MODE
+#define BLE_PRBS_9 0x00// P7(x) = x9+ x5+ 1 PRBS9 sequence ‘1111111110000011110 1....’ (in transmission order)
+#define BLE_EYELONG_1_0 0x04 // Repeated ‘11110000’ (in transmission order) sequence
+#define BLE_EYESHORT_1_0 0x08 // Repeated ‘10101010’ (in transmission order) sequence
+#define BLE_PRBS_15 0x0C // Pseudo Random Binary Sequence based on 15th degree polynomial P15(x) = x15+ x14+ x13 + x12+ x2+ x + 1
+#define BLE_ALL_1 0x10 // Repeated ‘11111111’ (in transmission order) sequence
+#define BLE_ALL_0 0x14 // Repeated ‘11111111’ (in transmission order) sequence
+#define BLE_EYELONG_0_1 0x18 // Repeated ‘00001111’ (in transmission order) sequence
+#define BLE_EYESHORT_0_1 0x1C // Repeated ‘01010101’ (in transmission order) sequence
+
+// packetParam1
+#define PREAMBLE_LENGTH_4_BITS 0x00 // 4bits
+#define PREAMBLE_LENGTH_8_BITS 0x10 // 8bits
+#define PREAMBLE_LENGTH_12_BITS 0x20 // 12bits
+#define PREAMBLE_LENGTH_16_BITS 0x30 // 16bits
+#define PREAMBLE_LENGTH_20_BITS 0x40 // 20bits
+#define PREAMBLE_LENGTH_24_BITS 0x50 // 24bits
+#define PREAMBLE_LENGTH_28_BITS 0x60 // 28bits
+#define PREAMBLE_LENGTH_32_BITS 0x70 // 32bits
+
+// FLRC pktParam2
+#define FLRC_SYNC_NOSYNC 0x00 // 21 bits preamble
+#define FLRC_SYNC_WORD_LEN_P32S 0x04 // 21 bits preamble + 32bit syncword
+
+// FLRC modParam1
+#define FLRC_BR_1_300_BW_1_2 0x45 // 1.3Mb/s 1.2MHz
+#define FLRC_BR_1_000_BW_1_2 0x69 // 1.04Mb/s 1.2MHz
+#define FLRC_BR_0_650_BW_0_6 0x86 // 0.65Mb/s 0.6MHz
+#define FLRC_BR_0_520_BW_0_6 0xAA // 0.52Mb/s 0.6MHz
+#define FLRC_BR_0_325_BW_0_3 0xC7 // 0.325Mb/s 0.3MHz
+#define FLRC_BR_0_260_BW_0_3 0xEB // 0.26Mb/s 0.3MHz
+
+// FLRC modParam2
+#define FLRC_CR_1_2 0x00
+#define FLRC_CR_3_4 0x02
+#define FLRC_CR_1_0 0x04
+
+typedef enum {
+ STDBY_RC = 0, // Device running on RC 13MHz, set STDBY_RC mode
+ STDBY_XOSC // Device running on XTAL 52MHz, set STDBY_XOSC mode
+} stby_t;
+
+typedef union {
+ struct {
+ uint8_t PreambleLength; // param1
+ uint8_t HeaderType; // param2
+ uint8_t PayloadLength; // param3
+ uint8_t crc; // param4
+ uint8_t InvertIQ; // param5
+ uint8_t unused[2];
+ } lora;
+ struct {
+ uint8_t PreambleLength; // param1
+ uint8_t SyncWordLength; // param2 bytes
+ uint8_t SyncWordMatch; // param3
+ uint8_t HeaderType; // param4
+ uint8_t PayloadLength; // param5
+ uint8_t CRCLength; // param6
+ uint8_t Whitening; // param7
+ } gfskFLRC;
+ struct {
+ uint8_t ConnectionState; // param1
+ uint8_t CrcLength; // param2
+ uint8_t BleTestPayload; // param3
+ uint8_t Whitening; // param4
+ uint8_t unused[3];
+ } ble;
+ uint8_t buf[7];
+} PacketParams_t;
+
+//TODO -- uint8_t LowDatarateOptimize; // param4
+typedef union {
+ struct {
+ uint8_t spreadingFactor; // param1
+ uint8_t bandwidth; // param2
+ uint8_t codingRate; // param3
+ } lora;
+ struct {
+ uint8_t bitrateBandwidth; // param1
+ uint8_t ModulationIndex; // param1
+ uint8_t ModulationShaping; // param3
+ } gfskBle;
+ struct {
+ uint8_t bitrateBandwidth; // param1
+ uint8_t CodingRate; // param1
+ uint8_t ModulationShaping; // param3
+ } flrc;
+ uint8_t buf[3];
+} ModulationParams_t;
+
+typedef union {
+ struct { //
+ uint16_t TxDone : 1; // 0
+ uint16_t RxDone : 1; // 1
+ uint16_t SyncWordValid: 1; // 2
+ uint16_t SyncWordError: 1; // 3
+ uint16_t HeaderValid: 1; // 4
+ uint16_t HeaderError: 1; // 5
+ uint16_t CrcError: 1; // 6
+ uint16_t RangingSlaveResponseDone: 1; // 7
+ uint16_t RangingSlaveRequestDiscard: 1; // 8
+ uint16_t RangingMasterResultValid: 1; // 9
+ uint16_t RangingMasterTimeout: 1; // 10
+ uint16_t RangingMasterRequestValid: 1; // 11
+ uint16_t CadDone: 1; // 12
+ uint16_t CadDetected: 1; // 13
+ uint16_t RxTxTimeout: 1; // 14
+ uint16_t PreambleDetected: 1; // 15
+ } bits;
+ uint16_t word;
+} IrqFlags_t;
+
+typedef union {
+ struct { //
+ uint8_t busy : 1; // 0
+ uint8_t reserved : 1; // 1
+ uint8_t cmdStatus : 3; // 2,3,4
+ uint8_t chipMode : 3; // 5,6,7
+ } bits;
+ uint8_t octet;
+} status_t;
+
+typedef enum {
+ CHIPMODE_NONE = 0,
+ CHIPMODE_RX,
+ CHIPMODE_TX
+} chipMode_e;
+
+typedef union {
+ struct {
+ uint8_t dataRAM : 1; // 0
+ uint8_t dataBuffer : 1; // 1
+ uint8_t instructionRAM : 1; // 2
+ } retentionBits;
+ uint8_t octet;
+} sleepConfig_t;
+
+
+typedef union {
+ struct {
+ status_t status;
+ uint8_t rfu;
+ uint8_t rssiSync;
+ struct {
+ uint8_t pktCtrlBusy : 1; // 0
+ uint8_t packetReceived : 1; // 1
+ uint8_t headerReceived : 1; // 2
+ uint8_t AbortErr : 1; // 3
+ uint8_t CrcError : 1; // 4
+ uint8_t LengthError : 1; // 5
+ uint8_t SyncError : 1; // 6
+ uint8_t reserved : 1; // 7
+ } errors;
+ struct {
+ uint8_t pktSent : 1; // 0
+ uint8_t res41 : 4; // 1,2,3,4
+ uint8_t rxNoAck : 1; // 5
+ uint8_t res67 : 1; // 6,7
+ } pkt_status;
+ struct {
+ uint8_t syncAddrsCode : 3; // 0,1,2
+ uint8_t reserved : 5; // 3,4,5,6,7
+ } sync;
+ } ble_gfsk_flrc;
+ struct {
+ status_t status;
+ uint8_t rssiSync;
+ uint8_t snr;
+ uint8_t reserved[4];
+ } lora;
+ uint8_t buf[6];
+} pktStatus_t;
+
+/**********************************************************/
+
+typedef union {
+ struct {
+ uint8_t irq0 : 2; // 0,1
+ uint8_t irq1 : 2; // 2,3
+ uint8_t alt_func : 4; // 4,5,6,7
+ } bits;
+ uint8_t octet;
+} RegAfIrq_t; // 0x053
+
+typedef union {
+ struct {
+ uint8_t dig_fe_en : 1; // 0
+ uint8_t zero_if : 1; // 1
+ uint8_t if_sel : 1; // 2
+ uint8_t lora_mode : 1; // 3
+ uint8_t res : 4; // 4,5,6,7
+ } bits;
+ uint8_t octet;
+} RegCfg_t; // 0x880
+
+typedef union {
+ struct {
+ uint8_t bw : 3; // 0,1,2
+ uint8_t res3 : 1; // 3
+ uint8_t interp_factor : 1; // 4,5,6
+ uint8_t res7 : 1; // 7
+ } bits;
+ uint8_t octet;
+} RegRxBw_t; // 0x881
+
+typedef union {
+ struct {
+ uint8_t DccBw : 2; // 0,1
+ uint8_t DccInit : 1; // 2
+ uint8_t IgnoreAutoDccRestart : 1; // 3
+ uint8_t DccForce : 1; // 4
+ uint8_t DccBypass : 1; // 5
+ uint8_t DccFreeze : 1; // 6
+ uint8_t res7 : 1; // 7
+ } bits;
+ uint8_t octet;
+} RegDcc_t; // 0x882
+
+typedef union {
+ struct {
+ uint8_t SyncAdrsIrqStatus : 1; // 0
+ uint8_t PreambleIrqStatus : 1; // 1
+ uint8_t dtb_pa2sel_sel : 2; // 2,3
+ uint8_t db_out_sel : 1; // 4
+ uint8_t reserved : 3; // 5,6,7
+ } bits;
+ uint8_t octet;
+} GfskDemodStatus_t; // 0x8cb
+
+typedef union {
+ struct {
+ uint8_t cont_rx : 1; // 0
+ uint8_t modem_bw : 3; // 1,2,3
+ uint8_t modem_sf : 4; // 4,5,6,7
+ } bits;
+ uint8_t octet;
+} LoRaPktPar0_t; // 0x902
+
+typedef union {
+ struct {
+ uint8_t coding_rate : 3; // 0,1,2
+ uint8_t ppm_offset : 2; // 3,4
+ uint8_t tx_mode : 1; // 5
+ uint8_t rxinvert_iq : 1; // 6
+ uint8_t implicit_header : 1; // 7
+ } bits;
+ uint8_t octet;
+} LoRaPktPar1_t; // 0x903
+
+typedef union {
+ struct {
+ uint8_t cadrxtx : 2; // 0,1
+ uint8_t sd_en : 1; // 2
+ uint8_t modem_en : 1; // 3
+ uint8_t lora_register_clear : 1; // 4
+ uint8_t crc_en : 1; // 5
+ uint8_t fine_sync_en : 1; // 6
+ uint8_t sd_force_tx_mode : 1; // 7
+ } bits;
+ uint8_t octet;
+} LoRaLrCtl_t; // 0x904
+
+typedef union {
+ struct {
+ uint8_t preamble_symb1_nb : 4; // 0,1,2,3
+ uint8_t preamble_symb_nb_exp : 4; // 4,5,6,7
+ } bits;
+ uint8_t octet;
+} LoRaPreambleReg_t; // 0x93f
+
+typedef union {
+ struct {
+ uint8_t rx_state : 4; // 0,1,2,3
+ uint8_t tx_state : 3; // 4,5,6
+ uint8_t tx_ranging_on : 1; // 7
+ } bits;
+ uint8_t octet;
+} LoRaModemStat_t; // 0x95c
+
+typedef union {
+ struct {
+ uint8_t mod_on : 1; // 0
+ uint8_t sd_on : 1; // 1
+ uint8_t mod_mode : 1; // 2 0=gfsk 1=flora
+ uint8_t tx_mode : 1; // 3
+ uint8_t gf_bt : 2; // 4,5 0=noFilter 1=BT1.0 2=BT0.5 3=BT0.3
+ uint8_t rxtxn : 1; // 6 0=tx 1=rx
+ uint8_t cal_en : 1; // 7
+ } bits;
+ uint8_t octet;
+} FskCfg_t; // 0x9a0
+
+typedef union {
+ struct {
+ uint8_t freqDev : 5; // 0,1,2,3,4
+ uint8_t sd_in_lsb : 1; // 5
+ uint8_t disable_dclk : 1; // 7
+ } bits;
+ uint8_t octet;
+} FskModDfH_t; // 0x9a1
+
+typedef union {
+ struct {
+ uint8_t pkt_ctrl_on : 1; // 0
+ uint8_t pkt_start_p : 1; // 1 0=idle 1=busy
+ uint8_t pkt_abort_p : 1; // 2
+ uint8_t pkt_software_clear_p : 1; // 3 software reset pulse
+ uint8_t pkt_rx_ntx : 1; // 4 0=tx 1=rx
+ uint8_t pkt_len_format : 1; // 5 0=fixed 1=dynamic
+ uint8_t pkt_protocol : 2; // 6,7 1=flora 2=ble 3=generic
+ } bits;
+ uint8_t octet;
+} PktCtrl0_t; // 0x9c0
+
+typedef union {
+ struct {
+ uint8_t infinite_preamble : 1; // 0
+ uint8_t sync_adrs_len : 3; // 1,2,3 bytes = sync_adrs_len + 1
+ uint8_t preamble_len : 3; // 4,5,6 bits = (preamble_len*4) + 4
+ uint8_t preamble_det_on : 1; // 7
+ } gfsk;
+ struct {
+ uint8_t reserved : 1; // 0
+ uint8_t sync_adrs_len : 2; // 1,2 0=preamble only 1=preamble+16bitSync 2=preamble+32bitSync
+ uint8_t reserved3 : 1; // 3
+ uint8_t agc_preamble_len : 3; // 4,5,6
+ uint8_t reserved7 : 1; // 7
+ } flrc;
+ uint8_t octet;
+} PktCtrl1_t; // 0x9c1
+
+typedef union {
+ struct {
+ uint8_t payload_len_N : 1; // 0
+ uint8_t tx_reserved : 4; // 1,2,3,4
+ uint8_t tx_no_ack : 1; // 5
+ uint8_t tx_pkt_type : 2; // 6,7 defines packet type field in header
+ } bits;
+ struct {
+ uint8_t infinite_rxtx : 1; // 0
+ uint8_t tx_payload_src : 1; // 1 0=fifo 1=prbs
+ uint8_t tx_type : 3; // 2,3,4 payload for BLE tx test
+ uint8_t cs_type : 3; // 5,6,7 connection state
+ } ble;
+ uint8_t octet;
+} PktTxHeader_t; // 0x9c2
+
+typedef union {
+ struct {
+ uint8_t crc_in_fifo : 1; // 0 1=received CRC written to FIFO at end
+ uint8_t flora_coding_rate : 2; // 1,2
+ uint8_t whit_disable : 1; // 3
+ uint8_t crc_mode : 2; // 4,5 0=nocrc 1=1byteCRC 2=2byteCRC 3=reserved
+ uint8_t rssi_mode : 2; // 6,7 enables rssi read mode of received packets 0=none 1=syncReg 2=avgReg 3=bothRegs
+ } bits;
+ uint8_t octet;
+} PktBitStreamCtrl_t; // 0x9c4
+
+typedef union {
+ struct {
+ uint8_t flora_preamble_20_16 : 5; // 0,1,2,3,4
+ uint8_t data_rate : 3; // 5,6,7
+ } bits;
+ uint8_t octet;
+} FloraPreambleHi_t; // 0x9ca
+
+typedef union {
+ struct {
+ uint8_t sync_adrs_bit_detections : 2; // 0,1 last bits matching 0=none 1=2bits 2=4bits 3=8bits
+ uint8_t reserved : 2; // 2,3
+ uint8_t sync_addr_mask : 3; // 4,5,6
+ uint8_t cont_rx : 1; // 7
+ } ble;
+ struct {
+ uint8_t sync_adrs_errors : 4; // 0,12,3 how many bit errors are tolerated in sync word
+ uint8_t sync_addr_mask : 3; // 4,5,6
+ uint8_t cont_rx : 1; // 7
+ } gfskflrc;
+ uint8_t octet;
+} PktSyncAdrs_t; // 0x9cd
+
+typedef union {
+ struct {
+ uint8_t tolerated_errors : 4; // 0,1,2,3 for sync word
+ uint8_t valid_status : 1; // 4 0x98c-98f is valid
+ uint8_t reserved : 3; // 5,6,7
+ } bits;
+ uint8_t octet;
+} FlrcSyncWordCtrl_t; // 0x98b
+
+typedef union {
+ struct {
+ uint8_t sync_word_irq : 1; // 0
+ uint8_t preamble_irq : 1; // 1
+ uint8_t stop_radio : 1; // 3
+ uint8_t reserved : 1; // 4,5,6,7
+ } bits;
+ uint8_t octet;
+} FlrcIrqStatus_t; // 0x990
+
+typedef union {
+ struct {
+ uint8_t tx_pwr : 5; // 0,1,2,3,4
+ uint8_t ramp_time : 3; // 5,6,7
+ } bits;
+ uint8_t octet;
+} PaPwrCtrl_t; // 0xa53
+
+class SX128x {
+ public:
+ SX128x(SPI&, PinName nss, PinName busy, PinName diox);
+
+ static Callback<void()> diox_topHalf; // low latency ISR context
+ Callback<void()> txDone; // user context
+ void (*rxDone)(uint8_t size, const pktStatus_t*); // user context
+ Callback<void()> chipModeChange; // read chipMode_e chipMode
+ void (*timeout)(bool tx); // user context
+
+ //! RF transmit packet buffer
+ uint8_t tx_buf[256]; // lora fifo size
+
+ //! RF receive packet buffer
+ uint8_t rx_buf[256]; // lora fifo size
+
+ void service(void);
+ uint8_t xfer(uint8_t opcode, uint8_t writeLen, uint8_t readLen, uint8_t* buf);
+ void start_tx(uint8_t pktLen, float timeout_ms); // tx_buf must be filled prior to calling
+ void start_rx(float timeout_ms); // timeout given in milliseconds, -1 = forever
+ void hw_reset(PinName nrst);
+ void set_tx_dbm(int8_t dbm);
+ void setMHz(float);
+ float getMHz(void);
+ void setStandby(stby_t);
+ void setSleep(bool warmStart);
+ void setFS(void);
+ void writeReg(uint16_t addr, uint32_t data, uint8_t len);
+ uint32_t readReg(uint16_t addr, uint8_t len);
+ void setPacketType(uint8_t);
+ uint8_t getPacketType(void);
+ void ReadBuffer(uint8_t size, uint8_t offset);
+ uint64_t getSyncAddr(uint8_t num);
+ void setSyncAddr(uint8_t num, uint64_t sa);
+ void setRegulator(uint8_t);
+ void setBufferBase(uint8_t txAddr, uint8_t rxAddr);
+
+ chipMode_e chipMode;
+ uint8_t periodBase;
+ static const float timeOutStep[4];
+
+ private:
+ SPI& spi;
+ DigitalOut nss;
+ DigitalIn busy;
+ InterruptIn diox;
+ static void dioxisr(void);
+ bool sleeping;
+};
+
+#endif /* SX126x_H */
+