wayne roberts / SX1232

Dependents:   chat_sx1232

sx1232.h

Committer:
dudmuck
Date:
2013-05-01
Revision:
1:67a841d57890
Parent:
0:06cc2cd9f340
Child:
2:8717baf6e00a

File content as of revision 1:67a841d57890:

/* 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,    //! 
    SERVICE_READ_FIFO //! request to call read_fifo()
} 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 */