driver for sx1280

Dependents:   alarm_slave_extended_SX1280 alarm_master_extended_Vance_SX1280

sx12xx.h

Committer:
Wayne Roberts
Date:
2020-07-10
Revision:
8:7b0b2e3ca9d2
Parent:
7:aa7047cdf47b

File content as of revision 8:7b0b2e3ca9d2:

#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_RANGING_ROLE         0xa3
#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 OPCODE_SAVE_CONTEXT             0xd5
/***************************************************************/
#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             0x903 // 8bit
#define REG_ADDR_LORA_LRCTL               0x904 // 8bit
#define REG_ADDR_LORA_SD_FREQ             0x906 // 24bit
#define REG_ADDR_LORA_IRQMASK             0x90f // 24bit
#define REG_ADDR_LORA_MASTER_REQ_ID       0x912 // 32bit
#define REG_ADDR_LORA_SLAVE_ID            0x916 // 32bit
#define REG_ADDR_RNGFLTWNDSIZE            0x91e // 32bit
#define REG_ADDR_RNGCFG0                  0x923 // 8bit
#define REG_ADDR_RNGCFG1                  0x924 // 7bit
#define REG_ADDR_LORA_FE_GAIN             0x929 // 8bit
#define REG_ADDR_LORA_DELAY_CAL           0x92b // 24bit
#define REG_ADDR_LORA_RNGDEBTH2           0x931 // 8bit
#define REG_ADDR_RNGDEBTH4H               0x935 // 8bit

#define REG_ADDR_LORA_PREAMBLE            0x93f // 8bit
#define REG_ADDR_LORA_SYNC                0x944 // LrCfg7, LrCfg8  post-preamble gap (AKA lora sync)
#define REG_ADDR_LORA_MODEMSTAT           0x95c // 8bit
#define REG_ADDR_RNGRESULT                0x961 // 24bit
#define REG_ADDR_RNGRSSI                  0x964 // 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          0x9d3 // 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_XTA_TRIM                 0xa0e // crystal trim
#define REG_ADDR_XTB_TRIM                 0xa0f // crystal trim
#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
#define LORA_BW_100     0x42 // 
#define LORA_BW_50      0x51 // 

// 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[3];
    } 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 ranging_res_bits         : 2; // 0,1
        uint8_t ranging_resp_en          : 1; // 2      slave enable
        uint8_t timing_synch_en          : 1; // 3
        uint8_t ranging_synched_start_en : 1; // 4
        uint8_t ranging_result_clear_reg : 1; // 5
        uint8_t rx_fifo_addr_clear       : 1; // 6
        uint8_t counters_clear_reg       : 1; // 7
    } bits;
    uint8_t octet;
} RngCfg0_t; // 0x923

typedef union {
    struct {
        uint8_t muxed_counter_select       : 4; // 0,1,2,3
        uint8_t ranging_result_mux_sel     : 2; // 4,5
        uint8_t ranging_result_trigger_sel : 1; // 6
        uint8_t res                        : 1; // 7
    } bits;
    uint8_t octet;
} RngCfg1_t; // 0x924

typedef union {
    struct {
        uint8_t ranging_filter_debias_th2 : 6; // 0,1,2,3,4,5
        uint8_t ranging_id_check_length   : 2; // 6,7
    } bits;
    uint8_t octet;
} RngDebTh2_t; // 0x931

typedef union {
    struct {
        uint8_t debias_th4         : 2; // 0,1
        uint8_t rng_rssi_threshold : 6; // 2...7
    } bits;
    uint8_t octet;
} RngDebTh4H_t; // 0x935

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, PinName nrst);

        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
        void (*cadDone)(bool);

        //! 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(void);
        void set_tx_dbm(int8_t dbm);
        void setMHz(float);
        float getMHz(void);
        void setStandby(stby_t);
        void setSleep(bool warm);
        void setFS(void);
        void setCAD(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];
        uint8_t pktType;

    private:
        SPI& spi;
        DigitalOut nss;
        DigitalIn busy;
        InterruptIn diox;
        DigitalInOut nrst;
        static void dioxisr(void);
        bool sleeping;
};

#endif /* SX126x_H */