ANTStatus ant_init(void) { ANTStatus status = ANT_STATUS_FAILED; ANT_FUNC_START(); stRxThreadInfo.stRxThread = 0; stRxThreadInfo.ucRunThread = 0; stRxThreadInfo.ucChipResetting = 0; stRxThreadInfo.pstEnabledStatusLock = &stEnabledStatusLock; g_fnStateCallback = 0; #ifdef ANT_DEVICE_NAME // Single transport path ant_channel_init(&stRxThreadInfo.astChannels[SINGLE_CHANNEL], ANT_DEVICE_NAME); #else // Separate data/command paths ant_channel_init(&stRxThreadInfo.astChannels[COMMAND_CHANNEL], ANT_COMMANDS_DEVICE_NAME); ant_channel_init(&stRxThreadInfo.astChannels[DATA_CHANNEL], ANT_DATA_DEVICE_NAME); #endif // Separate data/command paths // Make the eventfd. Want it non blocking so that we can easily reset it by reading. stRxThreadInfo.iRxShutdownEventFd = eventfd(0, EFD_NONBLOCK); // Check for error case if(stRxThreadInfo.iRxShutdownEventFd == -1) { ANT_ERROR("ANT init failed. Could not create event fd. Reason: %s", strerror(errno)); } else { status = ANT_STATUS_SUCCESS; } ANT_FUNC_END(); return status; }
uint32_t ant_hrm_init(ant_hrm_profile_t * p_profile, ant_channel_config_t const * p_channel_config, ant_hrm_tx_config_t const * p_tx_config) { ASSERT(p_profile != NULL); ASSERT(p_channel_config != NULL); p_profile->channel_number = p_channel_config->channel_number; if (p_tx_config != NULL) { p_profile->p_cb = p_tx_config->p_cb_buffer; ant_hrm_tx_cb_t * p_hrm_cb = (ant_hrm_tx_cb_t *)p_profile->p_cb; p_hrm_cb->page_1_present = p_tx_config->page_1_present; ASSERT((p_tx_config->main_page_number == ANT_HRM_PAGE_0) || (p_tx_config->main_page_number == ANT_HRM_PAGE_4)); p_hrm_cb->main_page_number = p_tx_config->main_page_number; p_hrm_cb->ext_page_number = p_hrm_cb->page_1_present ? ANT_HRM_PAGE_1 : ANT_HRM_PAGE_2; p_hrm_cb->message_counter = 0; p_hrm_cb->toggle_bit = true; } p_profile->page_0 = (ant_hrm_page0_data_t)DEFAULT_ANT_HRM_PAGE0(); p_profile->page_1 = (ant_hrm_page1_data_t)DEFAULT_ANT_HRM_PAGE1(); p_profile->page_2 = (ant_hrm_page2_data_t)DEFAULT_ANT_HRM_PAGE2(); p_profile->page_3 = (ant_hrm_page3_data_t)DEFAULT_ANT_HRM_PAGE3(); p_profile->page_4 = (ant_hrm_page4_data_t)DEFAULT_ANT_HRM_PAGE4(); LOG_ANT("ANT HRM channel %u init\n\r", p_profile->channel_number); return ant_channel_init(p_channel_config); }
/**@brief Function for setting up the ANT module to be ready for TX broadcast. */ static void ant_channel_tx_broadcast_setup(void) { uint32_t err_code; ant_channel_config_t broadcast_channel_config = { .channel_number = ANT_BROADCAST_CHANNEL_NUMBER, .channel_type = CHANNEL_TYPE_MASTER_TX_ONLY, .ext_assign = EXT_ASSIGN_NONE, .rf_freq = ANT_FREQUENCY, .transmission_type = ANT_BROADCAST_TRANSMISSION_TYPE, .device_type = ANT_BROADCAST_DEVICE_TYPE, .device_number = ANT_BROADCAST_DEVICE_NUMBER, .channel_period = ANT_CHANNEL_PERIOD, .network_number = ANT_NETWORK_NUMBER, }; err_code = ant_channel_init(&broadcast_channel_config); APP_ERROR_CHECK(err_code); // Fill tx buffer for the first frame. ant_message_send(); // Open channel. err_code = sd_ant_channel_open(ANT_BROADCAST_CHANNEL_NUMBER); APP_ERROR_CHECK(err_code); }
void ant_io_tx_setup(void) { uint32_t err_code; ant_channel_config_t channel_config = { .channel_number = ANT_CHANNEL_NUMBER, .channel_type = CHANNEL_TYPE_MASTER, .ext_assign = EXT_ASSIGN, .rf_freq = RF_FREQUENCY, .transmission_type = CHAN_ID_TRANS_TYPE, .device_type = CHAN_ID_DEV_TYPE, .device_number = CHAN_ID_DEV_NUM, .channel_period = CHANNEL_PERIOD, .network_number = ANT_CHANNEL_DEFAULT_NETWORK, }; // Configure channel parameters err_code = ant_channel_init(&channel_config); APP_ERROR_CHECK(err_code); // Open channel. err_code = sd_ant_channel_open(ANT_CHANNEL_NUMBER); APP_ERROR_CHECK(err_code); }
void ant_io_rx_setup(void) { uint32_t err_code; ant_channel_config_t channel_config = { .channel_number = ANT_CHANNEL_NUMBER, .channel_type = CHANNEL_TYPE_SLAVE, .ext_assign = EXT_ASSIGN, .rf_freq = RF_FREQUENCY, .transmission_type = CHAN_ID_TRANS_TYPE, .device_type = CHAN_ID_DEV_TYPE, .device_number = CHAN_ID_DEV_NUM, .channel_period = CHANNEL_PERIOD, .network_number = ANT_CHANNEL_DEFAULT_NETWORK, }; ant_search_config_t search_config = DEFAULT_ANT_SEARCH_CONFIG(ANT_CHANNEL_NUMBER); search_config.low_priority_timeout = ANT_LOW_PRIORITY_TIMEOUT_DISABLE; // Configure channel parameters err_code = ant_channel_init(&channel_config); APP_ERROR_CHECK(err_code); // Configure search err_code = ant_search_init(&search_config); APP_ERROR_CHECK(err_code); // Open channel. err_code = sd_ant_channel_open(ANT_CHANNEL_NUMBER); APP_ERROR_CHECK(err_code); }
/**@brief Function for initializing the ANT HRM profile instance. * * @param[in] p_profile Pointer to the profile instance. * @param[in] p_channel_config Pointer to the ANT channel configuration structure. * * @retval NRF_SUCCESS If initialization was successful. Otherwise, an error code is returned. */ static ret_code_t ant_hrm_init(ant_hrm_profile_t * p_profile, ant_channel_config_t const * p_channel_config) { p_profile->channel_number = p_channel_config->channel_number; p_profile->page_0 = DEFAULT_ANT_HRM_PAGE0(); p_profile->page_1 = DEFAULT_ANT_HRM_PAGE1(); p_profile->page_2 = DEFAULT_ANT_HRM_PAGE2(); p_profile->page_3 = DEFAULT_ANT_HRM_PAGE3(); p_profile->page_4 = DEFAULT_ANT_HRM_PAGE4(); NRF_LOG_INFO("ANT HRM channel %u init\r\n", p_profile->channel_number); return ant_channel_init(p_channel_config); }
/**@brief Function for initializing the ANT Bicycle Power Profile instance. * * @param[in] p_profile Pointer to the profile instance. * @param[in] p_channel_config Pointer to the ANT channel configuration structure. * * @retval NRF_SUCCESS If initialization was successful. Otherwise, an error code is returned. */ static ret_code_t ant_bpwr_init(ant_bpwr_profile_t * p_profile, ant_channel_config_t const * p_channel_config) { p_profile->channel_number = p_channel_config->channel_number; p_profile->page_1 = DEFAULT_ANT_BPWR_PAGE1(); p_profile->page_16 = DEFAULT_ANT_BPWR_PAGE16(); p_profile->page_17 = DEFAULT_ANT_BPWR_PAGE17(); p_profile->page_18 = DEFAULT_ANT_BPWR_PAGE18(); p_profile->page_80 = DEFAULT_ANT_COMMON_page80(); p_profile->page_81 = DEFAULT_ANT_COMMON_page81(); LOG_BPWR("ANT B-PWR channel %u init\n\r", p_profile->channel_number); return ant_channel_init(p_channel_config); }
/**@brief Function for initializing the ANT SDM profile instance. * * @param[in] p_profile Pointer to the profile instance. * @param[in] p_channel_config Pointer to the ANT channel configuration structure. * * @retval NRF_SUCCESS Successful initialization. * Error code when initialization failed. */ static ret_code_t ant_sdm_init(ant_sdm_profile_t * p_profile, ant_channel_config_t const * p_channel_config) { p_profile->channel_number = p_channel_config->channel_number; p_profile->page_1 = DEFAULT_ANT_SDM_PAGE1(); p_profile->page_2 = DEFAULT_ANT_SDM_PAGE2(); p_profile->page_3 = DEFAULT_ANT_SDM_PAGE3(); p_profile->page_22 = DEFAULT_ANT_SDM_PAGE22(); p_profile->common = DEFAULT_ANT_SDM_COMMON_DATA(); p_profile->page_80 = DEFAULT_ANT_COMMON_page80(); p_profile->page_81 = DEFAULT_ANT_COMMON_page81(); LOG_SDM("ANT SDM channel %u init\n\r", p_profile->channel_number); return ant_channel_init(p_channel_config); }
/**@brief Function for initializing the ANT BSC profile instance. * * @param[in] p_profile Pointer to the profile instance. * @param[in] p_channel_config Pointer to the ANT channel configuration structure. * * @retval NRF_SUCCESS If initialization was successful. Otherwise, an error code is returned. */ static ret_code_t ant_bsc_init(ant_bsc_profile_t * p_profile, ant_channel_config_t const * p_channel_config) { p_profile->channel_number = p_channel_config->channel_number; p_profile->page_0 = DEFAULT_ANT_BSC_PAGE0(); p_profile->page_1 = DEFAULT_ANT_BSC_PAGE1(); p_profile->page_2 = DEFAULT_ANT_BSC_PAGE2(); p_profile->page_3 = DEFAULT_ANT_BSC_PAGE3(); p_profile->page_4 = DEFAULT_ANT_BSC_PAGE4(); p_profile->page_5 = DEFAULT_ANT_BSC_PAGE5(); p_profile->page_comb_0 = DEFAULT_ANT_BSC_COMBINED_PAGE0(); LOG_BSC("ANT BSC channel %u init\n\r", p_profile->channel_number); return ant_channel_init(p_channel_config); }
/**@brief Function for setting up the ANT module to be ready for RX broadcast. */ static void ant_channel_rx_broadcast_setup(void) { uint32_t err_code; ant_channel_config_t broadcast_channel_config = { .channel_number = ANT_BROADCAST_CHANNEL_NUMBER, .channel_type = CHANNEL_TYPE_SLAVE, .ext_assign = EXT_ASSIGN_NONE, .rf_freq = RF_FREQ, .transmission_type = CHAN_ID_TRANS_TYPE, .device_type = CHAN_ID_DEV_TYPE, .device_number = CHAN_ID_DEV_NUM, .channel_period = CHAN_PERIOD, .network_number = ANT_NETWORK_NUMBER, }; err_code = ant_channel_init(&broadcast_channel_config); APP_ERROR_CHECK(err_code); // Open channel. err_code = sd_ant_channel_open(ANT_BROADCAST_CHANNEL_NUMBER); APP_ERROR_CHECK(err_code); }
/**@brief initialize application */ static void continuous_scan_init() { uint32_t err_code; // Set library config to report RSSI and Device ID err_code = sd_ant_lib_config_set(ANT_LIB_CONFIG_MESG_OUT_INC_RSSI | ANT_LIB_CONFIG_MESG_OUT_INC_DEVICE_ID); APP_ERROR_CHECK(err_code); // Configure channel 0 for scanning mode, but do not open it. // The scanning channel will be opened in scan mode for a short amount of time on a button press. ant_channel_config_t channel_config = { .channel_number = ANT_SCAN_CHANNEL_NUMBER, .channel_type = ANT_BS_CHANNEL_TYPE, .ext_assign = 0, .rf_freq = ANT_FREQUENCY, .transmission_type = ANT_TRANSMISSION_TYPE, .device_type = ANT_DEVICE_TYPE, .device_number = ANT_BS_DEVICE_NUMBER, .channel_period = 0, // Not used, since this is going to be scanning .network_number = ANT_NETWORK_NUMBER, }; err_code = ant_channel_init(&channel_config); APP_ERROR_CHECK(err_code); // Assign a second channel for sending messages on the reverse direction // There is no need to configure any other parameters, this channel is never opened; // its resources are used by ANT to send messages in the reverse direction while in // continuous scanning mode. err_code = sd_ant_channel_assign(ANT_RESPONSE_CHANNEL_NUMBER, ANT_BS_CHANNEL_TYPE, ANT_NETWORK_NUMBER, 0x00); APP_ERROR_CHECK(err_code); } /** @brief Add a newly discovered node to the m_node_list * * @param[in] device_number The device_number of the current to be added * @param[in] rssi The RSSI from the current node to be added */ void add_node_to_list(uint16_t device_number, uint8_t rssi) { uint8_t index = MAX_DEVICES; // Specifed maximum total number in the array uint8_t start = CONVERT_DEVICE_NUM_TO_INDEX(device_number); // Start index of the array uint8_t node_device_number; for(int i = 0; i < MAX_DEVICES; i++ ) { node_device_number = m_node_list[(start + i) % MAX_DEVICES].device_number; if( node_device_number == device_number ) // If this node already exists, don't add it return; if(node_device_number == 0) // If we found a place to put it { // Find the best place to put this node (the place closest to the hash function result) index = (start + i) % MAX_DEVICES; break; } } if( index == MAX_DEVICES ) return; m_node_list[index].device_number = device_number; m_node_list[index].rssi = rssi; }
void ant_search_sharing_setup(void) { uint32_t err_code; ant_channel_config_t channel_config = { .channel_type = CHANNEL_TYPE_SLAVE, .ext_assign = EXT_TYPE, .device_number = 0, .network_number = ANT_CHANNEL_DEFAULT_NETWORK, }; ant_search_config_t search_config = { .low_priority_timeout = CHAN_SEARCH_TIMEOUT, .high_priority_timeout = ANT_HIGH_PRIORITY_SEARCH_DISABLE, .search_sharing_cycles = CHAN_SEARCH_CYCLES, .search_priority = ANT_SEARCH_PRIORITY_DEFAULT, .waveform = ANT_WAVEFORM_FAST, // Use fast waveform to limit impact on acquisition time from searching on multiple frequencies }; m_rx_first_ch0 = false; m_rx_first_ch1 = false; // Configure channel parameters for channel 0 channel_config.channel_number = ANT_CHANNEL_NUMBER_0; channel_config.device_type = CHAN_ID_DEV_TYPE_CH0; channel_config.transmission_type = CHAN_ID_TRANS_TYPE_CH0; channel_config.channel_period = CHAN_PERIOD_CH0; channel_config.rf_freq = RF_FREQ_CH0; err_code = ant_channel_init(&channel_config); APP_ERROR_CHECK(err_code); // Configure search parameters for channel 0 search_config.channel_number = ANT_CHANNEL_NUMBER_0; err_code = ant_search_init(&search_config); APP_ERROR_CHECK(err_code); // Configure channel parameters for channel 1 channel_config.channel_number = ANT_CHANNEL_NUMBER_1; channel_config.device_type = CHAN_ID_DEV_TYPE_CH1; channel_config.transmission_type = CHAN_ID_TRANS_TYPE_CH1; channel_config.channel_period = CHAN_PERIOD_CH1; channel_config.rf_freq = RF_FREQ_CH1; err_code = ant_channel_init(&channel_config); APP_ERROR_CHECK(err_code); // Configure search parameters for channel 1 search_config.channel_number = ANT_CHANNEL_NUMBER_1; err_code = ant_search_init(&search_config); APP_ERROR_CHECK(err_code); // Open both channels err_code = sd_ant_channel_open(ANT_CHANNEL_NUMBER_0); APP_ERROR_CHECK(err_code); err_code = sd_ant_channel_open(ANT_CHANNEL_NUMBER_1); APP_ERROR_CHECK(err_code); } void ant_search_sharing_event_handler(ant_evt_t * p_ant_evt) { switch (p_ant_evt->event) { case EVENT_RX: switch(p_ant_evt->channel) { case ANT_CHANNEL_NUMBER_0: if(!m_rx_first_ch0) { m_rx_first_ch0 = true; LEDS_ON(BSP_LED_0_MASK); } break; case ANT_CHANNEL_NUMBER_1: if(!m_rx_first_ch1) { m_rx_first_ch1 = true; LEDS_ON(BSP_LED_1_MASK); } break; } break; default: break; } }
void ant_message_types_master_setup(void) { uint32_t err_code; ant_channel_config_t channel_config = { .channel_number = ANT_CHANNEL_NUMBER, .channel_type = CHANNEL_TYPE_MASTER, .ext_assign = EXT_ASSIGN, .rf_freq = RF_FREQUENCY, .transmission_type = CHAN_ID_TRANS_TYPE, .device_type = CHAN_ID_DEV_TYPE, .device_number = (uint16_t) (NRF_FICR->DEVICEID[0]), .channel_period = CHANNEL_PERIOD, .network_number = ANT_CHANNEL_DEFAULT_NETWORK, }; err_code = ant_channel_init(&channel_config); APP_ERROR_CHECK(err_code); //Set Tx Power err_code = sd_ant_channel_radio_tx_power_set(ANT_CHANNEL_NUMBER, RADIO_TX_POWER_LVL_3, ANT_CUSTOM_TRANSMIT_POWER); APP_ERROR_CHECK(err_code); // Open channel. err_code = sd_ant_channel_open(ANT_CHANNEL_NUMBER); APP_ERROR_CHECK(err_code); // Write counter value to last byte of the broadcast data. // The last byte is chosen to get the data more visible in the end of an printout // on the recieving end. memset(m_tx_buffer, 0, BROADCAST_DATA_BUFFER_SIZE); m_tx_buffer[BROADCAST_DATA_BUFFER_SIZE - 1] = m_counter; // Configure the initial payload of the broadcast data err_code = sd_ant_broadcast_message_tx(ANT_CHANNEL_NUMBER, BROADCAST_DATA_BUFFER_SIZE, m_tx_buffer); APP_ERROR_CHECK(err_code); //Set state to broadcasting state_message_types = BROADCAST; } void ant_message_types_master_bsp_evt_handler(bsp_event_t evt) { switch (evt) { case BSP_EVENT_KEY_0: state_message_types = BROADCAST; break; case BSP_EVENT_KEY_1: state_message_types = ACKNOWLEDGED; break; case BSP_EVENT_KEY_2: state_message_types = BURST; break; default: break; // no implementation needed } } void ant_message_types_master_event_handler(ant_evt_t * p_ant_evt) { uint32_t err_code; uint32_t led_output = LED_BROADCAST; switch (p_ant_evt->event) { // ANT broadcast/Acknowledged/Burst Success // Send the next message according to the current state and increment the counter. case EVENT_TX: // Intentional fall through case EVENT_TRANSFER_TX_COMPLETED: // Intentional fall through case EVENT_TRANSFER_TX_FAILED: LEDS_OFF(LEDS_MASK); m_tx_buffer[BROADCAST_DATA_BUFFER_SIZE - 1] = m_counter; if(state_message_types == BROADCAST) { // Send as broadcast err_code = sd_ant_broadcast_message_tx(ANT_CHANNEL_NUMBER, BROADCAST_DATA_BUFFER_SIZE, m_tx_buffer); APP_ERROR_CHECK(err_code); led_output = LED_BROADCAST; } else if(state_message_types == ACKNOWLEDGED) { // Send as acknowledged err_code = sd_ant_acknowledge_message_tx(ANT_CHANNEL_NUMBER, BROADCAST_DATA_BUFFER_SIZE, m_tx_buffer); APP_ERROR_CHECK(err_code); led_output = LED_ACKNOWLEDGED; } else if(state_message_types == BURST) { // If this is a new message, populate the burst buffer // with new dummy data. Otherwise, will retry sending the // same content. if(p_ant_evt->event != EVENT_TRANSFER_TX_FAILED) { for(uint32_t i = 0; i < BURST_BLOCK_SIZE; i++) { m_burst_data[i] = m_counter; m_counter++; } } // Queue a Burst Transfer. Since this is a small burst, queue entire burst. err_code = sd_ant_burst_handler_request(ANT_CHANNEL_NUMBER, BURST_BLOCK_SIZE, m_burst_data, (BURST_SEGMENT_START | BURST_SEGMENT_END)); APP_ERROR_CHECK(err_code); led_output = LED_BURST; } // Activate LED for 20ms LEDS_ON(led_output); nrf_delay_ms(20); LEDS_OFF(led_output); m_counter++; break; case TRANSFER_IN_PROGRESS: //Intentional fall through case TRANSFER_SEQUENCE_NUMBER_ERROR: //Intentional fall through case TRANSFER_IN_ERROR: //Intentional fall through case TRANSFER_BUSY: // Ignore these events; will retry burst transfer when we get the EVENT_TRANSFER_TX_FAILED event. break; default: break; } }