Driver library for SX1272/SX1276 transceivers

Dependents:   LORA_RX LORA_TX WindConcentrator hid_test ... more

/media/uploads/dudmuck/lora.png

Driver library for SX1272 and SX1276 radio transceivers.

This device uses CSS modulation to provide much improved link budget. The RF hardware is same as in FSK devices, just with added LoRa spread-spectrum modem.

This library provides functions to configure radio chip and transmit & receive packets.

Using This Library

Library function service_radio() must be called continuously from main loop, to service interrupts from radio.

/media/uploads/dudmuck/sx1272rf1_connector_300.jpg

Board Specific implementation

FunctionPointer for rf_switch callback allows the program to implement control of RF switch unique to their board. Example options are:

  • SKY13373 for external power amplifier implementation. Requires two DigitalOut pins.
  • SKY13350 using PA_BOOST. requires two DigitalOut pins.
  • PE4259-63: controlled directly by radio chip, no software function needed. However, in the case of SX1276MB1xAS, the RXTX pin on IO2 should be driven by this callback function when R16 is installed (without R15) on this shield board.

Some configurations may need to force the use of RFO or PA_BOOST, or a board could offer both options. The rf_switch function pointer callback should support the implementation choice on the board.

further reading

sx127x_lora.h

Committer:
dudmuck
Date:
2015-03-17
Revision:
11:4210303ac88d
Parent:
10:7382c260c4b1
Child:
12:bda42457c34a

File content as of revision 11:4210303ac88d:

#include "sx127x.h"

// LoRa registers
#define REG_LR_FIFOADDRPTR                          0x0d
#define REG_LR_FIFOTXBASEADDR                       0x0e
#define REG_LR_FIFORXBASEADDR                       0x0f
#define REG_LR_FIFORXCURRENTADDR /*REG_LR_RXDATAADDR*/  0x10
#define REG_LR_IRQFLAGSMASK                         0x11
#define REG_LR_IRQFLAGS                             0x12
#define REG_LR_RXNBBYTES                            0x13
#define REG_LR_RXHEADERCNTVALUE_MSB                 0x14
#define REG_LR_RXHEADERCNTVALUE_LSB                 0x15
#define REG_LR_RXPACKETCNTVALUE_MSB                 0x16
#define REG_LR_RXPACKETCNTVALUE_LSB                 0x17
#define REG_LR_MODEMSTAT                            0x18
#define REG_LR_PKTSNRVALUE                          0x19
#define REG_LR_PKTRSSIVALUE                         0x1a
#define REG_LR_RSSIVALUE                            0x1b
#define REG_LR_HOPCHANNEL                           0x1c
#define REG_LR_MODEMCONFIG                          0x1d
#define REG_LR_MODEMCONFIG2                         0x1e
#define REG_LR_SYMBTIMEOUTLSB                       0x1f
#define REG_LR_PREAMBLEMSB                          0x20
#define REG_LR_PREAMBLELSB                          0x21
#define REG_LR_PAYLOADLENGTH                        0x22 // and RX length for implicit
#define REG_LR_RX_MAX_PAYLOADLENGTH                 0x23 // length limit for explicit mode
#define REG_LR_HOPPERIOD                            0x24
#define REG_LR_RXBYTEADDR /*REG_LR_RXDATAADDR*/     0x25
#define REG_LR_MODEMCONFIG3                         0x26    // sx1272 REG_LR_PPM_CORRECTION_MSB
#define REG_LR_PPM_CORRECTION_LSB                   0x27
#define REG_LR_TEST28                               0x28  // est_freq_error
#define REG_LR_TEST29                               0x29    // est_freq_error
#define REG_LR_TEST2A                               0x2a    // est_freq_error
#define REG_LR_TEST2B                               0x2b    // 
#define REG_LR_WIDEBAND_RSSI                        0x2c 
#define REG_LR_AGCH_TH                              0x2d    // agc_upper_th
#define REG_LR_AGCL_TH                              0x2e    // agc_lower_th
#define REG_LR_IFFRQH                               0x2f    // if_freq(12:8)
#define REG_LR_IFFRQL                               0x30    // if_freq(7:0)
#define REG_LR_TEST31                               0x31    // if_freq_auto, ...
#define REG_LR_TEST32                               0x32    // 
#define REG_LR_TEST33                               0x33
#define REG_LR_CAD_PEAK_TO_NOISE_RATIO              0x34
#define REG_LR_CAD_MIN_PEAK                         0x35
#define REG_LR_DETECTION_THRESHOLD                  0x37
#define REG_LR_SYNC_BYTE                            0x39    // default 0x12 (value of 0x21 will isolate network)

typedef union {
    struct {    // sx127x register 0x12
        uint8_t CadDetected         : 1;    // 0
        uint8_t FhssChangeChannel   : 1;    // 1
        uint8_t CadDone             : 1;    // 2
        uint8_t TxDone              : 1;    // 3
        uint8_t ValidHeader         : 1;    // 4
        uint8_t PayloadCrcError     : 1;    // 5
        uint8_t RxDone              : 1;    // 6
        uint8_t RxTimeout           : 1;    // 7
    } bits;
    uint8_t octet;
} RegIrqFlags_t;

typedef union {
    struct {    // sx127x register 0x18
        uint8_t detect          : 1;    // 0
        uint8_t sync            : 1;    // 1
        uint8_t rx_ongoing      : 1;    // 2
        uint8_t header_valid    : 1;    // 3
        uint8_t clear           : 1;    // 4
        uint8_t RxCodingRate    : 3;    // 5,6,7
    } bits;
    uint8_t octet;
} RegModemStatus_t;

typedef union {
    struct {    // sx127x register 0x1c
        uint8_t FhssPresentChannel  : 6;    // 0,1,2,3,4,5
        uint8_t RxPayloadCrcOn      : 1;    // 6
        uint8_t PllTimeout          : 1;    // 7
    } bits;
    uint8_t octet;
} RegHopChannel_t;

typedef union {
    struct {    // sx1276 register 0x1d
        uint8_t ImplicitHeaderModeOn    : 1;    // 0
        uint8_t CodingRate              : 3;    // 1,2,3
        uint8_t Bw                      : 4;    // 4,5,6,7
    } sx1276bits;
    struct {    // sx1272 register 0x1d
        uint8_t LowDataRateOptimize     : 1;    // 0  ppm_offset: number of cyclic shifts possible to encode to symbol
        uint8_t RxPayloadCrcOn          : 1;    // 1
        uint8_t ImplicitHeaderModeOn    : 1;    // 2
        uint8_t CodingRate              : 3;    // 3,4,5
        uint8_t Bw                      : 2;    // 6,7
    } sx1272bits;
    uint8_t octet;
} RegModemConfig_t;

typedef union {
    struct {    // sx1276 register 0x1e
        uint8_t SymbTimeoutMsb          : 2;    // 0,1
        uint8_t RxPayloadCrcOn          : 1;    // 2
        uint8_t TxContinuousMode        : 1;    // 3
        uint8_t SpreadingFactor         : 4;    // 4,5,6,7
    } sx1276bits;
    struct {    // sx1272 register 0x1e
        uint8_t SymbTimeoutMsb          : 2;    // 0,1
        uint8_t AgcAutoOn               : 1;    // 2
        uint8_t TxContinuousMode        : 1;    // 3
        uint8_t SpreadingFactor         : 4;    // 4,5,6,7
    } sx1272bits;
    uint8_t octet;
} RegModemConfig2_t;

typedef union {
    struct {    // sx127x register 0x26
        uint8_t reserved    : 2;    // 0,1
        uint8_t AgcAutoOn   : 1;    // 2
        uint8_t LowDataRateOptimize  : 1;    // 3   ppm_offset, use when symbol duration exceeds 16ms
        uint8_t unused      : 4;    // 4,5,6,7 
    } sx1276bits;
    uint8_t octet;
    uint8_t sx1272_ppm_correction_msb;
} RegModemConfig3_t;


typedef union {
    struct {    // sx127x register 0x31
        uint8_t detect_trig_same_peaks_nb  : 3;    // 0,1,2
        uint8_t disable_pll_timeout        : 1;    // 3
        uint8_t tracking_intergral         : 2;    // 4,5
        uint8_t frame_sync_gain            : 1;    // 6
        uint8_t if_freq_auto               : 1;    // 7
    } bits;
    uint8_t octet;
} RegTest31_t;

//class SX127x_lora : public SX127x
class SX127x_lora {
    public:
        //SX127x_lora(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName rst, PinName dio_0, PinName dio_1, PinName fem_ctx, PinName fem_cps);
        SX127x_lora(SX127x& r);
        
        ~SX127x_lora();
        
        /** changes from FSK mode to LoRa mdoe */
        void enable(void);
        
        /** fills radio FIFO with payload contents, prior to transmission
         * @param len count of bytes to put into FIFO
         * @note tx_buf[] should contain desired payload (to send) prior to calling
         */
        void write_fifo(uint8_t len);     
        
        /** transmit a packet
         * @param len size of packet
         * @note Limited to (lora fifo size 256)
         */
        void start_tx(uint8_t len);
        
        /** start receive mode
         * @note the variable service_action needs to be monitored to indicate read_fifo() needs to be called to pull packet from FIFO.
         */
        void start_rx(void);
        
        /** Called by main program when indicated by service_action variable, to pull recevied packet from radio FIFO.
         * @returns count of bytes received
         * @note received packet in rx_buf[]
         */
        void read_fifo(uint8_t len);
        
        /** CodingRate: how much FEC to encoding onto packet */
        uint8_t getCodingRate(bool from_rx);    // false:transmitted, true:last recevied packet
        void setCodingRate(uint8_t cr);
        
        /** HeaderMode: explicit mode sents CodingRate and payload length, implicit mode requires assumption by receiver */
        bool getHeaderMode(void);
        void setHeaderMode(bool hm);

        /** bandwidth: SX1272 has three bandwidths. SX1276 adds more narrower bandwidths. */
        uint8_t getBw(void);
        void setBw(uint8_t bw);
        
        /** spreading factor: trade-off between data rate and processing gain (link budget) */
        uint8_t getSf(void);
        void setSf(uint8_t sf);        
        
        /** enable CRC in transmitted packet */
        bool getRxPayloadCrcOn(void);
        void setRxPayloadCrcOn(bool);
        
        bool getAgcAutoOn(void);
        void setAgcAutoOn(bool);
        
        float get_pkt_rssi(void);
        
        /** retrieve symbol duration from bandwidth and spreading factor
         * @returns symbol duration in milliseconds
         */        
        float get_symbol_period(void);
        
        service_action_e service(void); // (SLIH) ISR bottom half 
        
        bool poll_vh;
        
        RegIrqFlags_t       RegIrqFlags;            // 0x12
        uint8_t             RegRxNbBytes;           // 0x13
        RegModemStatus_t    RegModemStatus;         // 0x18
        int8_t              RegPktSnrValue;         // 0x19  signed, s/n can be negative
        uint8_t             RegPktRssiValue;        // 0x1a
        RegHopChannel_t     RegHopChannel;          // 0x1c
        RegModemConfig_t    RegModemConfig;         // 0x1d
        RegModemConfig2_t   RegModemConfig2;        // 0x1e
        uint16_t            RegPreamble;            // 0x20->0x21
        uint8_t             RegPayloadLength;       // 0x22
        uint8_t             RegRxMaxPayloadLength;  // 0x23
        uint8_t             RegHopPeriod;           // 0x24
        RegModemConfig3_t   RegModemConfig3;        // 0x26
        RegTest31_t         RegTest31;              // 0x31
        
        SX127x& m_xcvr;
        
    private:
        void set_nb_trig_peaks(int);                                                         
};