123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559 |
- #include "nrf21540.h"
- #include "nrf_assert.h"
- #include "nrf21540_defs.h"
- #include "nrf21540_macro.h"
- #include "nrf_radio.h"
- #include "nrf_ppi.h"
- #include "nrf_gpiote.h"
- #include "nrf_timer.h"
- #include "boards.h"
- #if NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
- #include "nrf_egu.h"
- #endif
- #define NRF21540_BUSY_CHECK(mode) \
- if (mode == NRF21540_EXEC_MODE_BLOCKING) \
- { \
- while(is_driver_busy()) \
- { \
- \
- } \
- } \
- else if (is_driver_busy()) \
- { \
- return NRF_ERROR_BUSY; \
- }
- #define NRF21540_ERROR_CHECK(invalid_state_condition) \
- if (device_state_get() == NRF21540_STATE_ERROR) \
- { \
- m_nrf21540_data.busy = false; \
- return NRF_ERROR_INTERNAL; \
- } \
- if (invalid_state_condition) \
- { \
- m_nrf21540_data.busy = false; \
- return NRF_ERROR_INVALID_STATE; \
- }
- typedef enum {
- NRF21540_STATE_OFF,
- NRF21540_STATE_READY,
- NRF21540_STATE_TX,
- NRF21540_STATE_RX,
- NRF21540_STATE_ERROR,
- } nrf21540_state_t;
- static struct
- {
- volatile nrf21540_state_t cur_state;
- volatile nrf21540_trx_t cur_direction;
- volatile bool busy;
- #if NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
- volatile uint32_t shorts;
- #endif
- } m_nrf21540_data;
- static inline bool is_driver_busy(void)
- {
- return m_nrf21540_data.busy;
- }
- static inline bool is_device_off(void)
- {
- return m_nrf21540_data.cur_state == NRF21540_STATE_OFF;
- }
- static inline bool is_device_on(void)
- {
- return m_nrf21540_data.cur_state != NRF21540_STATE_OFF;
- }
- static inline bool is_device_ready_for_transmission(void)
- {
- return (m_nrf21540_data.cur_state == NRF21540_STATE_TX ||
- m_nrf21540_data.cur_state == NRF21540_STATE_RX);
- }
- static inline void device_state_set(nrf21540_state_t new_state)
- {
- m_nrf21540_data.cur_state = new_state;
- }
- static inline nrf21540_state_t device_state_get(void)
- {
- return m_nrf21540_data.cur_state;
- }
- static inline nrf_radio_task_t nrf21540_task_get(nrf21540_trx_t dir)
- {
- return dir == NRF21540_TX ? NRF_RADIO_TASK_TXEN : NRF_RADIO_TASK_RXEN;
- }
- static void ppi_cleanup(void)
- {
- nrf_ppi_channel_disable(NRF21540_PDN_PPI_CHANNEL);
- nrf_ppi_channel_disable(NRF21540_USER_PPI_CHANNEL);
- nrf_ppi_channel_disable(NRF21540_TRX_PPI_CHANNEL);
- nrf_ppi_channel_and_fork_endpoint_setup(NRF21540_PDN_PPI_CHANNEL, 0, 0, 0);
- nrf_ppi_channel_and_fork_endpoint_setup(NRF21540_USER_PPI_CHANNEL, 0, 0, 0);
- nrf_ppi_channel_and_fork_endpoint_setup(NRF21540_TRX_PPI_CHANNEL, 0, 0, 0);
- }
- static void events_clear()
- {
- nrf_timer_event_clear(NRF21540_TIMER, NRF21540_TIMER_CC_PD_PG_EVENT);
- nrf_timer_event_clear(NRF21540_TIMER, NRF21540_TIMER_CC_START_TO_PDN_UP_EVENT);
- NRF21540_RADIO_EVENT_CLEAR(NRF21540_RADIO_EVENT_READY);
- NRF21540_RADIO_EVENT_CLEAR(NRF21540_RADIO_EVENT_DISABLED);
- }
- void NRF21540_TIMER_IRQ_HANDLER(void)
- {
- if (nrf_timer_event_check(NRF21540_TIMER, NRF21540_TIMER_CC_PD_PG_EVENT))
- {
- nrf_timer_event_clear(NRF21540_TIMER, NRF21540_TIMER_CC_PD_PG_EVENT);
- if (is_device_off() && nrf_gpio_pin_read(NRF21540_PDN_PIN) == 1)
- {
- device_state_set(NRF21540_STATE_READY);
- }
- else if (is_device_on() && nrf_gpio_pin_read(NRF21540_PDN_PIN) == 0)
- {
- device_state_set(NRF21540_STATE_OFF);
- ppi_cleanup();
- m_nrf21540_data.busy = false;
- }
- else
- {
- device_state_set(NRF21540_STATE_ERROR);
- ppi_cleanup();
- m_nrf21540_data.busy = false;
- }
- }
- }
- void NRF21540_RADIO_IRQ_HANDLER(void)
- {
- if (NRF21540_RADIO_EVENT_CHECK(NRF21540_RADIO_EVENT_READY))
- {
- NRF21540_RADIO_EVENT_CLEAR(NRF21540_RADIO_EVENT_READY);
- nrf_ppi_channel_disable(NRF21540_USER_PPI_CHANNEL);
- #if NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
- if (NRF21540_RADIO_SHORTS_ENABLE_CHECK(RADIO_SHORTS_READY_START_Msk))
- {
- nrf_radio_task_trigger(NRF_RADIO_TASK_START);
- }
- #endif
- if (device_state_get() == NRF21540_STATE_READY)
- {
- device_state_set(m_nrf21540_data.cur_direction == NRF21540_TX ?
- NRF21540_STATE_TX : NRF21540_STATE_RX);
- ppi_cleanup();
- NRF21540_RADIO_INT_DISABLE(NRF21540_RADIO_READY_Msk);
- m_nrf21540_data.busy = false;
- }
- }
- if (NRF21540_RADIO_EVENT_CHECK(NRF21540_RADIO_EVENT_DISABLED))
- {
- NRF21540_RADIO_EVENT_CLEAR(NRF21540_RADIO_EVENT_DISABLED);
- nrf_ppi_channel_disable(NRF21540_USER_PPI_CHANNEL);
- nrf_timer_task_trigger(NRF21540_TIMER, NRF_TIMER_TASK_START);
- if (is_device_ready_for_transmission())
- {
- NRF21540_RADIO_INT_DISABLE(NRF21540_RADIO_DISABLED_Msk);
- device_state_set(NRF21540_STATE_READY);
- }
- }
- }
- static void driver_reset(void)
- {
- device_state_set(NRF21540_STATE_OFF);
- ppi_cleanup();
- events_clear();
- NRF21540_RADIO_INT_DISABLE(NRF21540_RADIO_INTERRUPT_MASK);
- m_nrf21540_data.busy = false;
- }
- static ret_code_t trx_set(nrf21540_trx_t dir, uint32_t trigger_event,
- nrf21540_execution_mode_t mode)
- {
- ASSERT(!(mode == NRF21540_EXEC_MODE_BLOCKING && trigger_event != 0));
- NRF21540_BUSY_CHECK(mode);
- NRF21540_ERROR_CHECK((dir == NRF21540_TX && device_state_get() == NRF21540_STATE_TX) ||
- (dir == NRF21540_RX && device_state_get() == NRF21540_STATE_RX));
- uint32_t ramp_up_time = nrf_radio_modecnf0_ru_get() ? FAST_RAMP_UP_TIME : RAMP_UP_TIME;
- nrf_radio_task_t radio_task_to_start = nrf21540_task_get(dir);
- m_nrf21540_data.busy = true;
- events_clear();
- NRF21540_RADIO_INT_ENABLE(NRF21540_RADIO_READY_Msk);
- if (is_device_off())
- {
- nrf_ppi_channel_endpoint_setup(NRF21540_PDN_PPI_CHANNEL,
- (uint32_t)nrf_timer_event_address_get(NRF21540_TIMER,
- NRF21540_TIMER_CC_START_TO_PDN_UP_EVENT),
- nrf_gpiote_task_addr_get(NRF21540_PDN_GPIOTE_TASK_SET));
- nrf_ppi_channel_enable(NRF21540_PDN_PPI_CHANNEL);
- nrf_timer_cc_write(NRF21540_TIMER,
- NRF21540_TIMER_CC_PD_PG_CHANNEL,
- ramp_up_time - NRF21540_PA_PG_TRX_TIME_US);
- nrf_timer_cc_write(NRF21540_TIMER,
- NRF21540_TIMER_CC_START_TO_PDN_UP_CHANNEL,
- ramp_up_time - NRF21540_PA_PG_TRX_TIME_US - NRF21540_PD_PG_TIME_US);
- #if NRF21540_USE_GPIO_MANAGEMENT
- nrf21540_gpio_trx_enable(dir);
- #elif NRF21540_USE_SPI_MANAGEMENT
- nrf21540_spim_for_trx_configure(dir, NRF21540_ENABLE);
- #endif
- nrf_timer_shorts_enable(NRF21540_TIMER,
- NRF21540_TIMER_CC_FINISHED_CHANNEL_STOP_MASK |
- NRF21540_TIMER_CC_FINISHED_CHANNEL_CLEAR_MASK);
- NRF21540_RADIO_SHORTS_ENABLE(RADIO_SHORTS_READY_START_Msk);
- if (trigger_event == 0)
- {
-
- nrf_timer_task_trigger(NRF21540_TIMER, NRF_TIMER_TASK_START);
- nrf_radio_task_trigger(radio_task_to_start);
- }
- else
- {
-
- nrf_ppi_channel_and_fork_endpoint_setup(
- NRF21540_USER_PPI_CHANNEL,
- trigger_event,
- (uint32_t) nrf_timer_task_address_get(NRF21540_TIMER, NRF_TIMER_TASK_START),
- (uint32_t) nrf_radio_task_address_get(radio_task_to_start));
- nrf_ppi_channel_enable(NRF21540_USER_PPI_CHANNEL);
- }
- }
- else
- {
-
-
- NRF21540_ERROR_CHECK(device_state_get() == NRF21540_STATE_RX);
- if (trigger_event == 0)
- {
- nrf_radio_task_trigger(radio_task_to_start);
- }
- else
- {
-
- nrf_ppi_channel_endpoint_setup(
- NRF21540_USER_PPI_CHANNEL,
- trigger_event,
- (uint32_t) nrf_radio_task_address_get(radio_task_to_start));
- nrf_ppi_channel_enable(NRF21540_USER_PPI_CHANNEL);
- }
- }
- m_nrf21540_data.cur_direction = dir;
- if (mode == NRF21540_EXEC_MODE_BLOCKING)
- {
- while (!is_device_ready_for_transmission());
- }
- return NRF_SUCCESS;
- }
- ret_code_t nrf21540_init(void)
- {
- driver_reset();
-
- nrf_gpiote_task_configure(NRF21540_PDN_GPIOTE_CHANNEL_NO,
- NRF21540_PDN_PIN,
- (nrf_gpiote_polarity_t) GPIOTE_CONFIG_POLARITY_None,
- NRF_GPIOTE_INITIAL_VALUE_LOW);
- nrf_gpiote_task_enable(NRF21540_PDN_GPIOTE_CHANNEL_NO);
- nrf21540_gpio_init();
- NVIC_SetPriority(NRF21540_TIMER_IRQn, NRF21540_INTERRUPT_PRIORITY);
- NVIC_EnableIRQ(NRF21540_TIMER_IRQn);
- nrf_timer_int_enable(NRF21540_TIMER, NRF21540_TIM_INTERRUPT_MASK);
- #if NRF21540_USE_SPI_MANAGEMENT
- ret_code_t ret = NRF_SUCCESS;
- ret = nrf21540_spi_init();
- if (ret != NRF_SUCCESS)
- {
- device_state_set(NRF21540_STATE_ERROR);
- return ret;
- }
- #endif
- #if NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
- nrf_ppi_channel_endpoint_setup(NRF21540_RADIO_READY_TO_EGU_PPI_CHANNEL,
- nrf_radio_event_address_get(NRF_RADIO_EVENT_READY),
- (uint32_t)nrf_egu_task_address_get(NRF21540_EGU, NRF21540_RADIO_READY_EGU_TASK));
- nrf_ppi_channel_enable(NRF21540_RADIO_READY_TO_EGU_PPI_CHANNEL);
- nrf_ppi_channel_endpoint_setup(NRF21540_RADIO_DISABLED_TO_EGU_PPI_CHANNEL,
- nrf_radio_event_address_get(NRF_RADIO_EVENT_DISABLED),
- (uint32_t)nrf_egu_task_address_get(NRF21540_EGU, NRF21540_RADIO_DISABLED_EGU_TASK));
- nrf_ppi_channel_enable(NRF21540_RADIO_DISABLED_TO_EGU_PPI_CHANNEL);
- #endif
- NVIC_SetPriority(NRF21540_RADIO_IRQn, NRF21540_INTERRUPT_PRIORITY);
- NVIC_EnableIRQ(NRF21540_RADIO_IRQn);
- return NRF_SUCCESS;
- }
- ret_code_t nrf21540_pdn_drive(bool state, nrf21540_execution_mode_t mode)
- {
- NRF21540_BUSY_CHECK(mode);
- NRF21540_ERROR_CHECK((state == true && is_device_on()) ||
- (state == false && is_device_off()));
- nrf21540_state_t final_state;
- if (state)
- {
- final_state = NRF21540_STATE_READY;
- }
- else
- {
- final_state = NRF21540_STATE_OFF;
- }
- nrf_timer_cc_write(NRF21540_TIMER,
- NRF21540_TIMER_CC_PD_PG_CHANNEL,
- state ? NRF21540_PD_PG_TIME_US : 0);
- nrf_timer_shorts_enable(NRF21540_TIMER,
- NRF21540_TIMER_CC_FINISHED_CHANNEL_STOP_MASK |
- NRF21540_TIMER_CC_FINISHED_CHANNEL_CLEAR_MASK);
- nrf_timer_event_clear(NRF21540_TIMER, NRF21540_TIMER_CC_PD_PG_EVENT);
- nrf_gpiote_task_force(NRF21540_PDN_GPIOTE_CHANNEL_NO,
- !state ? NRF_GPIOTE_INITIAL_VALUE_LOW : NRF_GPIOTE_INITIAL_VALUE_HIGH);
- nrf_timer_task_trigger(NRF21540_TIMER, NRF_TIMER_TASK_START);
- if (mode == NRF21540_EXEC_MODE_BLOCKING)
- {
- while (device_state_get() != final_state)
- {
- }
- }
- return NRF_SUCCESS;
- }
- ret_code_t nrf21540_tx_set(uint32_t user_trigger_event, nrf21540_execution_mode_t mode)
- {
- NRF21540_ERROR_CHECK(device_state_get() == NRF21540_STATE_TX);
- return trx_set(NRF21540_TX, user_trigger_event, mode);
- }
- ret_code_t nrf21540_rx_set(uint32_t user_trigger_event, nrf21540_execution_mode_t mode)
- {
- NRF21540_ERROR_CHECK(device_state_get() == NRF21540_STATE_RX);
- return trx_set(NRF21540_RX, user_trigger_event, mode);
- }
- bool nrf21540_is_error(void)
- {
- return device_state_get() == NRF21540_STATE_ERROR ? true : false;
- }
- ret_code_t nrf21540_ant_set(nrf21540_antenna_t antenna)
- {
- NRF21540_BUSY_CHECK(NRF21540_EXEC_MODE_NON_BLOCKING);
- return nrf21540_gpio_ant_set(antenna);
- }
- ret_code_t nrf21540_pwr_mode_set(nrf21540_pwr_mode_t mode)
- {
- NRF21540_BUSY_CHECK(NRF21540_EXEC_MODE_NON_BLOCKING);
- #if NRF21540_USE_GPIO_MANAGEMENT
- return nrf21540_gpio_pwr_mode_set(mode);
- #elif NRF21540_USE_SPI_MANAGEMENT
- return nrf21540_spi_pwr_mode_set(mode);
- #endif
- }
- ret_code_t nrf21540_power_down(uint32_t user_trigger_event, nrf21540_execution_mode_t mode)
- {
- ASSERT(!(mode == NRF21540_EXEC_MODE_BLOCKING && user_trigger_event != 0));
- NRF21540_ERROR_CHECK(is_device_off());
- NRF21540_BUSY_CHECK(mode);
- m_nrf21540_data.busy = true;
- events_clear();
- NRF21540_RADIO_INT_ENABLE(NRF21540_RADIO_DISABLED_Msk);
- if (device_state_get() == NRF21540_STATE_READY)
- {
-
- (void)nrf21540_pdn_drive(false, NRF21540_EXEC_MODE_NON_BLOCKING);
- nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE);
- }
- else
- {
-
-
- uint32_t * trx_drv_task_address;
- nrf21540_trx_t cur_direction;
- if (device_state_get() == NRF21540_STATE_TX)
- {
- cur_direction = NRF21540_TX;
- }
- else if (device_state_get() == NRF21540_STATE_RX)
- {
- cur_direction = NRF21540_RX;
- }
- else
- {
- return NRF_ERROR_INTERNAL;
- }
- nrf_ppi_channel_endpoint_setup(NRF21540_PDN_PPI_CHANNEL,
- (uint32_t)nrf_timer_event_address_get(NRF21540_TIMER,
- NRF21540_TIMER_CC_TRX_PG_EVENT),
- nrf_gpiote_task_addr_get(NRF21540_PDN_GPIOTE_TASK_CLR));
- nrf_ppi_channel_enable(NRF21540_PDN_PPI_CHANNEL);
- nrf_timer_shorts_enable(NRF21540_TIMER,
- NRF21540_TIMER_CC_FINISHED_CHANNEL_STOP_MASK |
- NRF21540_TIMER_CC_FINISHED_CHANNEL_CLEAR_MASK);
- nrf_timer_cc_write(NRF21540_TIMER,
- NRF21540_TIMER_CC_TRX_PG_CHANNEL,
- NRF21540_TRX_PG_TIME_US);
- #if NRF21540_USE_GPIO_MANAGEMENT
- trx_drv_task_address = (uint32_t*) nrf21540_gpio_trx_task_start_address_get(cur_direction,
- NRF21540_DISABLE);
- #elif NRF21540_USE_SPI_MANAGEMENT
- nrf21540_spim_for_trx_configure(cur_direction, NRF21540_DISABLE);
- trx_drv_task_address = (uint32_t*) nrf21540_spim_trx_task_start_address_get();
- #endif
- if (user_trigger_event == 0)
- {
- *trx_drv_task_address = 1;
- nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE);
- }
- else
- {
-
- nrf_ppi_channel_and_fork_endpoint_setup(
- NRF21540_USER_PPI_CHANNEL,
- user_trigger_event,
- (uint32_t)nrf_radio_task_address_get(NRF_RADIO_TASK_DISABLE),
- (uint32_t) trx_drv_task_address);
- nrf_ppi_channel_enable(NRF21540_USER_PPI_CHANNEL);
- }
- if (mode == NRF21540_EXEC_MODE_BLOCKING)
- {
- while (is_device_on());
- }
- }
- return NRF_SUCCESS;
- }
|