static int dma_channel_program(struct dma_channel *channel, u16 packet_sz, u8 mode, dma_addr_t dma_addr, u32 len) { struct musb_dma_channel *musb_channel = channel->private_data; DBG(2, "ep%d-%s pkt_sz %d, dma_addr 0x%x length %d, mode %d\n", musb_channel->epnum, musb_channel->transmit ? "Tx" : "Rx", packet_sz, dma_addr, len, mode); BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN || channel->status == MUSB_DMA_STATUS_BUSY); channel->actual_len = 0; musb_channel->start_addr = dma_addr; musb_channel->len = len; musb_channel->max_packet_sz = packet_sz; channel->status = MUSB_DMA_STATUS_BUSY; if ((mode == 1) && (len >= packet_sz)) configure_channel(channel, packet_sz, 1, dma_addr, len); else configure_channel(channel, packet_sz, 0, dma_addr, len); return true; }
static int dma_channel_program(struct dma_channel *channel, u16 packet_sz, u8 mode, dma_addr_t dma_addr, u32 len) { struct musb_dma_channel *musb_channel = channel->private_data; struct musb_dma_controller *controller = musb_channel->controller; struct musb *musb = controller->private_data; DBG(2, "ep%d-%s pkt_sz %d, dma_addr 0x%x length %d, mode %d\n", musb_channel->epnum, musb_channel->transmit ? "Tx" : "Rx", packet_sz, dma_addr, len, mode); BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN || channel->status == MUSB_DMA_STATUS_BUSY); /* * make sure the DMA address is 4 byte aligned, if not * we use the PIO mode for OMAP 3630 and beyond */ if ((dma_addr % 4) && (musb->hwvers >= MUSB_HWVERS_1800)) return false; /* In version 1.4, if two DMA channels are simultaneously * enabled in opposite directions, there is a chance that * the DMA controller will hang. However, it is safe to * have multiple DMA channels enabled in the same direction * at the same time. */ if (musb->hwvers == MUSB_HWVERS_1400) { if (musb_channel->transmit && controller->rx_active) return false; else if (!musb_channel->transmit && controller->tx_active) return false; } channel->actual_len = 0; musb_channel->start_addr = dma_addr; musb_channel->len = len; musb_channel->max_packet_sz = packet_sz; channel->status = MUSB_DMA_STATUS_BUSY; if ((mode == 1) && (len >= packet_sz)) configure_channel(channel, packet_sz, 1, dma_addr, len); else configure_channel(channel, packet_sz, 0, dma_addr, len); return true; }
static void start_rx(hw_rx_cfg_t const* rx_cfg) { DPRINT("start_rx"); if (current_state == HW_RADIO_STATE_OFF) ezradio_hal_DeassertShutdown(); current_state = HW_RADIO_STATE_RX; configure_channel(&(rx_cfg->channel_id)); configure_syncword_class(rx_cfg->syncword_class, rx_cfg->channel_id.channel_header.ch_coding); rx_fifo_data_lenght = 0; if (rx_cfg->channel_id.channel_header.ch_coding == PHY_CODING_FEC_PN9) { ezradioStartRx(ez_channel_id, false); } else { ezradioStartRx(ez_channel_id, true); } DEBUG_RX_START(); if(rssi_valid_callback != 0) { // TODO calculate/predict rssi response time and wait until valid. For now we wait 200 us. hw_busy_wait(200); rssi_valid_callback(hw_radio_get_rssi()); } }
error_t hw_radio_init(alloc_packet_callback_t alloc_packet_cb, release_packet_callback_t release_packet_cb) { alloc_packet_callback = alloc_packet_cb; release_packet_callback = release_packet_cb; current_state = HW_RADIO_STATE_IDLE; cc1101_interface_init(&end_of_packet_isr); cc1101_interface_reset_radio_core(); cc1101_interface_write_rfsettings(&rf_settings); DPRINT("RF settings:"); uint8_t* p = (uint8_t*) &rf_settings; uint8_t i; for(i = 0; i < sizeof(RF_SETTINGS); i++) { DPRINT("\t0x%02X", p[i]); } // configure default channel, eirp and syncword configure_channel(¤t_channel_id); configure_eirp(current_eirp); configure_syncword_class(current_syncword_class); }
static int dma_channel_program(struct dma_channel *channel, u16 packet_sz, u8 mode, dma_addr_t dma_addr, u32 len) { struct musbfsh_dma_channel *musbfsh_channel = channel->private_data; //struct musbfsh_dma_controller *controller = musbfsh_channel->controller; //struct musfsh *musbfsh = controller->private_data; INFO("ep%d-%s pkt_sz %d, dma_addr 0x%x length %d, mode %d\n", musbfsh_channel->epnum, musbfsh_channel->transmit ? "Tx" : "Rx", packet_sz, dma_addr, len, mode); BUG_ON(channel->status == MUSBFSH_DMA_STATUS_UNKNOWN || channel->status == MUSBFSH_DMA_STATUS_BUSY); channel->actual_len = 0; musbfsh_channel->start_addr = dma_addr; musbfsh_channel->len = len; musbfsh_channel->max_packet_sz = packet_sz; channel->status = MUSBFSH_DMA_STATUS_BUSY; configure_channel(channel, packet_sz, mode, dma_addr, len); return true; }
static void start_rx(hw_rx_cfg_t const* rx_cfg) { DPRINT("start_rx"); if (current_state == HW_RADIO_STATE_OFF) ezradio_hal_DeassertShutdown(); current_state = HW_RADIO_STATE_RX; configure_channel(&(rx_cfg->channel_id)); configure_syncword_class(rx_cfg->syncword_class, rx_cfg->channel_id.channel_header.ch_coding); rx_fifo_data_lenght = 0; if (rx_cfg->channel_id.channel_header.ch_coding == PHY_CODING_FEC_PN9) { ezradioStartRx(ez_channel_id, false); } else { ezradioStartRx(ez_channel_id, true); } DEBUG_RX_START(); if(rssi_valid_callback != 0) { timer_post_task_delay(&report_rssi, TIMER_TICKS_PER_SEC / 5000); } }
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 int dma_channel_program(struct dma_channel *channel, u16 packet_sz, u8 mode, dma_addr_t dma_addr, u32 len) { struct musb_dma_channel *musb_channel = channel->private_data; struct musb_dma_controller *controller = musb_channel->controller; struct musb *musb = controller->private_data; DBG(2, "ep%d-%s pkt_sz %d, dma_addr 0x%x length %d, mode %d\n", musb_channel->epnum, musb_channel->transmit ? "Tx" : "Rx", packet_sz, (unsigned int)dma_addr, len, mode); BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN || channel->status == MUSB_DMA_STATUS_BUSY); /* Let targets check/tweak the arguments */ if (musb->ops->adjust_channel_params) { int ret = musb->ops->adjust_channel_params(channel, packet_sz, &mode, &dma_addr, &len); if (ret) return ret; } #if 0 /* * The DMA engine in RTL1.8 and above cannot handle * DMA addresses that are not aligned to a 4 byte boundary. * It ends up masking the last two bits of the address * programmed in DMA_ADDR. * * Fail such DMA transfers, so that the backup PIO mode * can carry out the transfer */ if ((musb->hwvers >= MUSB_HWVERS_1800) && (dma_addr % 4)) return false; #endif channel->actual_len = 0; musb_channel->start_addr = dma_addr; musb_channel->len = len; musb_channel->max_packet_sz = packet_sz; channel->status = MUSB_DMA_STATUS_BUSY; configure_channel(channel, packet_sz, mode, dma_addr, len); return true; }
error_t hw_radio_init(alloc_packet_callback_t alloc_packet_cb, release_packet_callback_t release_packet_cb) { /* EZRadio response structure union */ ezradio_cmd_reply_t ezradioReply; alloc_packet_callback = alloc_packet_cb; release_packet_callback = release_packet_cb; current_state = HW_RADIO_STATE_UNKOWN; /* Initialize EZRadio device. */ DPRINT("INIT ezradioInit"); ezradioInit(&ezradio_int_callback); /* Print EZRadio device number. */ DPRINT("INIT ezradio_part_info"); ezradio_part_info(&ezradioReply); DPRINT(" Device: Si%04x\n\n", ezradioReply.PART_INFO.PART); /* Enable Packet Trace Interface */ //ezradio_set_property(RADIO_CONFIG_SET_PROPERTY_PTI_ENABLE); /* Fix registers not correct set by radio configurator */ // latch on sync word detect - currently no threshold comparison (todo: optimize) //ezradio_set_property(RADIO_CONFIG_SET_PROPERTY_MODEM_RSSI_CONTROL); // disable jump detection (todo: optimize) //ezradio_set_property(RADIO_CONFIG_SET_PROPERTY_MODEM_RSSI_CONTROL2); /* Reset radio fifos. */ DPRINT("INIT ezradioResetTRxFifo"); ezradioResetTRxFifo(); // configure default channel, eirp and syncword configure_channel(¤t_channel_id); configure_eirp(current_eirp); configure_syncword_class(current_rx_cfg.syncword_class, current_channel_id.channel_header.ch_coding); sched_register_task((&report_rssi)); switch_to_idle_mode(); }
static void start_rx(hw_rx_cfg_t const* rx_cfg) { current_state = HW_RADIO_STATE_RX; cc1101_interface_strobe(RF_SFRX); configure_channel(&(rx_cfg->channel_id)); configure_syncword_class(rx_cfg->syncword_class); cc1101_interface_write_single_reg(PKTLEN, 0xFF); if(rx_packet_callback != 0) // when rx callback not set we ignore received packets cc1101_interface_set_interrupts_enabled(true); cc1101_interface_strobe(RF_SRX); if(rssi_valid_callback != 0) { // TODO calculate/predict rssi response time (see DN505) // and wait until valid. For now we wait 200 us. hw_busy_wait(200); rssi_valid_callback(hw_radio_get_rssi()); } }
static int dma_channel_program(struct dma_channel *channel, u16 packet_sz, u8 mode, dma_addr_t dma_addr, u32 len) { struct musb_dma_channel *musb_channel = channel->private_data; struct musb_dma_controller *controller = musb_channel->controller; struct musb *musb = controller->private_data; dev_dbg(musb->controller, "ep%d-%s pkt_sz %d, dma_addr 0x%x length %d, mode %d\n", musb_channel->epnum, musb_channel->transmit ? "Tx" : "Rx", packet_sz, dma_addr, len, mode); BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN || channel->status == MUSB_DMA_STATUS_BUSY); if (musb->ops->adjust_channel_params) { int ret = musb->ops->adjust_channel_params(channel, packet_sz, &mode, &dma_addr, &len); if (ret) return ret; } if ((musb->hwvers >= MUSB_HWVERS_1800) && (dma_addr % 4)) return false; channel->actual_len = 0; musb_channel->start_addr = dma_addr; musb_channel->len = len; musb_channel->max_packet_sz = packet_sz; channel->status = MUSB_DMA_STATUS_BUSY; configure_channel(channel, packet_sz, mode, dma_addr, len); return true; }
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; assert(packet->length < 63); // long packets not yet supported 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; cc1101_interface_strobe(RF_SIDLE); cc1101_interface_strobe(RF_SFTX); #ifdef FRAMEWORK_LOG_ENABLED // TODO more granular log_print_stack_string(LOG_STACK_PHY, "Data to TX Fifo:"); log_print_data(packet->data, packet->length + 1); #endif configure_channel((channel_id_t*)&(current_packet->tx_meta.tx_cfg.channel_id)); configure_eirp(current_packet->tx_meta.tx_cfg.eirp); configure_syncword_class(current_packet->tx_meta.tx_cfg.syncword_class); cc1101_interface_write_burst_reg(TXFIFO, packet->data, packet->length + 1); cc1101_interface_set_interrupts_enabled(true); cc1101_interface_strobe(RF_STX); return SUCCESS; }
/* Usage: * libbladeRF_example_boilerplate [serial #] * * If a serial number is supplied, the program will attempt to open the * device with the provided serial number. * * Otherwise, the first available device will be used. */ int main(int argc, char *argv[]) { int status; struct channel_config config; /** [Opening a device] */ struct bladerf *dev = NULL; struct bladerf_devinfo dev_info; /* Initialize the information used to identify the desired device * to all wildcard (i.e., "any device") values */ bladerf_init_devinfo(&dev_info); /* Request a device with the provided serial number. * Invalid strings should simply fail to match a device. */ if (argc >= 2) { strncpy(dev_info.serial, argv[1], sizeof(dev_info.serial) - 1); } status = bladerf_open_with_devinfo(&dev, &dev_info); if (status != 0) { fprintf(stderr, "Unable to open device: %s\n", bladerf_strerror(status)); return 1; } /** [Opening a device] */ /* Set up RX channel parameters */ config.channel = BLADERF_CHANNEL_RX(0); config.frequency = 910000000; config.bandwidth = 2000000; config.samplerate = 300000; config.gain = 39; status = configure_channel(dev, &config); if (status != 0) { fprintf(stderr, "Failed to configure RX channel. Exiting.\n"); goto out; } /* Set up TX channel parameters */ config.channel = BLADERF_CHANNEL_TX(0); config.frequency = 918000000; config.bandwidth = 1500000; config.samplerate = 250000; config.gain = -14; status = configure_channel(dev, &config); if (status != 0) { fprintf(stderr, "Failed to configure TX channel. Exiting.\n"); goto out; } /* Application code goes here. * * Don't forget to call bladerf_enable_module() before attempting to * transmit or receive samples! */ printf("Hello world\n"); out: bladerf_close(dev); return status; }
//***************************************************************************** // incomingPacketManager //This function waits for an incoming message, and then extracts the //value from the message. If the message is an config one, then it will assign //the config info to a global variable. The function will return the next action //to be taken. // Packet Structure: <Command 1 Byte><Size of data 2 bytes><Missed Data 2 bytes><Data 2 bytes> //***************************************************************************** void incomingPacketManager(void){ char requestBuffer[SERVER_RECV_BUF_SIZE] = {NULL}; bytesRecvd = recv(clientDescriptor, requestBuffer, sizeof(requestBuffer), 0); switch(requestBuffer[0]) { case Config: //RESET ADC and DMA: refresh_ADC(); ADC_STATE = HALTED; //RESET DMA STATE. refresh_DMA(); DMA_STATE = HALTED; //Extracts the required Data from config. confirmationPacket_ptr = &config_data; *confirmationPacket_ptr = requestBuffer[6]; confirmationPacket_ptr++; *confirmationPacket_ptr = requestBuffer[5]; generalConfirmationPacket[1] = 0; //First Byte of Data Size generalConfirmationPacket[2] = 2; //Second Byte of Data Size generalConfirmationPacket[3] = 0; //First Byte of Data lost generalConfirmationPacket[4] = 0; //Second Byte of Data Size confirmationPacket_ptr = &ammount_packets_to_be_sent; generalConfirmationPacket[6] = *confirmationPacket_ptr; confirmationPacket_ptr++; generalConfirmationPacket[5] = *confirmationPacket_ptr; bytesSent = send(clientDescriptor, (unsigned char *)generalConfirmationPacket, sizeof(generalConfirmationPacket), 0); turnLedOff(CC3000_SENDING_DATA_IND); toggleLed(CC3000_SENDING_DATA_IND); __delay_cycles(100000); toggleLed(CC3000_SENDING_DATA_IND); if (bytesSent != sizeof(generalConfirmationPacket)){check_socket_connection();} deviceconfigured = FALSE; break; case Start: if(deviceconfigured == FALSE){ configure_channel(&config_data);//This is where I configure the device to operate differently. deviceconfigured = TRUE; } if(DMA_STATE == HALTED){ //VIMP: The stop state must stop the DMA DMA0CTL += DMAEN; DMA_STATE = RUNNING; __delay_cycles(1000); } if(ADC_STATE == HALTED){ ADC10CTL0 |= ADC10ENC + ADC10SC; ADC_STATE = RUNNING; //VIMP: The stop state must stop the ADC __delay_cycles(100000); } for(i=0; i<ammount_packets_to_be_sent; i++){ while(DMA0_State != DONE && DMA1_State != DONE); //Waits while buffers are populated //This checks which buffer is full, and toggles the operation. if(sendingBuffer_ptr == buffer0_ptr){ //Buffer0 is fill or done DMA0_State = NOT_DONE; // Reset for next usage DMA1CTL += DMAEN; // Start or enable DMA1 buffer filling process } else{ //Buffer1 is fill or done DMA1_State = NOT_DONE; // Reset for next usage DMA0CTL += DMAEN; // Start or enable DMA0 buffer filling process } //********************************************************************************************* //This is a pointer manipulation method to include the missed ADC cycles into the packet header. sendingBuffer_ptr +=4; temp_ptr = &missed_samples; *sendingBuffer_ptr = *temp_ptr; temp_ptr++; sendingBuffer_ptr--; *sendingBuffer_ptr = *temp_ptr; sendingBuffer_ptr -=3; missed_samples = 0; //********************************************************************************************* if(currentCC3000State() & CC3000_CLIENT_CONNECTED){ bytesSent = send(clientDescriptor, sendingBuffer_ptr, ammount_of_samples_in_packet+packet_header_size, 0); toggleLed(CC3000_SENDING_DATA_IND); if (bytesSent != ammount_of_samples_in_packet+packet_header_size){ check_socket_connection(); } } if (clientDescriptor == -1){break;} } break; case Stop: //RESET ADC: refresh_ADC(); ADC_STATE = HALTED; //RESET DMA. refresh_DMA(); DMA_STATE = HALTED; // The confirmation packet being sent back contains no relevant information. generalConfirmationPacket[1] = 0; //First Byte of Data Size generalConfirmationPacket[2] = 2; //Second Byte of Data Size generalConfirmationPacket[3] = 0; //First Byte of Data lost generalConfirmationPacket[4] = 0; //Second Byte of Data Size generalConfirmationPacket[5] = 0; generalConfirmationPacket[6] = 0; bytesSent = send(clientDescriptor, (unsigned char *)generalConfirmationPacket, sizeof(generalConfirmationPacket), 0); turnLedOff(CC3000_SENDING_DATA_IND); toggleLed(CC3000_SENDING_DATA_IND); __delay_cycles(100000); toggleLed(CC3000_SENDING_DATA_IND); if (bytesSent != sizeof(generalConfirmationPacket)){check_socket_connection();} break; default: break; } }