void transmit_packet() { counter++; DPRINT("%d tx %d bytes\n", counter, PACKET_LENGTH); memcpy(&tx_packet->data, data, PACKET_LENGTH); hw_radio_send_packet(tx_packet, &packet_transmitted); }
void send_packet() { hw_radio_send_packet((hw_radio_packet_t*)(&NG(tx_buffer)), tx_callback); log_print_string("Sending packet with counter %u", NG(tx_buffer).counter); NG(tx_buffer).counter++; timer_post_task_delay(send_packet, TIMER_TICKS_PER_SEC + (get_rnd() %TIMER_TICKS_PER_SEC)); }
static void transmit_packet() { DPRINT("transmitting packet"); current_state = STATE_RUNNING; counter++; memcpy(data + 1, &id, sizeof(id)); memcpy(data + 1 + sizeof(id), &counter, sizeof(counter)); uint16_t crc = __builtin_bswap16(crc_calculate(data, sizeof(data) - 2)); memcpy(data + sizeof(data) - 2, &crc, 2); memcpy(&tx_packet->data, data, sizeof(data)); tx_cfg.channel_id = current_channel_id; tx_packet->tx_meta.tx_cfg = tx_cfg; hw_radio_send_packet(tx_packet, &packet_transmitted); }
static void packet_transmitted(hw_radio_packet_t* hw_radio_packet) { assert(dll_state == DLL_STATE_TX_FOREGROUND); switch_state(DLL_STATE_TX_FOREGROUND_COMPLETED); DPRINT("Transmitted packet with length = %i", hw_radio_packet->length); packet_t* packet = packet_queue_find_packet(hw_radio_packet); d7anp_signal_packet_transmitted(packet); if(process_received_packets_after_tx) { sched_post_task(&process_received_packets); process_received_packets_after_tx = false; } #ifdef RESPONDER_USE_FG_SCAN_OUTSIDE_TRANSACTION // TODO validate if still needed, if yes: needs to be tested /* * Resume the FG scan only after an unicast packet, otherwise, wait the * response period expiration. */ if (resume_fg_scan && packet->dll_header.control_target_address_set) { switch_state(DLL_STATE_FOREGROUND_SCAN); hw_rx_cfg_t rx_cfg = (hw_rx_cfg_t){ .channel_id.channel_header = current_access_profile->subbands[0].channel_header, .channel_id.center_freq_index = current_access_profile->subbands[0].channel_index_start, .syncword_class = PHY_SYNCWORD_CLASS1, }; hw_radio_set_rx(&rx_cfg, &packet_received, NULL); resume_fg_scan = false; } #else if (resume_fg_scan) { switch_state(DLL_STATE_FOREGROUND_SCAN); hw_rx_cfg_t rx_cfg = (hw_rx_cfg_t){ .channel_id.channel_header = current_access_profile->subbands[0].channel_header, .channel_id.center_freq_index = current_access_profile->subbands[0].channel_index_start, .syncword_class = PHY_SYNCWORD_CLASS1, }; hw_radio_set_rx(&rx_cfg, &packet_received, NULL); resume_fg_scan = false; } #endif } static void cca_rssi_valid(int16_t cur_rssi) { // When the radio goes back to Rx state, the rssi_valid callback may be still set. Skip it in this case if (dll_state != DLL_STATE_CCA1 && dll_state != DLL_STATE_CCA2) return; if (cur_rssi <= E_CCA) { if(dll_state == DLL_STATE_CCA1) { DPRINT("CCA1 RSSI: %d", cur_rssi); switch_state(DLL_STATE_CCA2); timer_post_task_delay(&execute_cca, 5); return; } else if(dll_state == DLL_STATE_CCA2) { // OK, send packet DPRINT("CCA2 RSSI: %d", cur_rssi); DPRINT("CCA2 succeeded, transmitting ..."); // log_print_data(current_packet->hw_radio_packet.data, current_packet->hw_radio_packet.length + 1); // TODO tmp switch_state(DLL_STATE_TX_FOREGROUND); d7anp_signal_packet_csma_ca_insertion_completed(true); error_t err = hw_radio_send_packet(¤t_packet->hw_radio_packet, &packet_transmitted); assert(err == SUCCESS); if (!resume_fg_scan) hw_radio_set_idle(); // ensure radio goes back to IDLE after transmission instead of to RX return; } } else { DPRINT("Channel not clear, RSSI: %i", cur_rssi); switch_state(DLL_STATE_CSMA_CA_RETRY); execute_csma_ca(); //switch_state(DLL_STATE_CCA_FAIL); //d7atp_signal_packet_csma_ca_insertion_completed(false); } } static void execute_cca() { assert(dll_state == DLL_STATE_CCA1 || dll_state == DLL_STATE_CCA2); hw_rx_cfg_t rx_cfg =(hw_rx_cfg_t){ .channel_id.channel_header = current_access_profile->subbands[0].channel_header, .channel_id.center_freq_index = current_access_profile->subbands[0].channel_index_start, .syncword_class = PHY_SYNCWORD_CLASS1, }; hw_radio_set_rx(&rx_cfg, NULL, &cca_rssi_valid); } static uint16_t calculate_tx_duration() { int data_rate = 6; // Normal rate: 6.9 bytes/tick // TODO select correct subband switch (current_access_profile->subbands[0].channel_header.ch_class) { case PHY_CLASS_LO_RATE: data_rate = 1; // Lo Rate: 1.2 bytes/tick break; case PHY_CLASS_HI_RATE: data_rate = 20; // High rate: 20.83 byte/tick } uint16_t duration = (current_packet->hw_radio_packet.length / data_rate) + 1; return duration; }