From 432a6dfd000fec3b69f5a4eeb1222b48b9ad5117 Mon Sep 17 00:00:00 2001 From: Brian Webb Date: Sat, 8 Sep 2012 12:02:00 -0700 Subject: [PATCH 01/10] RM: Fixed crashing when radio module is disabled. --- flight/Modules/Telemetry/telemetry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flight/Modules/Telemetry/telemetry.c b/flight/Modules/Telemetry/telemetry.c index 6c07cb51d..21fe81867 100644 --- a/flight/Modules/Telemetry/telemetry.c +++ b/flight/Modules/Telemetry/telemetry.c @@ -264,7 +264,7 @@ static void processObjEvent(UAVObjEvent * ev) if (ev->event == EV_UPDATED || ev->event == EV_UPDATED_MANUAL || ((ev->event == EV_UPDATED_PERIODIC) && (updateMode != UPDATEMODE_THROTTLED))) { #ifdef PIOS_PACKET_HANDLER // Don't send PipXStatus objects over the radio link. - if ((ev->obj == PipXStatusHandle()) && (getComPort() == 0) && PIOS_PACKET_HANDLER) + if (PIOS_PACKET_HANDLER && (ev->obj == PipXStatusHandle()) && (getComPort() == 0)) return; #endif // Send update to GCS (with retries) From 6623c55846aa01e7577ac59b04643e25b891cce6 Mon Sep 17 00:00:00 2001 From: Brian Webb Date: Tue, 11 Sep 2012 20:34:26 -0700 Subject: [PATCH 02/10] RFM22B: Moved ISR processing thread into the rfm22b driver. --- flight/Modules/Radio/radio.c | 11 ++---- flight/PiOS/Common/pios_rfm22b.c | 60 +++++++++++++++++++++++--------- 2 files changed, 46 insertions(+), 25 deletions(-) diff --git a/flight/Modules/Radio/radio.c b/flight/Modules/Radio/radio.c index b72f3ea12..65650d815 100644 --- a/flight/Modules/Radio/radio.c +++ b/flight/Modules/Radio/radio.c @@ -441,11 +441,9 @@ static void StatusHandler(PHStatusPacketHandle status, int8_t rssi, int8_t afc) */ static void radioStatusTask(void *parameters) { - static portTickType lastSysTime; PHStatusPacket status_packet; - while (1) { - lastSysTime = xTaskGetTickCount(); + while (1) { PipXStatusData pipxStatus; uint32_t pairID; @@ -524,12 +522,7 @@ static void radioStatusTask(void *parameters) } } - portTickType timeSinceUpdate; - do { - PIOS_RFM22_processPendingISR(5); - timeSinceUpdate = xTaskGetTickCount() - lastSysTime; - } - while(timeSinceUpdate < STATS_UPDATE_PERIOD_MS / portTICK_RATE_MS); + vTaskDelay(STATS_UPDATE_PERIOD_MS / portTICK_RATE_MS); } } diff --git a/flight/PiOS/Common/pios_rfm22b.c b/flight/PiOS/Common/pios_rfm22b.c index 9a39765a0..6029d8488 100644 --- a/flight/PiOS/Common/pios_rfm22b.c +++ b/flight/PiOS/Common/pios_rfm22b.c @@ -56,7 +56,9 @@ #include /* Local Defines */ -#define STACK_SIZE_BYTES 200 +#define STACK_SIZE_BYTES 200 +#define TASK_PRIORITY (tskIDLE_PRIORITY + 2) +#define ISR_TIMEOUT 5 // ms // RTC timer is running at 625Hz (1.6ms or 5 ticks == 8ms). // A 256 byte message at 56kbps should take less than 40ms @@ -163,6 +165,9 @@ struct pios_rfm22b_dev { uint32_t deviceID; + // The task handle + xTaskHandle taskHandle; + // ISR pending xSemaphoreHandle isrPending; @@ -175,6 +180,10 @@ struct pios_rfm22b_dev { // The supervisor countdown timer. uint16_t supv_timer; uint16_t resets; + + // Stats + uint32_t rfm32_errors; + uint32_t rfm32_irqs_processed; }; uint32_t random32 = 0x459ab8d8; @@ -206,6 +215,7 @@ static const uint8_t OUT_FF[64] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* Local function forwared declarations */ static void PIOS_RFM22B_Supervisor(uint32_t ppm_id); +static void PIOS_RFM22B_Task(void *parameters); static void rfm22_processInt(void); static void rfm22_setTxMode(uint8_t mode); @@ -509,6 +519,14 @@ int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, uint32_t spi_id, uint32_t slave_nu DEBUG_PRINTF(2, "RF frequency: %dHz\n\r", rfm22_getNominalCarrierFrequency()); DEBUG_PRINTF(2, "RF TX power: %d\n\r", rfm22_getTxPower()); + // Register the watchdog timer for the radio driver task +#ifdef PIOS_WDG_RFM22B + PIOS_WDG_RegisterFlag(PIOS_WDG_RFM22B); +#endif /* PIOS_WDG_RFM22B */ + + // Start the driver task. This task controls the radio state machine and removed all of the IO from the IRQ handler. + xTaskCreate(PIOS_RFM22B_Task, (signed char *)"PIOS_RFM22B_Task", STACK_SIZE_BYTES, (void*)rfm22b_dev, TASK_PRIORITY, &(rfm22b_dev->taskHandle)); + // 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); @@ -545,6 +563,30 @@ static void PIOS_RFM22B_RxStart(uint32_t rfm22b_id, uint16_t rx_bytes_avail) } +/** + * The task that controls the radio state machine. + */ +static void PIOS_RFM22B_Task(void *parameters) +{ + struct pios_rfm22b_dev *rfm22b_dev = (struct pios_rfm22b_dev *)parameters; + bool valid = PIOS_RFM22B_validate(rfm22b_dev); + PIOS_Assert(valid); + + while(1) + { +#ifdef PIOS_WDG_RFM22B + // Update the watchdog timer + //PIOS_WDG_UpdateFlag(PIOS_WDG_RFM22B); +#endif /* PIOS_WDG_RFM22B */ + + // Process any pending interrrupt + if ( xSemaphoreTake(g_rfm22b_dev->isrPending, ISR_TIMEOUT / portTICK_RATE_MS) == pdTRUE ) { + rfm22b_dev->rfm32_irqs_processed++; + rfm22_processInt(); + } + } +} + 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; @@ -767,9 +809,6 @@ static uint8_t rfm22_read_noclaim(uint8_t addr) // ************************************ // external interrupt -uint32_t rfm32_errors; -uint32_t rfm32_irqs_processed; - void PIOS_RFM22_EXT_Int(void) { bool valid = PIOS_RFM22B_validate(g_rfm22b_dev); @@ -779,23 +818,12 @@ void PIOS_RFM22_EXT_Int(void) if (!exec_using_spi) { if (xSemaphoreGiveFromISR(g_rfm22b_dev->isrPending, &pxHigherPriorityTaskWoken) != pdTRUE) { // Something went fairly seriously wrong - rfm32_errors++; + g_rfm22b_dev->rfm32_errors++; } portEND_SWITCHING_ISR(pxHigherPriorityTaskWoken); } } -void PIOS_RFM22_processPendingISR(uint32_t wait_ms) -{ - bool valid = PIOS_RFM22B_validate(g_rfm22b_dev); - PIOS_Assert(valid); - - if ( xSemaphoreTake(g_rfm22b_dev->isrPending, wait_ms / portTICK_RATE_MS) == pdTRUE ) { - rfm32_irqs_processed++; - rfm22_processInt(); - } -} - // ************************************ // set/get the current tx power setting From 8ca2e85f4c65d3272c54a2b7b73d208c0b3491ee Mon Sep 17 00:00:00 2001 From: Brian Webb Date: Wed, 12 Sep 2012 18:24:19 -0700 Subject: [PATCH 03/10] RFM22B: Removed incorrect defaulting of tx power level. --- flight/PiOS/Common/pios_rfm22b.c | 76 +++++++++++++------------------- flight/PiOS/inc/pios_rfm22b.h | 1 + 2 files changed, 31 insertions(+), 46 deletions(-) diff --git a/flight/PiOS/Common/pios_rfm22b.c b/flight/PiOS/Common/pios_rfm22b.c index 6029d8488..af15b8cc4 100644 --- a/flight/PiOS/Common/pios_rfm22b.c +++ b/flight/PiOS/Common/pios_rfm22b.c @@ -96,18 +96,6 @@ #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 @@ -181,6 +169,9 @@ struct pios_rfm22b_dev { uint16_t supv_timer; uint16_t resets; + // the transmit power to use for data transmissions + uint8_t tx_power; + // Stats uint32_t rfm32_errors; uint32_t rfm32_irqs_processed; @@ -345,8 +336,6 @@ volatile uint8_t osc_load_cap; // xtal frequency calibration value volatile uint8_t rssi; // the current RSSI (register value) volatile int8_t rssi_dBm; // dBm value -// the transmit power to use for data transmissions -uint8_t tx_power; // the tx power register read back volatile uint8_t tx_pwr; @@ -456,6 +445,9 @@ int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, uint32_t spi_id, uint32_t slave_nu // Initialize the TX pre-buffer pointer. tx_pre_buffer_size = 0; + // Initialize the max tx power level. + PIOS_RFM22B_SetTxPower(*rfm22b_id, cfg->maxTxPower); + // Create our (hopefully) unique 32 bit id from the processor serial number. uint8_t crcs[] = { 0, 0, 0, 0 }; { @@ -511,13 +503,12 @@ int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, uint32_t spi_id, uint32_t slave_nu rfm22_setFreqCalibration(cfg->RFXtalCap); rfm22_setNominalCarrierFrequency(cfg->frequencyHz); rfm22_setDatarate(cfg->maxRFBandwidth, true); - rfm22_setTxPower(cfg->maxTxPower); DEBUG_PRINTF(2, "\n\r"); DEBUG_PRINTF(2, "RF device ID: %x\n\r", rfm22b_dev->deviceID); 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()); + DEBUG_PRINTF(2, "RF TX power: %d\n\r", rfm22b_dev->tx_power); // Register the watchdog timer for the radio driver task #ifdef PIOS_WDG_RFM22B @@ -542,6 +533,26 @@ uint32_t PIOS_RFM22B_DeviceID(uint32_t rfm22b_id) return rfm22b_dev->deviceID; } +void PIOS_RFM22B_SetTxPower(uint32_t rfm22b_id, uint8_t tx_pwr) +{ + struct pios_rfm22b_dev *rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id; + bool valid = PIOS_RFM22B_validate(rfm22b_dev); + PIOS_Assert(valid); + + switch (tx_pwr) + { + case 0: rfm22b_dev->tx_power = RFM22_tx_pwr_txpow_0; break; // +1dBm ... 1.25mW + case 1: rfm22b_dev->tx_power = RFM22_tx_pwr_txpow_1; break; // +2dBm ... 1.6mW + case 2: rfm22b_dev->tx_power = RFM22_tx_pwr_txpow_2; break; // +5dBm ... 3.16mW + case 3: rfm22b_dev->tx_power = RFM22_tx_pwr_txpow_3; break; // +8dBm ... 6.3mW + case 4: rfm22b_dev->tx_power = RFM22_tx_pwr_txpow_4; break; // +11dBm .. 12.6mW + case 5: rfm22b_dev->tx_power = RFM22_tx_pwr_txpow_5; break; // +14dBm .. 25mW + case 6: rfm22b_dev->tx_power = RFM22_tx_pwr_txpow_6; break; // +17dBm .. 50mW + case 7: rfm22b_dev->tx_power = RFM22_tx_pwr_txpow_7; break; // +20dBm .. 100mW + default: break; + } +} + int8_t PIOS_RFM22B_RSSI(uint32_t rfm22b_id) { return rfm22_receivedRSSI(); @@ -824,30 +835,6 @@ void PIOS_RFM22_EXT_Int(void) } } -// ************************************ -// set/get the current tx power setting - -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; - } -} - -uint8_t rfm22_getTxPower(void) -{ - return tx_power; -} - // ************************************ uint32_t rfm22_minFrequency(void) @@ -1238,7 +1225,7 @@ uint8_t rfm22_txStart() // set the tx power rfm22_write(RFM22_tx_power, RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_1 | - RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | tx_power); + RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | g_rfm22b_dev->tx_power); // clear FIFOs rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_ffclrrx | RFM22_opfc2_ffclrtx); @@ -1301,7 +1288,7 @@ static void rfm22_setTxMode(uint8_t mode) // Set the tx power rfm22_write_noclaim(RFM22_tx_power,RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_1 | - RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | tx_power); + RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | g_rfm22b_dev->tx_power); uint8_t fd_bit = rfm22_read_noclaim(RFM22_modulation_mode_control2) & RFM22_mmc2_fd; if (mode == TX_CARRIER_MODE) @@ -1933,9 +1920,6 @@ int rfm22_resetModule(uint8_t mode, uint32_t min_frequency_hz, uint32_t max_freq temperature_reg = 0; - // set the TX power - tx_power = RFM22_DEFAULT_RF_POWER; - tx_pwr = 0; // **************** @@ -2123,7 +2107,7 @@ int rfm22_init_normal(uint32_t id, uint32_t min_frequency_hz, uint32_t max_frequ // 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); + RFM22_tx_pwr_lna_sw | g_rfm22b_dev->tx_power); // TX FIFO Almost Full Threshold (0 - 63) rfm22_write(RFM22_tx_fifo_control1, TX_FIFO_HI_WATERMARK); diff --git a/flight/PiOS/inc/pios_rfm22b.h b/flight/PiOS/inc/pios_rfm22b.h index 176b25710..0cc685da3 100644 --- a/flight/PiOS/inc/pios_rfm22b.h +++ b/flight/PiOS/inc/pios_rfm22b.h @@ -49,6 +49,7 @@ struct pios_rfm22b_cfg { /* Public Functions */ extern int32_t PIOS_RFM22B_Init(uint32_t *rfb22b_id, uint32_t spi_id, uint32_t slave_num, const struct pios_rfm22b_cfg *cfg); +extern void PIOS_RFM22B_SetTxPower(uint32_t rfm22b_id, uint8_t tx_pwr); extern uint32_t PIOS_RFM22B_DeviceID(uint32_t rfb22b_id); extern int8_t PIOS_RFM22B_RSSI(uint32_t rfm22b_id); extern int16_t PIOS_RFM22B_Resets(uint32_t rfm22b_id); From 057227726b733fabb236dbc5cd2e28ae98f85b0a Mon Sep 17 00:00:00 2001 From: Brian Webb Date: Wed, 12 Sep 2012 19:19:38 -0700 Subject: [PATCH 04/10] Radio: Make sure pios_packet_handler is set to 0 when radio module is not initialized. --- flight/Modules/Radio/radio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/flight/Modules/Radio/radio.c b/flight/Modules/Radio/radio.c index 65650d815..7b61dce34 100644 --- a/flight/Modules/Radio/radio.c +++ b/flight/Modules/Radio/radio.c @@ -166,8 +166,10 @@ static int32_t RadioInitialize(void) HwSettingsInitialize(); uint8_t optionalModules[HWSETTINGS_OPTIONALMODULES_NUMELEM]; HwSettingsOptionalModulesGet(optionalModules); - if (optionalModules[HWSETTINGS_OPTIONALMODULES_RADIO] != HWSETTINGS_OPTIONALMODULES_ENABLED) + if (optionalModules[HWSETTINGS_OPTIONALMODULES_RADIO] != HWSETTINGS_OPTIONALMODULES_ENABLED) { + pios_packet_handler = 0; return -1; + } #endif // Initalize out UAVOs From 80509d264e215886450830181c34ef51b9e557e3 Mon Sep 17 00:00:00 2001 From: Brian Webb Date: Fri, 14 Sep 2012 19:30:02 -0700 Subject: [PATCH 05/10] RFM22B: Start at cleaning up the processing interrupt handling, and starting to make it more of a state machine. Also removed the supervisor, which was causing unnecessary resets. The supervisor functionality is not in the the driver thread. --- flight/PiOS/Common/pios_rfm22b.c | 604 +++++++++-------------------- flight/PiOS/inc/pios_rfm22b_priv.h | 13 - 2 files changed, 182 insertions(+), 435 deletions(-) diff --git a/flight/PiOS/Common/pios_rfm22b.c b/flight/PiOS/Common/pios_rfm22b.c index af15b8cc4..cca0a3b9b 100644 --- a/flight/PiOS/Common/pios_rfm22b.c +++ b/flight/PiOS/Common/pios_rfm22b.c @@ -63,7 +63,7 @@ // 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 +#define PIOS_RFM22B_SUPERVISOR_TIMEOUT 100 // ms // this is too adjust the RF module so that it is on frequency #define OSC_LOAD_CAP 0x7F // cap = 12.5pf .. default @@ -144,6 +144,24 @@ enum pios_rfm22b_dev_magic { PIOS_RFM22B_DEV_MAGIC = 0x68e971b6, }; +enum pios_rfm22b_state { + RFM22B_STATE_INITIALIZING, + RFM22B_STATE_RESETTING, + RFM22B_STATE_ERROR, + RFM22B_STATE_RX_WAIT_PREAMBLE, + RFM22B_STATE_RX_WAIT_SYNC, + RFM22B_STATE_RX_DATA, + RFM22B_STATE_RX_COMPLETE, + RFM22B_STATE_TX_START, + RFM22B_STATE_TX_DATA, + RFM22B_STATE_TX_COMPLETE +}; + +enum pios_rfm22b_event { + RFM22B_EVENT_NONE, + RFM22B_EVENT_INT_RECEIVED +}; + struct pios_rfm22b_dev { enum pios_rfm22b_dev_magic magic; struct pios_rfm22b_cfg cfg; @@ -165,19 +183,18 @@ struct pios_rfm22b_dev { pios_com_callback tx_out_cb; uint32_t tx_out_context; - // The supervisor countdown timer. - uint16_t supv_timer; - uint16_t resets; - // the transmit power to use for data transmissions uint8_t tx_power; - // Stats - uint32_t rfm32_errors; - uint32_t rfm32_irqs_processed; -}; + // The state machine state and the current event + enum pios_rfm22b_state state; + enum pios_rfm22b_event event; -uint32_t random32 = 0x459ab8d8; + // Stats + uint16_t resets; + uint32_t errors; + uint32_t irqs_processed; +}; // Must ensure these prefilled arrays match the define sizes static const uint8_t FULL_PREAMBLE[FIFO_SIZE] = @@ -205,10 +222,10 @@ static const uint8_t OUT_FF[64] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; /* Local function forwared declarations */ -static void PIOS_RFM22B_Supervisor(uint32_t ppm_id); static void PIOS_RFM22B_Task(void *parameters); -static void rfm22_processInt(void); -static void rfm22_setTxMode(uint8_t mode); +static void PIOS_RFM22B_SetRxMode(enum pios_rfm22b_event state); +static void PIOS_RFM22B_InjectEvent(struct pios_rfm22b_dev *rfm22b_dev, enum pios_rfm22b_event event, bool inISR); +static void rfm22_processInt(struct pios_rfm22b_dev *rfm22b_dev); // SPI read/write functions static void rfm22_write(uint8_t addr, uint8_t data); @@ -301,8 +318,6 @@ volatile bool exec_using_spi; // set this if you want to access the SPI 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 @@ -366,8 +381,6 @@ volatile int8_t rx_packet_afc_Hz; // the receive packet frequency offset 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; // @@ -376,8 +389,6 @@ uint16_t timeout_ms = 20000; // uint16_t timeout_sync_ms = 3; // uint16_t timeout_data_ms = 20; // -struct pios_rfm22b_dev * rfm22b_dev_g; - static bool PIOS_RFM22B_validate(struct pios_rfm22b_dev * rfm22b_dev) { @@ -392,7 +403,6 @@ static struct pios_rfm22b_dev * PIOS_RFM22B_alloc(void) rfm22b_dev = (struct pios_rfm22b_dev *)pvPortMalloc(sizeof(*rfm22b_dev)); rfm22b_dev->spi_id = 0; if (!rfm22b_dev) return(NULL); - rfm22b_dev_g = rfm22b_dev; rfm22b_dev->magic = PIOS_RFM22B_DEV_MAGIC; return(rfm22b_dev); @@ -433,6 +443,15 @@ int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, uint32_t spi_id, uint32_t slave_nu rfm22b_dev->slave_num = slave_num; rfm22b_dev->spi_id = spi_id; + // Set the state to initializing. + rfm22b_dev->state = RFM22B_STATE_INITIALIZING; + rfm22b_dev->event = RFM22B_EVENT_NONE; + + // Initialize the stats. + rfm22b_dev->resets = 0; + rfm22b_dev->errors = 0; + rfm22b_dev->irqs_processed = 0; + // Bind the configuration to the device instance rfm22b_dev->cfg = *cfg; @@ -460,10 +479,6 @@ int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, uint32_t spi_id, uint32_t slave_nu 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); - // Initialize the supervisor timer. - rfm22b_dev->supv_timer = PIOS_RFM22B_SUPERVISOR_TIMEOUT; - rfm22b_dev->resets = 0; - // Initialize the external interrupt. PIOS_EXTI_Init(cfg->exti_cfg); @@ -518,26 +533,70 @@ int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, uint32_t spi_id, uint32_t slave_nu // Start the driver task. This task controls the radio state machine and removed all of the IO from the IRQ handler. xTaskCreate(PIOS_RFM22B_Task, (signed char *)"PIOS_RFM22B_Task", STACK_SIZE_BYTES, (void*)rfm22b_dev, TASK_PRIORITY, &(rfm22b_dev->taskHandle)); - // 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); - } - return(0); } +/** + * The RFM22B external interrupt routine. + */ +void PIOS_RFM22_EXT_Int(void) +{ + if (!PIOS_RFM22B_validate(g_rfm22b_dev)) + return; + + // Inject an interrupt event into the state machine. + PIOS_RFM22B_InjectEvent(g_rfm22b_dev, RFM22B_EVENT_INT_RECEIVED, true); +} + +/** + * Inject an event into the RFM22B state machine. + * \param[in] rfm22b_dev The device structure + * \param[in] event The event to inject + * \param[in] inISR Is this being called from an interrrup service routine? + */ +static void PIOS_RFM22B_InjectEvent(struct pios_rfm22b_dev *rfm22b_dev, enum pios_rfm22b_event event, bool inISR) +{ + + // Store the event. + rfm22b_dev->event = event; + + // Signal the semaphore to wake up the handler thread. + if (inISR) { + portBASE_TYPE pxHigherPriorityTaskWoken; + if (xSemaphoreGiveFromISR(rfm22b_dev->isrPending, &pxHigherPriorityTaskWoken) != pdTRUE) { + // Something went fairly seriously wrong + rfm22b_dev->errors++; + } + portEND_SWITCHING_ISR(pxHigherPriorityTaskWoken); + } + else + { + if (xSemaphoreGive(rfm22b_dev->isrPending) != pdTRUE) { + // Something went fairly seriously wrong + rfm22b_dev->errors++; + } + } +} + +/** + * Returns the unique device ID for th RFM22B device. + * \param[in] rfm22b_id The RFM22B device index. + * \return The unique device ID + */ 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; + if(PIOS_RFM22B_validate(rfm22b_dev)) + return rfm22b_dev->deviceID; + else + return 0; } void PIOS_RFM22B_SetTxPower(uint32_t rfm22b_id, uint8_t tx_pwr) { struct pios_rfm22b_dev *rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id; - bool valid = PIOS_RFM22B_validate(rfm22b_dev); - PIOS_Assert(valid); + if(!PIOS_RFM22B_validate(rfm22b_dev)) + return; switch (tx_pwr) { @@ -580,20 +639,46 @@ static void PIOS_RFM22B_RxStart(uint32_t rfm22b_id, uint16_t rx_bytes_avail) static void PIOS_RFM22B_Task(void *parameters) { struct pios_rfm22b_dev *rfm22b_dev = (struct pios_rfm22b_dev *)parameters; - bool valid = PIOS_RFM22B_validate(rfm22b_dev); - PIOS_Assert(valid); + if (!PIOS_RFM22B_validate(rfm22b_dev)) + return; + static portTickType lastEventTime; while(1) { #ifdef PIOS_WDG_RFM22B // Update the watchdog timer - //PIOS_WDG_UpdateFlag(PIOS_WDG_RFM22B); + PIOS_WDG_UpdateFlag(PIOS_WDG_RFM22B); #endif /* PIOS_WDG_RFM22B */ - // Process any pending interrrupt + // Wait for a signal indicating an external interrupt or a pending send/receive request. if ( xSemaphoreTake(g_rfm22b_dev->isrPending, ISR_TIMEOUT / portTICK_RATE_MS) == pdTRUE ) { - rfm22b_dev->rfm32_irqs_processed++; - rfm22_processInt(); + rfm22b_dev->irqs_processed++; + lastEventTime = xTaskGetTickCount(); + rfm22_processInt(rfm22b_dev); + } + else + { + // Has it been too long since the last event? + portTickType timeSinceEvent = xTaskGetTickCount() - lastEventTime; + if ((timeSinceEvent / portTICK_RATE_MS) > PIOS_RFM22B_SUPERVISOR_TIMEOUT) + { + rfm22b_dev->resets++; + 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); + + /* Start a packet transfer if one is available. */ + rfm22b_dev->state = RFM22B_STATE_RX_WAIT_PREAMBLE; + if(rfm22b_dev->state == RFM22B_STATE_RX_WAIT_PREAMBLE) + { + /* Switch to RX mode */ + PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); + } + } } } } @@ -616,9 +701,8 @@ static void PIOS_RFM22B_TxStart(uint32_t rfm22b_id, uint16_t tx_bytes_avail) 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 || - rf_mode == TX_PN_MODE || rf_mode == RX_SCAN_SPECTRUM) + // we are currently transmitting? + if (rfm22b_dev->state == RFM22B_STATE_TX_DATA) return; // is the channel clear to transmit on? @@ -674,47 +758,6 @@ static void PIOS_RFM22B_RegisterTxCallback(uint32_t rfm22b_id, pios_com_callback rfm22b_dev->tx_out_cb = tx_out_cb; } -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; - } - - /* If we're waiting for a receive, we just need to make sure that there are no packets waiting to be transmitted. */ - if(rf_mode == RX_WAIT_PREAMBLE_MODE) - { - /* Start a packet transfer if one is available. */ - PIOS_RFM22B_TxStart(rfm22b_id, 0); - return; - } - - /* The radio must be locked up if the timer reaches 0 */ - if(--(rfm22b_dev->supv_timer) != 0) - return; - ++(rfm22b_dev->resets); - - 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); - - /* Start a packet transfer if one is available. */ - rf_mode = RX_WAIT_PREAMBLE_MODE; - PIOS_RFM22B_TxStart(rfm22b_id, 0); - if(rf_mode == RX_WAIT_PREAMBLE_MODE) - { - /* Switch to RX mode */ - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); - } -} - // ************************************ // SPI read/write @@ -769,7 +812,6 @@ static void rfm22_write(uint8_t addr, uint8_t data) * toggle the NSS line * @param[in] addr The address of the RFM22b register to write * @param[in] data The data to write to that register - */ static void rfm22_write_noclaim(uint8_t addr, uint8_t data) { uint8_t buf[2] = {addr | 0x80, data}; @@ -779,6 +821,7 @@ static void rfm22_write_noclaim(uint8_t addr, uint8_t data) rfm22_deassertCs(); } } +*/ /** @@ -809,7 +852,7 @@ static uint8_t rfm22_read_noclaim(uint8_t addr) { uint8_t out[2] = {addr & 0x7F, 0xFF}; uint8_t in[2]; - if (PIOS_RFM22B_validate(rfm22b_dev_g)) { + if (PIOS_RFM22B_validate(g_rfm22b_dev)) { rfm22_assertCs(); PIOS_SPI_TransferBlock(g_rfm22b_dev->spi_id, out, in, sizeof(out), NULL); rfm22_deassertCs(); @@ -817,24 +860,6 @@ static uint8_t rfm22_read_noclaim(uint8_t addr) return in[1]; } -// ************************************ -// external interrupt - -void PIOS_RFM22_EXT_Int(void) -{ - bool valid = PIOS_RFM22B_validate(g_rfm22b_dev); - PIOS_Assert(valid); - - portBASE_TYPE pxHigherPriorityTaskWoken; - if (!exec_using_spi) { - if (xSemaphoreGiveFromISR(g_rfm22b_dev->isrPending, &pxHigherPriorityTaskWoken) != pdTRUE) { - // Something went fairly seriously wrong - g_rfm22b_dev->rfm32_errors++; - } - portEND_SWITCHING_ISR(pxHigherPriorityTaskWoken); - } -} - // ************************************ uint32_t rfm22_minFrequency(void) @@ -1082,51 +1107,7 @@ uint32_t rfm22_getDatarate(void) // ************************************ -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) +static void PIOS_RFM22B_SetRxMode(enum pios_rfm22b_event state) { exec_using_spi = true; @@ -1140,33 +1121,18 @@ void rfm22_setRxMode(uint8_t mode, bool multi_packet_mode) 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; - rfm22_write(RFM22_modulation_mode_control2, fd_bit | RFM22_mmc2_dtmod_fifo | - RFM22_mmc2_modtyp_gfsk); - } - // empty the rx buffer rx_buffer_wr = 0; // reset the timer rfm22_int_timer = 0; - rf_mode = mode; + g_rfm22b_dev->state = state; // Clear the TX buffer. tx_data_rd = tx_data_wr = 0; // 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 { - rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_rxmpk | RFM22_opfc2_ffclrrx | - RFM22_opfc2_ffclrtx); - rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_rxmpk); - } + rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_ffclrrx | RFM22_opfc2_ffclrtx); + rfm22_write(RFM22_op_and_func_ctrl2, 0x00); // enable RX interrupts rfm22_write(RFM22_interrupt_enable1, RFM22_ie1_encrcerror | RFM22_ie1_enpkvalid | @@ -1193,9 +1159,6 @@ uint8_t rfm22_txStart() exec_using_spi = true; - // Initialize the supervisor timer. - rfm22b_dev_g->supv_timer = PIOS_RFM22B_SUPERVISOR_TIMEOUT; - // disable interrupts rfm22_write(RFM22_interrupt_enable1, 0x00); rfm22_write(RFM22_interrupt_enable2, 0x00); @@ -1253,7 +1216,7 @@ uint8_t rfm22_txStart() // reset the timer rfm22_int_timer = 0; - rf_mode = TX_DATA_MODE; + g_rfm22b_dev->state = RFM22B_STATE_TX_DATA; // enable TX interrupts rfm22_write(RFM22_interrupt_enable1, RFM22_ie1_enpksent | RFM22_ie1_entxffaem); @@ -1267,104 +1230,10 @@ uint8_t rfm22_txStart() return 1; } - -static void rfm22_setTxMode(uint8_t mode) -{ - if (mode != TX_DATA_MODE && mode != TX_STREAM_MODE && mode != TX_CARRIER_MODE && mode != TX_PN_MODE) - return; // invalid mode - - rfm22_claimBus(); - rfm22_assertCs(); - - // Disaable interrupts (IE1, IE2 = 0) - uint8_t out_buf[3] = {RFM22_interrupt_enable1 | 0x80, 0x00, 0x00}; - PIOS_SPI_TransferBlock(g_rfm22b_dev->spi_id, out_buf, NULL, sizeof(out_buf), NULL); - rfm22_deassertCs(); - - // TUNE mode - rfm22_write_noclaim(RFM22_op_and_func_ctrl1,RFM22_opfc1_pllon); - - RX_LED_OFF; - - // Set the tx power - rfm22_write_noclaim(RFM22_tx_power,RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_1 | - RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | g_rfm22b_dev->tx_power); - - uint8_t fd_bit = rfm22_read_noclaim(RFM22_modulation_mode_control2) & RFM22_mmc2_fd; - if (mode == TX_CARRIER_MODE) - // blank carrier mode - for testing - rfm22_write_noclaim(RFM22_modulation_mode_control2, fd_bit | RFM22_mmc2_dtmod_pn9 | - RFM22_mmc2_modtyp_none); // FIFO mode, Blank carrier - else if (mode == TX_PN_MODE) - // psuedo random data carrier mode - for testing - rfm22_write_noclaim(RFM22_modulation_mode_control2, fd_bit | RFM22_mmc2_dtmod_pn9 | - RFM22_mmc2_modtyp_gfsk); // FIFO mode, PN9 carrier - else - // data transmission - // FIFO mode, GFSK modulation - rfm22_write_noclaim(RFM22_modulation_mode_control2, fd_bit | RFM22_mmc2_dtmod_fifo | - RFM22_mmc2_modtyp_gfsk); - - // clear FIFOs - rfm22_write_noclaim(RFM22_op_and_func_ctrl2, RFM22_opfc2_ffclrrx | RFM22_opfc2_ffclrtx); - rfm22_write_noclaim(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) - // set the total number of data bytes we are going to transmit - rfm22_write_noclaim(RFM22_transmit_packet_length, wr); - - uint16_t i = 0; - rfm22_assertCs(); - PIOS_SPI_TransferByte(g_rfm22b_dev->spi_id, 0x80 | RFM22_fifo_access); // Initiate burst write - if (mode == TX_STREAM_MODE) { - if (rd >= wr) - i += PIOS_SPI_TransferBlock(g_rfm22b_dev->spi_id, FULL_PREAMBLE, NULL, sizeof(FULL_PREAMBLE), NULL); - else // add the RF heaader - i += PIOS_SPI_TransferBlock(g_rfm22b_dev->spi_id, HEADER, NULL, sizeof(HEADER), NULL); - } - - // Send data if there is any and there is space in the buffer available - // Bytes available to send minus how many we have sent - int32_t bytes_to_send = wr - rd; - bytes_to_send = ((bytes_to_send + i)> FIFO_SIZE) ? (FIFO_SIZE - i) : bytes_to_send; - if (bytes_to_send > 0) - rd += PIOS_SPI_TransferBlock(g_rfm22b_dev->spi_id, &tx_buffer[rd], NULL, bytes_to_send, NULL); - - rfm22_deassertCs(); - - tx_data_rd = rd; - } - - // reset the timer - rfm22_int_timer = 0; - - rf_mode = mode; - - // enable TX interrupts - // rfm22_write(RFM22_interrupt_enable1, RFM22_ie1_enpksent | RFM22_ie1_entxffaem | RFM22_ie1_enfferr); - rfm22_write_noclaim(RFM22_interrupt_enable1, RFM22_ie1_enpksent | RFM22_ie1_entxffaem); - - // read interrupt status - clear interrupts - rfm22_read_noclaim(RFM22_interrupt_status1); - rfm22_read_noclaim(RFM22_interrupt_status2); - - // enable the transmitter - // rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton | RFM22_opfc1_txon); - rfm22_write_noclaim(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon | RFM22_opfc1_txon); - - rfm22_releaseBus(); - TX_LED_ON; -} - // ************************************ // external interrupt line triggered (or polled) from the rf chip -void rfm22_processRxInt(void) +void rfm22_processRxInt(struct pios_rfm22b_dev *rfm22b_dev) { register uint8_t int_stat1 = int_status1; register uint8_t int_stat2 = int_status2; @@ -1372,21 +1241,21 @@ void rfm22_processRxInt(void) // FIFO under/over flow error. Restart RX mode. if (device_status & (RFM22_ds_ffunfl | RFM22_ds_ffovfl)) { - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); return; } // Valid preamble detected - if (int_stat2 & RFM22_is2_ipreaval && (rf_mode == RX_WAIT_PREAMBLE_MODE)) + if (int_stat2 & RFM22_is2_ipreaval && (rfm22b_dev->state == RFM22B_STATE_RX_WAIT_PREAMBLE)) { - rf_mode = RX_WAIT_SYNC_MODE; + rfm22b_dev->state = RFM22B_STATE_RX_WAIT_SYNC; RX_LED_ON; } // Sync word detected - if (int_stat2 & RFM22_is2_iswdet && ((rf_mode == RX_WAIT_PREAMBLE_MODE || rf_mode == RX_WAIT_SYNC_MODE))) + if (int_stat2 & RFM22_is2_iswdet && ((rfm22b_dev->state == RFM22B_STATE_RX_WAIT_PREAMBLE || rfm22b_dev->state == RFM22B_STATE_RX_WAIT_SYNC))) { - rf_mode = RX_DATA_MODE; + rfm22b_dev->state = RFM22B_STATE_RX_DATA; RX_LED_ON; // read the 10-bit signed afc correction value @@ -1407,7 +1276,7 @@ void rfm22_processRxInt(void) // RX FIFO almost full, it needs emptying if (int_stat1 & RFM22_is1_irxffafull) { - if (rf_mode == RX_DATA_MODE) + if (rfm22b_dev->state == RFM22B_STATE_RX_DATA) { // read data from the rf chips FIFO buffer // read the total length of the packet data @@ -1416,22 +1285,22 @@ void rfm22_processRxInt(void) // The received packet is going to be larger than the specified length if ((rx_buffer_wr + RX_FIFO_HI_WATERMARK) > len) { - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); return; } // Another packet length error. if (((rx_buffer_wr + RX_FIFO_HI_WATERMARK) >= len) && !(int_stat1 & RFM22_is1_ipkvalid)) { - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); return; } // Fetch the data from the RX FIFO rfm22_claimBus(); rfm22_assertCs(); - PIOS_SPI_TransferByte(rfm22b_dev_g->spi_id,RFM22_fifo_access & 0x7F); - rx_buffer_wr += (PIOS_SPI_TransferBlock(rfm22b_dev_g->spi_id,OUT_FF, + PIOS_SPI_TransferByte(rfm22b_dev->spi_id,RFM22_fifo_access & 0x7F); + rx_buffer_wr += (PIOS_SPI_TransferBlock(rfm22b_dev->spi_id,OUT_FF, (uint8_t *) &rx_buffer[rx_buffer_wr],RX_FIFO_HI_WATERMARK,NULL) == 0) ? RX_FIFO_HI_WATERMARK : 0; rfm22_deassertCs(); @@ -1440,8 +1309,8 @@ void rfm22_processRxInt(void) // Clear the RX FIFO rfm22_claimBus(); rfm22_assertCs(); - PIOS_SPI_TransferByte(rfm22b_dev_g->spi_id,RFM22_fifo_access & 0x7F); - PIOS_SPI_TransferBlock(rfm22b_dev_g->spi_id,OUT_FF,NULL,RX_FIFO_HI_WATERMARK,NULL); + PIOS_SPI_TransferByte(rfm22b_dev->spi_id,RFM22_fifo_access & 0x7F); + PIOS_SPI_TransferBlock(rfm22b_dev->spi_id,OUT_FF,NULL,RX_FIFO_HI_WATERMARK,NULL); rfm22_deassertCs(); rfm22_releaseBus(); } @@ -1451,7 +1320,7 @@ void rfm22_processRxInt(void) if (int_stat1 & RFM22_is1_icrerror) { rfm22_int_timer = 0; // reset the timer - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); return; } @@ -1469,8 +1338,8 @@ void rfm22_processRxInt(void) // Fetch the data from the RX FIFO rfm22_claimBus(); rfm22_assertCs(); - PIOS_SPI_TransferByte(rfm22b_dev_g->spi_id,RFM22_fifo_access & 0x7F); - rx_buffer_wr += (PIOS_SPI_TransferBlock(rfm22b_dev_g->spi_id,OUT_FF, + PIOS_SPI_TransferByte(rfm22b_dev->spi_id,RFM22_fifo_access & 0x7F); + rx_buffer_wr += (PIOS_SPI_TransferBlock(rfm22b_dev->spi_id,OUT_FF, (uint8_t *) &rx_buffer[rx_buffer_wr],bytes_to_read,NULL) == 0) ? bytes_to_read : 0; rfm22_deassertCs(); @@ -1480,7 +1349,7 @@ void rfm22_processRxInt(void) if (rx_buffer_wr != len) { // we have a packet length error .. discard the packet - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); return; } @@ -1497,9 +1366,9 @@ void rfm22_processRxInt(void) rx_buffer[rx_buffer_wr++] = rx_packet_start_afc_Hz; // 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, - rx_buffer_wr, NULL, &need_yield); + if (rfm22b_dev->rx_in_cb) + (rfm22b_dev->rx_in_cb)(rfm22b_dev->rx_in_context, (uint8_t*)rx_buffer, + rx_buffer_wr, NULL, &need_yield); rx_buffer_wr = 0; } @@ -1507,13 +1376,13 @@ void rfm22_processRxInt(void) if(!rfm22_txStart()) { // Switch to RX mode - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); } } } -void rfm22_processTxInt(void) +void rfm22_processTxInt(struct pios_rfm22b_dev *rfm22b_dev) { register uint8_t int_stat1 = int_status1; @@ -1523,7 +1392,7 @@ void rfm22_processTxInt(void) // FIFO under/over flow error. Back to RX mode. if (device_status & (RFM22_ds_ffunfl | RFM22_ds_ffovfl)) { - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); return; } @@ -1531,7 +1400,7 @@ void rfm22_processTxInt(void) if (rfm22_int_timer >= timeout_data_ms) { rfm22_int_time_outs++; - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); return; } @@ -1541,7 +1410,7 @@ void rfm22_processTxInt(void) if (rfm22_int_timer >= 100) { rfm22_int_time_outs++; - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // back to rx mode + PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); // back to rx mode return; } } @@ -1570,30 +1439,27 @@ void rfm22_processTxInt(void) if(!rfm22_txStart()) { // Switch to RX mode - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); return; } } } -static void rfm22_processInt(void) +static void rfm22_processInt(struct pios_rfm22b_dev *rfm22b_dev) { // we haven't yet been initialized - if (!initialized || power_on_reset || !PIOS_RFM22B_validate(rfm22b_dev_g)) + if (!PIOS_RFM22B_validate(rfm22b_dev)) return; exec_using_spi = true; - // Reset the supervisor timer. - rfm22b_dev_g->supv_timer = PIOS_RFM22B_SUPERVISOR_TIMEOUT; - // 1. Read the interrupt statuses with burst read rfm22_claimBus(); // Set RC and the semaphore uint8_t write_buf[3] = {RFM22_interrupt_status1 & 0x7f, 0xFF, 0xFF}; uint8_t read_buf[3]; rfm22_assertCs(); - PIOS_SPI_TransferBlock(g_rfm22b_dev->spi_id, write_buf, read_buf, sizeof(write_buf), NULL); + PIOS_SPI_TransferBlock(rfm22b_dev->spi_id, write_buf, read_buf, sizeof(write_buf), NULL); rfm22_deassertCs(); int_status1 = read_buf[1]; int_status2 = read_buf[2]; @@ -1608,8 +1474,7 @@ static void rfm22_processInt(void) rfm22_releaseBus(); // Read the RSSI if we're in RX mode - if (rf_mode != TX_DATA_MODE && rf_mode != TX_STREAM_MODE && - rf_mode != TX_CARRIER_MODE && rf_mode != TX_PN_MODE) + if (rfm22b_dev->state != RFM22B_STATE_TX_DATA) { // read rx signal strength .. 45 = -100dBm, 205 = -20dBm rssi = rfm22_read(RFM22_rssi); @@ -1623,44 +1488,28 @@ static void rfm22_processInt(void) // the RF module has gone and done a reset - we need to re-initialize the rf module if (int_status2 & RFM22_is2_ipor) { - initialized = false; - power_on_reset = true; + rfm22b_dev->state = RFM22B_STATE_RESETTING; // Need to do something here! return; } - switch (rf_mode) + switch (rfm22b_dev->state) { - case RX_SCAN_SPECTRUM: + case RFM22B_STATE_RX_WAIT_PREAMBLE: + case RFM22B_STATE_RX_WAIT_SYNC: + case RFM22B_STATE_RX_DATA: + + rfm22_processRxInt(rfm22b_dev); break; - case RX_WAIT_PREAMBLE_MODE: - case RX_WAIT_SYNC_MODE: - case RX_DATA_MODE: - - rfm22_processRxInt(); - break; - - case TX_DATA_MODE: - case TX_STREAM_MODE: - - rfm22_processTxInt(); - break; - - case TX_CARRIER_MODE: - case TX_PN_MODE: - - // if (rfm22_int_timer >= TX_TEST_MODE_TIMELIMIT_MS) // 'nn'ms limit - // { - // rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // back to rx mode - // tx_data_rd = tx_data_wr = 0; // wipe TX buffer - // break; - // } + case RFM22B_STATE_TX_DATA: + rfm22_processTxInt(rfm22b_dev); 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 + // to rx mode + PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); break; } @@ -1698,70 +1547,16 @@ int32_t rfm22_receivedAFCHz(void) // ************************************ -// ************************************ - -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 g_rfm22b_dev->state; } // 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 (g_rfm22b_dev->state == RFM22B_STATE_TX_DATA); } // return true if the channel is clear to transmit on @@ -1771,7 +1566,7 @@ bool rfm22_channelIsClear(void) // we haven't yet been initialized return false; - if (rf_mode != RX_WAIT_PREAMBLE_MODE && rf_mode != RX_WAIT_SYNC_MODE) + if (g_rfm22b_dev->state != RFM22B_STATE_RX_WAIT_PREAMBLE && g_rfm22b_dev->state != RFM22B_STATE_RX_WAIT_SYNC) // we are receiving something or we are transmitting or we are scanning the spectrum return false; @@ -1781,13 +1576,7 @@ bool rfm22_channelIsClear(void) // return true if the transmiter is ready for use bool rfm22_txReady(void) { - if (!initialized) - // we haven't yet been initialized - return false; - - return (tx_data_rd == 0 && tx_data_wr == 0 && rf_mode != TX_DATA_MODE && - rf_mode != TX_STREAM_MODE && rf_mode != TX_CARRIER_MODE && rf_mode != TX_PN_MODE && - rf_mode != RX_SCAN_SPECTRUM); + return (tx_data_rd == 0 && tx_data_wr == 0 && g_rfm22b_dev->state != RFM22B_STATE_TX_DATA); } // ************************************ @@ -1797,25 +1586,11 @@ 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) @@ -1823,19 +1598,6 @@ 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 @@ -1843,8 +1605,6 @@ int rfm22_resetModule(uint8_t mode, uint32_t min_frequency_hz, uint32_t max_freq { initialized = false; - power_on_reset = false; - // **************** exec_using_spi = true; @@ -1886,7 +1646,7 @@ int rfm22_resetModule(uint8_t mode, uint32_t min_frequency_hz, uint32_t max_freq // **************** - rf_mode = mode; + g_rfm22b_dev->state = mode; device_status = int_status1 = int_status2 = ezmac_status = 0; @@ -1992,7 +1752,7 @@ int rfm22_resetModule(uint8_t mode, uint32_t min_frequency_hz, uint32_t max_freq // choose the 3 GPIO pin functions rfm22_write(RFM22_io_port_config, RFM22_io_port_default); // GPIO port use default value - if (rfm22b_dev_g->cfg.gpio_direction == GPIO0_TX_GPIO1_RX) { + if (g_rfm22b_dev->cfg.gpio_direction == GPIO0_TX_GPIO1_RX) { 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) } else { @@ -2011,7 +1771,7 @@ int rfm22_resetModule(uint8_t mode, uint32_t min_frequency_hz, uint32_t max_freq int rfm22_init_normal(uint32_t id, uint32_t min_frequency_hz, uint32_t max_frequency_hz, uint32_t freq_hop_step_size) { - int res = rfm22_resetModule(RX_WAIT_PREAMBLE_MODE, min_frequency_hz, max_frequency_hz); + int res = rfm22_resetModule(RFM22B_STATE_RX_WAIT_PREAMBLE, min_frequency_hz, max_frequency_hz); if (res < 0) return res; @@ -2118,7 +1878,7 @@ int rfm22_init_normal(uint32_t id, uint32_t min_frequency_hz, uint32_t max_frequ // RX FIFO Almost Full Threshold (0 - 63) rfm22_write(RFM22_rx_fifo_control, RX_FIFO_HI_WATERMARK); - rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); + PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); initialized = true; diff --git a/flight/PiOS/inc/pios_rfm22b_priv.h b/flight/PiOS/inc/pios_rfm22b_priv.h index 4535a472e..ce6bf96f5 100644 --- a/flight/PiOS/inc/pios_rfm22b_priv.h +++ b/flight/PiOS/inc/pios_rfm22b_priv.h @@ -50,17 +50,6 @@ extern const struct pios_com_driver pios_rfm22b_com_driver; // ************************************ -enum { RX_SCAN_SPECTRUM = 0, - RX_WAIT_PREAMBLE_MODE, - RX_WAIT_SYNC_MODE, - RX_DATA_MODE, - TX_DATA_MODE, - TX_STREAM_MODE, - TX_CARRIER_MODE, - TX_PN_MODE}; - -// ************************************ - #define BIT0 (1u << 0) #define BIT1 (1u << 1) #define BIT2 (1u << 2) @@ -609,8 +598,6 @@ uint32_t rfm22_freqHopSize(void); void rfm22_setDatarate(uint32_t datarate_bps, bool data_whitening); uint32_t rfm22_getDatarate(void); -void rfm22_setRxMode(uint8_t mode, bool multi_packet_mode); - int8_t rfm22_getRSSI(void); int8_t rfm22_receivedRSSI(void); From 61200f01f5707815da82f1be29e4bd985f0be833 Mon Sep 17 00:00:00 2001 From: Brian Webb Date: Sun, 16 Sep 2012 19:33:30 -0700 Subject: [PATCH 06/10] RFM22B: Major refactoring of te RFM22B driver to implement a state machine for the driver. The state machine should now be complete, and the driver seems to be working pretty well on both the RM and the pipx. --- flight/Libraries/packet_handler.c | 2 +- flight/PiOS/Common/pios_rfm22b.c | 840 ++++++++++++++++------------- flight/PiOS/inc/pios_rfm22b.h | 6 +- flight/PiOS/inc/pios_rfm22b_priv.h | 17 - 4 files changed, 461 insertions(+), 404 deletions(-) diff --git a/flight/Libraries/packet_handler.c b/flight/Libraries/packet_handler.c index c417371d7..9226c74ae 100644 --- a/flight/Libraries/packet_handler.c +++ b/flight/Libraries/packet_handler.c @@ -475,12 +475,12 @@ static uint8_t PHLTransmitPacket(PHPacketDataHandle data, PHPacketHandle p) // Set the sequence ID to the current ID. p->header.tx_seq = data->tx_seq_id++; + p->header.source_id = data->cfg.source_id; // Add the error correcting code. encode_data((unsigned char*)p, PHPacketSize(p), (unsigned char*)p); // Transmit the packet using the output stream. - p->header.source_id = data->cfg.source_id; if(data->output_stream(p) == -1) return 0; diff --git a/flight/PiOS/Common/pios_rfm22b.c b/flight/PiOS/Common/pios_rfm22b.c index cca0a3b9b..7a0e145dd 100644 --- a/flight/PiOS/Common/pios_rfm22b.c +++ b/flight/PiOS/Common/pios_rfm22b.c @@ -59,6 +59,8 @@ #define STACK_SIZE_BYTES 200 #define TASK_PRIORITY (tskIDLE_PRIORITY + 2) #define ISR_TIMEOUT 5 // ms +#define EVENT_QUEUE_SIZE 5 +#define PACKET_QUEUE_SIZE 3 // RTC timer is running at 625Hz (1.6ms or 5 ticks == 8ms). // A 256 byte message at 56kbps should take less than 40ms @@ -145,21 +147,35 @@ enum pios_rfm22b_dev_magic { }; enum pios_rfm22b_state { + RFM22B_STATE_UNINITIALIZED, RFM22B_STATE_INITIALIZING, - RFM22B_STATE_RESETTING, RFM22B_STATE_ERROR, - RFM22B_STATE_RX_WAIT_PREAMBLE, - RFM22B_STATE_RX_WAIT_SYNC, + RFM22B_STATE_RX_MODE, + RFM22B_STATE_WAIT_PREAMBLE, + RFM22B_STATE_WAIT_SYNC, RFM22B_STATE_RX_DATA, - RFM22B_STATE_RX_COMPLETE, RFM22B_STATE_TX_START, RFM22B_STATE_TX_DATA, - RFM22B_STATE_TX_COMPLETE + RFM22B_STATE_FATAL_ERROR, + + RFM22B_STATE_NUM_STATES // Must be last }; enum pios_rfm22b_event { - RFM22B_EVENT_NONE, - RFM22B_EVENT_INT_RECEIVED + RFM22B_EVENT_INITIALIZE, + RFM22B_EVENT_INT_RECEIVED, + RFM22B_EVENT_TX_MODE, + RFM22B_EVENT_RX_MODE, + RFM22B_EVENT_PREAMBLE_DETECTED, + RFM22B_EVENT_SYNC_DETECTED, + RFM22B_EVENT_RX_COMPLETE, + RFM22B_EVENT_SEND_PACKET, + RFM22B_EVENT_TX_START, + RFM22B_EVENT_TX_COMPLETE, + RFM22B_EVENT_ERROR, + RFM22B_EVENT_FATAL_ERROR, + + RFM22B_EVENT_NUM_EVENTS // Must be last }; struct pios_rfm22b_dev { @@ -188,12 +204,34 @@ struct pios_rfm22b_dev { // The state machine state and the current event enum pios_rfm22b_state state; - enum pios_rfm22b_event event; + // The event queue handle + xQueueHandle eventQueue; + + // device status register + uint8_t device_status; + // interrupt status register 1 + uint8_t int_status1; + // interrupt status register 2 + uint8_t int_status2; + // ezmac status register + uint8_t ezmac_status; // Stats uint16_t resets; uint32_t errors; uint32_t irqs_processed; + // the current RSSI (register value) + uint8_t rssi; + // RSSI in dBm + int8_t rssi_dBm; + + // The packet queue handle + xQueueHandle packetQueue; +}; + +struct pios_rfm22b_transition { + enum pios_rfm22b_event (*entry_fn) (struct pios_rfm22b_dev *rfm22b_dev); + enum pios_rfm22b_state next_state[RFM22B_EVENT_NUM_EVENTS]; }; // Must ensure these prefilled arrays match the define sizes @@ -223,14 +261,27 @@ static const uint8_t OUT_FF[64] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* Local function forwared declarations */ static void PIOS_RFM22B_Task(void *parameters); -static void PIOS_RFM22B_SetRxMode(enum pios_rfm22b_event state); static void PIOS_RFM22B_InjectEvent(struct pios_rfm22b_dev *rfm22b_dev, enum pios_rfm22b_event event, bool inISR); -static void rfm22_processInt(struct pios_rfm22b_dev *rfm22b_dev); +static bool rfm22_readStatus(struct pios_rfm22b_dev *rfm22b_dev); +static enum pios_rfm22b_event rfm22_setRxMode(struct pios_rfm22b_dev *rfm22b_dev); +static enum pios_rfm22b_event rfm22_detectPreamble(struct pios_rfm22b_dev *rfm22b_dev); +static enum pios_rfm22b_event rfm22_detectSync(struct pios_rfm22b_dev *rfm22b_dev); +static enum pios_rfm22b_event rfm22_rxData(struct pios_rfm22b_dev *rfm22b_dev); +static enum pios_rfm22b_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev); +static enum pios_rfm22b_event rfm22_txStart(struct pios_rfm22b_dev *rfm22b_dev); +static enum pios_rfm22b_event rfm22_txData(struct pios_rfm22b_dev *rfm22b_dev); +static enum pios_rfm22b_event rfm22_process_state_transition(struct pios_rfm22b_dev *rfm22b_dev, enum pios_rfm22b_event event); +static enum pios_rfm22b_event rfm22_error(struct pios_rfm22b_dev *rfm22b_dev); +static enum pios_rfm22b_event rfm22_fatal_error(struct pios_rfm22b_dev *rfm22b_dev); // SPI read/write functions +static void rfm22_assertCs(); +static void rfm22_deassertCs(); +static void rfm22_claimBus(); +static void rfm22_releaseBus(); static void rfm22_write(uint8_t addr, uint8_t data); static uint8_t rfm22_read(uint8_t addr); -uint8_t rfm22_txStart(); +static uint8_t rfm22_read_noclaim(uint8_t addr); /* Provide a COM driver */ static void PIOS_RFM22B_ChangeBaud(uint32_t rfm22b_id, uint32_t baud); @@ -248,6 +299,98 @@ const struct pios_com_driver pios_rfm22b_com_driver = { .bind_rx_cb = PIOS_RFM22B_RegisterRxCallback, }; +/* Te state transition table */ +const static struct pios_rfm22b_transition rfm22b_transitions[RFM22B_STATE_NUM_STATES] = { + [RFM22B_STATE_UNINITIALIZED] = { + .entry_fn = 0, + .next_state = { + [RFM22B_EVENT_INITIALIZE] = RFM22B_STATE_INITIALIZING, + [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, + }, + }, + [RFM22B_STATE_INITIALIZING] = { + .entry_fn = rfm22_init, + .next_state = { + [RFM22B_EVENT_RX_MODE] = RFM22B_STATE_RX_MODE, + [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, + [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, + }, + }, + [RFM22B_STATE_ERROR] = { + .entry_fn = rfm22_error, + .next_state = { + [RFM22B_EVENT_INITIALIZE] = RFM22B_STATE_INITIALIZING, + [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, + }, + }, + [RFM22B_STATE_RX_MODE] = { + .entry_fn = rfm22_setRxMode, + .next_state = { + [RFM22B_EVENT_INT_RECEIVED] = RFM22B_STATE_WAIT_PREAMBLE, + [RFM22B_EVENT_TX_START] = RFM22B_STATE_TX_START, + [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, + [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, + }, + }, + [RFM22B_STATE_WAIT_PREAMBLE] = { + .entry_fn = rfm22_detectPreamble, + .next_state = { + [RFM22B_EVENT_INT_RECEIVED] = RFM22B_STATE_WAIT_PREAMBLE, + [RFM22B_EVENT_PREAMBLE_DETECTED] = RFM22B_STATE_WAIT_SYNC, + [RFM22B_EVENT_TX_START] = RFM22B_STATE_TX_START, + [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, + [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, + }, + }, + [RFM22B_STATE_WAIT_SYNC] = { + .entry_fn = rfm22_detectSync, + .next_state = { + [RFM22B_EVENT_INT_RECEIVED] = RFM22B_STATE_WAIT_SYNC, + [RFM22B_EVENT_SYNC_DETECTED] = RFM22B_STATE_RX_DATA, + [RFM22B_EVENT_TX_START] = RFM22B_STATE_TX_START, + [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, + [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, + }, + }, + [RFM22B_STATE_RX_DATA] = { + .entry_fn = rfm22_rxData, + .next_state = { + [RFM22B_EVENT_INT_RECEIVED] = RFM22B_STATE_RX_DATA, + [RFM22B_EVENT_TX_MODE] = RFM22B_STATE_TX_DATA, + [RFM22B_EVENT_RX_COMPLETE] = RFM22B_STATE_TX_START, + [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, + [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, + }, + }, + [RFM22B_STATE_TX_START] = { + .entry_fn = rfm22_txStart, + .next_state = { + [RFM22B_EVENT_INT_RECEIVED] = RFM22B_STATE_TX_DATA, + [RFM22B_EVENT_TX_MODE] = RFM22B_STATE_TX_DATA, + [RFM22B_EVENT_RX_MODE] = RFM22B_STATE_RX_MODE, + [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, + [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, + }, + }, + [RFM22B_STATE_TX_DATA] = { + .entry_fn = rfm22_txData, + .next_state = { + [RFM22B_EVENT_INT_RECEIVED] = RFM22B_STATE_TX_DATA, + [RFM22B_EVENT_TX_MODE] = RFM22B_STATE_TX_DATA, + [RFM22B_EVENT_TX_COMPLETE] = RFM22B_STATE_TX_START, + [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, + [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, + }, + }, + [RFM22B_STATE_FATAL_ERROR] = { + .entry_fn = rfm22_fatal_error, + .next_state = { + [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, + [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, + }, + }, +}; + // xtal 10 ppm, 434MHz #define LOOKUP_SIZE 14 const uint32_t data_rate[] = { 500, 1000, 2000, 4000, 8000, 9600, 16000, 19200, 24000, 32000, 64000, 128000, 192000, 256000}; @@ -336,11 +479,6 @@ 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) @@ -348,12 +486,6 @@ volatile int16_t temperature_reg; // the temperature sensor reading volatile uint8_t osc_load_cap; // xtal frequency calibration value -volatile uint8_t rssi; // the current RSSI (register value) -volatile int8_t rssi_dBm; // dBm value - -// 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. @@ -373,18 +505,12 @@ volatile uint8_t rx_buffer[258] __attribute__ ((aligned(4))); volatile uint16_t rx_buffer_wr; // the received packet -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 int lookup_index; int ss_lookup_index; -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; // @@ -444,14 +570,23 @@ int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, uint32_t spi_id, uint32_t slave_nu rfm22b_dev->spi_id = spi_id; // Set the state to initializing. - rfm22b_dev->state = RFM22B_STATE_INITIALIZING; - rfm22b_dev->event = RFM22B_EVENT_NONE; + rfm22b_dev->state = RFM22B_STATE_UNINITIALIZED; + // Create the event queue + rfm22b_dev->eventQueue = xQueueCreate(EVENT_QUEUE_SIZE, sizeof(enum pios_rfm22b_event)); + + // Initialize the register values. + rfm22b_dev->device_status = 0; + rfm22b_dev->int_status1 = 0; + rfm22b_dev->int_status2 = 0; + rfm22b_dev->ezmac_status = 0; // Initialize the stats. rfm22b_dev->resets = 0; rfm22b_dev->errors = 0; rfm22b_dev->irqs_processed = 0; - + rfm22b_dev->rssi = 0; + rfm22b_dev->rssi_dBm = -127; + // Bind the configuration to the device instance rfm22b_dev->cfg = *cfg; @@ -464,6 +599,9 @@ int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, uint32_t spi_id, uint32_t slave_nu // Initialize the TX pre-buffer pointer. tx_pre_buffer_size = 0; + // Create the packet queue. + rfm22b_dev->packetQueue = xQueueCreate(PACKET_QUEUE_SIZE, sizeof(PHPacketHandle)); + // Initialize the max tx power level. PIOS_RFM22B_SetTxPower(*rfm22b_id, cfg->maxTxPower); @@ -482,49 +620,6 @@ int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, uint32_t spi_id, uint32_t slave_nu // Initialize the external interrupt. PIOS_EXTI_Init(cfg->exti_cfg); - // Initialize the radio device. - int initval = rfm22_init_normal(rfm22b_dev->deviceID, cfg->minFrequencyHz, cfg->maxFrequencyHz, 50000); - - 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); - - DEBUG_PRINTF(2, "\n\r"); - DEBUG_PRINTF(2, "RF device ID: %x\n\r", rfm22b_dev->deviceID); - 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", rfm22b_dev->tx_power); - // Register the watchdog timer for the radio driver task #ifdef PIOS_WDG_RFM22B PIOS_WDG_RegisterFlag(PIOS_WDG_RFM22B); @@ -533,6 +628,9 @@ int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, uint32_t spi_id, uint32_t slave_nu // Start the driver task. This task controls the radio state machine and removed all of the IO from the IRQ handler. xTaskCreate(PIOS_RFM22B_Task, (signed char *)"PIOS_RFM22B_Task", STACK_SIZE_BYTES, (void*)rfm22b_dev, TASK_PRIORITY, &(rfm22b_dev->taskHandle)); + // Initialize the radio device. + PIOS_RFM22B_InjectEvent(rfm22b_dev, RFM22B_EVENT_INITIALIZE, false); + return(0); } @@ -558,7 +656,8 @@ static void PIOS_RFM22B_InjectEvent(struct pios_rfm22b_dev *rfm22b_dev, enum pio { // Store the event. - rfm22b_dev->event = event; + if (xQueueSend(rfm22b_dev->eventQueue, &event, portMAX_DELAY) != pdTRUE) + return; // Signal the semaphore to wake up the handler thread. if (inISR) { @@ -612,11 +711,6 @@ void PIOS_RFM22B_SetTxPower(uint32_t rfm22b_id, uint8_t tx_pwr) } } -int8_t PIOS_RFM22B_RSSI(uint32_t rfm22b_id) -{ - return rfm22_receivedRSSI(); -} - int16_t PIOS_RFM22B_Resets(uint32_t rfm22b_id) { struct pios_rfm22b_dev *rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id; @@ -633,6 +727,32 @@ static void PIOS_RFM22B_RxStart(uint32_t rfm22b_id, uint16_t rx_bytes_avail) } +/** + * Insert a packet on the packet queue for sending. + * Note: If this finction succedds, the packet will be released by the driver, so no release is necessary. + * If this function doesn't success, the caller is still responsible for the packet. + * \param[in] rfm22b_id The rfm22b device. + * \param[in] p The packet handle. + * \param[in] max_delay The maximum time to delay waiting to queue the packet. + * \return true on success, false on failue to queue the packet. + */ +bool PIOS_RFM22B_Send_Packet(uint32_t rfm22b_id, PHPacketHandle p, uint32_t max_delay) +{ + struct pios_rfm22b_dev *rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id; + if(!PIOS_RFM22B_validate(rfm22b_dev)) + return false; + + // Store the packet handle in the packet queue + if (xQueueSend(rfm22b_dev->packetQueue, &p, max_delay) != pdTRUE) + return false; + + // Inject a send packet event + PIOS_RFM22B_InjectEvent(g_rfm22b_dev, RFM22B_EVENT_SEND_PACKET, false); + + // Success + return true; +} + /** * The task that controls the radio state machine. */ @@ -654,7 +774,19 @@ static void PIOS_RFM22B_Task(void *parameters) if ( xSemaphoreTake(g_rfm22b_dev->isrPending, ISR_TIMEOUT / portTICK_RATE_MS) == pdTRUE ) { rfm22b_dev->irqs_processed++; lastEventTime = xTaskGetTickCount(); - rfm22_processInt(rfm22b_dev); + + // Process events through the state machine. + enum pios_rfm22b_event event; + while (xQueueReceive(rfm22b_dev->eventQueue, &event, 0) == pdTRUE) + { + if ((event == RFM22B_EVENT_INT_RECEIVED) && + ((rfm22b_dev->state == RFM22B_STATE_UNINITIALIZED) || (rfm22b_dev->state == RFM22B_STATE_INITIALIZING))) + continue; + + // Process all state transitions. + while(event != RFM22B_EVENT_NUM_EVENTS) + event = rfm22_process_state_transition(rfm22b_dev, event); + } } else { @@ -663,21 +795,15 @@ static void PIOS_RFM22B_Task(void *parameters) if ((timeSinceEvent / portTICK_RATE_MS) > PIOS_RFM22B_SUPERVISOR_TIMEOUT) { rfm22b_dev->resets++; - TX_LED_OFF; - TX_LED_OFF; - /* Clear the TX buffer in case we locked up in a transmit */ - tx_data_wr = 0; + // Transsition through an error event. + enum pios_rfm22b_event event = RFM22B_EVENT_ERROR; + while(event != RFM22B_EVENT_NUM_EVENTS) + event = rfm22_process_state_transition(rfm22b_dev, event); - rfm22_init_normal(rfm22b_dev->deviceID, rfm22b_dev->cfg.minFrequencyHz, rfm22b_dev->cfg.maxFrequencyHz, 50000); - - /* Start a packet transfer if one is available. */ - rfm22b_dev->state = RFM22B_STATE_RX_WAIT_PREAMBLE; - if(rfm22b_dev->state == RFM22B_STATE_RX_WAIT_PREAMBLE) - { - /* Switch to RX mode */ - PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); - } + // Clear the event queue. + while (xQueueReceive(rfm22b_dev->eventQueue, &event, 0) == pdTRUE) + ; } } } @@ -695,23 +821,8 @@ static void PIOS_RFM22B_TxStart(uint32_t rfm22b_id, uint16_t tx_bytes_avail) tx_pre_buffer_size = (rfm22b_dev->tx_out_cb)(rfm22b_dev->tx_out_context, tx_pre_buffer, TX_BUFFER_SIZE, NULL, &need_yield); - if(tx_pre_buffer_size > 0) - { - // already have data to be sent - if (tx_data_wr > 0) - return; - - // we are currently transmitting? - if (rfm22b_dev->state == RFM22B_STATE_TX_DATA) - return; - - // is the channel clear to transmit on? - if (!rfm22_channelIsClear()) - return; - - // Start the transmit - rfm22_txStart(); - } + // Inject a send packet event + PIOS_RFM22B_InjectEvent(g_rfm22b_dev, RFM22B_EVENT_TX_START, false); } /** @@ -862,6 +973,39 @@ static uint8_t rfm22_read_noclaim(uint8_t addr) // ************************************ +static enum pios_rfm22b_event rfm22_process_state_transition(struct pios_rfm22b_dev *rfm22b_dev, enum pios_rfm22b_event event) +{ + + // No event + if (event == RFM22B_EVENT_NUM_EVENTS) + return RFM22B_EVENT_NUM_EVENTS; + + // Don't transition if there is no transition defined + enum pios_rfm22b_state next_state = rfm22b_transitions[rfm22b_dev->state].next_state[event]; + if (!next_state) + return RFM22B_EVENT_NUM_EVENTS; + + /* + * Move to the next state + * + * This is done prior to calling the new state's entry function to + * guarantee that the entry function never depends on the previous + * state. This way, it cannot ever know what the previous state was. + */ + enum pios_rfm22b_state prev_state = rfm22b_dev->state; + if (prev_state) ; + + rfm22b_dev->state = next_state; + + /* Call the entry function (if any) for the next state. */ + if (rfm22b_transitions[rfm22b_dev->state].entry_fn) + return rfm22b_transitions[rfm22b_dev->state].entry_fn(rfm22b_dev); + + return RFM22B_EVENT_NUM_EVENTS; +} + +// ************************************ + uint32_t rfm22_minFrequency(void) { return lower_carrier_frequency_limit_Hz; @@ -1107,7 +1251,7 @@ uint32_t rfm22_getDatarate(void) // ************************************ -static void PIOS_RFM22B_SetRxMode(enum pios_rfm22b_event state) +static enum pios_rfm22b_event rfm22_setRxMode(struct pios_rfm22b_dev *rfm22b_dev) { exec_using_spi = true; @@ -1123,9 +1267,6 @@ static void PIOS_RFM22B_SetRxMode(enum pios_rfm22b_event state) // empty the rx buffer rx_buffer_wr = 0; - // reset the timer - rfm22_int_timer = 0; - g_rfm22b_dev->state = state; // Clear the TX buffer. tx_data_rd = tx_data_wr = 0; @@ -1144,17 +1285,20 @@ static void PIOS_RFM22B_SetRxMode(enum pios_rfm22b_event state) rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon | RFM22_opfc1_rxon); exec_using_spi = false; + + // No event generated + return RFM22B_EVENT_NUM_EVENTS; } // ************************************ -uint8_t rfm22_txStart() +static enum pios_rfm22b_event rfm22_txStart(struct pios_rfm22b_dev *rfm22b_dev) { if((tx_pre_buffer_size == 0) || (exec_using_spi == true)) { // Clear the TX buffer. tx_data_rd = tx_data_wr = 0; - return 0; + return RFM22B_EVENT_RX_MODE; } exec_using_spi = true; @@ -1211,13 +1355,6 @@ uint8_t rfm22_txStart() rfm22_deassertCs(); rfm22_releaseBus(); - // ******************* - - // reset the timer - rfm22_int_timer = 0; - - g_rfm22b_dev->state = RFM22B_STATE_TX_DATA; - // enable TX interrupts rfm22_write(RFM22_interrupt_enable1, RFM22_ie1_enpksent | RFM22_ie1_entxffaem); @@ -1227,35 +1364,76 @@ uint8_t rfm22_txStart() TX_LED_ON; exec_using_spi = false; - return 1; + return RFM22B_EVENT_NUM_EVENTS; } // ************************************ -// external interrupt line triggered (or polled) from the rf chip -void rfm22_processRxInt(struct pios_rfm22b_dev *rfm22b_dev) +/** + * Read the RFM22B interrupt and device status registers + * \param[in] rfm22b_dev The device structure + */ +static bool rfm22_readStatus(struct pios_rfm22b_dev *rfm22b_dev) { - register uint8_t int_stat1 = int_status1; - register uint8_t int_stat2 = int_status2; + exec_using_spi = true; - // FIFO under/over flow error. Restart RX mode. - if (device_status & (RFM22_ds_ffunfl | RFM22_ds_ffovfl)) + // 1. Read the interrupt statuses with burst read + rfm22_claimBus(); // Set RC and the semaphore + uint8_t write_buf[3] = {RFM22_interrupt_status1 & 0x7f, 0xFF, 0xFF}; + uint8_t read_buf[3]; + rfm22_assertCs(); + PIOS_SPI_TransferBlock(g_rfm22b_dev->spi_id, write_buf, read_buf, sizeof(write_buf), NULL); + rfm22_deassertCs(); + rfm22b_dev->int_status1 = read_buf[1]; + rfm22b_dev->int_status2 = read_buf[2]; + + // Device status + rfm22b_dev->device_status = rfm22_read_noclaim(RFM22_device_status); + + // EzMAC status + rfm22b_dev->ezmac_status = rfm22_read_noclaim(RFM22_ezmac_status); + + // Release the bus + rfm22_releaseBus(); + + // the RF module has gone and done a reset - we need to re-initialize the rf module + if (rfm22b_dev->int_status2 & RFM22_is2_ipor) { - PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); - return; + exec_using_spi = false; + return false; } + exec_using_spi = false; + return true; +} + +static enum pios_rfm22b_event rfm22_detectPreamble(struct pios_rfm22b_dev *rfm22b_dev) +{ + + // Read the device status registers + if (!rfm22_readStatus(rfm22b_dev)) + return RFM22B_EVENT_ERROR; + // Valid preamble detected - if (int_stat2 & RFM22_is2_ipreaval && (rfm22b_dev->state == RFM22B_STATE_RX_WAIT_PREAMBLE)) + if (rfm22b_dev->int_status2 & RFM22_is2_ipreaval) { - rfm22b_dev->state = RFM22B_STATE_RX_WAIT_SYNC; RX_LED_ON; + return RFM22B_EVENT_PREAMBLE_DETECTED; } + return RFM22B_EVENT_NUM_EVENTS; +} + +static enum pios_rfm22b_event rfm22_detectSync(struct pios_rfm22b_dev *rfm22b_dev) +{ + + // Read the device status registers + if (!rfm22_readStatus(rfm22b_dev)) + return RFM22B_EVENT_ERROR; + // Sync word detected - if (int_stat2 & RFM22_is2_iswdet && ((rfm22b_dev->state == RFM22B_STATE_RX_WAIT_PREAMBLE || rfm22b_dev->state == RFM22B_STATE_RX_WAIT_SYNC))) + if (rfm22b_dev->int_status2 & RFM22_is2_iswdet) { - rfm22b_dev->state = RFM22B_STATE_RX_DATA; RX_LED_ON; // read the 10-bit signed afc correction value @@ -1267,65 +1445,65 @@ void rfm22_processRxInt(struct pios_rfm22b_dev *rfm22b_dev) // 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; + // read rx signal strength .. 45 = -100dBm, 205 = -20dBm + rfm22b_dev->rssi = rfm22_read(RFM22_rssi); + // convert to dBm + rfm22b_dev->rssi_dBm = (int8_t)(rfm22b_dev->rssi >> 1) - 122; + // remember the afc value for this packet rx_packet_start_afc_Hz = afc_correction_Hz; + + return RFM22B_EVENT_SYNC_DETECTED; } + return RFM22B_EVENT_NUM_EVENTS; +} + +static enum pios_rfm22b_event rfm22_rxData(struct pios_rfm22b_dev *rfm22b_dev) +{ + + // Read the device status registers + if (!rfm22_readStatus(rfm22b_dev)) + return RFM22B_EVENT_ERROR; + + // FIFO under/over flow error. Restart RX mode. + if (rfm22b_dev->device_status & (RFM22_ds_ffunfl | RFM22_ds_ffovfl)) + return RFM22B_EVENT_ERROR; + + exec_using_spi = true; + // RX FIFO almost full, it needs emptying - if (int_stat1 & RFM22_is1_irxffafull) + if (rfm22b_dev->int_status1 & RFM22_is1_irxffafull) { - if (rfm22b_dev->state == RFM22B_STATE_RX_DATA) - { - // 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); + // 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); - // The received packet is going to be larger than the specified length - if ((rx_buffer_wr + RX_FIFO_HI_WATERMARK) > len) - { - PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); - return; - } + // The received packet is going to be larger than the specified length + if ((rx_buffer_wr + RX_FIFO_HI_WATERMARK) > len) + return RFM22B_EVENT_ERROR; - // Another packet length error. - if (((rx_buffer_wr + RX_FIFO_HI_WATERMARK) >= len) && !(int_stat1 & RFM22_is1_ipkvalid)) - { - PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); - return; - } + // Another packet length error. + if (((rx_buffer_wr + RX_FIFO_HI_WATERMARK) >= len) && !(rfm22b_dev->int_status1 & RFM22_is1_ipkvalid)) + return RFM22B_EVENT_ERROR; - // Fetch the data from the RX FIFO - rfm22_claimBus(); - rfm22_assertCs(); - PIOS_SPI_TransferByte(rfm22b_dev->spi_id,RFM22_fifo_access & 0x7F); - rx_buffer_wr += (PIOS_SPI_TransferBlock(rfm22b_dev->spi_id,OUT_FF, - (uint8_t *) &rx_buffer[rx_buffer_wr],RX_FIFO_HI_WATERMARK,NULL) == 0) ? - RX_FIFO_HI_WATERMARK : 0; - rfm22_deassertCs(); - rfm22_releaseBus(); - } else { - // Clear the RX FIFO - rfm22_claimBus(); - rfm22_assertCs(); - PIOS_SPI_TransferByte(rfm22b_dev->spi_id,RFM22_fifo_access & 0x7F); - PIOS_SPI_TransferBlock(rfm22b_dev->spi_id,OUT_FF,NULL,RX_FIFO_HI_WATERMARK,NULL); - rfm22_deassertCs(); - rfm22_releaseBus(); - } + // Fetch the data from the RX FIFO + rfm22_claimBus(); + rfm22_assertCs(); + PIOS_SPI_TransferByte(rfm22b_dev->spi_id,RFM22_fifo_access & 0x7F); + rx_buffer_wr += (PIOS_SPI_TransferBlock(rfm22b_dev->spi_id,OUT_FF, + (uint8_t *) &rx_buffer[rx_buffer_wr],RX_FIFO_HI_WATERMARK,NULL) == 0) ? + RX_FIFO_HI_WATERMARK : 0; + rfm22_deassertCs(); + rfm22_releaseBus(); } // CRC error .. discard the received data - if (int_stat1 & RFM22_is1_icrerror) - { - rfm22_int_timer = 0; // reset the timer - PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); - return; - } + if (rfm22b_dev->int_status1 & RFM22_is1_icrerror) + return RFM22B_EVENT_ERROR; // Valid packet received - if (int_stat1 & RFM22_is1_ipkvalid) + if (rfm22b_dev->int_status1 & RFM22_is1_ipkvalid) { // read the total length of the packet data @@ -1348,21 +1526,16 @@ void rfm22_processRxInt(struct pios_rfm22b_dev *rfm22b_dev) if (rx_buffer_wr != len) { - // we have a packet length error .. discard the packet - PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); - return; + exec_using_spi = false; + return RFM22B_EVENT_ERROR; } // we have a valid received packet if (rx_buffer_wr > 0) { - // 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; // 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++] = rfm22b_dev->rssi_dBm; rx_buffer[rx_buffer_wr++] = rx_packet_start_afc_Hz; // Pass this packet on bool need_yield = false; @@ -1372,51 +1545,31 @@ void rfm22_processRxInt(struct pios_rfm22b_dev *rfm22b_dev) rx_buffer_wr = 0; } - // Send a packet if it's available. - if(!rfm22_txStart()) - { - // Switch to RX mode - PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); - } + // Start a new transaction + exec_using_spi = false; + return RFM22B_EVENT_RX_COMPLETE; } + exec_using_spi = false; + return RFM22B_EVENT_NUM_EVENTS; } -void rfm22_processTxInt(struct pios_rfm22b_dev *rfm22b_dev) +static enum pios_rfm22b_event rfm22_txData(struct pios_rfm22b_dev *rfm22b_dev) { - register uint8_t int_stat1 = int_status1; - // reset the timer - rfm22_int_timer = 0; + // Read the device status registers + if (!rfm22_readStatus(rfm22b_dev)) + return RFM22B_EVENT_ERROR; // FIFO under/over flow error. Back to RX mode. - if (device_status & (RFM22_ds_ffunfl | RFM22_ds_ffovfl)) + if (rfm22b_dev->device_status & (RFM22_ds_ffunfl | RFM22_ds_ffovfl)) { - PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); - return; - } - - // Transmit timeout. Abort the transmit. - if (rfm22_int_timer >= timeout_data_ms) - { - rfm22_int_time_outs++; - PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); - return; - } - - // 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++; - PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); // back to rx mode - return; - } + exec_using_spi = false; + return RFM22B_EVENT_ERROR; } // TX FIFO almost empty, it needs filling up - if (int_stat1 & RFM22_is1_ixtffaem) + if (rfm22b_dev->int_status1 & RFM22_is1_ixtffaem) { // top-up the rf chips TX FIFO buffer uint16_t max_bytes = FIFO_SIZE - TX_FIFO_LO_WATERMARK - 1; @@ -1432,117 +1585,15 @@ void rfm22_processTxInt(struct pios_rfm22b_dev *rfm22b_dev) } // Packet has been sent - if (int_stat1 & RFM22_is1_ipksent) + if (rfm22b_dev->int_status1 & RFM22_is1_ipksent) { - - // Send another packet if it's available. - if(!rfm22_txStart()) - { - // Switch to RX mode - PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); - return; - } - } - -} - -static void rfm22_processInt(struct pios_rfm22b_dev *rfm22b_dev) -{ - // we haven't yet been initialized - if (!PIOS_RFM22B_validate(rfm22b_dev)) - return; - - exec_using_spi = true; - - // 1. Read the interrupt statuses with burst read - rfm22_claimBus(); // Set RC and the semaphore - uint8_t write_buf[3] = {RFM22_interrupt_status1 & 0x7f, 0xFF, 0xFF}; - uint8_t read_buf[3]; - rfm22_assertCs(); - PIOS_SPI_TransferBlock(rfm22b_dev->spi_id, write_buf, read_buf, sizeof(write_buf), NULL); - rfm22_deassertCs(); - int_status1 = read_buf[1]; - int_status2 = read_buf[2]; - - // Device status - device_status = rfm22_read_noclaim(RFM22_device_status); - - // EzMAC status - ezmac_status = rfm22_read_noclaim(RFM22_ezmac_status); - - // Release the bus - rfm22_releaseBus(); - - // Read the RSSI if we're in RX mode - if (rfm22b_dev->state != RFM22B_STATE_TX_DATA) - { - // read rx signal strength .. 45 = -100dBm, 205 = -20dBm - rssi = rfm22_read(RFM22_rssi); - // convert to dBm - rssi_dBm = (int8_t)(rssi >> 1) - 122; - } - else - // read the tx power register - tx_pwr = rfm22_read(RFM22_tx_power); - - // the RF module has gone and done a reset - we need to re-initialize the rf module - if (int_status2 & RFM22_is2_ipor) - { - rfm22b_dev->state = RFM22B_STATE_RESETTING; - // Need to do something here! - return; - } - - switch (rfm22b_dev->state) - { - case RFM22B_STATE_RX_WAIT_PREAMBLE: - case RFM22B_STATE_RX_WAIT_SYNC: - case RFM22B_STATE_RX_DATA: - - rfm22_processRxInt(rfm22b_dev); - break; - - case RFM22B_STATE_TX_DATA: - - rfm22_processTxInt(rfm22b_dev); - break; - - default: // unknown mode - this should NEVER happen, maybe we should do a complete CPU reset here - // to rx mode - PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); - break; + exec_using_spi = false; + // Start a new transaction + return RFM22B_EVENT_TX_COMPLETE; } exec_using_spi = false; -} - -// ************************************ - -int8_t rfm22_getRSSI(void) -{ - exec_using_spi = true; - - rssi = rfm22_read(RFM22_rssi); // read rx signal strength .. 45 = -100dBm, 205 = -20dBm - rssi_dBm = (int8_t)(rssi >> 1) - 122; // convert to dBm - - exec_using_spi = false; - return rssi_dBm; -} - -int8_t rfm22_receivedRSSI(void) -{ // return the packets signal strength - if (!initialized) - return -127; - 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; + return RFM22B_EVENT_NUM_EVENTS; } // ************************************ @@ -1566,7 +1617,7 @@ bool rfm22_channelIsClear(void) // we haven't yet been initialized return false; - if (g_rfm22b_dev->state != RFM22B_STATE_RX_WAIT_PREAMBLE && g_rfm22b_dev->state != RFM22B_STATE_RX_WAIT_SYNC) + if (g_rfm22b_dev->state != RFM22B_STATE_RX_MODE && g_rfm22b_dev->state != RFM22B_STATE_WAIT_PREAMBLE && g_rfm22b_dev->state != RFM22B_STATE_WAIT_SYNC) // we are receiving something or we are transmitting or we are scanning the spectrum return false; @@ -1599,20 +1650,20 @@ uint8_t rfm22_getFreqCalibration(void) } // ************************************ -// reset the RF module +// Initialise this hardware layer module and the rf module -int rfm22_resetModule(uint8_t mode, uint32_t min_frequency_hz, uint32_t max_frequency_hz) +static enum pios_rfm22b_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev) { + uint32_t id = rfm22b_dev->deviceID; + uint32_t min_frequency_hz = rfm22b_dev->cfg.minFrequencyHz; + uint32_t max_frequency_hz = rfm22b_dev->cfg.maxFrequencyHz; + uint32_t freq_hop_step_size = 50000; + initialized = false; - - // **************** - exec_using_spi = true; - // **************** // 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 + rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_swres); // wait 26ms PIOS_DELAY_WaitmS(26); @@ -1623,18 +1674,18 @@ int rfm22_resetModule(uint8_t mode, uint32_t min_frequency_hz, uint32_t max_freq PIOS_DELAY_WaitmS(1); // 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; + rfm22b_dev->int_status1 = rfm22_read(RFM22_interrupt_status1); + rfm22b_dev->int_status2 = rfm22_read(RFM22_interrupt_status2); + if (rfm22b_dev->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); + rfm22b_dev->device_status = rfm22_read(RFM22_device_status); + rfm22b_dev->int_status1 = rfm22_read(RFM22_interrupt_status1); + rfm22b_dev->int_status2 = rfm22_read(RFM22_interrupt_status2); + rfm22b_dev->ezmac_status = rfm22_read(RFM22_ezmac_status); // disable all interrupts rfm22_write(RFM22_interrupt_enable1, 0x00); @@ -1646,16 +1697,10 @@ int rfm22_resetModule(uint8_t mode, uint32_t min_frequency_hz, uint32_t max_freq // **************** - g_rfm22b_dev->state = mode; - - device_status = int_status1 = int_status2 = ezmac_status = 0; - - rssi = 0; - rssi_dBm = -127; + rfm22b_dev->device_status = rfm22b_dev->int_status1 = rfm22b_dev->int_status2 = rfm22b_dev->ezmac_status = 0; rx_buffer_current = 0; rx_buffer_wr = 0; - rx_packet_rssi_dBm = -127; rx_packet_afc_Hz = 0; tx_data_rd = tx_data_wr = 0; @@ -1666,10 +1711,6 @@ int rfm22_resetModule(uint8_t mode, uint32_t min_frequency_hz, uint32_t max_freq 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; @@ -1680,8 +1721,6 @@ int rfm22_resetModule(uint8_t mode, uint32_t min_frequency_hz, uint32_t max_freq temperature_reg = 0; - tx_pwr = 0; - // **************** // read the RF chip ID bytes @@ -1698,19 +1737,16 @@ int rfm22_resetModule(uint8_t mode, uint32_t min_frequency_hz, uint32_t max_freq #if defined(RFM22_DEBUG) DEBUG_PRINTF(2, "rf device type: INCORRECT - should be 0x08\n\r"); #endif - return -1; // incorrect RF module type + // incorrect RF module type + return RFM22B_EVENT_FATAL_ERROR; } - - // 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 (device_version != RFM22_DEVICE_VERSION_B1) { #if defined(RFM22_DEBUG) DEBUG_PRINTF(2, "rf device version: INCORRECT\n\r"); #endif - return -2; // incorrect RF module version + // incorrect RF module version + return RFM22B_EVENT_FATAL_ERROR; } // **************** @@ -1752,7 +1788,7 @@ int rfm22_resetModule(uint8_t mode, uint32_t min_frequency_hz, uint32_t max_freq // choose the 3 GPIO pin functions rfm22_write(RFM22_io_port_config, RFM22_io_port_default); // GPIO port use default value - if (g_rfm22b_dev->cfg.gpio_direction == GPIO0_TX_GPIO1_RX) { + if (rfm22b_dev->cfg.gpio_direction == GPIO0_TX_GPIO1_RX) { 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) } else { @@ -1763,18 +1799,6 @@ int rfm22_resetModule(uint8_t mode, uint32_t min_frequency_hz, uint32_t max_freq // **************** - return 0; // OK -} - -// ************************************ -// Initialise this hardware layer module and the rf module - -int rfm22_init_normal(uint32_t id, uint32_t min_frequency_hz, uint32_t max_frequency_hz, uint32_t freq_hop_step_size) -{ - int res = rfm22_resetModule(RFM22B_STATE_RX_WAIT_PREAMBLE, min_frequency_hz, max_frequency_hz); - if (res < 0) - return res; - // initialize the frequency hopping step size freq_hop_step_size /= 10000; // in 10kHz increments if (freq_hop_step_size > 255) freq_hop_step_size = 255; @@ -1866,8 +1890,7 @@ int rfm22_init_normal(uint32_t id, uint32_t min_frequency_hz, uint32_t max_frequ rfm22_setNominalCarrierFrequency((min_frequency_hz + max_frequency_hz) / 2); // set the tx power - rfm22_write(RFM22_tx_power, RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_0 | - RFM22_tx_pwr_lna_sw | g_rfm22b_dev->tx_power); + rfm22_write(RFM22_tx_power, RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | rfm22b_dev->tx_power); // TX FIFO Almost Full Threshold (0 - 63) rfm22_write(RFM22_tx_fifo_control1, TX_FIFO_HI_WATERMARK); @@ -1878,11 +1901,60 @@ int rfm22_init_normal(uint32_t id, uint32_t min_frequency_hz, uint32_t max_frequ // RX FIFO Almost Full Threshold (0 - 63) rfm22_write(RFM22_rx_fifo_control, RX_FIFO_HI_WATERMARK); - PIOS_RFM22B_SetRxMode(RFM22B_STATE_RX_WAIT_PREAMBLE); + //rfm22_setRxMode(rfm22b_dev); + + rfm22_setFreqCalibration(rfm22b_dev->cfg.RFXtalCap); + rfm22_setNominalCarrierFrequency(rfm22b_dev->cfg.frequencyHz); + rfm22_setDatarate(rfm22b_dev->cfg.maxRFBandwidth, true); + + DEBUG_PRINTF(2, "\n\r"); + DEBUG_PRINTF(2, "RF device ID: %x\n\r", rfm22b_dev->deviceID); + 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", rfm22b_dev->tx_power); initialized = true; - return 0; // ok + return RFM22B_EVENT_RX_MODE; +} + +static enum pios_rfm22b_event rfm22_error(struct pios_rfm22b_dev *rfm22b_dev) +{ + return RFM22B_EVENT_INITIALIZE; +} + +/** + * A fatal error has occured in the state machine. + * this should not happen. + * \parem [in] rfm22b_dev The device structure + * \return enum pios_rfm22b_event The next event to inject + */ +static enum pios_rfm22b_event rfm22_fatal_error(struct pios_rfm22b_dev *rfm22b_dev) +{ + + // RF module error .. flash the LED's + 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); + + PIOS_Assert(0); + + return RFM22B_EVENT_FATAL_ERROR; } // ************************************ diff --git a/flight/PiOS/inc/pios_rfm22b.h b/flight/PiOS/inc/pios_rfm22b.h index 0cc685da3..451480960 100644 --- a/flight/PiOS/inc/pios_rfm22b.h +++ b/flight/PiOS/inc/pios_rfm22b.h @@ -31,6 +31,8 @@ #ifndef PIOS_RFM22B_H #define PIOS_RFM22B_H +#include + enum gpio_direction {GPIO0_TX_GPIO1_RX, GPIO0_RX_GPIO1_TX}; /* Global Types */ @@ -51,9 +53,9 @@ struct pios_rfm22b_cfg { extern int32_t PIOS_RFM22B_Init(uint32_t *rfb22b_id, uint32_t spi_id, uint32_t slave_num, const struct pios_rfm22b_cfg *cfg); extern void PIOS_RFM22B_SetTxPower(uint32_t rfm22b_id, uint8_t tx_pwr); extern uint32_t PIOS_RFM22B_DeviceID(uint32_t rfb22b_id); -extern int8_t PIOS_RFM22B_RSSI(uint32_t rfm22b_id); extern int16_t PIOS_RFM22B_Resets(uint32_t rfm22b_id); -extern void PIOS_RFM22_processPendingISR(uint32_t wait_ms); +extern bool PIOS_RFM22B_Send_Packet(uint32_t rfm22b_id, PHPacketHandle p, uint32_t max_delay); +extern uint32_t PIOS_RFM22B_Receive_Packet(uint32_t rfm22b_id, PHPacketHandle *p, uint32_t max_delay); #endif /* PIOS_RFM22B_H */ diff --git a/flight/PiOS/inc/pios_rfm22b_priv.h b/flight/PiOS/inc/pios_rfm22b_priv.h index ce6bf96f5..604efba63 100644 --- a/flight/PiOS/inc/pios_rfm22b_priv.h +++ b/flight/PiOS/inc/pios_rfm22b_priv.h @@ -598,16 +598,6 @@ uint32_t rfm22_freqHopSize(void); void rfm22_setDatarate(uint32_t datarate_bps, bool data_whitening); uint32_t rfm22_getDatarate(void); -int8_t rfm22_getRSSI(void); - -int8_t rfm22_receivedRSSI(void); -int32_t rfm22_receivedAFCHz(void); -uint16_t rfm22_receivedLength(void); -uint8_t * rfm22_receivedPointer(void); -void rfm22_receivedDone(void); - -int32_t rfm22_sendData(void *data, uint16_t length, bool send_immediately); - void rfm22_setFreqCalibration(uint8_t value); uint8_t rfm22_getFreqCalibration(void); @@ -627,16 +617,9 @@ bool rfm22_channelIsClear(void); bool rfm22_txReady(void); -void rfm22_1ms_tick(void); - void rfm22_TxDataByte_SetCallback(t_rfm22_TxDataByteCallback new_function); void rfm22_RxData_SetCallback(t_rfm22_RxDataCallback new_function); -int rfm22_init_scan_spectrum(uint32_t min_frequency_hz, uint32_t max_frequency_hz); -int rfm22_init_tx_stream(uint32_t min_frequency_hz, uint32_t max_frequency_hz); -int rfm22_init_rx_stream(uint32_t min_frequency_hz, uint32_t max_frequency_hz); -int rfm22_init_normal(uint32_t id, uint32_t min_frequency_hz, uint32_t max_frequency_hz, uint32_t freq_hop_step_size); - #endif /* PIOS_RFM22B_PRIV_H */ /** From a46e3cdec3bec787310d68738f9cc25cc00d3b6b Mon Sep 17 00:00:00 2001 From: Brian Webb Date: Sat, 22 Sep 2012 20:07:50 -0700 Subject: [PATCH 07/10] RFM22B: All outgoing data to the radio is now going through the PIOS_RFM22B_Send_Packet call. Also removed all global variables with the exception of the rx buffer. --- flight/Modules/Radio/radio.c | 31 +- .../PiOS/Boards/STM32103CB_PIPXTREME_Rev1.h | 11 +- flight/PiOS/Common/pios_rfm22b.c | 502 ++++++------------ flight/PiOS/inc/pios_rfm22b_priv.h | 38 -- 4 files changed, 161 insertions(+), 421 deletions(-) diff --git a/flight/Modules/Radio/radio.c b/flight/Modules/Radio/radio.c index 7b61dce34..e1fab89f2 100644 --- a/flight/Modules/Radio/radio.c +++ b/flight/Modules/Radio/radio.c @@ -48,6 +48,7 @@ #define STATS_UPDATE_PERIOD_MS 500 #define RADIOSTATS_UPDATE_PERIOD_MS 250 #define MAX_LOST_CONTACT_TIME 4 +#define PACKET_MAX_DELAY 50 #ifndef LINK_LED_ON #define LINK_LED_ON @@ -73,7 +74,6 @@ typedef struct { // The task handles. xTaskHandle radioReceiveTaskHandle; xTaskHandle radioStatusTaskHandle; - xTaskHandle sendPacketTaskHandle; // Queue handles. xQueueHandle radioPacketQueue; @@ -106,7 +106,6 @@ typedef struct { static void radioReceiveTask(void *parameters); static void radioStatusTask(void *parameters); -static void sendPacketTask(void *parameters); static void StatusHandler(PHStatusPacketHandle p, int8_t rssi, int8_t afc); static int32_t transmitPacket(PHPacketHandle packet); static void PPMHandler(uint16_t *channels); @@ -137,11 +136,9 @@ static int32_t RadioStart(void) // Start the tasks. xTaskCreate(radioReceiveTask, (signed char *)"RadioReceive", STACK_SIZE_BYTES, NULL, TASK_PRIORITY, &(data->radioReceiveTaskHandle)); xTaskCreate(radioStatusTask, (signed char *)"RadioStatus", STACK_SIZE_BYTES * 2, NULL, TASK_PRIORITY, &(data->radioStatusTaskHandle)); - xTaskCreate(sendPacketTask, (signed char *)"SendPacket", STACK_SIZE_BYTES, NULL, TASK_PRIORITY, &(data->sendPacketTaskHandle)); // Install the monitors TaskMonitorAdd(TASKINFO_RUNNING_MODEMRX, data->radioReceiveTaskHandle); - TaskMonitorAdd(TASKINFO_RUNNING_MODEMTX, data->sendPacketTaskHandle); TaskMonitorAdd(TASKINFO_RUNNING_MODEMSTAT, data->radioStatusTaskHandle); // Register the watchdog timers. @@ -289,9 +286,6 @@ static int32_t RadioInitialize(void) PipXSettingsPairIDGet(&(data->pairStats[0].pairID)); data->destination_id = data->pairStats[0].pairID ? data->pairStats[0].pairID : 0xffffffff; - // Create the packet queue. - data->radioPacketQueue = xQueueCreate(PACKET_QUEUE_SIZE, sizeof(PHPacketHandle)); - // Register the callbacks with the packet handler PHRegisterStatusHandler(pios_packet_handler, StatusHandler); PHRegisterOutputStream(pios_packet_handler, transmitPacket); @@ -342,27 +336,6 @@ static void radioReceiveTask(void *parameters) } } -/** - * Send packets to the radio. - */ -static void sendPacketTask(void *parameters) -{ - PHPacketHandle p; - - // Loop forever - while (1) { -#ifdef PIOS_INCLUDE_WDG - // Update the watchdog timer. - //PIOS_WDG_UpdateFlag(PIOS_WDG_SENDPACKET); -#endif /* PIOS_INCLUDE_WDG */ - // Wait for a packet on the queue. - if (xQueueReceive(data->radioPacketQueue, &p, MAX_PORT_DELAY) == pdTRUE) { - PIOS_COM_SendBuffer(PIOS_COM_RADIO, (uint8_t*)p, PH_PACKET_SIZE(p)); - PHReleaseTXPacket(pios_packet_handler, p); - } - } -} - /** * Transmit a packet to the radio port. * \param[in] buf Data buffer to send @@ -374,7 +347,7 @@ static int32_t transmitPacket(PHPacketHandle p) { uint16_t len = PH_PACKET_SIZE(p); data->txBytes += len; - if (xQueueSend(data->radioPacketQueue, &p, portMAX_DELAY) != pdTRUE) + if (!PIOS_RFM22B_Send_Packet(pios_rfm22b_id, p, PACKET_MAX_DELAY)) return -1; return len; } diff --git a/flight/PiOS/Boards/STM32103CB_PIPXTREME_Rev1.h b/flight/PiOS/Boards/STM32103CB_PIPXTREME_Rev1.h index d500c86ea..aaf265c58 100755 --- a/flight/PiOS/Boards/STM32103CB_PIPXTREME_Rev1.h +++ b/flight/PiOS/Boards/STM32103CB_PIPXTREME_Rev1.h @@ -71,13 +71,12 @@ TIM4 | RC In 1 | Servo 3 | Servo 2 | Servo 1 //------------------------ #define PIOS_WATCHDOG_TIMEOUT 500 #define PIOS_WDG_REGISTER BKP_DR4 -#define PIOS_WDG_COMUAVTALK 0x0001 -#define PIOS_WDG_RADIORECEIVE 0x0002 -#define PIOS_WDG_SENDPACKET 0x0004 +#define PIOS_WDG_COMGCS 0x0001 +#define PIOS_WDG_COMUAVTALK 0x0002 +#define PIOS_WDG_RADIORECEIVE 0x0004 #define PIOS_WDG_SENDDATA 0x0008 -#define PIOS_WDG_TRANSCOMM 0x0010 -#define PIOS_WDG_PPMINPUT 0x0020 -#define PIOS_WDG_COMGCS 0x0040 +#define PIOS_WDG_TRANSCOMM 0x0008 +#define PIOS_WDG_PPMINPUT 0x0010 //------------------------ // TELEMETRY diff --git a/flight/PiOS/Common/pios_rfm22b.c b/flight/PiOS/Common/pios_rfm22b.c index 7a0e145dd..e48a97318 100644 --- a/flight/PiOS/Common/pios_rfm22b.c +++ b/flight/PiOS/Common/pios_rfm22b.c @@ -76,13 +76,9 @@ // ************************************ -#define TX_TEST_MODE_TIMELIMIT_MS 30000 // TX test modes time limit (in ms) - #define TX_PREAMBLE_NIBBLES 12 // 7 to 511 (number of nibbles) #define RX_PREAMBLE_NIBBLES 6 // 5 to 31 (number of nibbles) -// 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 @@ -163,6 +159,7 @@ enum pios_rfm22b_state { enum pios_rfm22b_event { RFM22B_EVENT_INITIALIZE, + RFM22B_EVENT_INITIALIZED, RFM22B_EVENT_INT_RECEIVED, RFM22B_EVENT_TX_MODE, RFM22B_EVENT_RX_MODE, @@ -171,7 +168,9 @@ enum pios_rfm22b_event { RFM22B_EVENT_RX_COMPLETE, RFM22B_EVENT_SEND_PACKET, RFM22B_EVENT_TX_START, + RFM22B_EVENT_TX_STARTED, RFM22B_EVENT_TX_COMPLETE, + RFM22B_EVENT_TIMEOUT, RFM22B_EVENT_ERROR, RFM22B_EVENT_FATAL_ERROR, @@ -227,6 +226,23 @@ struct pios_rfm22b_dev { // The packet queue handle xQueueHandle packetQueue; + + // The current tx packet + PHPacketHandle tx_packet; + // the tx data read index + uint16_t tx_data_rd; + // the tx data write index + uint16_t tx_data_wr; + + // The frequency hopping step size + float frequency_step_size; + // current frequency hop channel + uint8_t frequency_hop_channel; + // the frequency hop step size + uint8_t frequency_hop_step_size_reg; + // afc correction reading (in Hz) + int32_t afc_correction_Hz; + int8_t rx_packet_start_afc_Hz; }; struct pios_rfm22b_transition { @@ -311,7 +327,7 @@ const static struct pios_rfm22b_transition rfm22b_transitions[RFM22B_STATE_NUM_S [RFM22B_STATE_INITIALIZING] = { .entry_fn = rfm22_init, .next_state = { - [RFM22B_EVENT_RX_MODE] = RFM22B_STATE_RX_MODE, + [RFM22B_EVENT_INITIALIZED] = RFM22B_STATE_TX_START, [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, }, @@ -327,7 +343,9 @@ const static struct pios_rfm22b_transition rfm22b_transitions[RFM22B_STATE_NUM_S .entry_fn = rfm22_setRxMode, .next_state = { [RFM22B_EVENT_INT_RECEIVED] = RFM22B_STATE_WAIT_PREAMBLE, + [RFM22B_EVENT_SEND_PACKET] = RFM22B_STATE_TX_START, [RFM22B_EVENT_TX_START] = RFM22B_STATE_TX_START, + [RFM22B_EVENT_TIMEOUT] = RFM22B_STATE_TX_START, [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, }, @@ -337,7 +355,9 @@ const static struct pios_rfm22b_transition rfm22b_transitions[RFM22B_STATE_NUM_S .next_state = { [RFM22B_EVENT_INT_RECEIVED] = RFM22B_STATE_WAIT_PREAMBLE, [RFM22B_EVENT_PREAMBLE_DETECTED] = RFM22B_STATE_WAIT_SYNC, + [RFM22B_EVENT_SEND_PACKET] = RFM22B_STATE_TX_START, [RFM22B_EVENT_TX_START] = RFM22B_STATE_TX_START, + [RFM22B_EVENT_TIMEOUT] = RFM22B_STATE_TX_START, [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, }, @@ -393,34 +413,34 @@ const static struct pios_rfm22b_transition rfm22b_transitions[RFM22B_STATE_NUM_S // xtal 10 ppm, 434MHz #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 +static const uint32_t data_rate[] = { 500, 1000, 2000, 4000, 8000, 9600, 16000, 19200, 24000, 32000, 64000, 128000, 192000, 256000}; +static const uint8_t modulation_index[] = { 16, 8, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; +static const uint32_t freq_deviation[] = { 4000, 4000, 4000, 4000, 4000, 4800, 8000, 9600, 12000, 16000, 32000, 64000, 96000, 128000}; +static const uint32_t rx_bandwidth[] = { 17500, 17500, 17500, 17500, 17500, 19400, 32200, 38600, 51200, 64100, 137900, 269300, 420200, 518800}; +static 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 -const uint8_t reg_1C[] = { 0x37, 0x37, 0x37, 0x37, 0x3A, 0x3B, 0x26, 0x28, 0x2E, 0x16, 0x07, 0x83, 0x8A, 0x8C}; // rfm22_if_filter_bandwidth +static const uint8_t reg_1C[] = { 0x37, 0x37, 0x37, 0x37, 0x3A, 0x3B, 0x26, 0x28, 0x2E, 0x16, 0x07, 0x83, 0x8A, 0x8C}; // rfm22_if_filter_bandwidth -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 +static const uint8_t reg_1D[] = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44}; // rfm22_afc_loop_gearshift_override +static const uint8_t reg_1E[] = { 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x02}; // rfm22_afc_timing_control -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 +static const uint8_t reg_1F[] = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03}; // rfm22_clk_recovery_gearshift_override +static const uint8_t reg_20[] = { 0xE8, 0xF4, 0xFA, 0x70, 0x3F, 0x34, 0x3F, 0x34, 0x2A, 0x3F, 0x3F, 0x5E, 0x3F, 0x2F}; // rfm22_clk_recovery_oversampling_ratio +static const uint8_t reg_21[] = { 0x60, 0x20, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x02, 0x02}; // rfm22_clk_recovery_offset2 +static const uint8_t reg_22[] = { 0x20, 0x41, 0x83, 0x06, 0x0C, 0x75, 0x0C, 0x75, 0x12, 0x0C, 0x0C, 0x5D, 0x0C, 0xBB}; // rfm22_clk_recovery_offset1 +static const uint8_t reg_23[] = { 0xC5, 0x89, 0x12, 0x25, 0x4A, 0x25, 0x4A, 0x25, 0x6F, 0x4A, 0x4A, 0x86, 0x4A, 0x0D}; // rfm22_clk_recovery_offset0 +static 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 +static 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 -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 = ±AFCLimiter[7:0] x (hbsel+1) x 625 Hz +static 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 = ±AFCLimiter[7:0] x (hbsel+1) x 625 Hz -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 +static const uint8_t reg_6E[] = { 0x04, 0x08, 0x10, 0x20, 0x41, 0x4E, 0x83, 0x9D, 0xC4, 0x08, 0x10, 0x20, 0x31, 0x41}; // rfm22_tx_data_rate1 +static const uint8_t reg_6F[] = { 0x19, 0x31, 0x62, 0xC5, 0x89, 0xA5, 0x12, 0x49, 0x9C, 0x31, 0x62, 0xC5, 0x27, 0x89}; // rfm22_tx_data_rate0 -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 +static const uint8_t reg_70[] = { 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D}; // rfm22_modulation_mode_control1 +static const uint8_t reg_71[] = { 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23}; // rfm22_modulation_mode_control2 -const uint8_t reg_72[] = { 0x06, 0x06, 0x06, 0x06, 0x06, 0x08, 0x0D, 0x0F, 0x13, 0x1A, 0x33, 0x66, 0x9A, 0xCD}; // rfm22_frequency_deviation +static const uint8_t reg_72[] = { 0x06, 0x06, 0x06, 0x06, 0x06, 0x08, 0x0D, 0x0F, 0x13, 0x1A, 0x33, 0x66, 0x9A, 0xCD}; // rfm22_frequency_deviation // ************************************ // Scan Spectrum settings @@ -433,87 +453,29 @@ const uint8_t reg_72[] = { 0x06, 0x06, 0x06, 0x06, 0x06, 0x #define SS_LOOKUP_SIZE 2 // xtal 1 ppm, 434MHz -const uint32_t ss_rx_bandwidth[] = { 2600, 10600}; +static const uint32_t ss_rx_bandwidth[] = { 2600, 10600}; -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 +static const uint8_t ss_reg_1C[] = { 0x51, 0x32}; // rfm22_if_filter_bandwidth +static const uint8_t ss_reg_1D[] = { 0x00, 0x00}; // rfm22_afc_loop_gearshift_override -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 +static const uint8_t ss_reg_20[] = { 0xE8, 0x38}; // rfm22_clk_recovery_oversampling_ratio +static const uint8_t ss_reg_21[] = { 0x60, 0x02}; // rfm22_clk_recovery_offset2 +static const uint8_t ss_reg_22[] = { 0x20, 0x4D}; // rfm22_clk_recovery_offset1 +static const uint8_t ss_reg_23[] = { 0xC5, 0xD3}; // rfm22_clk_recovery_offset0 +static const uint8_t ss_reg_24[] = { 0x00, 0x07}; // rfm22_clk_recovery_timing_loop_gain1 +static const uint8_t ss_reg_25[] = { 0x0F, 0xFF}; // rfm22_clk_recovery_timing_loop_gain0 -const uint8_t ss_reg_2A[] = { 0xFF, 0xFF}; // rfm22_afc_limiter .. AFC_pull_in_range = ±AFCLimiter[7:0] x (hbsel+1) x 625 Hz +static const uint8_t ss_reg_2A[] = { 0xFF, 0xFF}; // rfm22_afc_limiter .. AFC_pull_in_range = ±AFCLimiter[7:0] x (hbsel+1) x 625 Hz -const uint8_t ss_reg_70[] = { 0x24, 0x2D}; // rfm22_modulation_mode_control1 -const uint8_t ss_reg_71[] = { 0x2B, 0x23}; // rfm22_modulation_mode_control2 - -// ************************************ - -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 - -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 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 - -volatile uint8_t osc_load_cap; // xtal frequency calibration value - -// 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; +static const uint8_t ss_reg_70[] = { 0x24, 0x2D}; // rfm22_modulation_mode_control1 +static const uint8_t ss_reg_71[] = { 0x2B, 0x23}; // rfm22_modulation_mode_control2 // the current receive buffer in use (double buffer) volatile uint8_t rx_buffer_current; // the receive buffer .. received packet data is saved here volatile uint8_t rx_buffer[258] __attribute__ ((aligned(4))); // the receive buffer write index -volatile uint16_t rx_buffer_wr; - -// the received packet -volatile int8_t rx_packet_start_afc_Hz; // -volatile int8_t rx_packet_afc_Hz; // the receive packet frequency offset - -int lookup_index; -int ss_lookup_index; - -uint16_t timeout_ms = 20000; // -uint16_t timeout_sync_ms = 3; // -uint16_t timeout_data_ms = 20; // +volatile uint16_t rx_buffer_wr; static bool PIOS_RFM22B_validate(struct pios_rfm22b_dev * rfm22b_dev) @@ -596,9 +558,6 @@ int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, uint32_t spi_id, uint32_t slave_nu // Create a semaphore to know if an ISR needs responding to vSemaphoreCreateBinary( rfm22b_dev->isrPending ); - // Initialize the TX pre-buffer pointer. - tx_pre_buffer_size = 0; - // Create the packet queue. rfm22b_dev->packetQueue = xQueueCreate(PACKET_QUEUE_SIZE, sizeof(PHPacketHandle)); @@ -804,6 +763,13 @@ static void PIOS_RFM22B_Task(void *parameters) // Clear the event queue. while (xQueueReceive(rfm22b_dev->eventQueue, &event, 0) == pdTRUE) ; + lastEventTime = xTaskGetTickCount(); + } + else + { + enum pios_rfm22b_event event = RFM22B_EVENT_TIMEOUT; + while(event != RFM22B_EVENT_NUM_EVENTS) + event = rfm22_process_state_transition(rfm22b_dev, event); } } } @@ -815,6 +781,7 @@ static void PIOS_RFM22B_TxStart(uint32_t rfm22b_id, uint16_t tx_bytes_avail) bool valid = PIOS_RFM22B_validate(rfm22b_dev); PIOS_Assert(valid); +#ifdef NEVER // Get some data to send bool need_yield = false; if(tx_pre_buffer_size == 0) @@ -823,6 +790,7 @@ static void PIOS_RFM22B_TxStart(uint32_t rfm22b_id, uint16_t tx_bytes_avail) // Inject a send packet event PIOS_RFM22B_InjectEvent(g_rfm22b_dev, RFM22B_EVENT_TX_START, false); +#endif } /** @@ -1006,27 +974,17 @@ static enum pios_rfm22b_event rfm22_process_state_transition(struct pios_rfm22b_ // ************************************ -uint32_t rfm22_minFrequency(void) +static void rfm22_setNominalCarrierFrequency(struct pios_rfm22b_dev *rfm22b_dev, uint32_t frequency_hz) { - return lower_carrier_frequency_limit_Hz; -} -uint32_t rfm22_maxFrequency(void) -{ - return upper_carrier_frequency_limit_Hz; -} - -void rfm22_setNominalCarrierFrequency(uint32_t frequency_hz) -{ - - exec_using_spi = true; - - // ******* - - 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; + uint32_t min_frequency_hz = rfm22b_dev->cfg.minFrequencyHz; + uint32_t max_frequency_hz = rfm22b_dev->cfg.maxFrequencyHz; + if (frequency_hz < min_frequency_hz) + frequency_hz = min_frequency_hz; + else if (frequency_hz > max_frequency_hz) + frequency_hz = max_frequency_hz; + // holds the hbsel (1 or 2) + uint8_t hbsel; if (frequency_hz < 480000000) hbsel = 1; else @@ -1038,59 +996,37 @@ void rfm22_setNominalCarrierFrequency(uint32_t frequency_hz) 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; + // frequency hopping channel (0-255) + rfm22b_dev->frequency_step_size = 156.25f * hbsel; - rfm22_write(RFM22_frequency_hopping_channel_select, frequency_hop_channel); // frequency hopping channel (0-255) + // frequency hopping channel (0-255) + rfm22_write(RFM22_frequency_hopping_channel_select, rfm22b_dev->frequency_hop_channel); - rfm22_write(RFM22_frequency_offset1, 0); // no frequency offset - rfm22_write(RFM22_frequency_offset2, 0); // no frequency offset + // no frequency offset + rfm22_write(RFM22_frequency_offset1, 0); + // no frequency offset + rfm22_write(RFM22_frequency_offset2, 0); - 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) - //DEBUG_PRINTF(2, "rf setFreq: %u\n\r", carrier_frequency_hz); - // 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; + // set the carrier frequency + rfm22_write(RFM22_frequency_band_select, fb); + rfm22_write(RFM22_nominal_carrier_frequency1, fc >> 8); + rfm22_write(RFM22_nominal_carrier_frequency0, fc & 0xff); } 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; + g_rfm22b_dev->frequency_hop_channel = channel; + rfm22_write(RFM22_frequency_hopping_channel_select, channel); } uint32_t rfm22_freqHopSize(void) { // return the frequency hopping step size - return ((uint32_t)frequency_hop_step_size_reg * 10000); + return ((uint32_t)g_rfm22b_dev->frequency_hop_step_size_reg * 10000); } // ************************************ @@ -1109,15 +1045,12 @@ uint32_t rfm22_freqHopSize(void) void rfm22_setDatarate(uint32_t datarate_bps, bool data_whitening) { - exec_using_spi = true; - - lookup_index = 0; + // Find the closest data rate that is >= the value passed in + int 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]; + datarate_bps = data_rate[lookup_index]; // rfm22_if_filter_bandwidth rfm22_write(0x1C, reg_1C[lookup_index]); @@ -1145,7 +1078,7 @@ void rfm22_setDatarate(uint32_t datarate_bps, bool data_whitening) // rfm22_afc_limiter rfm22_write(0x2A, reg_2A[lookup_index]); - if (carrier_datarate_bps < 100000) + if (datarate_bps < 100000) // rfm22_chargepump_current_trimming_override rfm22_write(0x58, 0x80); else @@ -1176,84 +1109,12 @@ void rfm22_setDatarate(uint32_t datarate_bps, bool data_whitening) 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 - - // milliseconds - timeout_sync_ms = (8000ul * 16) / carrier_datarate_bps; - if (timeout_sync_ms < 3) - // because out timer resolution is only 1ms - timeout_sync_ms = 3; - - // milliseconds - timeout_data_ms = (8000ul * 100) / carrier_datarate_bps; - if (timeout_data_ms < 3) - // because out timer resolution is only 1ms - timeout_data_ms = 3; - - // ******************************** - -#if defined(RFM22_DEBUG) -/* - DEBUG_PRINTF(2, "rf datarate_bps: %d\n\r", datarate_bps); - DEBUG_PRINTF(2, "rf frequency_deviation: %d\n\r", frequency_deviation); - uint32_t frequency_deviation = freq_deviation[lookup_index]; // Hz - uint32_t modulation_bandwidth = datarate_bps + (2 * frequency_deviation); - 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]); -*/ -#endif - - // ******* - - exec_using_spi = false; -} - -uint32_t rfm22_getDatarate(void) -{ - return carrier_datarate_bps; } // ************************************ static enum pios_rfm22b_event rfm22_setRxMode(struct pios_rfm22b_dev *rfm22b_dev) { - exec_using_spi = true; // disable interrupts rfm22_write(RFM22_interrupt_enable1, 0x00); @@ -1269,7 +1130,7 @@ static enum pios_rfm22b_event rfm22_setRxMode(struct pios_rfm22b_dev *rfm22b_dev rx_buffer_wr = 0; // Clear the TX buffer. - tx_data_rd = tx_data_wr = 0; + rfm22b_dev->tx_data_rd = rfm22b_dev->tx_data_wr = 0; // clear FIFOs rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_ffclrrx | RFM22_opfc2_ffclrtx); @@ -1284,8 +1145,6 @@ static enum pios_rfm22b_event rfm22_setRxMode(struct pios_rfm22b_dev *rfm22b_dev // enable the receiver rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon | RFM22_opfc1_rxon); - exec_using_spi = false; - // No event generated return RFM22B_EVENT_NUM_EVENTS; } @@ -1294,14 +1153,15 @@ static enum pios_rfm22b_event rfm22_setRxMode(struct pios_rfm22b_dev *rfm22b_dev static enum pios_rfm22b_event rfm22_txStart(struct pios_rfm22b_dev *rfm22b_dev) { - if((tx_pre_buffer_size == 0) || (exec_using_spi == true)) + // See if there's a packet on the packet queue. + PHPacketHandle p; + if (xQueueReceive(rfm22b_dev->packetQueue, &p, 0) != pdTRUE) { // Clear the TX buffer. - tx_data_rd = tx_data_wr = 0; + rfm22b_dev->tx_data_rd = rfm22b_dev->tx_data_wr = 0; return RFM22B_EVENT_RX_MODE; } - - exec_using_spi = true; + rfm22b_dev->tx_packet = p; // disable interrupts rfm22_write(RFM22_interrupt_enable1, 0x00); @@ -1311,15 +1171,13 @@ static enum pios_rfm22b_event rfm22_txStart(struct pios_rfm22b_dev *rfm22b_dev) 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; + rfm22b_dev->tx_data_wr = PH_PACKET_SIZE(rfm22b_dev->tx_packet); RX_LED_OFF; // Set the destination address in the transmit header. // The destination address is the first 4 bytes of the message. + uint8_t *tx_buffer = (uint8_t*)(rfm22b_dev->tx_packet); rfm22_write(RFM22_transmit_header0, tx_buffer[0]); rfm22_write(RFM22_transmit_header1, tx_buffer[1]); rfm22_write(RFM22_transmit_header2, tx_buffer[2]); @@ -1342,16 +1200,16 @@ static enum pios_rfm22b_event rfm22_txStart(struct pios_rfm22b_dev *rfm22b_dev) // 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); + rfm22_write(RFM22_transmit_packet_length, rfm22b_dev->tx_data_wr); // add some data rfm22_claimBus(); rfm22_assertCs(); PIOS_SPI_TransferByte(g_rfm22b_dev->spi_id, RFM22_fifo_access | 0x80); - int bytes_to_write = (tx_data_wr - tx_data_rd); + int bytes_to_write = (rfm22b_dev->tx_data_wr - rfm22b_dev->tx_data_rd); bytes_to_write = (bytes_to_write > FIFO_SIZE) ? FIFO_SIZE: bytes_to_write; - PIOS_SPI_TransferBlock(g_rfm22b_dev->spi_id, &tx_buffer[tx_data_rd], NULL, bytes_to_write, NULL); - tx_data_rd += bytes_to_write; + PIOS_SPI_TransferBlock(g_rfm22b_dev->spi_id, &tx_buffer[rfm22b_dev->tx_data_rd], NULL, bytes_to_write, NULL); + rfm22b_dev->tx_data_rd += bytes_to_write; rfm22_deassertCs(); rfm22_releaseBus(); @@ -1363,8 +1221,7 @@ static enum pios_rfm22b_event rfm22_txStart(struct pios_rfm22b_dev *rfm22b_dev) TX_LED_ON; - exec_using_spi = false; - return RFM22B_EVENT_NUM_EVENTS; + return RFM22B_EVENT_TX_STARTED; } // ************************************ @@ -1375,7 +1232,6 @@ static enum pios_rfm22b_event rfm22_txStart(struct pios_rfm22b_dev *rfm22b_dev) */ static bool rfm22_readStatus(struct pios_rfm22b_dev *rfm22b_dev) { - exec_using_spi = true; // 1. Read the interrupt statuses with burst read rfm22_claimBus(); // Set RC and the semaphore @@ -1398,12 +1254,8 @@ static bool rfm22_readStatus(struct pios_rfm22b_dev *rfm22b_dev) // the RF module has gone and done a reset - we need to re-initialize the rf module if (rfm22b_dev->int_status2 & RFM22_is2_ipor) - { - exec_using_spi = false; return false; - } - exec_using_spi = false; return true; } @@ -1438,12 +1290,12 @@ static enum pios_rfm22b_event rfm22_detectSync(struct pios_rfm22b_dev *rfm22b_de // read the 10-bit signed afc correction value // bits 9 to 2 - afc_correction = (uint16_t)rfm22_read(RFM22_afc_correction_read) << 8; + uint16_t 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); + rfm22b_dev->afc_correction_Hz = (int32_t)(rfm22b_dev->frequency_step_size * afc_correction + 0.5f); // read rx signal strength .. 45 = -100dBm, 205 = -20dBm rfm22b_dev->rssi = rfm22_read(RFM22_rssi); @@ -1451,7 +1303,7 @@ static enum pios_rfm22b_event rfm22_detectSync(struct pios_rfm22b_dev *rfm22b_de rfm22b_dev->rssi_dBm = (int8_t)(rfm22b_dev->rssi >> 1) - 122; // remember the afc value for this packet - rx_packet_start_afc_Hz = afc_correction_Hz; + rfm22b_dev->rx_packet_start_afc_Hz = rfm22b_dev->afc_correction_Hz; return RFM22B_EVENT_SYNC_DETECTED; } @@ -1470,8 +1322,6 @@ static enum pios_rfm22b_event rfm22_rxData(struct pios_rfm22b_dev *rfm22b_dev) if (rfm22b_dev->device_status & (RFM22_ds_ffunfl | RFM22_ds_ffovfl)) return RFM22B_EVENT_ERROR; - exec_using_spi = true; - // RX FIFO almost full, it needs emptying if (rfm22b_dev->int_status1 & RFM22_is1_irxffafull) { @@ -1525,10 +1375,7 @@ static enum pios_rfm22b_event rfm22_rxData(struct pios_rfm22b_dev *rfm22b_dev) } if (rx_buffer_wr != len) - { - exec_using_spi = false; return RFM22B_EVENT_ERROR; - } // we have a valid received packet @@ -1536,7 +1383,7 @@ static enum pios_rfm22b_event rfm22_rxData(struct pios_rfm22b_dev *rfm22b_dev) { // Add the rssi and afc to the end of the packet. rx_buffer[rx_buffer_wr++] = rfm22b_dev->rssi_dBm; - rx_buffer[rx_buffer_wr++] = rx_packet_start_afc_Hz; + rx_buffer[rx_buffer_wr++] = rfm22b_dev->rx_packet_start_afc_Hz; // Pass this packet on bool need_yield = false; if (rfm22b_dev->rx_in_cb) @@ -1546,11 +1393,9 @@ static enum pios_rfm22b_event rfm22_rxData(struct pios_rfm22b_dev *rfm22b_dev) } // Start a new transaction - exec_using_spi = false; return RFM22B_EVENT_RX_COMPLETE; } - exec_using_spi = false; return RFM22B_EVENT_NUM_EVENTS; } @@ -1559,12 +1404,21 @@ static enum pios_rfm22b_event rfm22_txData(struct pios_rfm22b_dev *rfm22b_dev) // Read the device status registers if (!rfm22_readStatus(rfm22b_dev)) + { + // Free the tx packet + PHReleaseTXPacket(pios_packet_handler, rfm22b_dev->tx_packet); + rfm22b_dev->tx_packet = 0; + rfm22b_dev->tx_data_wr = rfm22b_dev->tx_data_rd = 0; return RFM22B_EVENT_ERROR; + } // FIFO under/over flow error. Back to RX mode. if (rfm22b_dev->device_status & (RFM22_ds_ffunfl | RFM22_ds_ffovfl)) { - exec_using_spi = false; + // Free the tx packet + PHReleaseTXPacket(pios_packet_handler, rfm22b_dev->tx_packet); + rfm22b_dev->tx_packet = 0; + rfm22b_dev->tx_data_wr = rfm22b_dev->tx_data_rd = 0; return RFM22B_EVENT_ERROR; } @@ -1572,14 +1426,15 @@ static enum pios_rfm22b_event rfm22_txData(struct pios_rfm22b_dev *rfm22b_dev) if (rfm22b_dev->int_status1 & RFM22_is1_ixtffaem) { // top-up the rf chips TX FIFO buffer + uint8_t *tx_buffer = (uint8_t*)(rfm22b_dev->tx_packet); uint16_t max_bytes = FIFO_SIZE - TX_FIFO_LO_WATERMARK - 1; rfm22_claimBus(); rfm22_assertCs(); PIOS_SPI_TransferByte(g_rfm22b_dev->spi_id, RFM22_fifo_access | 0x80); - int bytes_to_write = (tx_data_wr - tx_data_rd); + int bytes_to_write = (rfm22b_dev->tx_data_wr - rfm22b_dev->tx_data_rd); bytes_to_write = (bytes_to_write > max_bytes) ? max_bytes: bytes_to_write; - PIOS_SPI_TransferBlock(g_rfm22b_dev->spi_id, &tx_buffer[tx_data_rd], NULL, bytes_to_write, NULL); - tx_data_rd += bytes_to_write; + PIOS_SPI_TransferBlock(g_rfm22b_dev->spi_id, &tx_buffer[rfm22b_dev->tx_data_rd], NULL, bytes_to_write, NULL); + rfm22b_dev->tx_data_rd += bytes_to_write; rfm22_deassertCs(); rfm22_releaseBus(); } @@ -1587,12 +1442,14 @@ static enum pios_rfm22b_event rfm22_txData(struct pios_rfm22b_dev *rfm22b_dev) // Packet has been sent if (rfm22b_dev->int_status1 & RFM22_is1_ipksent) { - exec_using_spi = false; + // Free the tx packet + PHReleaseTXPacket(pios_packet_handler, rfm22b_dev->tx_packet); + rfm22b_dev->tx_packet = 0; + rfm22b_dev->tx_data_wr = rfm22b_dev->tx_data_rd = 0; // Start a new transaction return RFM22B_EVENT_TX_COMPLETE; } - exec_using_spi = false; return RFM22B_EVENT_NUM_EVENTS; } @@ -1613,10 +1470,6 @@ bool rfm22_transmitting(void) // return true if the channel is clear to transmit on bool rfm22_channelIsClear(void) { - if (!initialized) - // we haven't yet been initialized - return false; - if (g_rfm22b_dev->state != RFM22B_STATE_RX_MODE && g_rfm22b_dev->state != RFM22B_STATE_WAIT_PREAMBLE && g_rfm22b_dev->state != RFM22B_STATE_WAIT_SYNC) // we are receiving something or we are transmitting or we are scanning the spectrum return false; @@ -1624,29 +1477,12 @@ bool rfm22_channelIsClear(void) return true; } -// return true if the transmiter is ready for use -bool rfm22_txReady(void) -{ - return (tx_data_rd == 0 && tx_data_wr == 0 && g_rfm22b_dev->state != RFM22B_STATE_TX_DATA); -} - // ************************************ // set/get the frequency calibration value void rfm22_setFreqCalibration(uint8_t value) { - osc_load_cap = value; - - exec_using_spi = true; - - rfm22_write(RFM22_xtal_osc_load_cap, osc_load_cap); - - exec_using_spi = false; -} - -uint8_t rfm22_getFreqCalibration(void) -{ - return osc_load_cap; + rfm22_write(RFM22_xtal_osc_load_cap, value); } // ************************************ @@ -1659,9 +1495,6 @@ static enum pios_rfm22b_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev) uint32_t max_frequency_hz = rfm22b_dev->cfg.maxFrequencyHz; uint32_t freq_hop_step_size = 50000; - initialized = false; - exec_using_spi = true; - // software reset the RF chip .. following procedure according to Si4x3x Errata (rev. B) rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_swres); @@ -1693,39 +1526,25 @@ static enum pios_rfm22b_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev) // **************** - exec_using_spi = false; - - // **************** - rfm22b_dev->device_status = rfm22b_dev->int_status1 = rfm22b_dev->int_status2 = rfm22b_dev->ezmac_status = 0; rx_buffer_current = 0; rx_buffer_wr = 0; - rx_packet_afc_Hz = 0; - tx_data_rd = tx_data_wr = 0; + rfm22b_dev->tx_data_rd = rfm22b_dev->tx_data_wr = 0; + rfm22b_dev->tx_packet = NULL; - lookup_index = 0; - ss_lookup_index = 0; + rfm22b_dev->frequency_hop_channel = 0; - rf_bandwidth_used = 0; - ss_rf_bandwidth_used = 0; - - hbsel = 0; - frequency_step_size = 0.0f; - - frequency_hop_channel = 0; - - afc_correction = 0; - afc_correction_Hz = 0; - - temperature_reg = 0; + rfm22b_dev->afc_correction_Hz = 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 + // read the device type + uint8_t device_type = rfm22_read(RFM22_DEVICE_TYPE) & RFM22_DT_MASK; + // read the device version + uint8_t device_version = rfm22_read(RFM22_DEVICE_VERSION) & RFM22_DV_MASK; #if defined(RFM22_DEBUG) DEBUG_PRINTF(2, "rf device type: %d\n\r", device_type); @@ -1767,27 +1586,24 @@ static enum pios_rfm22b_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev) 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); + 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 + // 1MHz clock output + rfm22_write(RFM22_cpu_output_clk, RFM22_coc_1MHz); - rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton); // READY mode - // rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon); // TUNE mode + // READY mode + rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton); // choose the 3 GPIO pin functions - rfm22_write(RFM22_io_port_config, RFM22_io_port_default); // GPIO port use default value + // GPIO port use default value + rfm22_write(RFM22_io_port_config, RFM22_io_port_default); if (rfm22b_dev->cfg.gpio_direction == GPIO0_TX_GPIO1_RX) { 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) @@ -1802,7 +1618,7 @@ static enum pios_rfm22b_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev) // initialize the frequency hopping step size 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; + rfm22b_dev->frequency_hop_step_size_reg = freq_hop_step_size; // set the RF datarate rfm22_setDatarate(RFM22_DEFAULT_RF_DATARATE, true); @@ -1814,7 +1630,7 @@ static enum pios_rfm22b_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev) // setup to read the internal temperature sensor // ADC used to sample the temperature sensor - adc_config = RFM22_ac_adcsel_temp_sensor | RFM22_ac_adcref_bg; + uint8_t adc_config = RFM22_ac_adcsel_temp_sensor | RFM22_ac_adcref_bg; rfm22_write(RFM22_adc_config, adc_config); // adc offset @@ -1875,7 +1691,7 @@ static enum pios_rfm22b_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev) ((TX_PREAMBLE_NIBBLES >> 8) & 0x01)); #endif - // sync word + // 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); @@ -1884,10 +1700,10 @@ static enum pios_rfm22b_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev) rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_agcen); // set frequency hopping channel step size (multiples of 10kHz) - rfm22_write(RFM22_frequency_hopping_step_size, frequency_hop_step_size_reg); + rfm22_write(RFM22_frequency_hopping_step_size, rfm22b_dev->frequency_hop_step_size_reg); // set our nominal carrier frequency - rfm22_setNominalCarrierFrequency((min_frequency_hz + max_frequency_hz) / 2); + rfm22_setNominalCarrierFrequency(rfm22b_dev, (min_frequency_hz + max_frequency_hz) / 2); // set the tx power rfm22_write(RFM22_tx_power, RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | rfm22b_dev->tx_power); @@ -1901,21 +1717,11 @@ static enum pios_rfm22b_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev) // RX FIFO Almost Full Threshold (0 - 63) rfm22_write(RFM22_rx_fifo_control, RX_FIFO_HI_WATERMARK); - //rfm22_setRxMode(rfm22b_dev); - rfm22_setFreqCalibration(rfm22b_dev->cfg.RFXtalCap); - rfm22_setNominalCarrierFrequency(rfm22b_dev->cfg.frequencyHz); + rfm22_setNominalCarrierFrequency(rfm22b_dev, rfm22b_dev->cfg.frequencyHz); rfm22_setDatarate(rfm22b_dev->cfg.maxRFBandwidth, true); - DEBUG_PRINTF(2, "\n\r"); - DEBUG_PRINTF(2, "RF device ID: %x\n\r", rfm22b_dev->deviceID); - 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", rfm22b_dev->tx_power); - - initialized = true; - - return RFM22B_EVENT_RX_MODE; + return RFM22B_EVENT_INITIALIZED; } static enum pios_rfm22b_event rfm22_error(struct pios_rfm22b_dev *rfm22b_dev) diff --git a/flight/PiOS/inc/pios_rfm22b_priv.h b/flight/PiOS/inc/pios_rfm22b_priv.h index 604efba63..cea382220 100644 --- a/flight/PiOS/inc/pios_rfm22b_priv.h +++ b/flight/PiOS/inc/pios_rfm22b_priv.h @@ -582,44 +582,6 @@ typedef bool ( *t_rfm22_RxDataCallback ) (void *data, uint8_t len); void PIOS_RFM22_EXT_Int(void); -uint32_t rfm22_minFrequency(void); -uint32_t rfm22_maxFrequency(void); - -void rfm22_setNominalCarrierFrequency(uint32_t frequency_hz); -uint32_t rfm22_getNominalCarrierFrequency(void); - -float rfm22_getFrequencyStepSize(void); - -void rfm22_setFreqHopChannel(uint8_t channel); -uint8_t rfm22_freqHopChannel(void); - -uint32_t rfm22_freqHopSize(void); - -void rfm22_setDatarate(uint32_t datarate_bps, bool data_whitening); -uint32_t rfm22_getDatarate(void); - -void rfm22_setFreqCalibration(uint8_t value); -uint8_t rfm22_getFreqCalibration(void); - -void rfm22_setTxPower(uint8_t tx_pwr); -uint8_t rfm22_getTxPower(void); - -void rfm22_setTxStream(void); // TEST ONLY - -void rfm22_setTxNormal(void); -void rfm22_setTxCarrierMode(void); -void rfm22_setTxPNMode(void); - -int8_t rfm22_currentMode(void); -bool rfm22_transmitting(void); - -bool rfm22_channelIsClear(void); - -bool rfm22_txReady(void); - -void rfm22_TxDataByte_SetCallback(t_rfm22_TxDataByteCallback new_function); -void rfm22_RxData_SetCallback(t_rfm22_RxDataCallback new_function); - #endif /* PIOS_RFM22B_PRIV_H */ /** From a070e1cc3e772252d2552e90a8d6794aaf10c2dd Mon Sep 17 00:00:00 2001 From: Brian Webb Date: Sun, 23 Sep 2012 08:36:38 -0700 Subject: [PATCH 08/10] RFM22B: Added PIOS_RFM22B_Receive_Packet function and removed rx buffer. --- flight/Modules/Radio/radio.c | 31 ++------ flight/PiOS/Common/pios_rfm22b.c | 119 +++++++++++++++++++++++-------- 2 files changed, 93 insertions(+), 57 deletions(-) diff --git a/flight/Modules/Radio/radio.c b/flight/Modules/Radio/radio.c index e1fab89f2..41e732215 100644 --- a/flight/Modules/Radio/radio.c +++ b/flight/Modules/Radio/radio.c @@ -41,7 +41,7 @@ // **************** // Private constants -#define STACK_SIZE_BYTES 150 +#define STACK_SIZE_BYTES 200 #define TASK_PRIORITY (tskIDLE_PRIORITY + 2) #define PACKET_QUEUE_SIZE PIOS_PH_WIN_SIZE #define MAX_PORT_DELAY 200 @@ -232,20 +232,8 @@ static int32_t RadioInitialize(void) } /* Initalize the RFM22B radio COM device. */ - { - if (PIOS_RFM22B_Init(&pios_rfm22b_id, PIOS_RFM22_SPI_PORT, pios_rfm22b_cfg.slave_num, &pios_rfm22b_cfg)) { - return -1; - } - uint8_t * rx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_RFM22B_RF_RX_BUF_LEN); - uint8_t * tx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_RFM22B_RF_TX_BUF_LEN); - PIOS_Assert(rx_buffer); - PIOS_Assert(tx_buffer); - if (PIOS_COM_Init(&pios_com_rfm22b_id, &pios_rfm22b_com_driver, pios_rfm22b_id, - rx_buffer, PIOS_COM_RFM22B_RF_RX_BUF_LEN, - tx_buffer, PIOS_COM_RFM22B_RF_TX_BUF_LEN)) { - PIOS_Assert(0); - } - } + if (PIOS_RFM22B_Init(&pios_rfm22b_id, PIOS_RFM22_SPI_PORT, pios_rfm22b_cfg.slave_num, &pios_rfm22b_cfg)) + return -1; // Initialize the packet handler PacketHandlerConfig pios_ph_cfg = { @@ -311,18 +299,9 @@ static void radioReceiveTask(void *parameters) PIOS_WDG_UpdateFlag(PIOS_WDG_RADIORECEIVE); #endif /* PIOS_INCLUDE_WDG */ - // Get a RX packet from the packet handler if required. - if (p == NULL) - p = PHGetRXPacket(pios_packet_handler); - - if(p == NULL) { - // Wait a bit for a packet to come available. - vTaskDelay(5); - continue; - } - // Receive data from the radio port - rx_bytes = PIOS_COM_ReceiveBuffer(PIOS_COM_RADIO, (uint8_t*)p, PIOS_PH_MAX_PACKET, MAX_PORT_DELAY); + p = NULL; + rx_bytes = PIOS_RFM22B_Receive_Packet(pios_rfm22b_id, &p, MAX_PORT_DELAY); if(rx_bytes == 0) continue; data->rxBytes += rx_bytes; diff --git a/flight/PiOS/Common/pios_rfm22b.c b/flight/PiOS/Common/pios_rfm22b.c index e48a97318..723337e46 100644 --- a/flight/PiOS/Common/pios_rfm22b.c +++ b/flight/PiOS/Common/pios_rfm22b.c @@ -192,6 +192,9 @@ struct pios_rfm22b_dev { // ISR pending xSemaphoreHandle isrPending; + // Receive packet complete + xSemaphoreHandle rxsem; + // The COM callback functions. pios_com_callback rx_in_cb; uint32_t rx_in_context; @@ -234,6 +237,17 @@ struct pios_rfm22b_dev { // the tx data write index uint16_t tx_data_wr; + // The current rx packet + PHPacketHandle rx_packet; + // The previous rx packet + PHPacketHandle rx_packet_prev; + // The next rx packet + PHPacketHandle rx_packet_next; + // the receive buffer write index + uint16_t rx_buffer_wr; + // the receive buffer write index + uint16_t rx_packet_len; + // The frequency hopping step size float frequency_step_size; // current frequency hop channel @@ -470,13 +484,6 @@ static const uint8_t ss_reg_2A[] = { 0xFF, 0xFF}; // rfm22_afc_limiter .. AFC_p static const uint8_t ss_reg_70[] = { 0x24, 0x2D}; // rfm22_modulation_mode_control1 static const uint8_t ss_reg_71[] = { 0x2B, 0x23}; // rfm22_modulation_mode_control2 -// the current receive buffer in use (double buffer) -volatile uint8_t rx_buffer_current; -// the receive buffer .. received packet data is saved here -volatile uint8_t rx_buffer[258] __attribute__ ((aligned(4))); -// the receive buffer write index -volatile uint16_t rx_buffer_wr; - static bool PIOS_RFM22B_validate(struct pios_rfm22b_dev * rfm22b_dev) { @@ -552,12 +559,22 @@ int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, uint32_t spi_id, uint32_t slave_nu // Bind the configuration to the device instance rfm22b_dev->cfg = *cfg; + // Initialize the packets. + rfm22b_dev->rx_packet = NULL; + rfm22b_dev->rx_packet_next = NULL; + rfm22b_dev->rx_packet_prev = NULL; + rfm22b_dev->rx_packet_len = 0; + rfm22b_dev->tx_packet = NULL; + *rfm22b_id = (uint32_t)rfm22b_dev; g_rfm22b_dev = rfm22b_dev; // Create a semaphore to know if an ISR needs responding to vSemaphoreCreateBinary( rfm22b_dev->isrPending ); + // Create a semaphore to know when an rx packet is available + vSemaphoreCreateBinary( rfm22b_dev->rxsem ); + // Create the packet queue. rfm22b_dev->packetQueue = xQueueCreate(PACKET_QUEUE_SIZE, sizeof(PHPacketHandle)); @@ -712,6 +729,39 @@ bool PIOS_RFM22B_Send_Packet(uint32_t rfm22b_id, PHPacketHandle p, uint32_t max_ return true; } +/** + * Receive a packet from the radio. + * \param[in] rfm22b_id The rfm22b device. + * \param[in] p A pointer to the packet handle. + * \param[in] max_delay The maximum time to delay waiting for a packet. + * \return The number of bytes received. + */ +uint32_t PIOS_RFM22B_Receive_Packet(uint32_t rfm22b_id, PHPacketHandle *p, uint32_t max_delay) +{ + struct pios_rfm22b_dev * rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id; + if (!PIOS_RFM22B_validate(rfm22b_dev)) + return 0; + + // Allocate the next Rx packet + if (rfm22b_dev->rx_packet_next == NULL) + rfm22b_dev->rx_packet_next = PHGetRXPacket(pios_packet_handler); + + // Block on the semephore until the a packet has been received. + if (xSemaphoreTake(rfm22b_dev->rxsem, max_delay / portTICK_RATE_MS) != pdTRUE) + return 0; + + // Return the Rx packet if it's available. + uint32_t rx_len = 0; + if (rfm22b_dev->rx_packet_prev) + { + *p = rfm22b_dev->rx_packet_prev; + rfm22b_dev->rx_packet_prev = NULL; + rx_len = rfm22b_dev->rx_packet_len; + } + + return rx_len; +} + /** * The task that controls the radio state machine. */ @@ -1127,7 +1177,7 @@ static enum pios_rfm22b_event rfm22_setRxMode(struct pios_rfm22b_dev *rfm22b_dev TX_LED_OFF; // empty the rx buffer - rx_buffer_wr = 0; + rfm22b_dev->rx_buffer_wr = 0; // Clear the TX buffer. rfm22b_dev->tx_data_rd = rfm22b_dev->tx_data_wr = 0; @@ -1313,6 +1363,15 @@ static enum pios_rfm22b_event rfm22_detectSync(struct pios_rfm22b_dev *rfm22b_de static enum pios_rfm22b_event rfm22_rxData(struct pios_rfm22b_dev *rfm22b_dev) { + // Swap in the next packet buffer if required. + if (rfm22b_dev->rx_packet == NULL) + { + if (rfm22b_dev->rx_packet_next != NULL) + rfm22b_dev->rx_packet = rfm22b_dev->rx_packet_next; + else + return RFM22B_EVENT_ERROR; + } + uint8_t *rx_buffer = (uint8_t*)(rfm22b_dev->rx_packet); // Read the device status registers if (!rfm22_readStatus(rfm22b_dev)) @@ -1330,20 +1389,18 @@ static enum pios_rfm22b_event rfm22_rxData(struct pios_rfm22b_dev *rfm22b_dev) uint16_t len = rfm22_read(RFM22_received_packet_length); // The received packet is going to be larger than the specified length - if ((rx_buffer_wr + RX_FIFO_HI_WATERMARK) > len) + if ((rfm22b_dev->rx_buffer_wr + RX_FIFO_HI_WATERMARK) > len) return RFM22B_EVENT_ERROR; // Another packet length error. - if (((rx_buffer_wr + RX_FIFO_HI_WATERMARK) >= len) && !(rfm22b_dev->int_status1 & RFM22_is1_ipkvalid)) + if (((rfm22b_dev->rx_buffer_wr + RX_FIFO_HI_WATERMARK) >= len) && !(rfm22b_dev->int_status1 & RFM22_is1_ipkvalid)) return RFM22B_EVENT_ERROR; // Fetch the data from the RX FIFO rfm22_claimBus(); rfm22_assertCs(); PIOS_SPI_TransferByte(rfm22b_dev->spi_id,RFM22_fifo_access & 0x7F); - rx_buffer_wr += (PIOS_SPI_TransferBlock(rfm22b_dev->spi_id,OUT_FF, - (uint8_t *) &rx_buffer[rx_buffer_wr],RX_FIFO_HI_WATERMARK,NULL) == 0) ? - RX_FIFO_HI_WATERMARK : 0; + rfm22b_dev->rx_buffer_wr += (PIOS_SPI_TransferBlock(rfm22b_dev->spi_id ,OUT_FF, (uint8_t *)&rx_buffer[rfm22b_dev->rx_buffer_wr], RX_FIFO_HI_WATERMARK, NULL) == 0) ? RX_FIFO_HI_WATERMARK : 0; rfm22_deassertCs(); rfm22_releaseBus(); } @@ -1360,36 +1417,38 @@ static enum pios_rfm22b_event rfm22_rxData(struct pios_rfm22b_dev *rfm22b_dev) uint32_t len = rfm22_read(RFM22_received_packet_length); // their must still be data in the RX FIFO we need to get - if (rx_buffer_wr < len) + if (rfm22b_dev->rx_buffer_wr < len) { - int32_t bytes_to_read = len - rx_buffer_wr; + int32_t bytes_to_read = len - rfm22b_dev->rx_buffer_wr; // Fetch the data from the RX FIFO rfm22_claimBus(); rfm22_assertCs(); PIOS_SPI_TransferByte(rfm22b_dev->spi_id,RFM22_fifo_access & 0x7F); - rx_buffer_wr += (PIOS_SPI_TransferBlock(rfm22b_dev->spi_id,OUT_FF, - (uint8_t *) &rx_buffer[rx_buffer_wr],bytes_to_read,NULL) == 0) ? - bytes_to_read : 0; + rfm22b_dev->rx_buffer_wr += (PIOS_SPI_TransferBlock(rfm22b_dev->spi_id,OUT_FF, (uint8_t *)&rx_buffer[rfm22b_dev->rx_buffer_wr], bytes_to_read, NULL) == 0) ? bytes_to_read : 0; rfm22_deassertCs(); rfm22_releaseBus(); } - if (rx_buffer_wr != len) + if (rfm22b_dev->rx_buffer_wr != len) return RFM22B_EVENT_ERROR; // we have a valid received packet - if (rx_buffer_wr > 0) + if (rfm22b_dev->rx_buffer_wr > 0) { // Add the rssi and afc to the end of the packet. - rx_buffer[rx_buffer_wr++] = rfm22b_dev->rssi_dBm; - rx_buffer[rx_buffer_wr++] = rfm22b_dev->rx_packet_start_afc_Hz; - // Pass this packet on - bool need_yield = false; - if (rfm22b_dev->rx_in_cb) - (rfm22b_dev->rx_in_cb)(rfm22b_dev->rx_in_context, (uint8_t*)rx_buffer, - rx_buffer_wr, NULL, &need_yield); - rx_buffer_wr = 0; + rx_buffer[rfm22b_dev->rx_buffer_wr++] = rfm22b_dev->rssi_dBm; + rx_buffer[rfm22b_dev->rx_buffer_wr++] = rfm22b_dev->rx_packet_start_afc_Hz; + // Swap the Rx packets. + if (rfm22b_dev->rx_packet_prev == NULL) + { + rfm22b_dev->rx_packet_prev = rfm22b_dev->rx_packet; + rfm22b_dev->rx_packet = rfm22b_dev->rx_packet_next; + rfm22b_dev->rx_packet_len = rfm22b_dev->rx_buffer_wr; + // Signal the receive thread. + xSemaphoreGive(rfm22b_dev->rxsem); + } + rfm22b_dev->rx_buffer_wr = 0; } // Start a new transaction @@ -1528,11 +1587,9 @@ static enum pios_rfm22b_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev) rfm22b_dev->device_status = rfm22b_dev->int_status1 = rfm22b_dev->int_status2 = rfm22b_dev->ezmac_status = 0; - rx_buffer_current = 0; - rx_buffer_wr = 0; + rfm22b_dev->rx_buffer_wr = 0; rfm22b_dev->tx_data_rd = rfm22b_dev->tx_data_wr = 0; - rfm22b_dev->tx_packet = NULL; rfm22b_dev->frequency_hop_channel = 0; From 88be2ddf1e594d9b04312dd3deb7b0f87c5095ec Mon Sep 17 00:00:00 2001 From: Brian Webb Date: Mon, 24 Sep 2012 20:51:34 -0700 Subject: [PATCH 09/10] RFM22B: Added a message timeout event to the RFM22B state machine that will fire if a packet takes too long to transmit / receive. --- flight/PiOS/Common/pios_rfm22b.c | 88 ++++++++++++++++++++++++++------ 1 file changed, 72 insertions(+), 16 deletions(-) diff --git a/flight/PiOS/Common/pios_rfm22b.c b/flight/PiOS/Common/pios_rfm22b.c index 723337e46..b0f321a7b 100644 --- a/flight/PiOS/Common/pios_rfm22b.c +++ b/flight/PiOS/Common/pios_rfm22b.c @@ -145,13 +145,14 @@ enum pios_rfm22b_dev_magic { enum pios_rfm22b_state { RFM22B_STATE_UNINITIALIZED, RFM22B_STATE_INITIALIZING, - RFM22B_STATE_ERROR, RFM22B_STATE_RX_MODE, RFM22B_STATE_WAIT_PREAMBLE, RFM22B_STATE_WAIT_SYNC, RFM22B_STATE_RX_DATA, RFM22B_STATE_TX_START, RFM22B_STATE_TX_DATA, + RFM22B_STATE_TIMEOUT, + RFM22B_STATE_ERROR, RFM22B_STATE_FATAL_ERROR, RFM22B_STATE_NUM_STATES // Must be last @@ -161,7 +162,6 @@ enum pios_rfm22b_event { RFM22B_EVENT_INITIALIZE, RFM22B_EVENT_INITIALIZED, RFM22B_EVENT_INT_RECEIVED, - RFM22B_EVENT_TX_MODE, RFM22B_EVENT_RX_MODE, RFM22B_EVENT_PREAMBLE_DETECTED, RFM22B_EVENT_SYNC_DETECTED, @@ -257,6 +257,10 @@ struct pios_rfm22b_dev { // afc correction reading (in Hz) int32_t afc_correction_Hz; int8_t rx_packet_start_afc_Hz; + + // The maximum time (ms) that it should take to transmit / receive a packet. + uint32_t max_packet_time; + portTickType packet_start_time; }; struct pios_rfm22b_transition { @@ -301,6 +305,7 @@ static enum pios_rfm22b_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev); static enum pios_rfm22b_event rfm22_txStart(struct pios_rfm22b_dev *rfm22b_dev); static enum pios_rfm22b_event rfm22_txData(struct pios_rfm22b_dev *rfm22b_dev); static enum pios_rfm22b_event rfm22_process_state_transition(struct pios_rfm22b_dev *rfm22b_dev, enum pios_rfm22b_event event); +static enum pios_rfm22b_event rfm22_timeout(struct pios_rfm22b_dev *rfm22b_dev); static enum pios_rfm22b_event rfm22_error(struct pios_rfm22b_dev *rfm22b_dev); static enum pios_rfm22b_event rfm22_fatal_error(struct pios_rfm22b_dev *rfm22b_dev); @@ -346,20 +351,13 @@ const static struct pios_rfm22b_transition rfm22b_transitions[RFM22B_STATE_NUM_S [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, }, }, - [RFM22B_STATE_ERROR] = { - .entry_fn = rfm22_error, - .next_state = { - [RFM22B_EVENT_INITIALIZE] = RFM22B_STATE_INITIALIZING, - [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, - }, - }, [RFM22B_STATE_RX_MODE] = { .entry_fn = rfm22_setRxMode, .next_state = { [RFM22B_EVENT_INT_RECEIVED] = RFM22B_STATE_WAIT_PREAMBLE, [RFM22B_EVENT_SEND_PACKET] = RFM22B_STATE_TX_START, [RFM22B_EVENT_TX_START] = RFM22B_STATE_TX_START, - [RFM22B_EVENT_TIMEOUT] = RFM22B_STATE_TX_START, + [RFM22B_EVENT_TIMEOUT] = RFM22B_STATE_TIMEOUT, [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, }, @@ -371,7 +369,7 @@ const static struct pios_rfm22b_transition rfm22b_transitions[RFM22B_STATE_NUM_S [RFM22B_EVENT_PREAMBLE_DETECTED] = RFM22B_STATE_WAIT_SYNC, [RFM22B_EVENT_SEND_PACKET] = RFM22B_STATE_TX_START, [RFM22B_EVENT_TX_START] = RFM22B_STATE_TX_START, - [RFM22B_EVENT_TIMEOUT] = RFM22B_STATE_TX_START, + [RFM22B_EVENT_TIMEOUT] = RFM22B_STATE_TIMEOUT, [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, }, @@ -382,6 +380,7 @@ const static struct pios_rfm22b_transition rfm22b_transitions[RFM22B_STATE_NUM_S [RFM22B_EVENT_INT_RECEIVED] = RFM22B_STATE_WAIT_SYNC, [RFM22B_EVENT_SYNC_DETECTED] = RFM22B_STATE_RX_DATA, [RFM22B_EVENT_TX_START] = RFM22B_STATE_TX_START, + [RFM22B_EVENT_TIMEOUT] = RFM22B_STATE_TIMEOUT, [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, }, @@ -390,8 +389,8 @@ const static struct pios_rfm22b_transition rfm22b_transitions[RFM22B_STATE_NUM_S .entry_fn = rfm22_rxData, .next_state = { [RFM22B_EVENT_INT_RECEIVED] = RFM22B_STATE_RX_DATA, - [RFM22B_EVENT_TX_MODE] = RFM22B_STATE_TX_DATA, [RFM22B_EVENT_RX_COMPLETE] = RFM22B_STATE_TX_START, + [RFM22B_EVENT_TIMEOUT] = RFM22B_STATE_TIMEOUT, [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, }, @@ -400,8 +399,8 @@ const static struct pios_rfm22b_transition rfm22b_transitions[RFM22B_STATE_NUM_S .entry_fn = rfm22_txStart, .next_state = { [RFM22B_EVENT_INT_RECEIVED] = RFM22B_STATE_TX_DATA, - [RFM22B_EVENT_TX_MODE] = RFM22B_STATE_TX_DATA, [RFM22B_EVENT_RX_MODE] = RFM22B_STATE_RX_MODE, + [RFM22B_EVENT_TIMEOUT] = RFM22B_STATE_TIMEOUT, [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, }, @@ -410,8 +409,25 @@ const static struct pios_rfm22b_transition rfm22b_transitions[RFM22B_STATE_NUM_S .entry_fn = rfm22_txData, .next_state = { [RFM22B_EVENT_INT_RECEIVED] = RFM22B_STATE_TX_DATA, - [RFM22B_EVENT_TX_MODE] = RFM22B_STATE_TX_DATA, [RFM22B_EVENT_TX_COMPLETE] = RFM22B_STATE_TX_START, + [RFM22B_EVENT_TIMEOUT] = RFM22B_STATE_TIMEOUT, + [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, + [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, + }, + }, + [RFM22B_STATE_TIMEOUT] = { + .entry_fn = rfm22_timeout, + .next_state = { + [RFM22B_EVENT_TX_START] = RFM22B_STATE_TX_START, + [RFM22B_EVENT_INITIALIZE] = RFM22B_STATE_INITIALIZING, + [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, + [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, + }, + }, + [RFM22B_STATE_ERROR] = { + .entry_fn = rfm22_error, + .next_state = { + [RFM22B_EVENT_INITIALIZE] = RFM22B_STATE_INITIALIZING, [RFM22B_EVENT_ERROR] = RFM22B_STATE_ERROR, [RFM22B_EVENT_FATAL_ERROR] = RFM22B_STATE_FATAL_ERROR, }, @@ -569,6 +585,10 @@ int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, uint32_t spi_id, uint32_t slave_nu *rfm22b_id = (uint32_t)rfm22b_dev; g_rfm22b_dev = rfm22b_dev; + // Calculate the (approximate) maximum amount of time that it should take to transmit / receive a packet. + rfm22b_dev->max_packet_time = (uint16_t)((float)(PIOS_PH_MAX_PACKET * 8 * 1000) / (float)(rfm22b_dev->cfg.maxRFBandwidth) + 0.5); + rfm22b_dev->packet_start_time = 0; + // Create a semaphore to know if an ISR needs responding to vSemaphoreCreateBinary( rfm22b_dev->isrPending ); @@ -803,8 +823,6 @@ static void PIOS_RFM22B_Task(void *parameters) portTickType timeSinceEvent = xTaskGetTickCount() - lastEventTime; if ((timeSinceEvent / portTICK_RATE_MS) > PIOS_RFM22B_SUPERVISOR_TIMEOUT) { - rfm22b_dev->resets++; - // Transsition through an error event. enum pios_rfm22b_event event = RFM22B_EVENT_ERROR; while(event != RFM22B_EVENT_NUM_EVENTS) @@ -822,6 +840,24 @@ static void PIOS_RFM22B_Task(void *parameters) event = rfm22_process_state_transition(rfm22b_dev, event); } } + + // Have we locked up sending / receiving a packet? + if (rfm22b_dev->packet_start_time > 0) + { + portTickType cur_time = xTaskGetTickCount(); + + // Did the clock wrap around? + if (cur_time < rfm22b_dev->packet_start_time) + rfm22b_dev->packet_start_time = (cur_time > 0) ? cur_time : 1; + + // Have we been sending this packet too long? + if ((cur_time - rfm22b_dev->packet_start_time) > (rfm22b_dev->max_packet_time * 5)) + { + enum pios_rfm22b_event event = RFM22B_EVENT_TIMEOUT; + while(event != RFM22B_EVENT_NUM_EVENTS) + event = rfm22_process_state_transition(rfm22b_dev, event); + } + } } } @@ -1165,6 +1201,7 @@ void rfm22_setDatarate(uint32_t datarate_bps, bool data_whitening) static enum pios_rfm22b_event rfm22_setRxMode(struct pios_rfm22b_dev *rfm22b_dev) { + rfm22b_dev->packet_start_time = 0; // disable interrupts rfm22_write(RFM22_interrupt_enable1, 0x00); @@ -1212,6 +1249,9 @@ static enum pios_rfm22b_event rfm22_txStart(struct pios_rfm22b_dev *rfm22b_dev) return RFM22B_EVENT_RX_MODE; } rfm22b_dev->tx_packet = p; + rfm22b_dev->packet_start_time = xTaskGetTickCount(); + if (rfm22b_dev->packet_start_time == 0) + rfm22b_dev->packet_start_time = 1; // disable interrupts rfm22_write(RFM22_interrupt_enable1, 0x00); @@ -1319,6 +1359,9 @@ static enum pios_rfm22b_event rfm22_detectPreamble(struct pios_rfm22b_dev *rfm22 // Valid preamble detected if (rfm22b_dev->int_status2 & RFM22_is2_ipreaval) { + rfm22b_dev->packet_start_time = xTaskGetTickCount(); + if (rfm22b_dev->packet_start_time == 0) + rfm22b_dev->packet_start_time = 1; RX_LED_ON; return RFM22B_EVENT_PREAMBLE_DETECTED; } @@ -1452,6 +1495,7 @@ static enum pios_rfm22b_event rfm22_rxData(struct pios_rfm22b_dev *rfm22b_dev) } // Start a new transaction + rfm22b_dev->packet_start_time = 0; return RFM22B_EVENT_RX_COMPLETE; } @@ -1506,6 +1550,7 @@ static enum pios_rfm22b_event rfm22_txData(struct pios_rfm22b_dev *rfm22b_dev) rfm22b_dev->tx_packet = 0; rfm22b_dev->tx_data_wr = rfm22b_dev->tx_data_rd = 0; // Start a new transaction + rfm22b_dev->packet_start_time = 0; return RFM22B_EVENT_TX_COMPLETE; } @@ -1595,6 +1640,8 @@ static enum pios_rfm22b_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev) rfm22b_dev->afc_correction_Hz = 0; + rfm22b_dev->packet_start_time = 0; + // **************** // read the RF chip ID bytes @@ -1781,8 +1828,17 @@ static enum pios_rfm22b_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev) return RFM22B_EVENT_INITIALIZED; } +static enum pios_rfm22b_event rfm22_timeout(struct pios_rfm22b_dev *rfm22b_dev) +{ + rfm22b_dev->resets++; + rfm22b_dev->packet_start_time = 0; + return RFM22B_EVENT_TX_START; +} + static enum pios_rfm22b_event rfm22_error(struct pios_rfm22b_dev *rfm22b_dev) { + rfm22b_dev->resets++; + rfm22b_dev->packet_start_time = 0; return RFM22B_EVENT_INITIALIZE; } From 6972c29813d435b40dd56c66fc5a5f3c52a21e14 Mon Sep 17 00:00:00 2001 From: Brian Webb Date: Tue, 25 Sep 2012 18:10:15 -0700 Subject: [PATCH 10/10] RFM22B: Added check for timeout wating for sync on receive. This virtually eliminates the number of timeouts. --- flight/PiOS/Common/pios_rfm22b.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/flight/PiOS/Common/pios_rfm22b.c b/flight/PiOS/Common/pios_rfm22b.c index b0f321a7b..5f95ecb39 100644 --- a/flight/PiOS/Common/pios_rfm22b.c +++ b/flight/PiOS/Common/pios_rfm22b.c @@ -835,6 +835,7 @@ static void PIOS_RFM22B_Task(void *parameters) } else { + rfm22b_dev->resets = rfm22b_dev->state; enum pios_rfm22b_event event = RFM22B_EVENT_TIMEOUT; while(event != RFM22B_EVENT_NUM_EVENTS) event = rfm22_process_state_transition(rfm22b_dev, event); @@ -1400,6 +1401,11 @@ static enum pios_rfm22b_event rfm22_detectSync(struct pios_rfm22b_dev *rfm22b_de return RFM22B_EVENT_SYNC_DETECTED; } + else if (rfm22b_dev->int_status2 & !RFM22_is2_ipreaval) + { + // Waiting for sync timed out. + return RFM22B_EVENT_TX_START; + } return RFM22B_EVENT_NUM_EVENTS; }