error_t hw_radio_send_packet(hw_radio_packet_t* packet, tx_packet_callback_t tx_cb, uint16_t eta, uint8_t dll_header_bg_frame[2]) { assert(eta == 0); // advertising not implemented on si4460 for now // TODO error handling EINVAL, ESIZE, EOFF if(current_state == HW_RADIO_STATE_TX) return EBUSY; uint8_t data_length = packet->length + 1; if (packet->tx_meta.tx_cfg.channel_id.channel_header.ch_coding == PHY_CODING_FEC_PN9) { DPRINT("Original packet: %d", data_length); DPRINT_DATA(packet->data, data_length); data_length = fec_encode(packet->data, data_length); DPRINT("Encoded packet: %d", data_length); DPRINT_DATA(packet->data, data_length); } else { if (has_hardware_crc) data_length -= 2; } tx_packet_callback = tx_cb; if(current_state == HW_RADIO_STATE_RX) { //pending_rx_cfg.channel_id = current_channel_id; //pending_rx_cfg.syncword_class = current_syncword_class; should_rx_after_tx_completed = true; } current_state = HW_RADIO_STATE_TX; current_packet = packet; DPRINT("Data to TX Fifo:"); DPRINT_DATA(packet->data, data_length); DPRINT("TX ch header=%x, ind=%i", packet->tx_meta.tx_cfg.channel_id.channel_header_raw, packet->tx_meta.tx_cfg.channel_id.center_freq_index); configure_channel((channel_id_t*)&(packet->tx_meta.tx_cfg.channel_id)); configure_eirp(packet->tx_meta.tx_cfg.eirp); configure_syncword_class(current_packet->tx_meta.tx_cfg.syncword_class, current_packet->tx_meta.tx_cfg.channel_id.channel_header.ch_coding); DEBUG_TX_START(); DEBUG_RX_END(); ezradioStartTx(packet, ez_channel_id, should_rx_after_tx_completed, data_length); return SUCCESS; }
error_t hw_radio_send_packet(hw_radio_packet_t* packet, tx_packet_callback_t tx_cb) { // TODO error handling EINVAL, ESIZE, EOFF if(current_state == HW_RADIO_STATE_TX) return EBUSY; uint8_t data_length = packet->length + 1; if (packet->tx_meta.tx_cfg.channel_id.channel_header.ch_coding == PHY_CODING_FEC_PN9) { DPRINT(LOG_STACK_PHY, "Original packet: %d", data_length); DPRINT_DATA(packet->data, data_length); data_length = fec_encode(packet->data, data_length); DPRINT(LOG_STACK_PHY, "Encoded packet: %d", data_length); DPRINT_DATA(packet->data, data_length); } else { if (has_hardware_crc) data_length -= 2; } tx_packet_callback = tx_cb; if(current_state == HW_RADIO_STATE_RX) { //pending_rx_cfg.channel_id = current_channel_id; //pending_rx_cfg.syncword_class = current_syncword_class; should_rx_after_tx_completed = true; } current_state = HW_RADIO_STATE_TX; current_packet = packet; DPRINT(LOG_STACK_PHY, "Data to TX Fifo:"); DPRINT_DATA(packet->data, data_length); configure_channel((channel_id_t*)&(packet->tx_meta.tx_cfg.channel_id)); configure_eirp(packet->tx_meta.tx_cfg.eirp); configure_syncword_class(current_packet->tx_meta.tx_cfg.syncword_class, current_packet->tx_meta.tx_cfg.channel_id.channel_header.ch_coding); DEBUG_TX_START(); DEBUG_RX_END(); ezradioStartTx(packet, ez_channel_id, should_rx_after_tx_completed, data_length); return SUCCESS; }
static void process_serial_frame(fifo_t* fifo) { bool command_completed = false; bool completed_with_error = false; while(fifo_get_size(fifo)) { alp_action_t action; alp_parse_action(fifo, &action); switch(action.operation) { case ALP_OP_RETURN_TAG: if(action.tag_response.tag_id == command.tag_id) { command_completed = action.tag_response.completed; completed_with_error = action.tag_response.error; } else { DPRINT("received resp with unexpected tag_id (%i vs %i)", action.tag_response.tag_id, command.tag_id); // TODO unsolicited responses } break; case ALP_OP_WRITE_FILE_DATA: if(callbacks->write_file_data_callback) callbacks->write_file_data_callback(action.file_data_operand.file_offset.file_id, action.file_data_operand.file_offset.offset, action.file_data_operand.provided_data_length, action.file_data_operand.data); break; case ALP_OP_RETURN_FILE_DATA: if(callbacks->return_file_data_callback) callbacks->return_file_data_callback(action.file_data_operand.file_offset.file_id, action.file_data_operand.file_offset.offset, action.file_data_operand.provided_data_length, action.file_data_operand.data); break; case ALP_OP_RETURN_STATUS: if(action.status.type==ALP_ITF_ID_D7ASP) { d7ap_session_result_t interface_status = *((d7ap_session_result_t*)action.status.data); uint8_t addressee_len = d7ap_addressee_id_length(interface_status.addressee.ctrl.id_type); DPRINT("received resp from: "); DPRINT_DATA(interface_status.addressee.id, addressee_len); } if(callbacks->modem_interface_status_callback) callbacks->modem_interface_status_callback(action.status.type,&action.status.data); break; default: assert(false); } } if(command_completed) { DPRINT("command with tag %i completed @ %i", command.tag_id, timer_get_counter_value()); if(callbacks->command_completed_callback) callbacks->command_completed_callback(completed_with_error,command.tag_id); command.is_active = false; } }
static void process_rx_fifo(void *arg) { if(!parsed_header) { // <sync byte (0xC0)><version (0x00)><length of ALP command (1 byte)><ALP command> // TODO CRC if(fifo_get_size(&rx_fifo) > SERIAL_ALP_FRAME_HEADER_SIZE) { uint8_t header[SERIAL_ALP_FRAME_HEADER_SIZE]; fifo_peek(&rx_fifo, header, 0, SERIAL_ALP_FRAME_HEADER_SIZE); DPRINT_DATA(header, 3); // TODO tmp if(header[0] != SERIAL_ALP_FRAME_SYNC_BYTE || header[1] != SERIAL_ALP_FRAME_VERSION) { fifo_skip(&rx_fifo, 1); DPRINT("skip"); parsed_header = false; payload_len = 0; if(fifo_get_size(&rx_fifo) > SERIAL_ALP_FRAME_HEADER_SIZE) sched_post_task(&process_rx_fifo); return; } parsed_header = true; fifo_skip(&rx_fifo, SERIAL_ALP_FRAME_HEADER_SIZE); payload_len = header[2]; DPRINT("found header, payload size = %i", payload_len); sched_post_task(&process_rx_fifo); } } else { if(fifo_get_size(&rx_fifo) < payload_len) { DPRINT("payload not complete yet"); return; } // payload complete, start parsing // rx_fifo can be bigger than the current serial packet, init a subview fifo // which is restricted to payload_len so we can't parse past this packet. fifo_t payload_fifo; fifo_init_subview(&payload_fifo, &rx_fifo, 0, payload_len); process_serial_frame(&payload_fifo); // pop parsed bytes from original fifo fifo_skip(&rx_fifo, payload_len - fifo_get_size(&payload_fifo)); parsed_header = false; } }
static void ezradio_handle_end_of_packet() { // fill rx_meta rx_packet->rx_meta.rssi = hw_radio_get_latched_rssi(); rx_packet->rx_meta.lqi = 0; memcpy(&(rx_packet->rx_meta.rx_cfg.channel_id), ¤t_channel_id, sizeof(channel_id_t)); if (has_hardware_crc && current_rx_cfg.channel_id.channel_header.ch_coding != PHY_CODING_FEC_PN9) rx_packet->rx_meta.crc_status = HW_CRC_VALID; else rx_packet->rx_meta.crc_status = HW_CRC_UNAVAILABLE; rx_packet->rx_meta.timestamp = timer_get_counter_value(); //memcpy((void*)rx_packet->rx_meta.rx_cfg, (void*)¤t_rx_cfg, sizeof(hw_rx_metadata_t)); ezradio_fifo_info(EZRADIO_CMD_FIFO_INFO_ARG_FIFO_RX_BIT, NULL); DPRINT_DATA(rx_packet->data, rx_packet->length+1); if (current_rx_cfg.channel_id.channel_header.ch_coding == PHY_CODING_FEC_PN9) { fec_decode_packet(rx_packet->data, rx_packet->length, rx_packet->length); //assert length and data[0] can only differ 1 rx_packet->length = rx_packet->data[0]; } DPRINT_PACKET(rx_packet, false); DEBUG_RX_END(); // if(rx_packet_callback != NULL) // TODO this can happen while doing CCA but we should not be interrupting here (disable packet handler?) rx_packet_callback(rx_packet); // else // release_packet_callback(packet); if(current_state == HW_RADIO_STATE_RX) { start_rx(¤t_rx_cfg); } }
static void ezradio_int_callback() { //DPRINT("ezradio ISR"); ezradio_cmd_reply_t ezradioReply; ezradio_cmd_reply_t radioReplyLocal; ezradio_get_int_status(0x0, 0x0, 0x0, &ezradioReply); //ezradio_frr_a_read(3, &ezradioReply); //DPRINT(" - INT_PEND %s", byte_to_binary(ezradioReply.FRR_A_READ.FRR_A_VALUE)); DPRINT(" - INT_PEND %s", byte_to_binary(ezradioReply.GET_INT_STATUS.INT_PEND)); // DPRINT(" - INT_STATUS %s", byte_to_binary(ezradioReply.GET_INT_STATUS.INT_STATUS)); // DPRINT(" - PH_PEND %s", byte_to_binary(ezradioReply.GET_INT_STATUS.PH_PEND)); //DPRINT(" - PH_STATUS %s", byte_to_binary(ezradioReply.GET_INT_STATUS.PH_STATUS)); //DPRINT(" - PH_STATUS %s", byte_to_binary(ezradioReply.FRR_A_READ.FRR_B_VALUE)); // DPRINT(" - MODEM_PEND %s", byte_to_binary(ezradioReply.GET_INT_STATUS.MODEM_PEND)); // DPRINT(" - MODEM_STATUS %s", byte_to_binary(ezradioReply.GET_INT_STATUS.MODEM_STATUS)); // DPRINT(" - CHIP_PEND %s", byte_to_binary(ezradioReply.GET_INT_STATUS.CHIP_PEND)); // DPRINT(" - CHIP_STATUS %s", byte_to_binary(ezradioReply.GET_INT_STATUS.CHIP_STATUS)); //if (ezradioReply.FRR_A_READ.FRR_A_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_INT_PEND_PH_INT_PEND_BIT) if (ezradioReply.GET_INT_STATUS.INT_PEND & EZRADIO_CMD_GET_INT_STATUS_REP_INT_PEND_PH_INT_PEND_BIT) { //DPRINT("PH ISR"); switch(current_state) { case HW_RADIO_STATE_RX: if ((ezradioReply.GET_INT_STATUS.PH_STATUS & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_PACKET_RX_BIT) || (ezradioReply.GET_INT_STATUS.PH_STATUS & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_RX_FIFO_ALMOST_FULL_BIT)) { //DPRINT("PACKET_RX IRQ"); if(rx_packet_callback != NULL) { /* Check how many bytes we received. */ ezradio_fifo_info(0, &radioReplyLocal); DPRINT("RX ISR packetLength: %d", radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT); if (rx_fifo_data_lenght == 0) { DPRINT("RX FIFO: %d", radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT); uint8_t buffer[4]; ezradio_read_rx_fifo(4, buffer); if (current_rx_cfg.channel_id.channel_header.ch_coding == PHY_CODING_FEC_PN9) { uint8_t fec_buffer[4]; memcpy(fec_buffer, buffer, 4); fec_decode_packet(fec_buffer, 4, 4); expected_data_length = fec_calculated_decoded_length(fec_buffer[0]+1); DPRINT("RX Packet Length: %d / %d", fec_buffer[0], expected_data_length); } else { expected_data_length = buffer[0] + 1; } rx_packet = alloc_packet_callback(expected_data_length); memcpy(rx_packet->data, buffer, 4); rx_fifo_data_lenght += 4; radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT-=4; } if (ezradioReply.GET_INT_STATUS.PH_STATUS & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_PACKET_RX_BIT) { /* Read out the RX FIFO content. */ ezradio_read_rx_fifo(radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT, &(rx_packet->data[rx_fifo_data_lenght])); //ezradio_read_rx_fifo(radioReplyLocal2.PACKET_INFO.LENGTH, packet->data); ezradio_handle_end_of_packet(); return; } if (ezradioReply.GET_INT_STATUS.PH_STATUS & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_RX_FIFO_ALMOST_FULL_BIT) { while (radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT > 0) { DPRINT("RX FIFO: %d", radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT); /* Read out the FIFO Count bytes of RX FIFO */ ezradio_read_rx_fifo(radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT, &(rx_packet->data[rx_fifo_data_lenght])); rx_fifo_data_lenght += radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT; //DPRINT("%d of %d bytes collected", rx_fifo_data_lenght, rx_packet->data[0]+1); ezradio_fifo_info(0, &radioReplyLocal); if (rx_fifo_data_lenght >= expected_data_length) { ezradio_handle_end_of_packet(); return; } } ezradio_int_callback(); return; } } } else if (ezradioReply.GET_INT_STATUS.PH_STATUS & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_CRC_ERROR_BIT) //} else if ( ezradioReply.FRR_A_READ.FRR_B_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_PH_STATUS_CRC_ERROR_BIT) { DPRINT("- PACKET_RX CRC_ERROR IRQ"); /* Check how many bytes we received. */ ezradio_fifo_info(0, &radioReplyLocal); DPRINT("RX ISR packetLength: %d", radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT); //ezradio_cmd_reply_t radioReplyLocal2; //ezradio_get_packet_info(0, 0, 0, &radioReplyLocal2); if (rx_fifo_data_lenght == 0) { rx_packet = alloc_packet_callback(radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT); } /* Read out the RX FIFO content. */ ezradio_read_rx_fifo(radioReplyLocal.FIFO_INFO.RX_FIFO_COUNT, &(rx_packet->data[rx_fifo_data_lenght])); rx_packet->rx_meta.crc_status = HW_CRC_INVALID; rx_packet->length = rx_packet->data[0] + 1; DPRINT_DATA(rx_packet->data, rx_packet->length); DEBUG_RX_END(); if(rx_packet_callback != NULL) rx_packet_callback(rx_packet); else release_packet_callback(rx_packet); if(current_state == HW_RADIO_STATE_RX) { start_rx(¤t_rx_cfg); } } else { DPRINT((" - OTHER RX IRQ")); } break; case HW_RADIO_STATE_TX: if (ezradioReply.GET_INT_STATUS.PH_PEND & EZRADIO_CMD_GET_INT_STATUS_REP_PH_PEND_PACKET_SENT_PEND_BIT) //if (ezradioReply.FRR_A_READ.FRR_C_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_PH_PEND_PACKET_SENT_PEND_BIT) { DPRINT("PACKET_SENT IRQ"); DEBUG_TX_END(); if(tx_packet_callback != 0) { current_packet->tx_meta.timestamp = timer_get_counter_value(); DPRINT_DATA(current_packet->data, current_packet->length); tx_packet_callback(current_packet); } /* We can't switch back to Rx since the Rx callbacks are modified * during CCA, so we systematically go to idle */ switch_to_idle_mode(); // } else if (ezradioReply.FRR_A_READ.FRR_C_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_PH_PEND_TX_FIFO_ALMOST_EMPTY_PEND_BIT) // { // DPRINT(" - TX FIFO Almost empty IRQ "); // // ezradio_fifo_info(0, &radioReplyLocal); // DPRINT("TX FIFO Space: %d", radioReplyLocal.FIFO_INFO.TX_FIFO_SPACE); // // //Fill fifo // #ifdef HAL_RADIO_USE_HW_CRC // int16_t new_length = current_packet->length-1 - tx_fifo_data_length; // #else // int16_t new_length = current_packet->length+1 - tx_fifo_data_length; // #endif // if (new_length > radioReplyLocal.FIFO_INFO.TX_FIFO_SPACE) new_length = radioReplyLocal.FIFO_INFO.TX_FIFO_SPACE; // // while (new_length > 0) // { // ezradio_write_tx_fifo(new_length, &(current_packet->data[tx_fifo_data_length])); // tx_fifo_data_length += new_length; // DPRINT ("%d added -> %d", new_length, tx_fifo_data_length); // // #ifdef HAL_RADIO_USE_HW_CRC // new_length = current_packet->length-1 - tx_fifo_data_length; // #else // new_length = current_packet->length+1 - tx_fifo_data_length; // #endif // if (new_length > radioReplyLocal.FIFO_INFO.TX_FIFO_SPACE) new_length = radioReplyLocal.FIFO_INFO.TX_FIFO_SPACE; // } // // if (new_length == 0) // { // DPRINT("reprocess callback"); // ezradio_int_callback(); // return; // } // // DPRINT ("%d added -> %d", new_length, tx_fifo_data_length); } else { DPRINT(" - OTHER IRQ"); } break; default: //assert(false); DPRINT("State: %d", current_state); } } // if (ezradioReply.FRR_A_READ.FRR_A_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_INT_PEND_MODEM_INT_PEND_BIT) // { // DPRINT("MODEM ISR"); // } // if (ezradioReply.FRR_A_READ.FRR_A_VALUE & EZRADIO_CMD_GET_INT_STATUS_REP_INT_PEND_CHIP_INT_PEND_BIT) // { // DPRINT("CHIP ISR"); // // if (current_state != HW_RADIO_STATE_IDLE) // { // if (ezradioReply.GET_INT_STATUS.CHIP_STATUS & EZRADIO_CMD_GET_INT_STATUS_REP_CHIP_STATUS_STATE_CHANGE_BIT) // { // ezradio_request_device_state(&radioReplyLocal); // DPRINT(" - Current State %d", radioReplyLocal.REQUEST_DEVICE_STATE.CURR_STATE); // DPRINT(" - Current channel %d", radioReplyLocal.REQUEST_DEVICE_STATE.CURRENT_CHANNEL); // }else { // DPRINT(" - OTHER IRQ"); // } // } // } }