/** * @brief Handle incoming packets */ static void search_callback(uint8_t* data) { SET_PIN(PIN_RX); uint32_t checksum = (NRF_RADIO->RXCRC & 0x00FFFFFF); /* check if timeslot is about to end */ uint64_t radio_time_left = timeslot_get_remaining_time(); if (radio_time_left > RADIO_SAFETY_TIMING_US) { /* setup next RX */ order_search(); } CLEAR_PIN(PIN_RX); if (data == NULL || !packet_is_data_packet(data)) { return; } async_event_t async_evt; async_evt.type = EVENT_TYPE_PACKET; packet_create_from_data(data, &async_evt.callback.packet); async_evt.callback.packet.rx_crc = checksum; event_handler_push(&async_evt); /** @TODO: add packet chain handling */ }
void transport_control_timeslot_begin(uint64_t global_timer_value) { uint32_t aa; uint32_t error_code = rbc_mesh_access_address_get(&aa); APP_ERROR_CHECK(error_code); radio_init(aa); step_timer_index = 0xFF; global_time = global_timer_value; order_search(); transport_control_step(); }
/* packet processing, executed in APP_LOW */ void tc_packet_handler(uint8_t* data, uint32_t crc, uint64_t timestamp) { // LOGi("_6"); SET_PIN(PIN_RX); mesh_packet_t* p_packet = (mesh_packet_t*) data; // printArray(p_packet, sizeof(mesh_packet_t)); if (p_packet->header.length > MESH_PACKET_OVERHEAD + RBC_MESH_VALUE_MAX_LEN) { // LOGi("_2"); /* invalid packet, ignore */ CLEAR_PIN(PIN_RX); mesh_packet_ref_count_dec(p_packet); /* from rx_cb */ return; } ble_gap_addr_t addr; memcpy(addr.addr, p_packet->addr, BLE_GAP_ADDR_LEN); addr.addr_type = p_packet->header.addr_type; mesh_adv_data_t* p_mesh_adv_data = mesh_packet_adv_data_get(p_packet); if (p_mesh_adv_data != NULL) { // LOGi("_3"); /* filter mesh packets on handle range */ if (p_mesh_adv_data->handle <= RBC_MESH_APP_MAX_HANDLE) { // LOGi("_4"); mesh_app_packet_handle(p_mesh_adv_data, timestamp); } } /* this packet is no longer needed in this context */ mesh_packet_ref_count_dec(p_packet); /* from rx_cb */ if (g_state.queue_saturation) { // LOGi("_5"); order_search(); g_state.queue_saturation = false; } CLEAR_PIN(PIN_RX); }
/** * @brief Handle trickle timing events */ static void trickle_step_callback(void) { TICK_PIN(6); /* check if timeslot is about to end */ if (timeslot_get_remaining_time() < RADIO_SAFETY_TIMING_US) return; uint64_t time_now = global_time + timer_get_timestamp(); trickle_time_update(time_now); packet_t packet; bool has_anything_to_send = false; mesh_srv_packet_assemble(&packet, PACKET_DATA_MAX_LEN * PACKET_MAX_CHAIN_LEN, &has_anything_to_send); if (has_anything_to_send) { TICK_PIN(PIN_MESH_TX); radio_disable(); uint8_t packet_and_addr_type = PACKET_TYPE_ADV_NONCONN | ((packet.sender.addr_type == BLE_GAP_ADDR_TYPE_PUBLIC)? 0 : PACKET_ADDR_TYPE_MASK); uint8_t* temp_data_ptr = &packet.data[0]; uint8_t* tx_data_ptr = &tx_data[0]; tx_data_ptr[PACKET_TYPE_POS] = packet_and_addr_type; /* Code structured for packet chaining, although this is yet to be implemented. */ do { uint8_t min_len = ((packet.length > PACKET_DATA_MAX_LEN)? PACKET_DATA_MAX_LEN : packet.length); tx_data_ptr[PACKET_PADDING_POS] = 0; tx_data_ptr[PACKET_LENGTH_POS] = (min_len + PACKET_ADDR_LEN); tx_data_ptr[PACKET_TYPE_POS] = packet_and_addr_type; memcpy(&tx_data_ptr[PACKET_ADDR_POS], packet.sender.addr, PACKET_ADDR_LEN); memcpy(&tx_data_ptr[PACKET_DATA_POS], &temp_data_ptr[0], min_len); radio_event_t tx_event; tx_event.access_address = 0; rbc_mesh_channel_get(&tx_event.channel); tx_event.event_type = RADIO_EVENT_TYPE_TX; tx_event.packet_ptr = &tx_data_ptr[0]; tx_event.start_time = 0; tx_event.callback.tx = NULL; radio_order(&tx_event); TICK_PIN(0); } while (0); order_search(); /* search for the rest of the timeslot */ } /* order next processing */ uint64_t next_time; uint64_t end_time = timeslot_get_end_time(); uint32_t error_code = mesh_srv_get_next_processing_time(&next_time); if (error_code == NRF_SUCCESS && next_time < global_time + end_time) { timer_abort(step_timer_index); step_timer_index = timer_order_cb(next_time - global_time, trickle_step_callback); } }
static void radio_idle_callback(void) { /* If the processor is unable to keep up, we should back down, and give it time */ if (!g_state.queue_saturation) order_search(); }