cervin sx1265 operating with transceiver firmware

Dependents:   lr1110_wifi_geolocation_device lr1110_wifi_geolocation_gateway

To use this driver, your LR1110 must be programmed as transceiver (not modem, which is LoRaWAN only).
Visit https://github.com/Lora-net/lr1110_updater_tool to update your LR1110, or change it from modem to transceiver if necessary.

sx12xx.h

Committer:
Wayne Roberts
Date:
2021-02-05
Revision:
1:29294cae9f9a
Parent:
0:987d9022c152

File content as of revision 1:29294cae9f9a:

#include "mbed.h"
#ifndef SX1265_H
#define SX1265_H

#define XTAL_FREQ_HZ            32000000
#define FREQ_STEP               0.95367431640625 // ( ( double )( XTAL_FREQ / ( double )FREQ_DIV ) )
#define GFSK_BITRATE_NUMERATOR       1024000000


#define OPCODE_GET_STATUS               0x0100
#define OPCODE_GET_VERSION              0x0101
#define OPCODE_WRITEREGMEM32            0x0105
#define OPCODE_READREGMEM32             0x0106
#define OPCODE_CLEAR_RX_BUFFER          0x010b
#define OPCODE_WRITE_BUFFER8            0x0109
#define OPCODE_READ_BUFFER8             0x010a
#define OPCODE_GET_ERRORS               0x010d
#define OPCODE_CLEAR_ERRORS             0x010e
#define OPCODE_CALIBRATE                0x010f
#define OPCODE_SET_REGULATOR_MODE       0x0110
#define OPCODE_CALIBRATE_IMAGE          0x0111  // operating band change
#define OPCODE_SET_DIO_AS_RFSWITCH      0x0112
#define OPCODE_CLEAR_IRQ                0x0114
#define OPCODE_SET_SLEEP                0x011b
#define OPCODE_SET_STANDBY              0x011c
#define OPCODE_SET_FS                   0x011d
#define OPCODE_SET_DIOIRQPARAMS         0x0113
#define OPCODE_SET_TCXO_MODE            0x0117
#define OPCODE_GET_DEVEUI               0x0125
#define OPCODE_GET_JOINEUI              0x0126
#define OPCODE_GET_DEVICE_PIN           0x0127
#define OPCODE_RESET_STATS              0x0200
#define OPCODE_GET_STATS                0x0201
#define OPCODE_GET_PACKET_TYPE          0x0202
#define OPCODE_GET_RX_BUFFER_STATUS     0x0203
#define OPCODE_GET_PKT_STATUS           0x0204
#define OPCODE_GET_RSSI_INST            0x0205
#define OPCODE_SET_GFSK_SYNC_WORD       0x0206
#define OPCODE_SET_LORA_PUBLIC_NETWORK  0x0208
#define OPCODE_SET_RX                   0x0209
#define OPCODE_SET_RF_FREQ_HZ           0x020b // 0x00f30058
#define OPCODE_SET_TX                   0x020a
#define OPCODE_AUTO_TX_RX               0x020c
#define OPCODE_SET_CAD_PARAMS           0x020d
#define OPCODE_SET_PACKET_TYPE          0x020e
#define OPCODE_SET_MODULATION           0x020f
#define OPCODE_SET_PACKET_PARAM         0x0210
#define OPCODE_SET_TXPARAMS             0x0211
#define OPCODE_SET_GFSK_PKT_ADDRESS     0x0212
#define OPCODE_SET_RXTX_FALLBACK_MODE   0x0213
#define OPCODE_SET_RX_DUTYCYCLE         0x0214
#define OPCODE_SET_PA_CONFIG            0x0215
#define OPCODE_STOP_TIMEOUT_ON_PREAMBLE 0x0217
#define OPCODE_SET_CAD                  0x0218
#define OPCODE_SET_TXCW                 0x0219
#define OPCODE_SET_TX_PREAMBLE          0x021a
#define OPCODE_SET_LORA_SYNC_TIMEOUT    0x021b
#define OPCODE_SET_GFSK_CRC_PARAMS      0x0224
#define OPCODE_SET_GFSK_WHITENING       0x0225
#define OPCODE_SET_RX_BOSSTED           0x0227

#define OPCODE_WIFI_SCAN                0x0300
#define OPCODE_GET_WIFI_NB_RESULTS      0x0305
#define OPCODE_WIFI_READ_RESULTS        0x0306
#define OPCODE_WIFI_RESET_CT            0x0307
#define OPCODE_WIFI_READ_CT             0x0308

#define OPCODE_GNSS_SET_CONSTELLATION   0x0400
#define OPCODE_GNSS_SET_MODE            0x0408
#define OPCODE_GNSS_AUTONOMOUS          0x0409
#define OPCODE_GNSS_ASSISTED            0x040a
#define OPCODE_GNSS_GET_RESULT_SIZE     0x040c
#define OPCODE_GNSS_READ_RESULTS        0x040d
#define OPCODE_GNSS_ALMANAC_FULL_UPDATE 0x040e
#define OPCODE_GNSS_SET_ASSISTED_POS    0x0410
#define OPCODE_GNSS_GET_NBSVDET         0x0417
#define OPCODE_GNSS_GET_SVDET           0x0418

#define OPCODE_CRYPTO_SET_KEY               0x0502
#define OPCODE_CRYPTO_DIRIVE_STORE_KEY      0x0503
#define OPCODE_CRYPTO_PROCESS_JOIN_ACC      0x0504
#define OPCODE_CRYPTO_COMPUTE_AES_CMAC      0x0505
#define OPCODE_CRYPTO_VERIFY_AES_CMAC       0x0506
#define OPCODE_CRYPTO_AES_ENCRYPT01         0x0507
#define OPCODE_CRYPTO_AES_ENCRYPT           0x0508
#define OPCODE_CRYPTO_AES_DECRYPT           0x0509
#define OPCODE_CRYPTO_STORE_TO_FLASH        0x050a
#define OPCODE_CRYPTO_RESTORE_FROM_FLASH    0x050b
#define OPCODE_CRYPTO_SET_PARAM             0x050d
#define OPCODE_CRYPTO_GET_PARAM             0x050e

/* for 0x0112 command: */
#define DIO_en_IDX        0
#define DIO_stby_IDX      1
#define DIO_rx_IDX        2
#define DIO_tx_IDX        3
#define DIO_txhp_IDX      4
#define DIO_gnss_IDX      6
#define DIO_wifi_IDX      7

#define DIO5_BIT         0x01
#define DIO6_BIT         0x02
#define DIO7_BIT         0x04
#define DIO8_BIT         0x08
#define DIO10_BIT        0x10

enum {
    /* 0x00 */ TCXO_VOLTS_1v6 = 0,
    /* 0x01 */ TCXO_VOLTS_1v8,
    /* 0x02 */ TCXO_VOLTS_1V8,
    /* 0x03 */ TCXO_VOLTS_2v2,
    /* 0x04 */ TCXO_VOLTS_2v4,
    /* 0x05 */ TCXO_VOLTS_2v7,
    /* 0x06 */ TCXO_VOLTS_3v0,
    /* 0x07 */ TCXO_VOLTS_3v3,
};

/* valid memory ranges:
 * 000c1000 - 000c2000  1024 dwords
 * 00800000 - 00810000  16384 dwords
 *
 * 00f00000 - 00f00050  20 dwords
 * 00f01000 - 00f01048  18 dwords
 * 00f02000 - 00f02014  5 dwords
 * 00f02018 - 00f02024  3 dwords
 * 00f03000 - 00f03034  13 dwords
 * 00f04000 - 00f04018  6 dwords
 * 00f04020 - 00f04040  8 dwords
 * 00f0f000 - 00f0f004  1 dwords
 * 00f0f008 - 00f0f010  2 dwords
 * 00f10000 - 00f11ffc  (lockup)
 * 00f11000 - 00f11058  22 dwords
 * 00f12000 - 00f1200c  3 dwords
 * 00f12010 - 00f12040  12 dwords
 * 00f13000 - 00f15034  2061 dwords
 * 00f16000 - 00f16014  5 dwords
 * 00f17000 - 00f17058  22 dwords
 * 00f18000 - 00f18020  8 dwords
 * 00f19000 - 00f190a4  41 dwords
 * 00f1a000 - 00f1a034  13 dwords
 * 00f1f000 - 00f1f004  1 dwords
 * 00f1f00c - 00f1f014  2 dwords
 * 00f20000 - 00f20020  8 dwords
 * 00f20100 - 00f2013c  15 dwords
 * 00f20200 - 00f20250  20 dwords
 * 00f20300 - 00f20390  36 dwords
 * 00f20400 - 00f204c0  48 dwords
 * 00f20500 - 00f2050c  3 dwords
 * 00f20540 - 00f20598  22 dwords
 * 00f30000 - 00f300cc  51 dwords
 */

/* 800000->8000xx: cmd buffer
 */
#define REG_ADDR_REGULATOR_MODE         0x0080036c
#define REG_ADDR_GNSS_CONST             0x008003b8
#define REG_ADDR_GNSS_MODE              0x008004b4
#define REG_ADDR_GNSS_ASSIST_LAT        0x008008ec 
#define REG_ADDR_GNSS_ASSIST_LON        0x008008f0 
#define REG_ADDR_TCXO                   0x00f0003c
#define REG_ADDR_DIO5                   0x00f03018 
#define REG_ADDR_DIO6                   0x00f0301c 
#define REG_ADDR_DIO7                   0x00f03020 
#define REG_ADDR_DIO8                   0x00f03024 
#define REG_ADDR_DIO10                  0x00f0302c 
#define REG_ADDR_COUNTER                0x00f04014
#define REG_ADDR_GFSK_BWF               0x00f20124 
#define REG_ADDR_GFSK_CFG0              0x00f20314 
#define REG_ADDR_GFSK_BITRATE           0x00f20338
#define REG_ADDR_GFSK_FDEV              0x00f2033c
#define REG_ADDR_GFSK_CFG1              0x00f2034c  // gfsk preambleDetect, gfsk preambleLength
#define REG_ADDR_GFSK_CFG2              0x00f20350  // gfsk sync word length (in bits)
#define REG_ADDR_GFSK_SYNC_LO           0x00f20354  // gfsk sync word lo
#define REG_ADDR_GFSK_SYNC_HI           0x00f20358  // gfsk sync word hi
#define REG_ADDR_GFSK_CFG3              0x00f2035c  // gfsk fixlen/varlen
#define REG_ADDR_GFSK_PAYLOAD_LENGTH_A  0x00f20360  // lowest 8bits  todo:tx-or-rx?
#define REG_ADDR_GFSK_PAYLOAD_LENGTH_B  0x00f20368  // payload-length-bits[27:20], addrComp:[17:16]
#define REG_ADDR_GFSK_CFG5              0x00f20370  // gfsk whitening, crcType
#define REG_ADDR_GFSK_CRC_POLY          0x00f20374
#define REG_ADDR_GFSK_CRC_INIT          0x00f20378
#define REG_ADDR_LORA_CONFIG0           0x00f20414
#define REG_ADDR_LORA_CONFIGC           0x00f2041c
#define REG_ADDR_LORA_CONFIGA           0x00f20420
#define REG_ADDR_LORA_CONFIGB           0x00f20428
#define REG_ADDR_LORA_SYNC              0x00f20460
#define REG_ADDR_RFFREQ                 0x00f30058
#define REG_ADDR_TX_PARAMS_A            0x00f30074
#define REG_ADDR_TX_PARAMS_B            0x00f30078
#define REG_ADDR_TX_PARAMS_C            0x00f30080
#define REG_ADDR_TX_PARAMS_D            0x00f30088
//#define REG_ADDR_             0x
//

#define GFSK_CRC_OFF            0x01
#define GFSK_CRC_1_BYTE         0x00
#define GFSK_CRC_2_BYTE         0x02
#define GFSK_CRC_1_BYTE_INV     0x04
#define GFSK_CRC_2_BYTE_INV     0x06

#define GFSK_BT_OFF             0x00
#define GFSK_BT_0_3             0x08
#define GFSK_BT_0_5             0x09
#define GFSK_BT_0_7             0x0a
#define GFSK_BT_1_0             0x0b

#define GFSK_RX_BW_4800         0x1f
#define GFSK_RX_BW_5800         0x17
#define GFSK_RX_BW_7300         0x0f
#define GFSK_RX_BW_9700         0x1e
#define GFSK_RX_BW_11700        0x16
#define GFSK_RX_BW_14600        0x0e
#define GFSK_RX_BW_19500        0x1d
#define GFSK_RX_BW_23400        0x15
#define GFSK_RX_BW_29300        0x0d
#define GFSK_RX_BW_39000        0x1c
#define GFSK_RX_BW_46900        0x14
#define GFSK_RX_BW_58600        0x0c
#define GFSK_RX_BW_78200        0x1b
#define GFSK_RX_BW_93800        0x13
#define GFSK_RX_BW_117300       0x0b
#define GFSK_RX_BW_156200       0x1a
#define GFSK_RX_BW_187200       0x12
#define GFSK_RX_BW_234300       0x0a
#define GFSK_RX_BW_312000       0x19
#define GFSK_RX_BW_373600       0x11
#define GFSK_RX_BW_467000       0x09

#define GFSK_PBLDET_LENGTH_OFF  0x00
#define GFSK_PBLDET_LENGTH_8    0x04
#define GFSK_PBLDET_LENGTH_16   0x05
#define GFSK_PBLDET_LENGTH_24   0x06
#define GFSK_PBLDET_LENGTH_32   0x07

enum {
    /* 0 */ LORA_BW_7_8KHz = 0,
    /* 1 */ LORA_BW_15_6KHz,
    /* 2 */ LORA_BW_31_25KHz,
    /* 3 */ LORA_BW_62_5KHz,
    /* 4 */ LORA_BW_125KHz,
    /* 5 */ LORA_BW_250KHz,
    /* 6 */ LORA_BW_500KHz,
    /* 7 */ LORA_BW_1000KHz,
};

typedef union {
    struct {
        uint8_t lf_rc  : 1; // 0
        uint8_t hf_rc  : 1; // 1
        uint8_t pll    : 1; // 2
        uint8_t adc    : 1; // 3
        uint8_t img    : 1; // 4
        uint8_t pll_tx : 1; // 5
        uint8_t rfu    : 2; // 6,7
    } bits;
    uint8_t octet;
} calibParams_t;  // for opcode 0x010f


typedef union {
    struct __attribute__((packed)) {
        uint8_t dcdc_en    : 1; // 0
        uint32_t _todo_    :31; // 1 -> 31
    } bits;
    uint32_t dword;
} regulatorMode_t;  // 0x0080036c

typedef union {
    struct __attribute__((packed)) {
        uint8_t gps        : 1; // 0
        uint8_t beidou     : 1; // 1
        uint32_t _todo_    :30; // 2 -> 31
    } bits;
    uint32_t dword;
} gnssConstellation_t;  // 0x008003b8

typedef union {
    struct __attribute__((packed)) {
        uint8_t todo              : 1; // 0
        uint8_t gnss_scan_single  : 1; // 1     0=dual-scanning
        uint32_t _todo_           :30; // 2 -> 31
    } bits;
    uint32_t dword;
} gnssMode_t;  // 0x008004b4

typedef union {
    struct __attribute__((packed)) {
        uint16_t todo           :16; // 0 -> 15
        uint8_t volts           : 3; // 16,17,18
        uint32_t _todo_         :13; // 19 -> 31
    } bits;
    uint32_t dword;
} tcxo_t;  // 0x00f0003c

typedef union {
    struct __attribute__((packed)) {
        uint8_t todo           : 1; // 0
        uint8_t enable         : 1; // 1
        uint32_t _todo_        :30; // 2 -> 31
    } bits;
    uint32_t dword;
} dioEnable_t;  // 0x00f030xx 

typedef union {
    struct __attribute__((packed)) {
        uint32_t todo           : 20; // 0 -> 19
        uint8_t bwf_lo          : 3; // 20,21,22        /* ? receiver bandwidth exponent ? */
        uint8_t _todo_          : 1; // 23
        uint8_t bwf_hi          : 2; // 24,25        /* ? receiver bandwidth mantissa ? */
        uint8_t todo_           : 6; // 26,27,28,29,30,31
    } bits;
    uint32_t dword;
} gfskBW_t;  // 0x00f20124 

typedef union {
    struct __attribute__((packed)) {
        uint8_t modem_sf        : 4; // 0,1,2,3
        uint8_t modem_bw        : 4; // 4,5,6,7
        uint8_t coding_rate     : 4; // 8,9,10,11        TODO:not all 4 bits
        uint8_t ppm_offset      : 1; // 12      LowDatarateOptimize
        uint8_t todo_a          : 3; // 13,14,15
        uint8_t crc_on          : 1; // 16
        uint8_t implicit_header : 1; // 17
        uint8_t todo_b          : 6; // 18,19,20,21,22,23
        uint8_t payload_length  : 8; // 24,25,26,27,28,29,30,31
    } bits;
    uint32_t dword;
} loraConfig0_t;  // at 0x00f20414

typedef union {
    struct {
        uint16_t preamble_length  : 16; // 0 -> 15
        uint16_t todo             : 16; // 16 -> 31
    } bits;
    uint32_t dword;
} loraConfigC_t;  // at 0x00f2041c

typedef union {
    struct {
        uint8_t todo_a        : 8; // 0,1,2,3,4,5,6,7
        uint8_t todo_b        : 2; // 8,9
        uint8_t invertIQ      : 1; // 10
        uint32_t todo_c       :21; // 11,12,13,14  15,16,17,18  19,20,21,22  23,24,25,26   27,28,29,30  31
    } bits;
    uint32_t dword;
} loraConfigA_t;  // at 0xf20420

typedef union {
    struct {
        uint8_t todo_a        : 1; // 0
        uint8_t invertIQ      : 1; // 1
        uint32_t todo_b       :30; // 2,3,4,5  6,7,8,9  10,11,12,13  14,15,16,17  18,19,20,21  22,23,24,25  26,27,28,29  30,31
    } bits;
    uint32_t dword;
} loraConfigB_t;  // at 0x00f20428

typedef union {
    struct {
        uint8_t ppg_a        : 4; // 0,1,2,3
        uint8_t todo         : 4; // 4,5,6,7
        uint8_t ppg_b        : 4; // 8,9,10,11
        uint8_t todo_        : 4; // 12,13,14,15
        uint16_t _todo       :16; // 16 -> 31
    } bits;
    uint32_t dword;
} loraSync_t;  // at 0x00f20460

typedef union {
    struct {
        uint32_t todo_        :20; // 0,1,2,3  4,5,6,7   8,9,10,11  12,13,14,15   16,17,18,19
        uint8_t bt            : 4; // 20,21,22,23       (0=0.3  1=0.5  2=0.7  3=1.0)
        uint8_t shaping_en    : 1; // 24
        uint8_t todo          : 7; // 25,26,27,28,29,30,31
    } bits;
    uint32_t dword;
} gfskConfig0_t;  // at 0x00f20314 

typedef union {
    struct {
        uint16_t preamble_length    :16; // 0,1,2,3  4,5,6,7   8,9,10,11  12,13,14,15
        uint8_t preamble_det_len    : 4; // 16,17,18,19   0=8bit  1=16bit  2=24bit  3=32bit
        uint8_t preamble_det_enable : 1; // 20
        uint16_t todo               :11; // 21,22,23,24  25,26,27,28, 29,30,31
    } bits;
    uint32_t dword;
} gfskConfig1_t;  // at 0x00f2034c

typedef union {
    struct __attribute__((packed)) {
        uint32_t _todo              :20; // 0,1,2,3  4,5,6,7   8,9,10,11  12,13,14,15  16,17,18,19
        uint8_t sync_word_length    : 7; // 20,21,22,23,24,25,26   length in bits
        uint16_t todo               : 5; // 27,28,29,30,31
    } bits;
    uint32_t dword;
} gfskConfig2_t;  // at 0x00f20350

typedef union {
    struct {
        uint8_t variable_length     : 1; // 0
        uint32_t todo               :31; // 1 -> 31
    } bits;
    uint32_t dword;
} gfskConfig3_t;  // at 0x00f2035c

typedef union {
    struct __attribute__((packed)) {
        uint8_t todo                : 8; // 0 -> 7
        uint8_t node_adrs           : 8; // 8 -> 15
        uint8_t addr_comp           : 2; // 16,17
        uint8_t _todo               : 2; // 18,19
        uint8_t payload_length      : 8; // 20,21,22,23  24,25,26,27
        uint8_t todo_               : 4; // 28,29,30,31
    } bits;
    uint32_t dword;
} gfskConfig4_t;  // at 0x00f20368

typedef union {
    struct {
        uint8_t crc_off             : 1; // 0
        uint8_t todo                : 3; // 1,2,3
        uint8_t crc_size            : 1; // 4       0=one-byte   1=two-byte
        uint8_t _todo               : 3; // 5,6,7
        uint8_t crc_invert          : 1; // 8
        uint8_t _todo_              : 7; // 9,10,11,12  13,14,15
        uint8_t whitening_enable    : 1; // 16
        uint16_t todo_              :15; // 17,18,19,20  21,22,23,24  25,26,27,28  29,30,31
    } bits;
    uint32_t dword;
} gfskConfig5_t;  // at 0x00f20370  

typedef union {
    struct {
        uint8_t _todo              : 8; // 0 -> 7
        uint8_t RegPASupply        : 1; // 8
        uint32_t todo_             :23; // 9 -> 31
    } bits;
    uint32_t dword;
} txParamsA_t;  // at 0x00f30074

typedef union {
    struct {
        uint8_t _todo              : 1; // 0
        uint8_t PaSel              : 1; // 1
        uint8_t __todo             : 2; // 2,3
        uint8_t PaHPSel            : 3; // 4,5,6
        uint8_t todo               : 1; // 7
        uint8_t PaDutyCycle        : 3; // 8,9,10
        uint32_t todo_             :21; // 11 -> 31
    } bits;
    uint32_t dword;
} txParamsB_t;  // at 0x00f30078

typedef union {
    struct __attribute__((packed)) {
        uint8_t todo                : 8; // 0 -> 7
        uint8_t pa_ramp_time        : 3; // 8,9,10
        uint8_t _todo               : 1; // 11
        uint8_t tx_dbm              : 5; // 12,13,14,15,16
        uint16_t todo_              :15; // 17 -> 31
    } bits;
    uint32_t dword;
} txParamsC_t;  // at 0x00f30080

typedef union {
    struct {
        uint32_t todo_       :28; // 0 -> 27
        uint8_t PaSel        : 1; // 28
        uint8_t todo         : 3; // 29,30,31
    } bits;
    uint32_t dword;
} txParamsD_t;  // at 0x00f30088

enum {
    /* 0 */ CMD_FAIL = 0,
    /* 1 */ CMD_PERR,
    /* 2 */ CMD_OK,
    /* 3 */ CMD_DAT
};

enum {
    /* 0 */ PACKET_TYPE_NONE = 0,
    /* 1 */ PACKET_TYPE_GFSK,
    /* 2 */ PACKET_TYPE_LORA,
};

typedef union {
    struct {
        uint32_t ___              : 2;    // 0,1
        uint32_t TxDone           : 1;    // 2
        uint32_t RxDone           : 1;    // 3
        uint32_t PreambleDetected : 1;    // 4
        uint32_t SyncHeaderValid  : 1;    // 5
        uint32_t HeaderErr        : 1;    // 6
        uint32_t Err              : 1;    // 7
        uint32_t CadDone          : 1;    // 8
        uint32_t CadDetected      : 1;    // 9
        uint32_t Timeout          : 1;    // 10
        uint32_t __               : 8;    // 11,12,13,14,15,16,17,18
        uint32_t GNSSDone         : 1;    // 19
        uint32_t WifiDone         : 1;    // 20
        uint32_t lowBat           : 1;    // 21
        uint32_t CmdErr           : 1;    // 22
        uint32_t Error            : 1;    // 23
        uint32_t FskLenError      : 1;    // 24
        uint32_t FskAddrError     : 1;    // 25
        uint32_t _                : 6;    // 26,27,28,29,30,31
    } bits;
    uint32_t dword;
} irq_t;

typedef union {
    struct {
        uint16_t bootloader    : 1;    // 0
        uint16_t chipMode      : 3;    // 1,2,3
        uint16_t resetStatus   : 4;    // 4,5,6,7
        uint16_t intActive     : 1;    // 8
        uint16_t cmdStatus     : 3;    // 9,10,11
        uint16_t rfu           : 4;    // 12,13,14,15
    } bits;
    uint16_t word;
} stat_t;

typedef union {
    struct {
        uint16_t lf_rc_calib    : 1;    // 0
        uint16_t hf_rc_calib    : 1;    // 1
        uint16_t adc_calib      : 1;    // 2
        uint16_t pll_calib      : 1;    // 3
        uint16_t img_calib      : 1;    // 4
        uint16_t hf_xosc_start_  : 1;    // 5
        uint16_t lf_xosc_start  : 1;    // 6
        uint16_t pll_lock       : 1;    // 7
        uint16_t rx_adc_offset  : 1;    // 8
        uint16_t rfu            : 7;    // 9,10,11,12,13,14,15
    } bits;
    uint16_t word;
} ErrorStat_t;

typedef union {
    struct {
        uint8_t signal   : 2;    // 0,1
        uint8_t datarate : 6;    // 2,3,4,5,6,7
    } bits;
    uint16_t octet;
} wifiType_t;

typedef union {
    struct {
        uint8_t channelID       : 4;    // 0,1,2,3
        uint8_t macValidationID : 4;    // 4,5,6,7
    } bits;
    uint16_t octet;
} wifiChanInfo_t;

typedef enum {
    CHIPMODE_NONE = 0,
    CHIPMODE_RX,
    CHIPMODE_TX
} chipMote_e;

class SX1265 {
    public:
        SX1265(SPI&, PinName nss, PinName busy, PinName dio9, PinName nrst, uint32_t default_irqs = 0x3ffffff, unsigned tcxoTimeout = 2048, uint8_t tcxoVolts = TCXO_VOLTS_2v7);
        static Callback<void()> dio9_topHalf;    // low latency ISR context
        uint16_t xfer(uint16_t opcode, uint16_t writeLen, uint16_t readLen, uint8_t* buf);
        uint32_t service(void);
        void hw_reset(void);
        const char *cmdStatus_toString(uint8_t);
        uint8_t setMHz(float);
        float getMHz(void);
        void to_big_endian16(uint16_t in, uint8_t *out);
        void to_big_endian32(uint32_t in, uint8_t *out);
        void to_big_endian24(uint32_t in, uint8_t *out);
        uint32_t from_big_endian32(const uint8_t *in);
        //int memRegRead(uint32_t addr, uint16_t len_dwords, uint8_t *dest);
        int memRegRead(uint32_t addr, uint16_t len_dwords, uint32_t *dest);
        uint8_t getPacketType(void);
        void setPacketType(uint8_t);
        void start_tx(uint8_t pktLen);  // tx_buf must be filled prior to calling

        Timer t;
        ErrorStat_t errorStat;

        //! RF transmit packet buffer
        uint8_t tx_buf[256];    // lora fifo size
        
        //! RF receive packet buffer
        uint8_t rx_buf[256];    // lora fifo size

        Callback<void()> chipModeChange; // read chipMode_e chipMode
        Callback<void()> txDone; // user context
        void (*cadDone)(bool detected); // user context
        void (*rxDone)(uint8_t size, float rssi, float snr); // user context
        void (*timeout)(bool tx); // user context
        unsigned txTimeout;
        uint16_t err_opcode;
        uint8_t rx_buf_offset;
        chipMote_e chipMode;

        void GetPaConfig(uint8_t*); /* for read-modify-write */
        void GetLoRaModulationParameters(uint8_t*); /* for read-modify-write */
        void GetLoRaPacketParameters(uint8_t*); /* for read-modify-write */
        void GetGfskModulationParameters(uint8_t*); /* for read-modify-write */
        void GetGfskPacketParameters(uint8_t*); /* for read-modify-write */

    private:
        SPI& spi;
        DigitalOut nss;
        DigitalIn busy;
        InterruptIn dio9;
        DigitalInOut nrst;
        static void dio9isr(void);
        bool sleeping;
        uint16_t prev_opcode;
        uint16_t this_opcode;
        bool inService;
        void enable_default_irqs_(void);

    public:
        uint32_t default_irqs;

    private:
        unsigned tcxoStartDelay;
        uint8_t tcxoVolts;
        uint8_t rxArgs[3];
};

#endif /* SX1265_H */