driver for SX1232 transceiver

Dependents:   chat_sx1232

summary

The SX1232 is a fully integrated ISM band transceiver optimized for use in the (EN 300 220-1) 868 MHz band in Europe and the (FCC Part 15) 915 MHz band in the US with a minimum of external components. It offers a combination of high link budget and low current consumption in all operating modes.

features

This part offers similar functionality to XBee PRO 900 modules, except RF performance would be improved, especially at slower data-rates. This is due to available narrower receiver bandwidths, and higher TX power, among other things. Additionally, its probably redundant to have a microcontroller on your wireless module, since the mbed cpu can drive radio directly.

This version of driver library supports packet size up to FIFO size (64bytes) to keep it simple and small. For larger packet sizes, a different driver could support the FIFO flow control pins.

wiring connections

Minimum required connections are SPI: mosi, miso, sclk, cs, one interrupt pin, and optional hardware reset pin.

example code

For example usage see Demo Chat Application.

specification of chip

Information on device. /media/uploads/dudmuck/sm1232.png

sx1232.h

Committer:
dudmuck
Date:
2013-05-02
Revision:
2:8717baf6e00a
Parent:
1:67a841d57890

File content as of revision 2:8717baf6e00a:

/* SX1232 driver
 * Copyright (c) 2013 Semtech
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
#ifndef SX1232_H
#define SX1232_H

#include "mbed.h"

#define XTAL_FREQ   32000000

#define FREQ_STEP_MHZ     61.03515625e-6
#define FREQ_STEP_KHZ     61.03515625e-3
#define FREQ_STEP_HZ      61.03515625

/******************************************************************************/
/*!
 * SX1232 Internal registers Address
 */
#define REG_FIFO                                    0x00
// Common settings
#define REG_OPMODE                                  0x01
#define REG_BITRATEMSB                              0x02
#define REG_BITRATELSB                              0x03
#define REG_FDEVMSB                                 0x04 
#define REG_FDEVLSB                                 0x05
#define REG_FRFMSB                                  0x06
#define REG_FRFMID                                  0x07
#define REG_FRFLSB                                  0x08
// Tx settings
#define REG_PACONFIG                                0x09
#define REG_PARAMP                                  0x0A
#define REG_OCP                                     0x0B 
// Rx settings
#define REG_LNA                                     0x0C
#define REG_RXCONFIG                                0x0D
#define REG_RSSICONFIG                              0x0E
#define REG_RSSICOLLISION                           0x0F
#define REG_RSSITHRESH                              0x10
#define REG_RSSIVALUE                               0x11
#define REG_RXBW                                    0x12 
#define REG_AFCBW                                   0x13
#define REG_OOKPEAK                                 0x14
#define REG_OOKFIX                                  0x15
#define REG_OOKAVG                                  0x16
#define REG_RES17                                   0x17
#define REG_RES18                                   0x18
#define REG_RES19                                   0x19
#define REG_AFCFEI                                  0x1A
#define REG_AFCMSB                                  0x1B
#define REG_AFCLSB                                  0x1C
#define REG_FEIMSB                                  0x1D
#define REG_FEILSB                                  0x1E
#define REG_PREAMBLEDETECT                          0x1F
#define REG_RXTIMEOUT1                              0x20
#define REG_RXTIMEOUT2                              0x21
#define REG_RXTIMEOUT3                              0x22
#define REG_RXDELAY                                 0x23
// Oscillator settings
#define REG_OSC                                     0x24
// Packet handler settings
#define REG_PREAMBLEMSB                             0x25
#define REG_PREAMBLELSB                             0x26
#define REG_SYNCCONFIG                              0x27
#define REG_SYNCVALUE1                              0x28
#define REG_SYNCVALUE2                              0x29
#define REG_SYNCVALUE3                              0x2A
#define REG_SYNCVALUE4                              0x2B
#define REG_SYNCVALUE5                              0x2C
#define REG_SYNCVALUE6                              0x2D
#define REG_SYNCVALUE7                              0x2E
#define REG_SYNCVALUE8                              0x2F
#define REG_PACKETCONFIG1                           0x30
#define REG_PACKETCONFIG2                           0x31
#define REG_PAYLOADLENGTH                           0x32
#define REG_NODEADRS                                0x33
#define REG_BROADCASTADRS                           0x34
#define REG_FIFOTHRESH                              0x35
// SM settings
#define REG_SEQCONFIG1                              0x36
#define REG_SEQCONFIG2                              0x37
#define REG_TIMERRESOL                              0x38
#define REG_TIMER1COEF                              0x39
#define REG_TIMER2COEF                              0x3A
// Service settings
#define REG_IMAGECAL                                0x3B
#define REG_TEMP                                    0x3C
#define REG_LOWBAT                                  0x3D
// Status
#define REG_IRQFLAGS1                               0x3E
#define REG_IRQFLAGS2                               0x3F
// I/O settings
#define REG_DIOMAPPING1                             0x40
#define REG_DIOMAPPING2                             0x41
// Version
#define REG_VERSION                                 0x42
// Additional settings
#define REG_AGCREF                                  0x43
#define REG_AGCTHRESH1                              0x44
#define REG_AGCTHRESH2                              0x45
#define REG_AGCTHRESH3                              0x46
#define REG_PLLHOP                                  0x4B
#define REG_TCXO                                    0x58
#define REG_PADAC                                   0x5A
#define REG_PLL                                     0x5C
#define REG_PLLLOWPN                                0x5E
#define REG_FORMERTEMP                              0x6C
#define REG_BITRATEFRAC                             0x70

/******************************************************************************/

typedef enum {
    RF_OPMODE_SLEEP = 0,
    RF_OPMODE_STANDBY,
    RF_OPMODE_SYNTHESIZER_TX,
    RF_OPMODE_TRANSMITTER,
    RF_OPMODE_SYNTHESIZER_RX,
    RF_OPMODE_RECEIVER
} chip_mode_e;

/******************************************************************************/

typedef union {
    struct {    // sx1232 register 0x01
        uint8_t Mode                : 3;    // 0,1,2
        uint8_t ModulationShaping   : 2;    // 3,4  FSK/OOK
        uint8_t ModulationType      : 2;    // 5,6  FSK/OOK
        uint8_t LongRangeMode       : 1;    // 7    change this bit only in sleep mode
    } bits;
    uint8_t octet;
} RegOpMode_t;

typedef union {
    struct {    // sx1232 register 0x09
        uint8_t OutputPower : 4;    // 0,1,2,3
        uint8_t unused      : 3;    // 4,5,6
        uint8_t PaSelect    : 1;    // 7        1=PA_BOOST
    } bits;
    uint8_t octet;
} RegPaConfig_t;

typedef union {
    struct {    // sx1232 register 0x0c
        uint8_t lna_i_boost  : 2;    // 0,1
        uint8_t unused       : 1;    // 2
        uint8_t trim_rx_crfo : 2;    // 3,4     add caps to RFo
        uint8_t rxfe_gain    : 3;    // 5,6,7        1=PA_BOOST
    } bits;
    uint8_t octet;
} RegLna_t; // RXFE

typedef union {
    struct {    // sx1232 register 0x0d
        uint8_t RxTrigger               : 3;    // 0,1,2: 0=none 1=rssiInt 6=preambleDet 7=both
        uint8_t AgcAutoOn               : 1;    // 3
        uint8_t AfcAutoOn               : 1;    // 4
        uint8_t RestartRxWithPllLock    : 1;    // 5    manual rx restart, for use with FHSS
        uint8_t RestartRxWithoutPllLock : 1;    // 6    manual rx restart
        uint8_t RestartRxOnCollision    : 1;    // 7    collision detector (see RegRssiCollision at 0x0f)
    } bits;
    uint8_t octet;
} RegRxConfig_t;

typedef union {
    struct {    // sx1232 register 0x14
        uint8_t OokPeakThreshStep   : 3;    // 0,1,2
        uint8_t OokThreshType       : 2;    // 3,4
        uint8_t BitSyncOn           : 1;    // 5
        uint8_t barker_en           : 1;    // 6
        uint8_t bsync_opt           : 1;    // 7    not used
    } bits;
    uint8_t octet;
} RegOokPeak_t; // DEMOD1 0x14

typedef union {
    struct {    // sx1232 register 0x1a
        uint8_t AfcAutoClearOn  : 1;    // 0
        uint8_t AfcClear        : 1;    // 1    manual clear
        uint8_t unused1         : 1;    // 2
        uint8_t fei_range       : 1;    // 3    FEI range limited by: 0=rxbw    1=fs/2
        uint8_t AgcStart        : 1;    // 4    manual trigger AGC
        uint8_t unused          : 3;    // 5,6,7 
    } bits;
    uint8_t octet;
} RegAfcFei_t;

typedef union {
    struct {    // sx1232 register 0x1f
        uint8_t PreambleDetectorTol     : 5;    // 0,1,2,3,4    allowed chip errors
        uint8_t PreambleDetectorSize    : 2;    // 5,6      00b=1bytes... 11b=4bytes
        uint8_t PreambleDetectorOn      : 1;    // 7
    } bits;
    uint8_t octet;
} RegPreambleDetect_t;

typedef union {
    struct {    // sx1232 register 0x27
        uint8_t SyncSize            : 3;    // 0,1,2
        uint8_t FifoFillCondition   : 1;    // 3    rx fifo fill starting 0=start-on-sync
        uint8_t SyncOn              : 1;    // 4    enable pattern recognition
        uint8_t PreamblePolarity    : 1;    // 5    0=0xaa 1=0x55
        uint8_t AutoRestartRxMode   : 2;    // 6,7  00b=manual restart, 01b=auto-restart after fifo pulled, and 10b=add wait-for-pll
    } bits; // manual Rx restart is in RegRxConfig
    uint8_t octet;
} RegSyncConfig_t;

typedef union {
    struct {    // sx1232 register 0x30
        uint8_t CrCWhiteningType : 1;    // 0       1=IBM-crc   0=ccitt-crc
        uint8_t AddressFiltering : 2;    // 1,2     11b = two-byte nodeadrs at 0x2c->0x2f
        uint8_t CrcAutoClearOff  : 1;    // 3
        uint8_t CrcOn            : 1;    // 4
        uint8_t DcFree           : 2;    // 5,6 
        uint8_t PacketFormatVariable : 1;    // 7       1=variable length, 0=fixed
    } bits;
    uint8_t octet;
} RegPktConfig1_t;

typedef union {
    struct {    // sx1232 register 0x31
        uint8_t PayloadLengthHi  : 3;    // 0,1,2       PayloadLength(10:8)
        uint8_t BeaconOn         : 1;    // 3
        uint8_t IoHomePowerFrame : 1;    // 4   CRC LFSR init: 0=0x1d0f, 1=0x0000=powerlink
        uint8_t IoHomeOn         : 1;    // 5
        uint8_t DataModePacket   : 1;    // 6   1=packet mode, 0=continuous mode
        uint8_t unused           : 1;    // 7 
    } bits;
    uint8_t octet;
} RegPktConfig2_t;

typedef union {
    struct {    // sx1232 register 0x35
        uint8_t FifoThreshold       : 6;    // 0,1,2,3,4,5       PayloadLength(10:8)
        uint8_t unused              : 1;    // 6 
        uint8_t TxStartCondition    : 1;    // 7        0=fifoThresh 1=fifoNotEmpty
    } bits;
    uint8_t octet;
} RegFifoThreshold_t;

typedef union {
    struct {    // sx1232 register 0x36
        uint8_t FromTransmit        : 1;    // 0
        uint8_t FromIdle            : 1;    // 1
        uint8_t LowPowerSelection   : 1;    // 2
        uint8_t FromStart           : 2;    // 3,4
        uint8_t IdleMode            : 1;    // 5 
        uint8_t SequencerStop       : 1;    // 6 
        uint8_t SequencerStart      : 1;    // 7
    } bits;
    uint8_t octet;
} RegSeqConfig1_t;   // @0x36

typedef union {
    struct {    // sx1232 register 0x37
        uint8_t FromPacketReceived  : 3;    // 0,1,2
        uint8_t FromRxTimeout       : 2;    // 3,4
        uint8_t FromReceive         : 3;    // 5,6,7
    } bits;
    uint8_t octet;
} RegSeqConfig2_t;   // @0x37

typedef union {
    struct {    // sx1232 register 0x38
        uint8_t timer2_resol   : 2;    // 0,1
        uint8_t timer1_resol   : 2;    // 2,3
        uint8_t force_hlm_irq  : 1;    // 4 
        uint8_t hlm_started    : 1;    // 5 
        uint8_t unused         : 2;    // 6,7
    } bits;
    uint8_t octet;
} RegTimerResol_t ;   // HL42 @0x38

typedef union {
    struct {    // sx1232 register 0x3e
        uint8_t SyncAddressMatch    : 1;    // 0 
        uint8_t PreambleDetect      : 1;    // 1 
        uint8_t Timeout             : 1;    // 2    rx-timeout
        uint8_t Rssi                : 1;    // 3 
        uint8_t PllLock             : 1;    // 4 
        uint8_t TxReady             : 1;    // 5 
        uint8_t RxReady             : 1;    // 6 
        uint8_t ModeReady           : 1;    // 7 
    } bits;
    uint8_t octet;
} RegIrqFlags1_t;   // STAT0

typedef union {
    struct {    // sx1232 register 0x3f
        uint8_t LowBat          : 1;    // 0    "eol"
        uint8_t CrcOk           : 1;    // 1 
        uint8_t PayloadReady    : 1;    // 2 
        uint8_t PacketSent      : 1;    // 3 
        uint8_t FifoOverrun     : 1;    // 4 
        uint8_t FifoLevel       : 1;    // 5 
        uint8_t FifoEmpty       : 1;    // 6 
        uint8_t FifoFull        : 1;    // 7 
    } bits;
    uint8_t octet;
} RegIrqFlags2_t;   // STAT1 @0x3f

typedef union {
    struct {    // sx1232 register 0x40
        uint8_t Dio3Mapping     : 2;    // 0,1
        uint8_t Dio2Mapping     : 2;    // 2,3
        uint8_t Dio1Mapping     : 2;    // 4,5
        uint8_t Dio0Mapping     : 2;    // 6,7 
    } bits;
    uint8_t octet;
} RegDioMapping1_t;

typedef union {
    struct {    // sx1232 register 0x41
        uint8_t MapPreambleDetect : 1;    // 0      //DIO4 assign: 1b=preambleDet 0b=rssiThresh
        uint8_t io_mode           : 3;    // 1,2,3  //0=normal,1=debug,2=fpga,3=pll_tx,4=pll_rx,5=analog
        uint8_t Dio5Mapping       : 2;    // 4,5
        uint8_t Dio4Mapping       : 2;    // 6,7 
    } bits;
    uint8_t octet;
} RegDioMapping2_t;

/***************************************************/

typedef enum {
    SERVICE_NONE = 0,
    SERVICE_ERROR,
    //! request to call read_fifo()
    SERVICE_READ_FIFO,
    //! notification to application of transmit complete
    SERVICE_TX_DONE
} service_action_e;

/** FSK radio transceiver for 800/900MHz.
 * Compared with ADF7023 in Xbee PRO 900:
 *  Receiver bandwidth configurable to narrower operation, for performance at lower bitrates.
 *  Transmit power option to +20dBm.
 *  Superior blocking immunity in receiver.
 * http://www.semtech.com/apps/product.php?pn=sx1232
 */
class SX1232 {
    public:
            /** Create SX1232 instance
         * @param mosi SPI master-out pin
         * @param miso SPI master-in pin
         * @param sclk SPI clock pin
         * @param cs SPI chip-select pin
         * @param rst radio hardware reset pin
         * @param dio_0 interrupt pin from radio
         */
        SX1232(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName rst, PinName dio_0);
        
        ~SX1232();
        
        /** set receiver bandwidth
         * @note Value is selected to frequency deviation and bit-rate (occupied bandwidth)
         * @note Narrower bandwidths may require AFC, depending on reference crystal accuracy
         * @note RX start-up time is slower at narrower bandwidths
         * @note you cannot change bandwith while in receive mode
         * @note usable range is 2.6KHz to 250KHz
         */
        void set_rx_dcc_bw_hz(uint32_t dccValue, uint32_t bw_hz );
        /** get receiver bandwidth
         * @returns the receiver bandwidth in Hz
         */
        uint32_t get_rx_bw_hz(uint8_t addr);
        
        /** set center operating frequency
         * @param MHz operating frequency in MHz
         */
        void set_frf_MHz( float MHz );
        
        /** get center operating frequency
         * @returns operating frequency in MHz
         */
        float get_frf_MHz(void);
        
        /** set over-the-air bitrate
         * @param bps bits per second
         * @note TX frequency deviation must be set according to desired modulation index
         * @note you cannot change bitrate while in receive mode
         */
        void set_bitrate(uint32_t bps);
        /** get over-the-air bitrte
         * @returns bits per second
         */
        uint32_t get_bitrate(void);
        
        /** set transmitted frequency deviation
         * @param hz frequency deviation in Hz
         * @note occupied bandwith is primarily determined by fdev; set receiver bandwidth appropriately
         * @note usable range is 600Hz to 200KHz
         */
        void set_tx_fdev_hz(uint32_t hz);
        /** get transmitted frequency deviation
         * @returns transmitter frequency deviation in Hz
         */
        uint32_t get_tx_fdev_hz(void);
        
        /** enable AFC with preamble detector
         * @note AFC generally used when crystal tolerance is worse than receiver bandwidth.  Narrower bandwidths require better ppm on crystal, without AFC.
         * @note this enables with RxTrigger on preamble detect without RSSI threshold.
         * @note other option is to also use RSSI threshold, but requires calibration from ambient RSSI on vacant channel.
         */
        void enable_afc(char enable);
        
        /** write payload length
         * @note PayloadLength is maximum 255 in variable-length packet format, or fixed-length maximum of 2047 bytes.
         * @note if PacketFormat is fixed-length, then PayloadLength of 0 enables unlimited length mode.
         * @note In variable length mode, this sets maximum allowed received packet length.
         * @param len PayloadLength
         */
        void set_RegPayloadLength(uint16_t len);
        /** read payload length
         */
        uint16_t get_PayloadLength(void);        
        
        /** transmit a packet
         * @param len size of packet, variable-length format only.  unused in fixed-length format.
         * @note Limited to 64 bytes. Lengths greater than 64 require flow control (radio FIFO size)
         */
        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[]
         */
        int read_fifo(void);
        
        void set_opmode(chip_mode_e mode);
        
        /** reset radio using pin
         */
        void hw_reset(void);
        /** initialise SX1232 class to radio
         * @note this is called from class instantiation, but must also be manually called after hardware reset
         */
        void init(void);
        
        /** read register from radio
         * @param addr register address
         * @returns the value read from the register
         */
        uint8_t read_reg(uint8_t addr);
        int16_t read_reg_s16(uint8_t addr);  // for signed 16bit values, such as AFC/FEI
        
        /** write register to radio
         * @param addr register address
         * @param data byte to write
         */
        void write_reg(uint8_t addr, uint8_t data);
                
        //! set from ISR to indicate an action to be performed from main loop
        volatile service_action_e service_action;
        
        //! RF transmit packet buffer
        uint8_t tx_buf[64]; 
        
        //! RF receive packet buffer
        uint8_t rx_buf[64]; 
        
        //! operating mode
        RegOpMode_t RegOpMode; 
        
        //! pin assignments
        RegDioMapping1_t RegDioMapping1; 
        
        //! pin assignments
        RegDioMapping2_t RegDioMapping2; 
        
        //! packet format configuration
        RegPktConfig1_t RegPktConfig1; 
        
        //! packet mode control and payload length MSB
        RegPktConfig2_t RegPktConfig2; 
        
        //! payload length LSByte
        uint8_t RegPayloadLength; 
        
        //! TxStartCondition
        RegFifoThreshold_t RegFifoThreshold; 
        
        //! AutoRestartRx configuration and start-of-frame control
        RegSyncConfig_t RegSyncConfig; 
        
        //! receiver preamble detector control
        RegPreambleDetect_t RegPreambleDetect; 
        
        //! TX preamble length
        uint8_t RegPreambleMsb; 
        
        //! TX preamble length
        uint8_t RegPreambleLsb; 
        
        //! transmitter power configuration
        RegPaConfig_t RegPaConfig; 
        
        //! AFC/AGC configuration
        RegRxConfig_t RegRxConfig; 
        
        // receiver front-end
        RegLna_t RegLna; 
        
        //! sequencer timing
        RegTimerResol_t RegTimerResol; 
        
        //! receiver: trigger level for RSSI interrupt
        uint8_t RegRssiThresh; 
        
        //! sequencer control
        RegSeqConfig1_t RegSeqConfig1; 
        
        //! sequencer control
        RegSeqConfig2_t RegSeqConfig2; 
        
        //! AFC clearing control and manual AFC trigger
        RegAfcFei_t RegAfcFei; 
        
        RegOokPeak_t RegOokPeak;
        
    private:
        SPI m_spi;
        DigitalOut m_cs;
        DigitalInOut reset_pin;
        void dio0_callback(void);
        void ComputeRxBwMantExp( uint32_t rxBwValue, uint8_t* mantisse, uint8_t* exponent );
        uint32_t ComputeRxBw( uint8_t mantisse, uint8_t exponent );
        void write_fifo__varlen(uint8_t len);
        void write_fifo__fixedlen(void);
        
        
    protected:
        InterruptIn dio0;
        FunctionPointer _callback_rx;
};


#endif /* SX1232_H */