2012-02-29 05:30:06 +01:00
/**
2012-03-18 18:22:05 +01:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* @ addtogroup PIOS PIOS Core hardware abstraction layer
* @ {
* @ addtogroup PIOS_RFM22B Radio Functions
* @ brief PIOS interface for for the RFM22B radio
* @ {
*
* @ file pios_rfm22b . c
* @ author The OpenPilot Team , http : //www.openpilot.org Copyright (C) 2012.
* @ brief Implements a driver the the RFM22B driver
* @ see The GNU Public License ( GPL ) Version 3
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-02-29 05:30:06 +01:00
/*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
2012-03-18 18:22:05 +01:00
// *****************************************************************
// RFM22B hardware layer
//
// This module uses the RFM22B's internal packet handling hardware to
// encapsulate our own packet data.
//
// The RFM22B internal hardware packet handler configuration is as follows ..
//
// 4-byte (32-bit) preamble .. alternating 0's & 1's
// 4-byte (32-bit) sync
// 1-byte packet length (number of data bytes to follow)
// 0 to 255 user data bytes
//
// Our own packet data will also contain it's own header and 32-bit CRC
// as a single 16-bit CRC is not sufficient for wireless comms.
//
// *****************************************************************
2012-02-29 05:30:06 +01:00
/* Project Includes */
# include "pios.h"
# if defined(PIOS_INCLUDE_RFM22B)
2012-03-18 18:22:05 +01:00
# include <string.h> // memmove
# include <stm32f10x.h>
# include <stopwatch.h>
2012-03-16 03:29:54 +01:00
# include <packet_handler.h>
2012-02-29 05:30:06 +01:00
2012-03-16 03:29:54 +01:00
# include <pios_rfm22b_priv.h>
2012-03-08 02:05:42 +01:00
2012-03-18 18:22:05 +01:00
/* Local Defines */
# define STACK_SIZE_BYTES 200
2012-02-29 05:30:06 +01:00
2012-04-22 03:31:49 +02:00
// RTC timer is running at 625Hz (1.6ms or 5 ticks == 8ms).
// A 256 byte message at 56kbps should take less than 40ms
// Note: This timeout should be rate dependent.
# define PIOS_RFM22B_SUPERVISOR_TIMEOUT 65 // ~100ms
2012-03-18 18:22:05 +01:00
// this is too adjust the RF module so that it is on frequency
# define OSC_LOAD_CAP 0x7F // cap = 12.5pf .. default
# define OSC_LOAD_CAP_1 0x7D // board 1
# define OSC_LOAD_CAP_2 0x7B // board 2
# define OSC_LOAD_CAP_3 0x7E // board 3
# define OSC_LOAD_CAP_4 0x7F // board 4
2012-03-16 03:29:54 +01:00
2012-03-18 18:22:05 +01:00
// ************************************
2012-02-29 05:30:06 +01:00
2012-03-18 18:22:05 +01:00
# define TX_TEST_MODE_TIMELIMIT_MS 30000 // TX test modes time limit (in ms)
2012-02-29 05:30:06 +01:00
2012-03-18 18:22:05 +01:00
//#define TX_PREAMBLE_NIBBLES 8 // 7 to 511 (number of nibbles)
//#define RX_PREAMBLE_NIBBLES 5 // 5 to 31 (number of nibbles)
# define TX_PREAMBLE_NIBBLES 12 // 7 to 511 (number of nibbles)
# define RX_PREAMBLE_NIBBLES 6 // 5 to 31 (number of nibbles)
2012-04-06 05:24:50 +02:00
// the size of the rf modules internal transmit buffers.
# define TX_BUFFER_SIZE 256
// the size of the rf modules internal FIFO buffers
# define FIFO_SIZE 64
2012-03-18 18:22:05 +01:00
# define TX_FIFO_HI_WATERMARK 62 // 0-63
# define TX_FIFO_LO_WATERMARK 32 // 0-63
# define RX_FIFO_HI_WATERMARK 32 // 0-63
# define PREAMBLE_BYTE 0x55 // preamble byte (preceeds SYNC_BYTE's)
# define SYNC_BYTE_1 0x2D // RF sync bytes (32-bit in all)
# define SYNC_BYTE_2 0xD4 //
# define SYNC_BYTE_3 0x4B //
# define SYNC_BYTE_4 0x59 //
// ************************************
// the default TX power level
# define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_0 // +1dBm ... 1.25mW
//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_1 // +2dBm ... 1.6mW
//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_2 // +5dBm ... 3.16mW
//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_3 // +8dBm ... 6.3mW
//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_4 // +11dBm .. 12.6mW
//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_5 // +14dBm .. 25mW
//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_6 // +17dBm .. 50mW
//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_7 // +20dBm .. 100mW
// ************************************
// the default RF datarate
//#define RFM22_DEFAULT_RF_DATARATE 500 // 500 bits per sec
//#define RFM22_DEFAULT_RF_DATARATE 1000 // 1k bits per sec
//#define RFM22_DEFAULT_RF_DATARATE 2000 // 2k bits per sec
//#define RFM22_DEFAULT_RF_DATARATE 4000 // 4k bits per sec
//#define RFM22_DEFAULT_RF_DATARATE 8000 // 8k bits per sec
//#define RFM22_DEFAULT_RF_DATARATE 9600 // 9.6k bits per sec
//#define RFM22_DEFAULT_RF_DATARATE 16000 // 16k bits per sec
//#define RFM22_DEFAULT_RF_DATARATE 19200 // 19k2 bits per sec
//#define RFM22_DEFAULT_RF_DATARATE 24000 // 24k bits per sec
//#define RFM22_DEFAULT_RF_DATARATE 32000 // 32k bits per sec
//#define RFM22_DEFAULT_RF_DATARATE 64000 // 64k bits per sec
# define RFM22_DEFAULT_RF_DATARATE 128000 // 128k bits per sec
//#define RFM22_DEFAULT_RF_DATARATE 192000 // 192k bits per sec
//#define RFM22_DEFAULT_RF_DATARATE 256000 // 256k bits per sec .. NOT YET WORKING
// ************************************
# define RFM22_DEFAULT_SS_RF_DATARATE 125 // 128bps
// ************************************
// Normal data streaming
// GFSK modulation
// no manchester encoding
// data whitening
// FIFO mode
// 5-nibble rx preamble length detection
// 10-nibble tx preamble length
// AFC enabled
/* Local type definitions */
2012-02-29 05:30:06 +01:00
enum pios_rfm22b_dev_magic {
PIOS_RFM22B_DEV_MAGIC = 0x68e971b6 ,
} ;
struct pios_rfm22b_dev {
enum pios_rfm22b_dev_magic magic ;
2012-05-07 05:47:21 +02:00
struct pios_rfm22b_cfg cfg ;
2012-02-29 05:30:06 +01:00
2012-04-11 05:22:53 +02:00
uint32_t deviceID ;
2012-02-29 05:30:06 +01:00
2012-04-11 05:22:53 +02:00
// The COM callback functions.
2012-02-29 05:30:06 +01:00
pios_com_callback rx_in_cb ;
uint32_t rx_in_context ;
pios_com_callback tx_out_cb ;
uint32_t tx_out_context ;
2012-04-22 03:31:49 +02:00
// The supervisor countdown timer.
uint16_t supv_timer ;
uint16_t resets ;
2012-02-29 05:30:06 +01:00
} ;
2012-03-18 18:22:05 +01:00
uint32_t random32 = 0x459ab8d8 ;
/* Local function forwared declarations */
2012-04-22 03:31:49 +02:00
static void PIOS_RFM22B_Supervisor ( uint32_t ppm_id ) ;
static void rfm22_processInt ( void ) ;
static void PIOS_RFM22_EXT_Int ( void ) ;
static void rfm22_setTxMode ( uint8_t mode ) ;
2012-04-06 05:24:50 +02:00
// SPI read/write functions
void rfm22_startBurstWrite ( uint8_t addr ) ;
inline void rfm22_burstWrite ( uint8_t data )
{
PIOS_SPI_TransferByte ( RFM22_PIOS_SPI , data ) ;
}
void rfm22_endBurstWrite ( void ) ;
void rfm22_write ( uint8_t addr , uint8_t data ) ;
void rfm22_startBurstRead ( uint8_t addr ) ;
inline uint8_t rfm22_burstRead ( void )
{
return PIOS_SPI_TransferByte ( RFM22_PIOS_SPI , 0xff ) ;
}
void rfm22_endBurstRead ( void ) ;
uint8_t rfm22_read ( uint8_t addr ) ;
uint8_t rfm22_txStart ( ) ;
2012-03-18 18:22:05 +01:00
/* Provide a COM driver */
static void PIOS_RFM22B_ChangeBaud ( uint32_t rfm22b_id , uint32_t baud ) ;
static void PIOS_RFM22B_RegisterRxCallback ( uint32_t rfm22b_id , pios_com_callback rx_in_cb , uint32_t context ) ;
static void PIOS_RFM22B_RegisterTxCallback ( uint32_t rfm22b_id , pios_com_callback tx_out_cb , uint32_t context ) ;
static void PIOS_RFM22B_TxStart ( uint32_t rfm22b_id , uint16_t tx_bytes_avail ) ;
static void PIOS_RFM22B_RxStart ( uint32_t rfm22b_id , uint16_t rx_bytes_avail ) ;
/* Local variables */
const struct pios_com_driver pios_rfm22b_com_driver = {
. set_baud = PIOS_RFM22B_ChangeBaud ,
. tx_start = PIOS_RFM22B_TxStart ,
. rx_start = PIOS_RFM22B_RxStart ,
. bind_tx_cb = PIOS_RFM22B_RegisterTxCallback ,
. bind_rx_cb = PIOS_RFM22B_RegisterRxCallback ,
} ;
2012-04-06 05:24:50 +02:00
// External interrupt configuration
static const struct pios_exti_cfg pios_exti_rfm22b_cfg __exti_config = {
. vector = PIOS_RFM22_EXT_Int ,
. line = PIOS_RFM22_EXTI_LINE ,
. pin = {
. gpio = PIOS_RFM22_EXTI_GPIO_PORT ,
. init = {
. GPIO_Pin = PIOS_RFM22_EXTI_GPIO_PIN ,
. GPIO_Mode = GPIO_Mode_IN_FLOATING ,
} ,
} ,
. irq = {
. init = {
. NVIC_IRQChannel = PIOS_RFM22_EXTI_IRQn ,
. NVIC_IRQChannelPreemptionPriority = PIOS_RFM22_EXTI_PRIO ,
. NVIC_IRQChannelSubPriority = 0 ,
. NVIC_IRQChannelCmd = ENABLE ,
} ,
} ,
. exti = {
. init = {
. EXTI_Line = PIOS_RFM22_EXTI_LINE ,
. EXTI_Mode = EXTI_Mode_Interrupt ,
. EXTI_Trigger = EXTI_Trigger_Falling ,
. EXTI_LineCmd = ENABLE ,
} ,
} ,
} ;
2012-03-18 18:22:05 +01:00
// xtal 10 ppm, 434MHz
2012-04-06 05:24:50 +02:00
# define LOOKUP_SIZE 14
const uint32_t data_rate [ ] = { 500 , 1000 , 2000 , 4000 , 8000 , 9600 , 16000 , 19200 , 24000 , 32000 , 64000 , 128000 , 192000 , 256000 } ;
const uint8_t modulation_index [ ] = { 16 , 8 , 4 , 2 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 } ;
const uint32_t freq_deviation [ ] = { 4000 , 4000 , 4000 , 4000 , 4000 , 4800 , 8000 , 9600 , 12000 , 16000 , 32000 , 64000 , 96000 , 128000 } ;
const uint32_t rx_bandwidth [ ] = { 17500 , 17500 , 17500 , 17500 , 17500 , 19400 , 32200 , 38600 , 51200 , 64100 , 137900 , 269300 , 420200 , 518800 } ;
const int8_t est_rx_sens_dBm [ ] = { - 118 , - 118 , - 117 , - 116 , - 115 , - 115 , - 112 , - 112 , - 110 , - 109 , - 106 , - 103 , - 101 , - 100 } ; // estimated receiver sensitivity for BER = 1E-3
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
const uint8_t reg_1C [ ] = { 0x37 , 0x37 , 0x37 , 0x37 , 0x3A , 0x3B , 0x26 , 0x28 , 0x2E , 0x16 , 0x07 , 0x83 , 0x8A , 0x8C } ; // rfm22_if_filter_bandwidth
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
const uint8_t reg_1D [ ] = { 0x44 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 , 0x44 } ; // rfm22_afc_loop_gearshift_override
const uint8_t reg_1E [ ] = { 0x0A , 0x0A , 0x0A , 0x0A , 0x0A , 0x0A , 0x0A , 0x0A , 0x0A , 0x0A , 0x0A , 0x0A , 0x0A , 0x02 } ; // rfm22_afc_timing_control
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
const uint8_t reg_1F [ ] = { 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 } ; // rfm22_clk_recovery_gearshift_override
const uint8_t reg_20 [ ] = { 0xE8 , 0xF4 , 0xFA , 0x70 , 0x3F , 0x34 , 0x3F , 0x34 , 0x2A , 0x3F , 0x3F , 0x5E , 0x3F , 0x2F } ; // rfm22_clk_recovery_oversampling_ratio
const uint8_t reg_21 [ ] = { 0x60 , 0x20 , 0x00 , 0x01 , 0x02 , 0x02 , 0x02 , 0x02 , 0x03 , 0x02 , 0x02 , 0x01 , 0x02 , 0x02 } ; // rfm22_clk_recovery_offset2
const uint8_t reg_22 [ ] = { 0x20 , 0x41 , 0x83 , 0x06 , 0x0C , 0x75 , 0x0C , 0x75 , 0x12 , 0x0C , 0x0C , 0x5D , 0x0C , 0xBB } ; // rfm22_clk_recovery_offset1
const uint8_t reg_23 [ ] = { 0xC5 , 0x89 , 0x12 , 0x25 , 0x4A , 0x25 , 0x4A , 0x25 , 0x6F , 0x4A , 0x4A , 0x86 , 0x4A , 0x0D } ; // rfm22_clk_recovery_offset0
const uint8_t reg_24 [ ] = { 0x00 , 0x00 , 0x00 , 0x02 , 0x07 , 0x07 , 0x07 , 0x07 , 0x07 , 0x07 , 0x07 , 0x05 , 0x07 , 0x07 } ; // rfm22_clk_recovery_timing_loop_gain1
const uint8_t reg_25 [ ] = { 0x0A , 0x23 , 0x85 , 0x0E , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0x74 , 0xFF , 0xFF } ; // rfm22_clk_recovery_timing_loop_gain0
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
const uint8_t reg_2A [ ] = { 0x0E , 0x0E , 0x0E , 0x0E , 0x0E , 0x0D , 0x0D , 0x0E , 0x12 , 0x17 , 0x31 , 0x50 , 0x50 , 0x50 } ; // rfm22_afc_limiter .. AFC_pull_in_range = <20> AFCLimiter[7:0] x (hbsel+1) x 625 Hz
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
const uint8_t reg_6E [ ] = { 0x04 , 0x08 , 0x10 , 0x20 , 0x41 , 0x4E , 0x83 , 0x9D , 0xC4 , 0x08 , 0x10 , 0x20 , 0x31 , 0x41 } ; // rfm22_tx_data_rate1
const uint8_t reg_6F [ ] = { 0x19 , 0x31 , 0x62 , 0xC5 , 0x89 , 0xA5 , 0x12 , 0x49 , 0x9C , 0x31 , 0x62 , 0xC5 , 0x27 , 0x89 } ; // rfm22_tx_data_rate0
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
const uint8_t reg_70 [ ] = { 0x2D , 0x2D , 0x2D , 0x2D , 0x2D , 0x2D , 0x2D , 0x2D , 0x2D , 0x0D , 0x0D , 0x0D , 0x0D , 0x0D } ; // rfm22_modulation_mode_control1
const uint8_t reg_71 [ ] = { 0x23 , 0x23 , 0x23 , 0x23 , 0x23 , 0x23 , 0x23 , 0x23 , 0x23 , 0x23 , 0x23 , 0x23 , 0x23 , 0x23 } ; // rfm22_modulation_mode_control2
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
const uint8_t reg_72 [ ] = { 0x06 , 0x06 , 0x06 , 0x06 , 0x06 , 0x08 , 0x0D , 0x0F , 0x13 , 0x1A , 0x33 , 0x66 , 0x9A , 0xCD } ; // rfm22_frequency_deviation
2012-03-18 18:22:05 +01:00
// ************************************
// Scan Spectrum settings
// GFSK modulation
// no manchester encoding
// data whitening
// FIFO mode
// 5-nibble rx preamble length detection
// 10-nibble tx preamble length
# define SS_LOOKUP_SIZE 2
// xtal 1 ppm, 434MHz
2012-04-06 05:24:50 +02:00
const uint32_t ss_rx_bandwidth [ ] = { 2600 , 10600 } ;
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
const uint8_t ss_reg_1C [ ] = { 0x51 , 0x32 } ; // rfm22_if_filter_bandwidth
const uint8_t ss_reg_1D [ ] = { 0x00 , 0x00 } ; // rfm22_afc_loop_gearshift_override
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
const uint8_t ss_reg_20 [ ] = { 0xE8 , 0x38 } ; // rfm22_clk_recovery_oversampling_ratio
const uint8_t ss_reg_21 [ ] = { 0x60 , 0x02 } ; // rfm22_clk_recovery_offset2
const uint8_t ss_reg_22 [ ] = { 0x20 , 0x4D } ; // rfm22_clk_recovery_offset1
const uint8_t ss_reg_23 [ ] = { 0xC5 , 0xD3 } ; // rfm22_clk_recovery_offset0
const uint8_t ss_reg_24 [ ] = { 0x00 , 0x07 } ; // rfm22_clk_recovery_timing_loop_gain1
const uint8_t ss_reg_25 [ ] = { 0x0F , 0xFF } ; // rfm22_clk_recovery_timing_loop_gain0
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
const uint8_t ss_reg_2A [ ] = { 0xFF , 0xFF } ; // rfm22_afc_limiter .. AFC_pull_in_range = <20> AFCLimiter[7:0] x (hbsel+1) x 625 Hz
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
const uint8_t ss_reg_70 [ ] = { 0x24 , 0x2D } ; // rfm22_modulation_mode_control1
const uint8_t ss_reg_71 [ ] = { 0x2B , 0x23 } ; // rfm22_modulation_mode_control2
2012-03-18 18:22:05 +01:00
// ************************************
volatile bool initialized = false ;
# if defined(RFM22_EXT_INT_USE)
volatile bool exec_using_spi ; // set this if you want to access the SPI bus outside of the interrupt
# endif
uint8_t device_type ; // the RF chips device ID number
uint8_t device_version ; // the RF chips revision number
volatile uint8_t rf_mode ; // holds our current RF mode
uint32_t lower_carrier_frequency_limit_Hz ; // the minimum RF frequency we can use
uint32_t upper_carrier_frequency_limit_Hz ; // the maximum RF frequency we can use
uint32_t carrier_frequency_hz ; // the current RF frequency we are on
uint32_t carrier_datarate_bps ; // the RF data rate we are using
uint32_t rf_bandwidth_used ; // the RF bandwidth currently used
uint32_t ss_rf_bandwidth_used ; // the RF bandwidth currently used
uint8_t hbsel ; // holds the hbsel (1 or 2)
float frequency_step_size ; // holds the minimum frequency step size
uint8_t frequency_hop_channel ; // current frequency hop channel
uint8_t frequency_hop_step_size_reg ; //
uint8_t adc_config ; // holds the adc config reg value
volatile uint8_t device_status ; // device status register
volatile uint8_t int_status1 ; // interrupt status register 1
volatile uint8_t int_status2 ; // interrupt status register 2
volatile uint8_t ezmac_status ; // ezmac status register
volatile int16_t afc_correction ; // afc correction reading
volatile int32_t afc_correction_Hz ; // afc correction reading (in Hz)
volatile int16_t temperature_reg ; // the temperature sensor reading
# if defined(RFM22_DEBUG)
volatile uint8_t prev_device_status ; // just for debugging
volatile uint8_t prev_int_status1 ; // " "
volatile uint8_t prev_int_status2 ; // " "
volatile uint8_t prev_ezmac_status ; // " "
2012-06-07 06:14:07 +02:00
const char * debug_msg = " " ;
const char * error_msg = " " ;
2012-04-06 05:24:50 +02:00
static uint32_t debug_val = 0 ;
2012-03-18 18:22:05 +01:00
# endif
volatile uint8_t osc_load_cap ; // xtal frequency calibration value
volatile uint8_t rssi ; // the current RSSI (register value)
2012-04-18 02:36:05 +02:00
volatile int8_t rssi_dBm ; // dBm value
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// the transmit power to use for data transmissions
uint8_t tx_power ;
// the tx power register read back
volatile uint8_t tx_pwr ;
// The transmit buffer. Holds data that is being transmitted.
uint8_t tx_buffer [ TX_BUFFER_SIZE ] __attribute__ ( ( aligned ( 4 ) ) ) ;
// The transmit buffer. Hosts data that is wating to be transmitted.
uint8_t tx_pre_buffer [ TX_BUFFER_SIZE ] __attribute__ ( ( aligned ( 4 ) ) ) ;
// The tx pre-buffer write index.
uint16_t tx_pre_buffer_size ;
// the tx data read index
volatile uint16_t tx_data_rd ;
// the tx data write index
volatile uint16_t tx_data_wr ;
// the current receive buffer in use (double buffer)
volatile uint8_t rx_buffer_current ;
// the receive buffer .. received packet data is saved here
2012-04-18 02:36:05 +02:00
volatile uint8_t rx_buffer [ 258 ] __attribute__ ( ( aligned ( 4 ) ) ) ;
2012-04-06 05:24:50 +02:00
// the receive buffer write index
volatile uint16_t rx_buffer_wr ;
// the received packet
2012-04-18 02:36:05 +02:00
volatile int8_t rx_packet_start_rssi_dBm ; //
volatile int8_t rx_packet_start_afc_Hz ; //
volatile int8_t rx_packet_rssi_dBm ; // the received packet signal strength
volatile int8_t rx_packet_afc_Hz ; // the receive packet frequency offset
2012-03-18 18:22:05 +01:00
int lookup_index ;
int ss_lookup_index ;
volatile bool power_on_reset ; // set if the RF module has reset itself
volatile uint16_t rfm22_int_timer ; // used to detect if the RF module stops responding. thus act accordingly if it does stop responding.
volatile uint16_t rfm22_int_time_outs ; // counter
volatile uint16_t prev_rfm22_int_time_outs ; //
uint16_t timeout_ms = 20000 ; //
uint16_t timeout_sync_ms = 3 ; //
uint16_t timeout_data_ms = 20 ; //
2012-04-06 05:24:50 +02:00
struct pios_rfm22b_dev * rfm22b_dev_g ;
2012-03-18 18:22:05 +01:00
2012-02-29 05:30:06 +01:00
static bool PIOS_RFM22B_validate ( struct pios_rfm22b_dev * rfm22b_dev )
{
return ( rfm22b_dev - > magic = = PIOS_RFM22B_DEV_MAGIC ) ;
}
# if defined(PIOS_INCLUDE_FREERTOS)
static struct pios_rfm22b_dev * PIOS_RFM22B_alloc ( void )
{
struct pios_rfm22b_dev * rfm22b_dev ;
rfm22b_dev = ( struct pios_rfm22b_dev * ) pvPortMalloc ( sizeof ( * rfm22b_dev ) ) ;
if ( ! rfm22b_dev ) return ( NULL ) ;
2012-04-06 05:24:50 +02:00
rfm22b_dev_g = rfm22b_dev ;
2012-02-29 05:30:06 +01:00
rfm22b_dev - > magic = PIOS_RFM22B_DEV_MAGIC ;
return ( rfm22b_dev ) ;
}
# else
static struct pios_rfm22b_dev pios_rfm22b_devs [ PIOS_RFM22B_MAX_DEVS ] ;
static uint8_t pios_rfm22b_num_devs ;
static struct pios_rfm22b_dev * PIOS_RFM22B_alloc ( void )
{
struct pios_rfm22b_dev * rfm22b_dev ;
2012-03-18 18:22:05 +01:00
if ( pios_rfm22b_num_devs > = PIOS_RFM22B_MAX_DEVS )
return NULL ;
2012-02-29 05:30:06 +01:00
rfm22b_dev = & pios_rfm22b_devs [ pios_rfm22b_num_devs + + ] ;
rfm22b_dev - > magic = PIOS_RFM22B_DEV_MAGIC ;
return ( rfm22b_dev ) ;
}
# endif
/**
2012-03-18 18:22:05 +01:00
* Initialise an RFM22B device
*/
2012-02-29 05:30:06 +01:00
int32_t PIOS_RFM22B_Init ( uint32_t * rfm22b_id , const struct pios_rfm22b_cfg * cfg )
{
PIOS_DEBUG_Assert ( rfm22b_id ) ;
PIOS_DEBUG_Assert ( cfg ) ;
2012-03-16 03:29:54 +01:00
// Allocate the device structure.
2012-06-06 06:10:32 +02:00
struct pios_rfm22b_dev * rfm22b_dev = ( struct pios_rfm22b_dev * ) PIOS_RFM22B_alloc ( ) ;
2012-02-29 05:30:06 +01:00
if ( ! rfm22b_dev )
return ( - 1 ) ;
2012-03-16 03:29:54 +01:00
// Bind the configuration to the device instance
2012-05-07 05:47:21 +02:00
rfm22b_dev - > cfg = * cfg ;
2012-02-29 05:30:06 +01:00
* rfm22b_id = ( uint32_t ) rfm22b_dev ;
2012-04-11 05:22:53 +02:00
// Initialize the TX pre-buffer pointer.
2012-04-06 05:24:50 +02:00
tx_pre_buffer_size = 0 ;
2012-04-11 05:22:53 +02:00
// Create our (hopefully) unique 32 bit id from the processor serial number.
uint8_t crcs [ ] = { 0 , 0 , 0 , 0 } ;
{
char serial_no_str [ 33 ] ;
PIOS_SYS_SerialNumberGet ( serial_no_str ) ;
// Create a 32 bit value using 4 8 bit CRC values.
for ( uint8_t i = 0 ; serial_no_str [ i ] ! = 0 ; + + i )
crcs [ i % 4 ] = PIOS_CRC_updateByte ( crcs [ i % 4 ] , serial_no_str [ i ] ) ;
}
rfm22b_dev - > deviceID = crcs [ 0 ] | crcs [ 1 ] < < 8 | crcs [ 2 ] < < 16 | crcs [ 3 ] < < 24 ;
DEBUG_PRINTF ( 2 , " RF device ID: %x \n \r " , rfm22b_dev - > deviceID ) ;
2012-04-22 03:31:49 +02:00
// Initialize the supervisor timer.
rfm22b_dev - > supv_timer = PIOS_RFM22B_SUPERVISOR_TIMEOUT ;
rfm22b_dev - > resets = 0 ;
2012-03-18 18:22:05 +01:00
// Initialize the radio device.
2012-04-18 02:36:05 +02:00
int initval = rfm22_init_normal ( rfm22b_dev - > deviceID , cfg - > minFrequencyHz , cfg - > maxFrequencyHz , 50000 ) ;
2012-03-18 18:22:05 +01:00
if ( initval < 0 )
{
// RF module error .. flash the LED's
# if defined(PIOS_COM_DEBUG)
DEBUG_PRINTF ( 2 , " RF ERROR res: %d \n \r \n \r " , initval ) ;
# endif
for ( unsigned int j = 0 ; j < 16 ; j + + )
{
USB_LED_ON ;
LINK_LED_ON ;
RX_LED_OFF ;
TX_LED_OFF ;
PIOS_DELAY_WaitmS ( 200 ) ;
USB_LED_OFF ;
LINK_LED_OFF ;
RX_LED_ON ;
TX_LED_ON ;
PIOS_DELAY_WaitmS ( 200 ) ;
}
PIOS_DELAY_WaitmS ( 1000 ) ;
return initval ;
}
rfm22_setFreqCalibration ( cfg - > RFXtalCap ) ;
rfm22_setNominalCarrierFrequency ( cfg - > frequencyHz ) ;
rfm22_setDatarate ( cfg - > maxRFBandwidth , TRUE ) ;
rfm22_setTxPower ( cfg - > maxTxPower ) ;
DEBUG_PRINTF ( 2 , " \n \r " ) ;
2012-04-11 05:22:53 +02:00
DEBUG_PRINTF ( 2 , " RF device ID: %x \n \r " , rfm22b_dev - > deviceID ) ;
2012-03-18 18:22:05 +01:00
DEBUG_PRINTF ( 2 , " RF datarate: %dbps \n \r " , rfm22_getDatarate ( ) ) ;
DEBUG_PRINTF ( 2 , " RF frequency: %dHz \n \r " , rfm22_getNominalCarrierFrequency ( ) ) ;
DEBUG_PRINTF ( 2 , " RF TX power: %d \n \r " , rfm22_getTxPower ( ) ) ;
2012-04-22 03:31:49 +02:00
// Setup a real-time clock callback to kickstart the radio if a transfer lock sup.
if ( ! PIOS_RTC_RegisterTickCallback ( PIOS_RFM22B_Supervisor , * rfm22b_id ) ) {
PIOS_DEBUG_Assert ( 0 ) ;
}
2012-02-29 05:30:06 +01:00
return ( 0 ) ;
}
2012-04-11 05:22:53 +02:00
uint32_t PIOS_RFM22B_DeviceID ( uint32_t rfm22b_id )
{
struct pios_rfm22b_dev * rfm22b_dev = ( struct pios_rfm22b_dev * ) rfm22b_id ;
return rfm22b_dev - > deviceID ;
}
2012-04-22 03:31:49 +02:00
int8_t PIOS_RFM22B_RSSI ( uint32_t rfm22b_id )
2012-04-11 05:22:53 +02:00
{
2012-04-18 02:36:05 +02:00
return rfm22_receivedRSSI ( ) ;
2012-04-11 05:22:53 +02:00
}
2012-04-22 03:31:49 +02:00
int16_t PIOS_RFM22B_Resets ( uint32_t rfm22b_id )
{
struct pios_rfm22b_dev * rfm22b_dev = ( struct pios_rfm22b_dev * ) rfm22b_id ;
return rfm22b_dev - > resets ;
}
2012-02-29 05:30:06 +01:00
static void PIOS_RFM22B_RxStart ( uint32_t rfm22b_id , uint16_t rx_bytes_avail )
{
struct pios_rfm22b_dev * rfm22b_dev = ( struct pios_rfm22b_dev * ) rfm22b_id ;
bool valid = PIOS_RFM22B_validate ( rfm22b_dev ) ;
PIOS_Assert ( valid ) ;
}
2012-03-08 02:05:42 +01:00
2012-02-29 05:30:06 +01:00
static void PIOS_RFM22B_TxStart ( uint32_t rfm22b_id , uint16_t tx_bytes_avail )
{
struct pios_rfm22b_dev * rfm22b_dev = ( struct pios_rfm22b_dev * ) rfm22b_id ;
bool valid = PIOS_RFM22B_validate ( rfm22b_dev ) ;
PIOS_Assert ( valid ) ;
2012-04-06 05:24:50 +02:00
// Get some data to send
bool need_yield = false ;
2012-06-06 06:10:32 +02:00
if ( tx_pre_buffer_size = = 0 )
2012-04-06 05:24:50 +02:00
tx_pre_buffer_size = ( rfm22b_dev - > tx_out_cb ) ( rfm22b_dev - > tx_out_context , tx_pre_buffer ,
2012-06-06 06:10:32 +02:00
TX_BUFFER_SIZE , NULL , & need_yield ) ;
2012-04-06 05:24:50 +02:00
if ( tx_pre_buffer_size > 0 )
{
// already have data to be sent
if ( tx_data_wr > 0 )
return ;
// we are currently transmitting or scanning the spectrum
if ( rf_mode = = TX_DATA_MODE | | rf_mode = = TX_STREAM_MODE | | rf_mode = = TX_CARRIER_MODE | |
2012-06-06 06:10:32 +02:00
rf_mode = = TX_PN_MODE | | rf_mode = = RX_SCAN_SPECTRUM )
2012-04-06 05:24:50 +02:00
return ;
// is the channel clear to transmit on?
if ( ! rfm22_channelIsClear ( ) )
return ;
// Start the transmit
rfm22_txStart ( ) ;
}
2012-02-29 05:30:06 +01:00
}
/**
2012-03-18 18:22:05 +01:00
* Changes the baud rate of the RFM22B peripheral without re - initialising .
* \ param [ in ] rfm22b_id RFM22B name ( GPS , TELEM , AUX )
* \ param [ in ] baud Requested baud rate
*/
2012-02-29 05:30:06 +01:00
static void PIOS_RFM22B_ChangeBaud ( uint32_t rfm22b_id , uint32_t baud )
{
struct pios_rfm22b_dev * rfm22b_dev = ( struct pios_rfm22b_dev * ) rfm22b_id ;
bool valid = PIOS_RFM22B_validate ( rfm22b_dev ) ;
PIOS_Assert ( valid ) ;
}
static void PIOS_RFM22B_RegisterRxCallback ( uint32_t rfm22b_id , pios_com_callback rx_in_cb , uint32_t context )
{
struct pios_rfm22b_dev * rfm22b_dev = ( struct pios_rfm22b_dev * ) rfm22b_id ;
bool valid = PIOS_RFM22B_validate ( rfm22b_dev ) ;
PIOS_Assert ( valid ) ;
/*
* Order is important in these assignments since ISR uses _cb
* field to determine if it ' s ok to dereference _cb and _context
*/
rfm22b_dev - > rx_in_context = context ;
rfm22b_dev - > rx_in_cb = rx_in_cb ;
}
static void PIOS_RFM22B_RegisterTxCallback ( uint32_t rfm22b_id , pios_com_callback tx_out_cb , uint32_t context )
{
struct pios_rfm22b_dev * rfm22b_dev = ( struct pios_rfm22b_dev * ) rfm22b_id ;
bool valid = PIOS_RFM22B_validate ( rfm22b_dev ) ;
PIOS_Assert ( valid ) ;
/*
* Order is important in these assignments since ISR uses _cb
* field to determine if it ' s ok to dereference _cb and _context
*/
rfm22b_dev - > tx_out_context = context ;
rfm22b_dev - > tx_out_cb = tx_out_cb ;
}
2012-04-22 03:31:49 +02:00
static void PIOS_RFM22B_Supervisor ( uint32_t rfm22b_id )
{
/* Recover our device context */
struct pios_rfm22b_dev * rfm22b_dev = ( struct pios_rfm22b_dev * ) rfm22b_id ;
if ( ! PIOS_RFM22B_validate ( rfm22b_dev ) ) {
/* Invalid device specified */
return ;
}
2012-06-06 06:10:32 +02:00
/* If we're waiting for a receive, we just need to make sure that there are no packets waiting to be transmitted. */
2012-06-07 02:44:56 +02:00
if ( rf_mode = = RX_WAIT_PREAMBLE_MODE )
2012-06-06 06:10:32 +02:00
{
/* Start a packet transfer if one is available. */
PIOS_RFM22B_TxStart ( rfm22b_id , 0 ) ;
2012-04-22 03:31:49 +02:00
return ;
2012-06-06 06:10:32 +02:00
}
2012-04-22 03:31:49 +02:00
/* The radio must be locked up if the timer reaches 0 */
if ( - - ( rfm22b_dev - > supv_timer ) ! = 0 )
return ;
+ + ( rfm22b_dev - > resets ) ;
2012-06-06 06:10:32 +02:00
TX_LED_OFF ;
TX_LED_OFF ;
/* Clear the TX buffer in case we locked up in a transmit */
tx_data_wr = 0 ;
rfm22_init_normal ( rfm22b_dev - > deviceID , rfm22b_dev - > cfg . minFrequencyHz , rfm22b_dev - > cfg . maxFrequencyHz , 50000 ) ;
2012-04-22 03:31:49 +02:00
/* Start a packet transfer if one is available. */
2012-06-07 02:44:56 +02:00
rf_mode = RX_WAIT_PREAMBLE_MODE ;
2012-06-06 06:10:32 +02:00
PIOS_RFM22B_TxStart ( rfm22b_id , 0 ) ;
2012-06-07 02:44:56 +02:00
if ( rf_mode = = RX_WAIT_PREAMBLE_MODE )
2012-04-22 03:31:49 +02:00
{
2012-06-06 06:10:32 +02:00
/* Switch to RX mode */
2012-04-22 03:31:49 +02:00
rfm22_setRxMode ( RX_WAIT_PREAMBLE_MODE , false ) ;
}
}
static void rfm22_setDebug ( const char * msg )
2012-03-16 03:29:54 +01:00
{
2012-04-06 05:24:50 +02:00
debug_msg = msg ;
2012-03-16 03:29:54 +01:00
}
2012-04-22 03:31:49 +02:00
static void rfm22_setError ( const char * msg )
2012-03-18 18:22:05 +01:00
{
2012-04-06 05:24:50 +02:00
error_msg = msg ;
2012-03-18 18:22:05 +01:00
}
2012-02-29 05:30:06 +01:00
2012-03-18 18:22:05 +01:00
// ************************************
// SPI read/write
void rfm22_startBurstWrite ( uint8_t addr )
{
// wait 1us .. so we don't toggle the CS line to quickly
PIOS_DELAY_WaituS ( 1 ) ;
// chip select line LOW
2012-05-05 18:40:44 +02:00
PIOS_SPI_RC_PinSet ( RFM22_PIOS_SPI , 0 , 0 ) ;
2012-03-18 18:22:05 +01:00
PIOS_SPI_TransferByte ( RFM22_PIOS_SPI , 0x80 | addr ) ;
}
void rfm22_endBurstWrite ( void )
{
// chip select line HIGH
2012-05-05 18:40:44 +02:00
PIOS_SPI_RC_PinSet ( RFM22_PIOS_SPI , 0 , 1 ) ;
2012-03-18 18:22:05 +01:00
}
void rfm22_write ( uint8_t addr , uint8_t data )
{
// wait 1us .. so we don't toggle the CS line to quickly
PIOS_DELAY_WaituS ( 1 ) ;
// chip select line LOW
2012-05-05 18:40:44 +02:00
PIOS_SPI_RC_PinSet ( RFM22_PIOS_SPI , 0 , 0 ) ;
2012-03-18 18:22:05 +01:00
PIOS_SPI_TransferByte ( RFM22_PIOS_SPI , 0x80 | addr ) ;
PIOS_SPI_TransferByte ( RFM22_PIOS_SPI , data ) ;
// chip select line HIGH
2012-05-05 18:40:44 +02:00
PIOS_SPI_RC_PinSet ( RFM22_PIOS_SPI , 0 , 1 ) ;
2012-03-18 18:22:05 +01:00
}
void rfm22_startBurstRead ( uint8_t addr )
{
// wait 1us .. so we don't toggle the CS line to quickly
PIOS_DELAY_WaituS ( 1 ) ;
// chip select line LOW
2012-05-05 18:40:44 +02:00
PIOS_SPI_RC_PinSet ( RFM22_PIOS_SPI , 0 , 0 ) ;
2012-03-18 18:22:05 +01:00
PIOS_SPI_TransferByte ( RFM22_PIOS_SPI , addr & 0x7f ) ;
}
void rfm22_endBurstRead ( void )
{
// chip select line HIGH
2012-05-05 18:40:44 +02:00
PIOS_SPI_RC_PinSet ( RFM22_PIOS_SPI , 0 , 1 ) ;
2012-03-18 18:22:05 +01:00
}
uint8_t rfm22_read ( uint8_t addr )
{
uint8_t rdata ;
// wait 1us .. so we don't toggle the CS line to quickly
PIOS_DELAY_WaituS ( 1 ) ;
// chip select line LOW
2012-05-05 18:40:44 +02:00
PIOS_SPI_RC_PinSet ( RFM22_PIOS_SPI , 0 , 0 ) ;
2012-03-18 18:22:05 +01:00
PIOS_SPI_TransferByte ( RFM22_PIOS_SPI , addr & 0x7f ) ;
rdata = PIOS_SPI_TransferByte ( RFM22_PIOS_SPI , 0xff ) ;
// chip select line HIGH
2012-05-05 18:40:44 +02:00
PIOS_SPI_RC_PinSet ( RFM22_PIOS_SPI , 0 , 1 ) ;
2012-03-18 18:22:05 +01:00
return rdata ;
}
// ************************************
// external interrupt
2012-04-22 03:31:49 +02:00
static void PIOS_RFM22_EXT_Int ( void )
2012-03-18 18:22:05 +01:00
{
2012-04-06 05:24:50 +02:00
rfm22_setDebug ( " Ext Int " ) ;
if ( ! exec_using_spi )
rfm22_processInt ( ) ;
rfm22_setDebug ( " Ext Done " ) ;
2012-03-18 18:22:05 +01:00
}
2012-03-16 03:29:54 +01:00
2012-03-18 18:22:05 +01:00
void rfm22_disableExtInt ( void )
{
2012-04-06 05:24:50 +02:00
# if defined(RFM22_EXT_INT_USE)
rfm22_setDebug ( " Disable Int " ) ;
2012-03-18 18:22:05 +01:00
// Configure the external interrupt
2012-04-06 05:24:50 +02:00
GPIO_EXTILineConfig ( PIOS_RFM22_EXTI_PORT_SOURCE , PIOS_RFM22_EXTI_PIN_SOURCE ) ;
EXTI_InitTypeDef EXTI_InitStructure = pios_exti_rfm22b_cfg . exti . init ;
2012-03-18 18:22:05 +01:00
EXTI_InitStructure . EXTI_LineCmd = DISABLE ;
EXTI_Init ( & EXTI_InitStructure ) ;
2012-04-06 05:24:50 +02:00
EXTI_ClearFlag ( PIOS_RFM22_EXTI_LINE ) ;
rfm22_setDebug ( " Disable Int done " ) ;
# endif
2012-03-18 18:22:05 +01:00
}
void rfm22_enableExtInt ( void )
{
2012-04-06 05:24:50 +02:00
# if defined(RFM22_EXT_INT_USE)
rfm22_setDebug ( " Ensable Int " ) ;
if ( PIOS_EXTI_Init ( & pios_exti_rfm22b_cfg ) )
PIOS_Assert ( 0 ) ;
rfm22_setDebug ( " Ensable Int done " ) ;
# endif
2012-03-18 18:22:05 +01:00
}
// ************************************
// set/get the current tx power setting
2012-03-16 03:29:54 +01:00
2012-03-18 18:22:05 +01:00
void rfm22_setTxPower ( uint8_t tx_pwr )
{
switch ( tx_pwr )
{
case 0 : tx_power = RFM22_tx_pwr_txpow_0 ; break ; // +1dBm ... 1.25mW
case 1 : tx_power = RFM22_tx_pwr_txpow_1 ; break ; // +2dBm ... 1.6mW
case 2 : tx_power = RFM22_tx_pwr_txpow_2 ; break ; // +5dBm ... 3.16mW
case 3 : tx_power = RFM22_tx_pwr_txpow_3 ; break ; // +8dBm ... 6.3mW
case 4 : tx_power = RFM22_tx_pwr_txpow_4 ; break ; // +11dBm .. 12.6mW
case 5 : tx_power = RFM22_tx_pwr_txpow_5 ; break ; // +14dBm .. 25mW
case 6 : tx_power = RFM22_tx_pwr_txpow_6 ; break ; // +17dBm .. 50mW
case 7 : tx_power = RFM22_tx_pwr_txpow_7 ; break ; // +20dBm .. 100mW
default : break ;
2012-03-16 03:29:54 +01:00
}
2012-03-18 18:22:05 +01:00
}
uint8_t rfm22_getTxPower ( void )
{
return tx_power ;
}
// ************************************
2012-03-16 03:29:54 +01:00
2012-03-18 18:22:05 +01:00
uint32_t rfm22_minFrequency ( void )
{
return lower_carrier_frequency_limit_Hz ;
}
uint32_t rfm22_maxFrequency ( void )
{
return upper_carrier_frequency_limit_Hz ;
2012-02-29 05:30:06 +01:00
}
2012-03-18 18:22:05 +01:00
void rfm22_setNominalCarrierFrequency ( uint32_t frequency_hz )
{
exec_using_spi = TRUE ;
2012-02-29 05:30:06 +01:00
2012-03-18 18:22:05 +01:00
// *******
2012-06-06 06:10:32 +02:00
if ( frequency_hz < lower_carrier_frequency_limit_Hz )
frequency_hz = lower_carrier_frequency_limit_Hz ;
else if ( frequency_hz > upper_carrier_frequency_limit_Hz )
frequency_hz = upper_carrier_frequency_limit_Hz ;
2012-03-18 18:22:05 +01:00
if ( frequency_hz < 480000000 )
hbsel = 1 ;
else
hbsel = 2 ;
uint8_t fb = ( uint8_t ) ( frequency_hz / ( 10000000 * hbsel ) ) ;
uint32_t fc = ( uint32_t ) ( frequency_hz - ( 10000000 * hbsel * fb ) ) ;
fc = ( fc * 64u ) / ( 10000ul * hbsel ) ;
fb - = 24 ;
// carrier_frequency_hz = frequency_hz;
carrier_frequency_hz = ( ( uint32_t ) fb + 24 + ( ( float ) fc / 64000 ) ) * 10000000 * hbsel ;
if ( hbsel > 1 )
fb | = RFM22_fbs_hbsel ;
fb | = RFM22_fbs_sbse ; // is this the RX LO polarity?
frequency_step_size = 156.25f * hbsel ;
rfm22_write ( RFM22_frequency_hopping_channel_select , frequency_hop_channel ) ; // frequency hopping channel (0-255)
rfm22_write ( RFM22_frequency_offset1 , 0 ) ; // no frequency offset
rfm22_write ( RFM22_frequency_offset2 , 0 ) ; // no frequency offset
rfm22_write ( RFM22_frequency_band_select , fb ) ; // set the carrier frequency
rfm22_write ( RFM22_nominal_carrier_frequency1 , fc > > 8 ) ; // " "
rfm22_write ( RFM22_nominal_carrier_frequency0 , fc & 0xff ) ; // " "
// *******
# if defined(RFM22_DEBUG)
2012-05-07 05:47:21 +02:00
//DEBUG_PRINTF(2, "rf setFreq: %u\n\r", carrier_frequency_hz);
2012-03-18 18:22:05 +01:00
// DEBUG_PRINTF(2, "rf setFreq frequency_step_size: %0.2f\n\r", frequency_step_size);
# endif
exec_using_spi = FALSE ;
}
uint32_t rfm22_getNominalCarrierFrequency ( void )
{
return carrier_frequency_hz ;
}
float rfm22_getFrequencyStepSize ( void )
{
return frequency_step_size ;
}
void rfm22_setFreqHopChannel ( uint8_t channel )
{ // set the frequency hopping channel
frequency_hop_channel = channel ;
rfm22_write ( RFM22_frequency_hopping_channel_select , frequency_hop_channel ) ;
}
uint8_t rfm22_freqHopChannel ( void )
{ // return the current frequency hopping channel
return frequency_hop_channel ;
}
uint32_t rfm22_freqHopSize ( void )
{ // return the frequency hopping step size
return ( ( uint32_t ) frequency_hop_step_size_reg * 10000 ) ;
}
// ************************************
// radio datarate about 19200 Baud
// radio frequency deviation 45kHz
// radio receiver bandwidth 67kHz.
//
// Carson's rule:
// The signal bandwidth is about 2(Delta-f + fm) ..
//
// Delta-f = frequency deviation
// fm = maximum frequency of the signal
//
// This gives 2(45 + 9.6) = 109.2kHz.
void rfm22_setDatarate ( uint32_t datarate_bps , bool data_whitening )
{
exec_using_spi = TRUE ;
lookup_index = 0 ;
while ( lookup_index < ( LOOKUP_SIZE - 1 ) & & data_rate [ lookup_index ] < datarate_bps )
lookup_index + + ;
carrier_datarate_bps = datarate_bps = data_rate [ lookup_index ] ;
rf_bandwidth_used = rx_bandwidth [ lookup_index ] ;
2012-04-07 02:36:35 +02:00
// rfm22_if_filter_bandwidth
rfm22_write ( 0x1C , reg_1C [ lookup_index ] ) ;
// rfm22_afc_loop_gearshift_override
rfm22_write ( 0x1D , reg_1D [ lookup_index ] ) ;
// RFM22_afc_timing_control
rfm22_write ( 0x1E , reg_1E [ lookup_index ] ) ;
// RFM22_clk_recovery_gearshift_override
rfm22_write ( 0x1F , reg_1F [ lookup_index ] ) ;
// rfm22_clk_recovery_oversampling_ratio
rfm22_write ( 0x20 , reg_20 [ lookup_index ] ) ;
// rfm22_clk_recovery_offset2
rfm22_write ( 0x21 , reg_21 [ lookup_index ] ) ;
// rfm22_clk_recovery_offset1
rfm22_write ( 0x22 , reg_22 [ lookup_index ] ) ;
// rfm22_clk_recovery_offset0
rfm22_write ( 0x23 , reg_23 [ lookup_index ] ) ;
// rfm22_clk_recovery_timing_loop_gain1
rfm22_write ( 0x24 , reg_24 [ lookup_index ] ) ;
// rfm22_clk_recovery_timing_loop_gain0
rfm22_write ( 0x25 , reg_25 [ lookup_index ] ) ;
// rfm22_afc_limiter
rfm22_write ( 0x2A , reg_2A [ lookup_index ] ) ;
2012-03-18 18:22:05 +01:00
if ( carrier_datarate_bps < 100000 )
2012-04-07 02:36:35 +02:00
// rfm22_chargepump_current_trimming_override
rfm22_write ( 0x58 , 0x80 ) ;
2012-03-18 18:22:05 +01:00
else
2012-04-07 02:36:35 +02:00
// rfm22_chargepump_current_trimming_override
rfm22_write ( 0x58 , 0xC0 ) ;
2012-03-18 18:22:05 +01:00
2012-04-07 02:36:35 +02:00
// rfm22_tx_data_rate1
rfm22_write ( 0x6E , reg_6E [ lookup_index ] ) ;
// rfm22_tx_data_rate0
rfm22_write ( 0x6F , reg_6F [ lookup_index ] ) ;
2012-03-18 18:22:05 +01:00
// Enable data whitening
// uint8_t txdtrtscale_bit = rfm22_read(RFM22_modulation_mode_control1) & RFM22_mmc1_txdtrtscale;
// rfm22_write(RFM22_modulation_mode_control1, txdtrtscale_bit | RFM22_mmc1_enwhite);
if ( ! data_whitening )
2012-04-07 02:36:35 +02:00
// rfm22_modulation_mode_control1
rfm22_write ( 0x70 , reg_70 [ lookup_index ] & ~ RFM22_mmc1_enwhite ) ;
2012-03-18 18:22:05 +01:00
else
2012-04-07 02:36:35 +02:00
// rfm22_modulation_mode_control1
rfm22_write ( 0x70 , reg_70 [ lookup_index ] | RFM22_mmc1_enwhite ) ;
2012-03-18 18:22:05 +01:00
2012-04-07 02:36:35 +02:00
// rfm22_modulation_mode_control2
rfm22_write ( 0x71 , reg_71 [ lookup_index ] ) ;
2012-03-18 18:22:05 +01:00
2012-04-07 02:36:35 +02:00
// rfm22_frequency_deviation
rfm22_write ( 0x72 , reg_72 [ lookup_index ] ) ;
2012-03-18 18:22:05 +01:00
rfm22_write ( RFM22_ook_counter_value1 , 0x00 ) ;
rfm22_write ( RFM22_ook_counter_value2 , 0x00 ) ;
// ********************************
// calculate the TX register values
/*
uint16_t fd = frequency_deviation / 625 ;
uint8_t mmc1 = RFM22_mmc1_enphpwdn | RFM22_mmc1_manppol ;
uint16_t txdr ;
if ( datarate_bps < 30000 )
{
txdr = ( datarate_bps * 20972 ) / 10000 ;
mmc1 | = RFM22_mmc1_txdtrtscale ;
}
else
txdr = ( datarate_bps * 6553 ) / 100000 ;
uint8_t mmc2 = RFM22_mmc2_dtmod_fifo | RFM22_mmc2_modtyp_gfsk ; // FIFO mode, GFSK
// uint8_t mmc2 = RFM22_mmc2_dtmod_pn9 | RFM22_mmc2_modtyp_gfsk; // PN9 mode, GFSK .. TX TEST MODE
if ( fd & 0x100 ) mmc2 | = RFM22_mmc2_fd ;
rfm22_write ( RFM22_frequency_deviation , fd ) ; // set the TX peak frequency deviation
rfm22_write ( RFM22_modulation_mode_control1 , mmc1 ) ;
rfm22_write ( RFM22_modulation_mode_control2 , mmc2 ) ;
rfm22_write ( RFM22_tx_data_rate1 , txdr > > 8 ) ; // set the TX data rate
rfm22_write ( RFM22_tx_data_rate0 , txdr ) ; // " "
*/
// ********************************
// determine a clear channel time
// initialise the stopwatch with a suitable resolution for the datarate
//STOPWATCH_init(4000000ul / carrier_datarate_bps); // set resolution to the time for 1 nibble (4-bits) at rf datarate
// ********************************
// determine suitable time-out periods
2012-04-07 02:36:35 +02:00
// milliseconds
timeout_sync_ms = ( 8000ul * 16 ) / carrier_datarate_bps ;
2012-03-18 18:22:05 +01:00
if ( timeout_sync_ms < 3 )
2012-04-07 02:36:35 +02:00
// because out timer resolution is only 1ms
timeout_sync_ms = 3 ;
2012-03-18 18:22:05 +01:00
2012-04-07 02:36:35 +02:00
// milliseconds
timeout_data_ms = ( 8000ul * 100 ) / carrier_datarate_bps ;
2012-03-18 18:22:05 +01:00
if ( timeout_data_ms < 3 )
2012-04-07 02:36:35 +02:00
// because out timer resolution is only 1ms
timeout_data_ms = 3 ;
2012-03-18 18:22:05 +01:00
// ********************************
# if defined(RFM22_DEBUG)
2012-05-07 05:47:21 +02:00
/*
2012-03-18 18:22:05 +01:00
DEBUG_PRINTF ( 2 , " rf datarate_bps: %d \n \r " , datarate_bps ) ;
DEBUG_PRINTF ( 2 , " rf frequency_deviation: %d \n \r " , frequency_deviation ) ;
2012-05-07 05:47:21 +02:00
uint32_t frequency_deviation = freq_deviation [ lookup_index ] ; // Hz
uint32_t modulation_bandwidth = datarate_bps + ( 2 * frequency_deviation ) ;
2012-03-18 18:22:05 +01:00
DEBUG_PRINTF ( 2 , " rf modulation_bandwidth: %u \n \r " , modulation_bandwidth ) ;
DEBUG_PRINTF ( 2 , " rf_rx_bandwidth[%u]: %u \n \r " , lookup_index , rx_bandwidth [ lookup_index ] ) ;
DEBUG_PRINTF ( 2 , " rf est rx sensitivity[%u]: %ddBm \n \r " , lookup_index , est_rx_sens_dBm [ lookup_index ] ) ;
2012-05-07 05:47:21 +02:00
*/
2012-03-18 18:22:05 +01:00
# endif
// *******
exec_using_spi = FALSE ;
}
uint32_t rfm22_getDatarate ( void )
{
return carrier_datarate_bps ;
}
// ************************************
void rfm22_setSSBandwidth ( uint32_t bandwidth_index )
{
exec_using_spi = TRUE ;
ss_lookup_index = bandwidth_index ;
ss_rf_bandwidth_used = ss_rx_bandwidth [ lookup_index ] ;
// ********************************
rfm22_write ( 0x1C , ss_reg_1C [ ss_lookup_index ] ) ; // rfm22_if_filter_bandwidth
rfm22_write ( 0x1D , ss_reg_1D [ ss_lookup_index ] ) ; // rfm22_afc_loop_gearshift_override
rfm22_write ( 0x20 , ss_reg_20 [ ss_lookup_index ] ) ; // rfm22_clk_recovery_oversampling_ratio
rfm22_write ( 0x21 , ss_reg_21 [ ss_lookup_index ] ) ; // rfm22_clk_recovery_offset2
rfm22_write ( 0x22 , ss_reg_22 [ ss_lookup_index ] ) ; // rfm22_clk_recovery_offset1
rfm22_write ( 0x23 , ss_reg_23 [ ss_lookup_index ] ) ; // rfm22_clk_recovery_offset0
rfm22_write ( 0x24 , ss_reg_24 [ ss_lookup_index ] ) ; // rfm22_clk_recovery_timing_loop_gain1
rfm22_write ( 0x25 , ss_reg_25 [ ss_lookup_index ] ) ; // rfm22_clk_recovery_timing_loop_gain0
rfm22_write ( 0x2A , ss_reg_2A [ ss_lookup_index ] ) ; // rfm22_afc_limiter
rfm22_write ( 0x58 , 0x80 ) ; // rfm22_chargepump_current_trimming_override
rfm22_write ( 0x70 , ss_reg_70 [ ss_lookup_index ] ) ; // rfm22_modulation_mode_control1
rfm22_write ( 0x71 , ss_reg_71 [ ss_lookup_index ] ) ; // rfm22_modulation_mode_control2
rfm22_write ( RFM22_ook_counter_value1 , 0x00 ) ;
rfm22_write ( RFM22_ook_counter_value2 , 0x00 ) ;
// ********************************
# if defined(RFM22_DEBUG)
DEBUG_PRINTF ( 2 , " ss_rf_rx_bandwidth[%u]: %u \n \r " , ss_lookup_index , ss_rx_bandwidth [ ss_lookup_index ] ) ;
# endif
// *******
exec_using_spi = FALSE ;
}
// ************************************
void rfm22_setRxMode ( uint8_t mode , bool multi_packet_mode )
{
exec_using_spi = TRUE ;
// disable interrupts
rfm22_write ( RFM22_interrupt_enable1 , 0x00 ) ;
rfm22_write ( RFM22_interrupt_enable2 , 0x00 ) ;
2012-04-06 05:24:50 +02:00
// Switch to TUNE mode
rfm22_write ( RFM22_op_and_func_ctrl1 , RFM22_opfc1_pllon ) ;
2012-03-18 18:22:05 +01:00
RX_LED_OFF ;
TX_LED_OFF ;
if ( rf_mode = = TX_CARRIER_MODE | | rf_mode = = TX_PN_MODE )
{
// FIFO mode, GFSK modulation
uint8_t fd_bit = rfm22_read ( RFM22_modulation_mode_control2 ) & RFM22_mmc2_fd ;
2012-04-06 05:24:50 +02:00
rfm22_write ( RFM22_modulation_mode_control2 , fd_bit | RFM22_mmc2_dtmod_fifo |
2012-06-07 02:44:56 +02:00
RFM22_mmc2_modtyp_gfsk ) ;
2012-03-18 18:22:05 +01:00
}
2012-04-06 05:24:50 +02:00
// empty the rx buffer
rx_buffer_wr = 0 ;
// reset the timer
rfm22_int_timer = 0 ;
2012-03-18 18:22:05 +01:00
rf_mode = mode ;
2012-04-06 05:24:50 +02:00
// Clear the TX buffer.
tx_data_rd = tx_data_wr = 0 ;
2012-03-18 18:22:05 +01:00
// clear FIFOs
if ( ! multi_packet_mode )
{
rfm22_write ( RFM22_op_and_func_ctrl2 , RFM22_opfc2_ffclrrx | RFM22_opfc2_ffclrtx ) ;
rfm22_write ( RFM22_op_and_func_ctrl2 , 0x00 ) ;
} else {
2012-04-06 05:24:50 +02:00
rfm22_write ( RFM22_op_and_func_ctrl2 , RFM22_opfc2_rxmpk | RFM22_opfc2_ffclrrx |
RFM22_opfc2_ffclrtx ) ;
2012-03-18 18:22:05 +01:00
rfm22_write ( RFM22_op_and_func_ctrl2 , RFM22_opfc2_rxmpk ) ;
}
2012-04-06 05:24:50 +02:00
// enable RX interrupts
rfm22_write ( RFM22_interrupt_enable1 , RFM22_ie1_encrcerror | RFM22_ie1_enpkvalid |
2012-06-07 02:44:56 +02:00
RFM22_ie1_enrxffafull | RFM22_ie1_enfferr ) ;
2012-04-06 05:24:50 +02:00
rfm22_write ( RFM22_interrupt_enable2 , RFM22_ie2_enpreainval | RFM22_ie2_enpreaval |
2012-06-07 02:44:56 +02:00
RFM22_ie2_enswdet ) ;
2012-04-06 05:24:50 +02:00
2012-03-18 18:22:05 +01:00
// enable the receiver
rfm22_write ( RFM22_op_and_func_ctrl1 , RFM22_opfc1_pllon | RFM22_opfc1_rxon ) ;
exec_using_spi = FALSE ;
}
// ************************************
uint16_t rfm22_addHeader ( )
{
uint16_t i = 0 ;
for ( uint16_t j = ( TX_PREAMBLE_NIBBLES + 1 ) / 2 ; j > 0 ; j - - )
{
rfm22_burstWrite ( PREAMBLE_BYTE ) ;
i + + ;
}
rfm22_burstWrite ( SYNC_BYTE_1 ) ; i + + ;
rfm22_burstWrite ( SYNC_BYTE_2 ) ; i + + ;
return i ;
}
// ************************************
2012-04-06 05:24:50 +02:00
uint8_t rfm22_txStart ( )
{
if ( ( tx_pre_buffer_size = = 0 ) | | ( exec_using_spi = = TRUE ) )
{
// Clear the TX buffer.
tx_data_rd = tx_data_wr = 0 ;
return 0 ;
}
exec_using_spi = TRUE ;
// Disable interrrupts.
PIOS_IRQ_Disable ( ) ;
2012-04-22 03:31:49 +02:00
// Initialize the supervisor timer.
2012-06-06 06:10:32 +02:00
rfm22b_dev_g - > supv_timer = PIOS_RFM22B_SUPERVISOR_TIMEOUT ;
2012-04-22 03:31:49 +02:00
2012-04-06 05:24:50 +02:00
// disable interrupts
rfm22_write ( RFM22_interrupt_enable1 , 0x00 ) ;
rfm22_write ( RFM22_interrupt_enable2 , 0x00 ) ;
// TUNE mode
rfm22_write ( RFM22_op_and_func_ctrl1 , RFM22_opfc1_pllon ) ;
// Queue the data up for sending
memcpy ( tx_buffer , tx_pre_buffer , tx_pre_buffer_size ) ;
tx_data_rd = 0 ;
tx_data_wr = tx_pre_buffer_size ;
tx_pre_buffer_size = 0 ;
RX_LED_OFF ;
2012-04-18 02:36:05 +02:00
// Set the destination address in the transmit header.
// The destination address is the first 4 bytes of the message.
rfm22_write ( RFM22_transmit_header0 , tx_buffer [ 0 ] ) ;
rfm22_write ( RFM22_transmit_header1 , tx_buffer [ 1 ] ) ;
rfm22_write ( RFM22_transmit_header2 , tx_buffer [ 2 ] ) ;
rfm22_write ( RFM22_transmit_header3 , tx_buffer [ 3 ] ) ;
2012-04-06 05:24:50 +02:00
// FIFO mode, GFSK modulation
uint8_t fd_bit = rfm22_read ( RFM22_modulation_mode_control2 ) & RFM22_mmc2_fd ;
rfm22_write ( RFM22_modulation_mode_control2 , fd_bit | RFM22_mmc2_dtmod_fifo |
2012-06-07 02:44:56 +02:00
RFM22_mmc2_modtyp_gfsk ) ;
2012-04-06 05:24:50 +02:00
// set the tx power
rfm22_write ( RFM22_tx_power , RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_1 |
2012-06-07 02:44:56 +02:00
RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | tx_power ) ;
2012-04-06 05:24:50 +02:00
// clear FIFOs
rfm22_write ( RFM22_op_and_func_ctrl2 , RFM22_opfc2_ffclrrx | RFM22_opfc2_ffclrtx ) ;
rfm22_write ( RFM22_op_and_func_ctrl2 , 0x00 ) ;
// *******************
// add some data to the chips TX FIFO before enabling the transmitter
// set the total number of data bytes we are going to transmit
rfm22_write ( RFM22_transmit_packet_length , tx_data_wr ) ;
// add some data
rfm22_startBurstWrite ( RFM22_fifo_access ) ;
for ( uint16_t i = 0 ; ( tx_data_rd < tx_data_wr ) & & ( i < FIFO_SIZE ) ; + + tx_data_rd , + + i )
rfm22_burstWrite ( tx_buffer [ tx_data_rd ] ) ;
rfm22_endBurstWrite ( ) ;
// *******************
// reset the timer
rfm22_int_timer = 0 ;
rf_mode = TX_DATA_MODE ;
// enable TX interrupts
rfm22_write ( RFM22_interrupt_enable1 , RFM22_ie1_enpksent | RFM22_ie1_entxffaem ) ;
// enable the transmitter
rfm22_write ( RFM22_op_and_func_ctrl1 , RFM22_opfc1_pllon | RFM22_opfc1_txon ) ;
// Re-ensable interrrupts.
PIOS_IRQ_Enable ( ) ;
TX_LED_ON ;
exec_using_spi = FALSE ;
return 1 ;
}
2012-04-22 03:31:49 +02:00
static void rfm22_setTxMode ( uint8_t mode )
2012-03-18 18:22:05 +01:00
{
2012-04-06 05:24:50 +02:00
rfm22_setDebug ( " setTxMode " ) ;
2012-03-18 18:22:05 +01:00
if ( mode ! = TX_DATA_MODE & & mode ! = TX_STREAM_MODE & & mode ! = TX_CARRIER_MODE & & mode ! = TX_PN_MODE )
return ; // invalid mode
exec_using_spi = TRUE ;
// disable interrupts
rfm22_write ( RFM22_interrupt_enable1 , 0x00 ) ;
rfm22_write ( RFM22_interrupt_enable2 , 0x00 ) ;
2012-06-07 02:44:56 +02:00
// TUNE mode
rfm22_write ( RFM22_op_and_func_ctrl1 , RFM22_opfc1_pllon ) ;
2012-03-18 18:22:05 +01:00
RX_LED_OFF ;
// set the tx power
2012-04-06 05:24:50 +02:00
rfm22_write ( RFM22_tx_power , RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_1 |
2012-06-07 02:44:56 +02:00
RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | tx_power ) ;
2012-03-18 18:22:05 +01:00
uint8_t fd_bit = rfm22_read ( RFM22_modulation_mode_control2 ) & RFM22_mmc2_fd ;
if ( mode = = TX_CARRIER_MODE )
// blank carrier mode - for testing
2012-04-06 05:24:50 +02:00
rfm22_write ( RFM22_modulation_mode_control2 , fd_bit | RFM22_mmc2_dtmod_pn9 |
RFM22_mmc2_modtyp_none ) ; // FIFO mode, Blank carrier
2012-03-18 18:22:05 +01:00
else if ( mode = = TX_PN_MODE )
// psuedo random data carrier mode - for testing
2012-04-06 05:24:50 +02:00
rfm22_write ( RFM22_modulation_mode_control2 , fd_bit | RFM22_mmc2_dtmod_pn9 |
RFM22_mmc2_modtyp_gfsk ) ; // FIFO mode, PN9 carrier
2012-03-18 18:22:05 +01:00
else
// data transmission
2012-04-06 05:24:50 +02:00
// FIFO mode, GFSK modulation
rfm22_write ( RFM22_modulation_mode_control2 , fd_bit | RFM22_mmc2_dtmod_fifo |
RFM22_mmc2_modtyp_gfsk ) ;
2012-03-18 18:22:05 +01:00
// clear FIFOs
rfm22_write ( RFM22_op_and_func_ctrl2 , RFM22_opfc2_ffclrrx | RFM22_opfc2_ffclrtx ) ;
rfm22_write ( RFM22_op_and_func_ctrl2 , 0x00 ) ;
// add some data to the chips TX FIFO before enabling the transmitter
{
uint16_t rd = 0 ;
uint16_t wr = tx_data_wr ;
if ( mode = = TX_DATA_MODE )
2012-04-06 05:24:50 +02:00
// set the total number of data bytes we are going to transmit
rfm22_write ( RFM22_transmit_packet_length , wr ) ;
2012-03-18 18:22:05 +01:00
uint16_t max_bytes = FIFO_SIZE - 1 ;
uint16_t i = 0 ;
rfm22_startBurstWrite ( RFM22_fifo_access ) ;
if ( mode = = TX_STREAM_MODE ) {
if ( rd > = wr ) {
// no data to send - yet .. just send preamble pattern
while ( true ) {
rfm22_burstWrite ( PREAMBLE_BYTE ) ;
if ( + + i > = max_bytes ) break ;
}
} else // add the RF heaader
i + = rfm22_addHeader ( ) ;
}
// add some data
for ( uint16_t j = wr - rd ; j > 0 ; j - - ) {
2012-04-06 05:24:50 +02:00
rfm22_burstWrite ( tx_buffer [ rd + + ] ) ;
2012-03-18 18:22:05 +01:00
if ( + + i > = max_bytes )
break ;
}
rfm22_endBurstWrite ( ) ;
tx_data_rd = rd ;
}
2012-04-06 05:24:50 +02:00
// reset the timer
rfm22_int_timer = 0 ;
2012-03-18 18:22:05 +01:00
rf_mode = mode ;
// enable TX interrupts
// rfm22_write(RFM22_interrupt_enable1, RFM22_ie1_enpksent | RFM22_ie1_entxffaem | RFM22_ie1_enfferr);
rfm22_write ( RFM22_interrupt_enable1 , RFM22_ie1_enpksent | RFM22_ie1_entxffaem ) ;
// read interrupt status - clear interrupts
rfm22_read ( RFM22_interrupt_status1 ) ;
rfm22_read ( RFM22_interrupt_status2 ) ;
// enable the transmitter
// rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton | RFM22_opfc1_txon);
rfm22_write ( RFM22_op_and_func_ctrl1 , RFM22_opfc1_pllon | RFM22_opfc1_txon ) ;
TX_LED_ON ;
// *******************
exec_using_spi = FALSE ;
2012-04-06 05:24:50 +02:00
rfm22_setDebug ( " setTxMode end " ) ;
2012-03-18 18:22:05 +01:00
}
// ************************************
// external interrupt line triggered (or polled) from the rf chip
void rfm22_processRxInt ( void )
{
register uint8_t int_stat1 = int_status1 ;
register uint8_t int_stat2 = int_status2 ;
2012-04-06 05:24:50 +02:00
rfm22_setDebug ( " processRxInt " ) ;
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// FIFO under/over flow error. Restart RX mode.
if ( device_status & ( RFM22_ds_ffunfl | RFM22_ds_ffovfl ) )
{
rfm22_setError ( " R_UNDER/OVERRUN " ) ;
rfm22_setRxMode ( RX_WAIT_PREAMBLE_MODE , false ) ;
return ;
}
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// Valid preamble detected
2012-06-07 02:44:56 +02:00
if ( int_stat2 & RFM22_is2_ipreaval & & ( rf_mode = = RX_WAIT_PREAMBLE_MODE ) )
2012-04-06 05:24:50 +02:00
{
2012-06-07 02:44:56 +02:00
rf_mode = RX_WAIT_SYNC_MODE ;
RX_LED_ON ;
rfm22_setDebug ( " pream_det " ) ;
2012-04-06 05:24:50 +02:00
}
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// Sync word detected
2012-06-07 02:44:56 +02:00
if ( int_stat2 & RFM22_is2_iswdet & & ( ( rf_mode = = RX_WAIT_PREAMBLE_MODE | | rf_mode = = RX_WAIT_SYNC_MODE ) ) )
2012-04-06 05:24:50 +02:00
{
2012-06-07 02:44:56 +02:00
rf_mode = RX_DATA_MODE ;
RX_LED_ON ;
rfm22_setDebug ( " sync_det " ) ;
// read the 10-bit signed afc correction value
// bits 9 to 2
afc_correction = ( uint16_t ) rfm22_read ( RFM22_afc_correction_read ) < < 8 ;
// bits 1 & 0
afc_correction | = ( uint16_t ) rfm22_read ( RFM22_ook_counter_value1 ) & 0x00c0 ;
afc_correction > > = 6 ;
// convert the afc value to Hz
afc_correction_Hz = ( int32_t ) ( frequency_step_size * afc_correction + 0.5f ) ;
// remember the rssi for this packet
rx_packet_start_rssi_dBm = rssi_dBm ;
// remember the afc value for this packet
rx_packet_start_afc_Hz = afc_correction_Hz ;
2012-03-18 18:22:05 +01:00
}
2012-04-06 05:24:50 +02:00
// RX FIFO almost full, it needs emptying
2012-03-18 18:22:05 +01:00
if ( int_stat1 & RFM22_is1_irxffafull )
2012-04-06 05:24:50 +02:00
{
2012-03-18 18:22:05 +01:00
if ( rf_mode = = RX_DATA_MODE )
2012-04-06 05:24:50 +02:00
{
// read data from the rf chips FIFO buffer
// read the total length of the packet data
uint16_t len = rfm22_read ( RFM22_received_packet_length ) ;
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// The received packet is going to be larger than the specified length
if ( ( rx_buffer_wr + RX_FIFO_HI_WATERMARK ) > len )
{
rfm22_setError ( " r_size_error1 " ) ;
2012-03-18 18:22:05 +01:00
rfm22_setRxMode ( RX_WAIT_PREAMBLE_MODE , false ) ;
return ;
}
2012-04-06 05:24:50 +02:00
// Another packet length error.
if ( ( ( rx_buffer_wr + RX_FIFO_HI_WATERMARK ) > = len ) & & ! ( int_stat1 & RFM22_is1_ipkvalid ) )
{
rfm22_setError ( " r_size_error2 " ) ;
2012-03-18 18:22:05 +01:00
rfm22_setRxMode ( RX_WAIT_PREAMBLE_MODE , false ) ;
return ;
}
2012-04-06 05:24:50 +02:00
// Fetch the data from the RX FIFO
2012-03-18 18:22:05 +01:00
rfm22_startBurstRead ( RFM22_fifo_access ) ;
2012-04-06 05:24:50 +02:00
for ( uint8_t i = 0 ; i < RX_FIFO_HI_WATERMARK ; + + i )
rx_buffer [ rx_buffer_wr + + ] = rfm22_burstRead ( ) ;
2012-03-18 18:22:05 +01:00
rfm22_endBurstRead ( ) ;
}
else
{ // just clear the RX FIFO
rfm22_startBurstRead ( RFM22_fifo_access ) ;
for ( register uint16_t i = RX_FIFO_HI_WATERMARK ; i > 0 ; i - - )
rfm22_burstRead ( ) ; // read a byte from the rf modules RX FIFO buffer
rfm22_endBurstRead ( ) ;
}
}
2012-04-06 05:24:50 +02:00
// CRC error .. discard the received data
2012-03-18 18:22:05 +01:00
if ( int_stat1 & RFM22_is1_icrerror )
2012-04-06 05:24:50 +02:00
{
rfm22_int_timer = 0 ; // reset the timer
rfm22_setError ( " CRC_ERR " ) ;
rfm22_setRxMode ( RX_WAIT_PREAMBLE_MODE , false ) ;
return ;
2012-03-18 18:22:05 +01:00
}
2012-04-06 05:24:50 +02:00
// Valid packet received
2012-03-18 18:22:05 +01:00
if ( int_stat1 & RFM22_is1_ipkvalid )
2012-04-06 05:24:50 +02:00
{
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// read the total length of the packet data
register uint16_t len = rfm22_read ( RFM22_received_packet_length ) ;
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// their must still be data in the RX FIFO we need to get
if ( rx_buffer_wr < len )
2012-03-18 18:22:05 +01:00
{
2012-04-06 05:24:50 +02:00
// Fetch the data from the RX FIFO
rfm22_startBurstRead ( RFM22_fifo_access ) ;
while ( rx_buffer_wr < len )
rx_buffer [ rx_buffer_wr + + ] = rfm22_burstRead ( ) ;
rfm22_endBurstRead ( ) ;
2012-03-18 18:22:05 +01:00
}
2012-04-06 05:24:50 +02:00
if ( rx_buffer_wr ! = len )
{
// we have a packet length error .. discard the packet
rfm22_setError ( " r_pack_len_error " ) ;
debug_val = len ;
2012-06-07 02:44:56 +02:00
rfm22_setRxMode ( RX_WAIT_PREAMBLE_MODE , false ) ;
2012-04-06 05:24:50 +02:00
return ;
}
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// we have a valid received packet
rfm22_setDebug ( " VALID_R_PACKET " ) ;
2012-03-18 18:22:05 +01:00
2012-04-18 02:36:05 +02:00
if ( rx_buffer_wr > 0 )
2012-03-18 18:22:05 +01:00
{
2012-04-06 05:24:50 +02:00
// remember the rssi for this packet
rx_packet_rssi_dBm = rx_packet_start_rssi_dBm ;
// remember the afc offset for this packet
rx_packet_afc_Hz = rx_packet_start_afc_Hz ;
2012-04-18 02:36:05 +02:00
// Add the rssi and afc to the end of the packet.
rx_buffer [ rx_buffer_wr + + ] = rx_packet_start_rssi_dBm ;
rx_buffer [ rx_buffer_wr + + ] = rx_packet_start_afc_Hz ;
2012-04-06 05:24:50 +02:00
// Pass this packet on
bool need_yield = false ;
if ( rfm22b_dev_g - > rx_in_cb )
( rfm22b_dev_g - > rx_in_cb ) ( rfm22b_dev_g - > rx_in_context , ( uint8_t * ) rx_buffer ,
2012-06-07 02:44:56 +02:00
rx_buffer_wr , NULL , & need_yield ) ;
2012-04-06 05:24:50 +02:00
rx_buffer_wr = 0 ;
2012-03-18 18:22:05 +01:00
}
2012-04-06 05:24:50 +02:00
// Send a packet if it's available.
if ( ! rfm22_txStart ( ) )
{
// Switch to RX mode
rfm22_setDebug ( " Set RX " ) ;
rfm22_setRxMode ( RX_WAIT_PREAMBLE_MODE , false ) ;
}
2012-03-18 18:22:05 +01:00
}
2012-04-06 05:24:50 +02:00
rfm22_setDebug ( " processRxInt end " ) ;
2012-03-18 18:22:05 +01:00
}
void rfm22_processTxInt ( void )
{
register uint8_t int_stat1 = int_status1 ;
2012-04-06 05:24:50 +02:00
// reset the timer
rfm22_int_timer = 0 ;
// FIFO under/over flow error. Back to RX mode.
if ( device_status & ( RFM22_ds_ffunfl | RFM22_ds_ffovfl ) )
{
rfm22_setError ( " T_UNDER/OVERRUN " ) ;
2012-03-18 18:22:05 +01:00
rfm22_setRxMode ( RX_WAIT_PREAMBLE_MODE , false ) ;
return ;
2012-04-06 05:24:50 +02:00
}
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// Transmit timeout. Abort the transmit.
if ( rfm22_int_timer > = timeout_data_ms )
{
rfm22_int_time_outs + + ;
rfm22_setRxMode ( RX_WAIT_PREAMBLE_MODE , false ) ;
return ;
}
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// the rf module is not in tx mode
if ( ( device_status & RFM22_ds_cps_mask ) ! = RFM22_ds_cps_tx )
{
if ( rfm22_int_timer > = 100 )
{
rfm22_int_time_outs + + ;
rfm22_setError ( " T_TIMEOUT " ) ;
rfm22_setRxMode ( RX_WAIT_PREAMBLE_MODE , false ) ; // back to rx mode
return ;
}
}
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// TX FIFO almost empty, it needs filling up
if ( int_stat1 & RFM22_is1_ixtffaem )
{
// top-up the rf chips TX FIFO buffer
uint16_t max_bytes = FIFO_SIZE - TX_FIFO_LO_WATERMARK - 1 ;
rfm22_startBurstWrite ( RFM22_fifo_access ) ;
for ( uint16_t i = 0 ; ( tx_data_rd < tx_data_wr ) & & ( i < max_bytes ) ; + + i , + + tx_data_rd )
rfm22_burstWrite ( tx_buffer [ tx_data_rd ] ) ;
rfm22_endBurstWrite ( ) ;
2012-03-18 18:22:05 +01:00
}
2012-04-06 05:24:50 +02:00
// Packet has been sent
2012-03-18 18:22:05 +01:00
if ( int_stat1 & RFM22_is1_ipksent )
2012-04-06 05:24:50 +02:00
{
rfm22_setDebug ( " T_Sent " ) ;
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// Send another packet if it's available.
if ( ! rfm22_txStart ( ) )
2012-03-18 18:22:05 +01:00
{
2012-04-06 05:24:50 +02:00
// Switch to RX mode
rfm22_setDebug ( " Set RX " ) ;
rfm22_setRxMode ( RX_WAIT_PREAMBLE_MODE , false ) ;
2012-03-18 18:22:05 +01:00
return ;
}
}
2012-04-06 05:24:50 +02:00
rfm22_setDebug ( " ProcessTxInt done " ) ;
2012-03-18 18:22:05 +01:00
}
2012-04-22 03:31:49 +02:00
static void rfm22_processInt ( void )
2012-03-18 18:22:05 +01:00
{
2012-04-06 05:24:50 +02:00
rfm22_setDebug ( " ProcessInt " ) ;
2012-03-18 18:22:05 +01:00
// this is called from the external interrupt handler
if ( ! initialized | | power_on_reset )
2012-04-06 05:24:50 +02:00
// we haven't yet been initialized
return ;
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
exec_using_spi = TRUE ;
2012-03-18 18:22:05 +01:00
2012-04-22 03:31:49 +02:00
// Reset the supervisor timer.
2012-06-06 06:10:32 +02:00
rfm22b_dev_g - > supv_timer = PIOS_RFM22B_SUPERVISOR_TIMEOUT ;
2012-04-22 03:31:49 +02:00
2012-04-06 05:24:50 +02:00
// read interrupt status registers - clears the interrupt line
int_status1 = rfm22_read ( RFM22_interrupt_status1 ) ;
int_status2 = rfm22_read ( RFM22_interrupt_status2 ) ;
2012-03-18 18:22:05 +01:00
// read device status register
device_status = rfm22_read ( RFM22_device_status ) ;
// read ezmac status register
ezmac_status = rfm22_read ( RFM22_ezmac_status ) ;
2012-04-06 05:24:50 +02:00
// Read the RSSI if we're in RX mode
if ( rf_mode ! = TX_DATA_MODE & & rf_mode ! = TX_STREAM_MODE & &
2012-06-07 02:44:56 +02:00
rf_mode ! = TX_CARRIER_MODE & & rf_mode ! = TX_PN_MODE )
2012-03-18 18:22:05 +01:00
{
2012-04-06 05:24:50 +02:00
// read rx signal strength .. 45 = -100dBm, 205 = -20dBm
rssi = rfm22_read ( RFM22_rssi ) ;
// convert to dBm
2012-04-18 02:36:05 +02:00
rssi_dBm = ( int8_t ) ( rssi > > 1 ) - 122 ;
2012-03-18 18:22:05 +01:00
}
else
2012-04-06 05:24:50 +02:00
// read the tx power register
tx_pwr = rfm22_read ( RFM22_tx_power ) ;
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// the RF module has gone and done a reset - we need to re-initialize the rf module
2012-03-18 18:22:05 +01:00
if ( int_status2 & RFM22_is2_ipor )
2012-04-06 05:24:50 +02:00
{
2012-03-18 18:22:05 +01:00
initialized = FALSE ;
power_on_reset = TRUE ;
2012-04-06 05:24:50 +02:00
rfm22_setError ( " Reset " ) ;
// Need to do something here!
2012-03-18 18:22:05 +01:00
return ;
}
switch ( rf_mode )
{
case RX_SCAN_SPECTRUM :
break ;
case RX_WAIT_PREAMBLE_MODE :
case RX_WAIT_SYNC_MODE :
case RX_DATA_MODE :
2012-04-06 05:24:50 +02:00
rfm22_processRxInt ( ) ;
2012-03-18 18:22:05 +01:00
break ;
case TX_DATA_MODE :
case TX_STREAM_MODE :
2012-04-06 05:24:50 +02:00
rfm22_processTxInt ( ) ;
2012-03-18 18:22:05 +01:00
break ;
case TX_CARRIER_MODE :
case TX_PN_MODE :
2012-04-06 05:24:50 +02:00
// if (rfm22_int_timer >= TX_TEST_MODE_TIMELIMIT_MS) // 'nn'ms limit
2012-03-18 18:22:05 +01:00
// {
// rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // back to rx mode
// tx_data_rd = tx_data_wr = 0; // wipe TX buffer
// break;
// }
break ;
default : // unknown mode - this should NEVER happen, maybe we should do a complete CPU reset here
rfm22_setRxMode ( RX_WAIT_PREAMBLE_MODE , false ) ; // to rx mode
break ;
}
2012-04-06 05:24:50 +02:00
exec_using_spi = FALSE ;
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
rfm22_setDebug ( " ProcessInt done " ) ;
2012-03-18 18:22:05 +01:00
}
// ************************************
2012-04-18 02:36:05 +02:00
int8_t rfm22_getRSSI ( void )
2012-03-18 18:22:05 +01:00
{
exec_using_spi = TRUE ;
rssi = rfm22_read ( RFM22_rssi ) ; // read rx signal strength .. 45 = -100dBm, 205 = -20dBm
2012-04-18 02:36:05 +02:00
rssi_dBm = ( int8_t ) ( rssi > > 1 ) - 122 ; // convert to dBm
2012-03-18 18:22:05 +01:00
exec_using_spi = FALSE ;
return rssi_dBm ;
}
2012-04-18 02:36:05 +02:00
int8_t rfm22_receivedRSSI ( void )
2012-03-18 18:22:05 +01:00
{ // return the packets signal strength
if ( ! initialized )
2012-04-18 02:36:05 +02:00
return - 127 ;
2012-03-18 18:22:05 +01:00
else
return rx_packet_rssi_dBm ;
}
int32_t rfm22_receivedAFCHz ( void )
{ // return the packets offset frequency
if ( ! initialized )
return 0 ;
else
return rx_packet_afc_Hz ;
}
// ************************************
// ************************************
void rfm22_setTxStream ( void ) // TEST ONLY
{
if ( ! initialized )
return ;
tx_data_rd = tx_data_wr = 0 ;
rfm22_setTxMode ( TX_STREAM_MODE ) ;
}
// ************************************
void rfm22_setTxNormal ( void )
{
if ( ! initialized )
return ;
// if (rf_mode == TX_CARRIER_MODE || rf_mode == TX_PN_MODE)
if ( rf_mode ! = RX_SCAN_SPECTRUM )
{
rfm22_setRxMode ( RX_WAIT_PREAMBLE_MODE , false ) ;
tx_data_rd = tx_data_wr = 0 ;
rx_packet_start_rssi_dBm = 0 ;
rx_packet_start_afc_Hz = 0 ;
rx_packet_rssi_dBm = 0 ;
rx_packet_afc_Hz = 0 ;
}
}
// enable a blank tx carrier (for frequency alignment)
void rfm22_setTxCarrierMode ( void )
{
if ( ! initialized )
return ;
if ( rf_mode ! = TX_CARRIER_MODE & & rf_mode ! = RX_SCAN_SPECTRUM )
rfm22_setTxMode ( TX_CARRIER_MODE ) ;
}
// enable a psuedo random data tx carrier (for spectrum inspection)
void rfm22_setTxPNMode ( void )
{
if ( ! initialized )
return ;
if ( rf_mode ! = TX_PN_MODE & & rf_mode ! = RX_SCAN_SPECTRUM )
rfm22_setTxMode ( TX_PN_MODE ) ;
}
// ************************************
// return the current mode
int8_t rfm22_currentMode ( void )
{
return rf_mode ;
}
// return TRUE if we are transmitting
bool rfm22_transmitting ( void )
{
return ( rf_mode = = TX_DATA_MODE | | rf_mode = = TX_STREAM_MODE | | rf_mode = = TX_CARRIER_MODE | | rf_mode = = TX_PN_MODE ) ;
}
// return TRUE if the channel is clear to transmit on
bool rfm22_channelIsClear ( void )
{
if ( ! initialized )
2012-04-06 05:24:50 +02:00
// we haven't yet been initialized
return FALSE ;
2012-03-18 18:22:05 +01:00
if ( rf_mode ! = RX_WAIT_PREAMBLE_MODE & & rf_mode ! = RX_WAIT_SYNC_MODE )
2012-04-06 05:24:50 +02:00
// we are receiving something or we are transmitting or we are scanning the spectrum
return FALSE ;
2012-03-18 18:22:05 +01:00
return TRUE ;
}
// return TRUE if the transmiter is ready for use
bool rfm22_txReady ( void )
{
if ( ! initialized )
2012-04-06 05:24:50 +02:00
// we haven't yet been initialized
return FALSE ;
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
return ( tx_data_rd = = 0 & & tx_data_wr = = 0 & & rf_mode ! = TX_DATA_MODE & &
2012-06-07 02:44:56 +02:00
rf_mode ! = TX_STREAM_MODE & & rf_mode ! = TX_CARRIER_MODE & & rf_mode ! = TX_PN_MODE & &
rf_mode ! = RX_SCAN_SPECTRUM ) ;
2012-03-18 18:22:05 +01:00
}
// ************************************
// set/get the frequency calibration value
void rfm22_setFreqCalibration ( uint8_t value )
{
osc_load_cap = value ;
if ( ! initialized | | power_on_reset )
return ; // we haven't yet been initialized
uint8_t prev_rf_mode = rf_mode ;
if ( rf_mode = = TX_CARRIER_MODE | | rf_mode = = TX_PN_MODE )
{
rfm22_setRxMode ( RX_WAIT_PREAMBLE_MODE , false ) ;
tx_data_rd = tx_data_wr = 0 ;
}
exec_using_spi = TRUE ;
rfm22_write ( RFM22_xtal_osc_load_cap , osc_load_cap ) ;
exec_using_spi = FALSE ;
if ( prev_rf_mode = = TX_CARRIER_MODE | | prev_rf_mode = = TX_PN_MODE )
rfm22_setTxMode ( prev_rf_mode ) ;
}
uint8_t rfm22_getFreqCalibration ( void )
{
return osc_load_cap ;
}
// ************************************
// can be called from an interrupt if you wish
void rfm22_1ms_tick ( void )
{ // call this once every ms
if ( ! initialized ) return ; // we haven't yet been initialized
if ( rf_mode ! = RX_SCAN_SPECTRUM )
{
if ( rfm22_int_timer < 0xffff ) rfm22_int_timer + + ;
}
}
// ************************************
// reset the RF module
int rfm22_resetModule ( uint8_t mode , uint32_t min_frequency_hz , uint32_t max_frequency_hz )
{
initialized = false ;
# if defined(RFM22_EXT_INT_USE)
rfm22_disableExtInt ( ) ;
# endif
power_on_reset = false ;
// ****************
exec_using_spi = TRUE ;
// ****************
// setup the SPI port
// chip select line HIGH
2012-05-05 18:40:44 +02:00
PIOS_SPI_RC_PinSet ( RFM22_PIOS_SPI , 0 , 1 ) ;
2012-03-18 18:22:05 +01:00
// set SPI port SCLK frequency .. 4.5MHz
PIOS_SPI_SetClockSpeed ( RFM22_PIOS_SPI , PIOS_SPI_PRESCALER_16 ) ;
// set SPI port SCLK frequency .. 2.25MHz
// PIOS_SPI_SetClockSpeed(RFM22_PIOS_SPI, PIOS_SPI_PRESCALER_32);
// set SPI port SCLK frequency .. 285kHz .. purely for hardware fault finding
// PIOS_SPI_SetClockSpeed(RFM22_PIOS_SPI, PIOS_SPI_PRESCALER_256);
// ****************
// software reset the RF chip .. following procedure according to Si4x3x Errata (rev. B)
rfm22_write ( RFM22_op_and_func_ctrl1 , RFM22_opfc1_swres ) ; // software reset the radio
PIOS_DELAY_WaitmS ( 26 ) ; // wait 26ms
for ( int i = 50 ; i > 0 ; i - - )
{
PIOS_DELAY_WaitmS ( 1 ) ; // wait 1ms
// read the status registers
int_status1 = rfm22_read ( RFM22_interrupt_status1 ) ;
int_status2 = rfm22_read ( RFM22_interrupt_status2 ) ;
if ( int_status2 & RFM22_is2_ichiprdy ) break ;
}
// ****************
// read status - clears interrupt
device_status = rfm22_read ( RFM22_device_status ) ;
int_status1 = rfm22_read ( RFM22_interrupt_status1 ) ;
int_status2 = rfm22_read ( RFM22_interrupt_status2 ) ;
ezmac_status = rfm22_read ( RFM22_ezmac_status ) ;
// disable all interrupts
rfm22_write ( RFM22_interrupt_enable1 , 0x00 ) ;
rfm22_write ( RFM22_interrupt_enable2 , 0x00 ) ;
// ****************
exec_using_spi = FALSE ;
// ****************
rf_mode = mode ;
device_status = int_status1 = int_status2 = ezmac_status = 0 ;
rssi = 0 ;
2012-04-18 02:36:05 +02:00
rssi_dBm = - 127 ;
2012-03-18 18:22:05 +01:00
rx_buffer_current = 0 ;
rx_buffer_wr = 0 ;
2012-04-18 02:36:05 +02:00
rx_packet_rssi_dBm = - 127 ;
2012-03-18 18:22:05 +01:00
rx_packet_afc_Hz = 0 ;
tx_data_rd = tx_data_wr = 0 ;
lookup_index = 0 ;
ss_lookup_index = 0 ;
rf_bandwidth_used = 0 ;
ss_rf_bandwidth_used = 0 ;
rfm22_int_timer = 0 ;
rfm22_int_time_outs = 0 ;
prev_rfm22_int_time_outs = 0 ;
hbsel = 0 ;
frequency_step_size = 0.0f ;
frequency_hop_channel = 0 ;
afc_correction = 0 ;
afc_correction_Hz = 0 ;
temperature_reg = 0 ;
// set the TX power
tx_power = RFM22_DEFAULT_RF_POWER ;
tx_pwr = 0 ;
// ****************
// read the RF chip ID bytes
device_type = rfm22_read ( RFM22_DEVICE_TYPE ) & RFM22_DT_MASK ; // read the device type
device_version = rfm22_read ( RFM22_DEVICE_VERSION ) & RFM22_DV_MASK ; // read the device version
# if defined(RFM22_DEBUG)
DEBUG_PRINTF ( 2 , " rf device type: %d \n \r " , device_type ) ;
DEBUG_PRINTF ( 2 , " rf device version: %d \n \r " , device_version ) ;
# endif
if ( device_type ! = 0x08 )
{
# if defined(RFM22_DEBUG)
DEBUG_PRINTF ( 2 , " rf device type: INCORRECT - should be 0x08 \n \r " ) ;
# endif
return - 1 ; // incorrect RF module type
}
// if (device_version != RFM22_DEVICE_VERSION_V2) // V2
// return -2; // incorrect RF module version
// if (device_version != RFM22_DEVICE_VERSION_A0) // A0
// return -2; // incorrect RF module version
if ( device_version ! = RFM22_DEVICE_VERSION_B1 ) // B1
{
# if defined(RFM22_DEBUG)
DEBUG_PRINTF ( 2 , " rf device version: INCORRECT \n \r " ) ;
# endif
return - 2 ; // incorrect RF module version
}
// ****************
// set the minimum and maximum carrier frequency allowed
if ( min_frequency_hz < RFM22_MIN_CARRIER_FREQUENCY_HZ ) min_frequency_hz = RFM22_MIN_CARRIER_FREQUENCY_HZ ;
else
if ( min_frequency_hz > RFM22_MAX_CARRIER_FREQUENCY_HZ ) min_frequency_hz = RFM22_MAX_CARRIER_FREQUENCY_HZ ;
if ( max_frequency_hz < RFM22_MIN_CARRIER_FREQUENCY_HZ ) max_frequency_hz = RFM22_MIN_CARRIER_FREQUENCY_HZ ;
else
if ( max_frequency_hz > RFM22_MAX_CARRIER_FREQUENCY_HZ ) max_frequency_hz = RFM22_MAX_CARRIER_FREQUENCY_HZ ;
if ( min_frequency_hz > max_frequency_hz )
{ // swap them over
uint32_t tmp = min_frequency_hz ;
min_frequency_hz = max_frequency_hz ;
max_frequency_hz = tmp ;
}
lower_carrier_frequency_limit_Hz = min_frequency_hz ;
upper_carrier_frequency_limit_Hz = max_frequency_hz ;
// ****************
// calibrate our RF module to be exactly on frequency .. different for every module
osc_load_cap = OSC_LOAD_CAP ; // default
rfm22_write ( RFM22_xtal_osc_load_cap , osc_load_cap ) ;
// ****************
// disable Low Duty Cycle Mode
rfm22_write ( RFM22_op_and_func_ctrl2 , 0x00 ) ;
rfm22_write ( RFM22_cpu_output_clk , RFM22_coc_1MHz ) ; // 1MHz clock output
rfm22_write ( RFM22_op_and_func_ctrl1 , RFM22_opfc1_xton ) ; // READY mode
// rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon); // TUNE mode
// choose the 3 GPIO pin functions
rfm22_write ( RFM22_io_port_config , RFM22_io_port_default ) ; // GPIO port use default value
rfm22_write ( RFM22_gpio0_config , RFM22_gpio0_config_drv3 | RFM22_gpio0_config_txstate ) ; // GPIO0 = TX State (to control RF Switch)
rfm22_write ( RFM22_gpio1_config , RFM22_gpio1_config_drv3 | RFM22_gpio1_config_rxstate ) ; // GPIO1 = RX State (to control RF Switch)
rfm22_write ( RFM22_gpio2_config , RFM22_gpio2_config_drv3 | RFM22_gpio2_config_cca ) ; // GPIO2 = Clear Channel Assessment
// ****************
return 0 ; // OK
}
// ************************************
int rfm22_init_scan_spectrum ( uint32_t min_frequency_hz , uint32_t max_frequency_hz )
{
# if defined(RFM22_DEBUG)
DEBUG_PRINTF ( 2 , " \n \r RF init scan spectrum \n \r " ) ;
# endif
int res = rfm22_resetModule ( RX_SCAN_SPECTRUM , min_frequency_hz , max_frequency_hz ) ;
if ( res < 0 )
return res ;
// rfm22_setSSBandwidth(0);
rfm22_setSSBandwidth ( 1 ) ;
// FIFO mode, GFSK modulation
uint8_t fd_bit = rfm22_read ( RFM22_modulation_mode_control2 ) & RFM22_mmc2_fd ;
rfm22_write ( RFM22_modulation_mode_control2 , RFM22_mmc2_trclk_clk_none | RFM22_mmc2_dtmod_fifo | fd_bit | RFM22_mmc2_modtyp_gfsk ) ;
rfm22_write ( RFM22_cpu_output_clk , RFM22_coc_1MHz ) ; // 1MHz clock output
rfm22_write ( RFM22_rssi_threshold_clear_chan_indicator , 0 ) ;
rfm22_write ( RFM22_preamble_detection_ctrl1 , 31 < < 3 ) ; // 31-nibbles rx preamble detection
// avoid packet detection
rfm22_write ( RFM22_data_access_control , RFM22_dac_enpacrx | RFM22_dac_encrc ) ;
rfm22_write ( RFM22_header_control1 , 0x0f ) ;
rfm22_write ( RFM22_header_control2 , 0x77 ) ;
rfm22_write ( RFM22_sync_word3 , SYNC_BYTE_1 ) ;
rfm22_write ( RFM22_sync_word2 , SYNC_BYTE_2 ) ;
rfm22_write ( RFM22_sync_word1 , SYNC_BYTE_3 ^ 0xff ) ;
rfm22_write ( RFM22_sync_word0 , SYNC_BYTE_4 ^ 0xff ) ;
// all the bits to be checked
rfm22_write ( RFM22_header_enable3 , 0xff ) ;
rfm22_write ( RFM22_header_enable2 , 0xff ) ;
rfm22_write ( RFM22_header_enable1 , 0xff ) ;
rfm22_write ( RFM22_header_enable0 , 0xff ) ;
2012-04-06 05:24:50 +02:00
// set frequency hopping channel step size (multiples of 10kHz)
// rfm22_write(RFM22_frequency_hopping_step_size, 0);
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// set our nominal carrier frequency
rfm22_setNominalCarrierFrequency ( min_frequency_hz ) ;
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// set minimum tx power
rfm22_write ( RFM22_tx_power , RFM22_tx_pwr_lna_sw | 0 ) ;
2012-03-18 18:22:05 +01:00
rfm22_write ( RFM22_agc_override1 , RFM22_agc_ovr1_sgi | RFM22_agc_ovr1_agcen ) ;
// rfm22_write(RFM22_vco_current_trimming, 0x7f);
// rfm22_write(RFM22_vco_calibration_override, 0x40);
// rfm22_write(RFM22_chargepump_current_trimming_override, 0x80);
// Enable RF module external interrupt
rfm22_enableExtInt ( ) ;
rfm22_setRxMode ( RX_SCAN_SPECTRUM , true ) ;
initialized = true ;
return 0 ; // OK
}
// ************************************
int rfm22_init_tx_stream ( uint32_t min_frequency_hz , uint32_t max_frequency_hz )
{
# if defined(RFM22_DEBUG)
DEBUG_PRINTF ( 2 , " \n \r RF init TX stream \n \r " ) ;
# endif
int res = rfm22_resetModule ( TX_STREAM_MODE , min_frequency_hz , max_frequency_hz ) ;
if ( res < 0 )
return res ;
frequency_hop_step_size_reg = 0 ;
// set the RF datarate
rfm22_setDatarate ( RFM22_DEFAULT_RF_DATARATE , FALSE ) ;
// FIFO mode, GFSK modulation
uint8_t fd_bit = rfm22_read ( RFM22_modulation_mode_control2 ) & RFM22_mmc2_fd ;
rfm22_write ( RFM22_modulation_mode_control2 , RFM22_mmc2_trclk_clk_none | RFM22_mmc2_dtmod_fifo | fd_bit | RFM22_mmc2_modtyp_gfsk ) ;
// disable the internal Tx & Rx packet handlers (without CRC)
rfm22_write ( RFM22_data_access_control , 0 ) ;
rfm22_write ( RFM22_preamble_length , TX_PREAMBLE_NIBBLES ) ; // x-nibbles tx preamble
rfm22_write ( RFM22_preamble_detection_ctrl1 , RX_PREAMBLE_NIBBLES < < 3 ) ; // x-nibbles rx preamble detection
rfm22_write ( RFM22_header_control1 , RFM22_header_cntl1_bcen_none | RFM22_header_cntl1_hdch_none ) ; // header control - we are not using the header
rfm22_write ( RFM22_header_control2 , RFM22_header_cntl2_fixpklen | RFM22_header_cntl2_hdlen_none | RFM22_header_cntl2_synclen_32 | ( ( TX_PREAMBLE_NIBBLES > > 8 ) & 0x01 ) ) ; // no header bytes, synchronization word length 3, 2 used, packet length not included in header (fixed packet length).
rfm22_write ( RFM22_sync_word3 , SYNC_BYTE_1 ) ; // sync word
rfm22_write ( RFM22_sync_word2 , SYNC_BYTE_2 ) ; //
// rfm22_write(RFM22_modem_test, 0x01);
rfm22_write ( RFM22_agc_override1 , RFM22_agc_ovr1_agcen ) ;
// rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_sgi | RFM22_agc_ovr1_agcen);
rfm22_write ( RFM22_frequency_hopping_step_size , frequency_hop_step_size_reg ) ; // set frequency hopping channel step size (multiples of 10kHz)
rfm22_setNominalCarrierFrequency ( ( min_frequency_hz + max_frequency_hz ) / 2 ) ; // set our nominal carrier frequency
rfm22_write ( RFM22_tx_power , RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | tx_power ) ; // set the tx power
// rfm22_write(RFM22_tx_power, RFM22_tx_pwr_lna_sw | tx_power); // set the tx power
// rfm22_write(RFM22_vco_current_trimming, 0x7f);
// rfm22_write(RFM22_vco_calibration_override, 0x40);
// rfm22_write(RFM22_chargepump_current_trimming_override, 0x80);
rfm22_write ( RFM22_tx_fifo_control1 , TX_FIFO_HI_WATERMARK ) ; // TX FIFO Almost Full Threshold (0 - 63)
rfm22_write ( RFM22_tx_fifo_control2 , TX_FIFO_LO_WATERMARK ) ; // TX FIFO Almost Empty Threshold (0 - 63)
// Enable RF module external interrupt
rfm22_enableExtInt ( ) ;
initialized = true ;
return 0 ; // OK
}
// ************************************
int rfm22_init_rx_stream ( uint32_t min_frequency_hz , uint32_t max_frequency_hz )
{
# if defined(RFM22_DEBUG)
DEBUG_PRINTF ( 2 , " \n \r RF init RX stream \n \r " ) ;
# endif
int res = rfm22_resetModule ( RX_WAIT_PREAMBLE_MODE , min_frequency_hz , max_frequency_hz ) ;
if ( res < 0 )
return res ;
frequency_hop_step_size_reg = 0 ;
// set the RF datarate
rfm22_setDatarate ( RFM22_DEFAULT_RF_DATARATE , FALSE ) ;
// FIFO mode, GFSK modulation
uint8_t fd_bit = rfm22_read ( RFM22_modulation_mode_control2 ) & RFM22_mmc2_fd ;
rfm22_write ( RFM22_modulation_mode_control2 , RFM22_mmc2_trclk_clk_none | RFM22_mmc2_dtmod_fifo | fd_bit | RFM22_mmc2_modtyp_gfsk ) ;
// disable the internal Tx & Rx packet handlers (without CRC)
rfm22_write ( RFM22_data_access_control , 0 ) ;
rfm22_write ( RFM22_preamble_length , TX_PREAMBLE_NIBBLES ) ; // x-nibbles tx preamble
rfm22_write ( RFM22_preamble_detection_ctrl1 , RX_PREAMBLE_NIBBLES < < 3 ) ; // x-nibbles rx preamble detection
rfm22_write ( RFM22_header_control1 , RFM22_header_cntl1_bcen_none | RFM22_header_cntl1_hdch_none ) ; // header control - we are not using the header
rfm22_write ( RFM22_header_control2 , RFM22_header_cntl2_fixpklen | RFM22_header_cntl2_hdlen_none | RFM22_header_cntl2_synclen_32 | ( ( TX_PREAMBLE_NIBBLES > > 8 ) & 0x01 ) ) ; // no header bytes, synchronization word length 3, 2 used, packet length not included in header (fixed packet length).
rfm22_write ( RFM22_sync_word3 , SYNC_BYTE_1 ) ; // sync word
rfm22_write ( RFM22_sync_word2 , SYNC_BYTE_2 ) ; //
// no header bits to be checked
rfm22_write ( RFM22_header_enable3 , 0x00 ) ;
rfm22_write ( RFM22_header_enable2 , 0x00 ) ;
rfm22_write ( RFM22_header_enable1 , 0x00 ) ;
rfm22_write ( RFM22_header_enable0 , 0x00 ) ;
// rfm22_write(RFM22_modem_test, 0x01);
rfm22_write ( RFM22_agc_override1 , RFM22_agc_ovr1_agcen ) ;
// rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_sgi | RFM22_agc_ovr1_agcen);
rfm22_write ( RFM22_frequency_hopping_step_size , frequency_hop_step_size_reg ) ; // set frequency hopping channel step size (multiples of 10kHz)
rfm22_setNominalCarrierFrequency ( ( min_frequency_hz + max_frequency_hz ) / 2 ) ; // set our nominal carrier frequency
// rfm22_write(RFM22_vco_current_trimming, 0x7f);
// rfm22_write(RFM22_vco_calibration_override, 0x40);
// rfm22_write(RFM22_chargepump_current_trimming_override, 0x80);
2012-04-06 05:24:50 +02:00
// RX FIFO Almost Full Threshold (0 - 63)
rfm22_write ( RFM22_rx_fifo_control , RX_FIFO_HI_WATERMARK ) ;
2012-03-18 18:22:05 +01:00
// Enable RF module external interrupt
rfm22_enableExtInt ( ) ;
rfm22_setRxMode ( RX_WAIT_PREAMBLE_MODE , false ) ;
initialized = true ;
return 0 ; // OK
}
// ************************************
// Initialise this hardware layer module and the rf module
2012-04-18 02:36:05 +02:00
int rfm22_init_normal ( uint32_t id , uint32_t min_frequency_hz , uint32_t max_frequency_hz , uint32_t freq_hop_step_size )
2012-03-18 18:22:05 +01:00
{
int res = rfm22_resetModule ( RX_WAIT_PREAMBLE_MODE , min_frequency_hz , max_frequency_hz ) ;
if ( res < 0 )
return res ;
2012-04-06 05:24:50 +02:00
// initialize the frequency hopping step size
2012-03-18 18:22:05 +01:00
freq_hop_step_size / = 10000 ; // in 10kHz increments
if ( freq_hop_step_size > 255 ) freq_hop_step_size = 255 ;
frequency_hop_step_size_reg = freq_hop_step_size ;
// set the RF datarate
rfm22_setDatarate ( RFM22_DEFAULT_RF_DATARATE , TRUE ) ;
// FIFO mode, GFSK modulation
uint8_t fd_bit = rfm22_read ( RFM22_modulation_mode_control2 ) & RFM22_mmc2_fd ;
rfm22_write ( RFM22_modulation_mode_control2 , RFM22_mmc2_trclk_clk_none | RFM22_mmc2_dtmod_fifo | fd_bit | RFM22_mmc2_modtyp_gfsk ) ;
// setup to read the internal temperature sensor
2012-04-06 05:24:50 +02:00
// ADC used to sample the temperature sensor
adc_config = RFM22_ac_adcsel_temp_sensor | RFM22_ac_adcref_bg ;
rfm22_write ( RFM22_adc_config , adc_config ) ;
// adc offset
rfm22_write ( RFM22_adc_sensor_amp_offset , 0 ) ;
// temp sensor calibration .. <20> 40C to +64C 0.5C resolution
rfm22_write ( RFM22_temp_sensor_calib , RFM22_tsc_tsrange0 | RFM22_tsc_entsoffs ) ;
// temp sensor offset
rfm22_write ( RFM22_temp_value_offset , 0 ) ;
// start an ADC conversion
rfm22_write ( RFM22_adc_config , adc_config | RFM22_ac_adcstartbusy ) ;
// set the RSSI threshold interrupt to about -90dBm
rfm22_write ( RFM22_rssi_threshold_clear_chan_indicator , ( - 90 + 122 ) * 2 ) ;
2012-03-18 18:22:05 +01:00
// enable the internal Tx & Rx packet handlers (without CRC)
rfm22_write ( RFM22_data_access_control , RFM22_dac_enpacrx | RFM22_dac_enpactx ) ;
2012-04-06 05:24:50 +02:00
// x-nibbles tx preamble
rfm22_write ( RFM22_preamble_length , TX_PREAMBLE_NIBBLES ) ;
// x-nibbles rx preamble detection
rfm22_write ( RFM22_preamble_detection_ctrl1 , RX_PREAMBLE_NIBBLES < < 3 ) ;
2012-03-18 18:22:05 +01:00
2012-04-11 05:22:53 +02:00
# ifdef PIOS_RFM22_NO_HEADER
2012-04-06 05:24:50 +02:00
// header control - we are not using the header
rfm22_write ( RFM22_header_control1 , RFM22_header_cntl1_bcen_none | RFM22_header_cntl1_hdch_none ) ;
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// no header bytes, synchronization word length 3, 2, 1 & 0 used, packet length included in header.
rfm22_write ( RFM22_header_control2 , RFM22_header_cntl2_hdlen_none |
RFM22_header_cntl2_synclen_3210 | ( ( TX_PREAMBLE_NIBBLES > > 8 ) & 0x01 ) ) ;
2012-04-11 05:22:53 +02:00
# else
// header control - using a 4 by header with broadcast of 0xffffffff
rfm22_write ( RFM22_header_control1 ,
RFM22_header_cntl1_bcen_0 |
RFM22_header_cntl1_bcen_1 |
RFM22_header_cntl1_bcen_2 |
RFM22_header_cntl1_bcen_3 |
RFM22_header_cntl1_hdch_0 |
RFM22_header_cntl1_hdch_1 |
RFM22_header_cntl1_hdch_2 |
RFM22_header_cntl1_hdch_3 ) ;
// Check all bit of all bytes of the header
rfm22_write ( RFM22_header_enable0 , 0xff ) ;
rfm22_write ( RFM22_header_enable1 , 0xff ) ;
rfm22_write ( RFM22_header_enable2 , 0xff ) ;
rfm22_write ( RFM22_header_enable3 , 0xff ) ;
// Set the ID to be checked
2012-04-18 02:36:05 +02:00
rfm22_write ( RFM22_check_header0 , id & 0xff ) ;
rfm22_write ( RFM22_check_header1 , ( id > > 8 ) & 0xff ) ;
rfm22_write ( RFM22_check_header2 , ( id > > 16 ) & 0xff ) ;
rfm22_write ( RFM22_check_header3 , ( id > > 24 ) & 0xff ) ;
2012-04-11 05:22:53 +02:00
// 4 header bytes, synchronization word length 3, 2, 1 & 0 used, packet length included in header.
rfm22_write ( RFM22_header_control2 ,
RFM22_header_cntl2_hdlen_3210 |
RFM22_header_cntl2_synclen_3210 |
( ( TX_PREAMBLE_NIBBLES > > 8 ) & 0x01 ) ) ;
# endif
2012-04-06 05:24:50 +02:00
// sync word
rfm22_write ( RFM22_sync_word3 , SYNC_BYTE_1 ) ;
rfm22_write ( RFM22_sync_word2 , SYNC_BYTE_2 ) ;
rfm22_write ( RFM22_sync_word1 , SYNC_BYTE_3 ) ;
rfm22_write ( RFM22_sync_word0 , SYNC_BYTE_4 ) ;
2012-03-18 18:22:05 +01:00
rfm22_write ( RFM22_agc_override1 , RFM22_agc_ovr1_agcen ) ;
2012-04-06 05:24:50 +02:00
// set frequency hopping channel step size (multiples of 10kHz)
rfm22_write ( RFM22_frequency_hopping_step_size , frequency_hop_step_size_reg ) ;
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// set our nominal carrier frequency
rfm22_setNominalCarrierFrequency ( ( min_frequency_hz + max_frequency_hz ) / 2 ) ;
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// set the tx power
rfm22_write ( RFM22_tx_power , RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_0 |
RFM22_tx_pwr_lna_sw | tx_power ) ;
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// TX FIFO Almost Full Threshold (0 - 63)
rfm22_write ( RFM22_tx_fifo_control1 , TX_FIFO_HI_WATERMARK ) ;
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// TX FIFO Almost Empty Threshold (0 - 63)
rfm22_write ( RFM22_tx_fifo_control2 , TX_FIFO_LO_WATERMARK ) ;
2012-03-18 18:22:05 +01:00
2012-04-06 05:24:50 +02:00
// RX FIFO Almost Full Threshold (0 - 63)
rfm22_write ( RFM22_rx_fifo_control , RX_FIFO_HI_WATERMARK ) ;
2012-03-18 18:22:05 +01:00
// Enable RF module external interrupt
rfm22_enableExtInt ( ) ;
rfm22_setRxMode ( RX_WAIT_PREAMBLE_MODE , false ) ;
initialized = true ;
return 0 ; // ok
}
// ************************************
# endif
/**
* @ }
* @ }
*/