__interrupt #endif static void lin_pdca_int_rx_handler_node1(void) { U8 index = 0; U8 l_handle = 0xFF; // Check ID Value for the current message for(index = 0; index < NUMBER_OF_LIN_FRAMES_NODE1; index ++) { if(lin_descript_list_node1[index].l_id == usart_lin_get_id_char(usart_lin_node1)) { l_handle = index; break; } } // Check if the ID received is registered into the lin description list if (l_handle!=0xFF) { if (pdca_get_transfer_status(USART_LIN_NODE1_RX_PDCA_CHANNEL)&PDCA_TRANSFER_COMPLETE) { pdca_disable_interrupt_transfer_complete(USART_LIN_NODE1_RX_PDCA_CHANNEL); lin_get_response (1,lin_descript_list_node1[l_handle].l_pt_data); // Start of the associated task lin_descript_list_node1[l_handle].l_pt_function(lin_descript_list_node1[l_handle].l_pt_data); lin_handle_node1 = 0xFF; // End of communication } } }
void aic23b_dac_mute(bool mute) { #if (AIC23B_MODE==AIC23B_MODE_DAC) /* if(mute==true) { pdca_disable(AIC23B_SSC_TX_PDCA_CHANNEL); } else { pdca_enable(AIC23B_SSC_TX_PDCA_CHANNEL); } */ if (mute) { uint32_t save_dac_reload_callback_opt; // Disable the reload callback function save_dac_reload_callback_opt = aic23b_output_params.callback_opt; aic23b_output_params.callback_opt = 0; // Disable the transfer complete interruption and wait until the transfer is complete pdca_disable_interrupt_reload_counter_zero(AIC23B_SSC_TX_PDCA_CHANNEL); while (!(pdca_get_transfer_status(AIC23B_SSC_TX_PDCA_CHANNEL) & PDCA_TRANSFER_COMPLETE)); // Re-enable the reload callback function aic23b_output_params.callback_opt = save_dac_reload_callback_opt; } else { // Re-enable the reload interrupt pdca_enable_interrupt_reload_counter_zero(AIC23B_SSC_TX_PDCA_CHANNEL); } #endif }
//this gets an experiment, plus additional data, from the host //A full cluster will be transferred void get_experiment_from_host_to_SD(void) { USB_USART->rtor=0; //going to use PDCA for receiving data, so disable receive timeout pdca_disable(USB_USART_RX_PDCA_CHANNEL); my_pdca_init_channel(USB_USART_RX_PDCA_CHANNEL, (uint32_t)(&bank0[0]),samplebuffer_size, USB_USART_RX_PDCA_PID, 0, 0, PDCA_TRANSFER_SIZE_BYTE); pdca_enable(USB_USART_RX_PDCA_CHANNEL); while(!(pdca_get_transfer_status(USB_USART_RX_PDCA_CHANNEL) & AVR32_PDCA_TRC_MASK)); //wait until transfer is done pdca_disable(USB_USART_RX_PDCA_CHANNEL); //reset USART RX channel to receive host commands USB_USART->cr|=AVR32_USART_CR_STTTO_MASK; //changing back to receiving command mode USB_USART->rtor=15000; //so reenable timeout pdca_load_channel(USB_USART_RX_PDCA_CHANNEL, (&host_USART_buffer),(uint32_t)(sizeof(host_USART_buffer))); pdca_enable(USB_USART_RX_PDCA_CHANNEL); spi_selectChip(SD_MMC_SPI, SD_MMC_SPI_NPCS); while(check_busy_fast()!=0xFF); spi_unselectChip(SD_MMC_SPI, SD_MMC_SPI_NPCS); my_SD_SPI_block_write_multi(bank0,experiment_base_address,blocks_per_cluster); //write data to SD spi_selectChip(SD_MMC_SPI, SD_MMC_SPI_NPCS); while(check_busy_fast()!=0xFF); spi_unselectChip(SD_MMC_SPI, SD_MMC_SPI_NPCS); }
ISR(tpa6130_abdac_tx_pdca_int_handler, TPA6130_ABDAC_PDCA_IRQ_GROUP, TPA6130_ABDAC_PDCA_INT_LEVEL) { if (pdca_get_transfer_status(TPA6130_ABDAC_PDCA_CHANNEL) & PDCA_TRANSFER_COMPLETE) { pdca_disable_interrupt_transfer_complete(TPA6130_ABDAC_PDCA_CHANNEL); if (tpa6130_output_param.callback_opt & AUDIO_DAC_OUT_OF_SAMPLE_CB) tpa6130_output_param.callback(AUDIO_DAC_OUT_OF_SAMPLE_CB); } if (pdca_get_transfer_status(TPA6130_ABDAC_PDCA_CHANNEL) & PDCA_TRANSFER_COUNTER_RELOAD_IS_ZERO) { pdca_disable_interrupt_reload_counter_zero(TPA6130_ABDAC_PDCA_CHANNEL); if (tpa6130_output_param.callback_opt & AUDIO_DAC_RELOAD_CB) tpa6130_output_param.callback(AUDIO_DAC_RELOAD_CB); } }
void ms3_dac_mute(bool mute) { if (mute) { U32 save_dac_reload_callback_opt; // Mute all channels // ms3_write_reg(MS3_MUTE_VOL_CTRL, 0xAF); // Disable the reload callback function save_dac_reload_callback_opt = ms3_output_params.callback_opt; ms3_output_params.callback_opt = 0; // Disable the transfer complete interruption and wait until the transfer is complete pdca_disable_interrupt_reload_counter_zero(MS3_SSC_TX_PDCA_CHANNEL); while (!(pdca_get_transfer_status(MS3_SSC_TX_PDCA_CHANNEL) & PDCA_TRANSFER_COMPLETE)); // Re-enable the reload callback function ms3_output_params.callback_opt = save_dac_reload_callback_opt; // Set as gpio pin gpio_enable_gpio(MS3_GPIO_MAP, sizeof(MS3_GPIO_MAP) / sizeof(MS3_GPIO_MAP[0])); } else { // Re-enable the reload interrupt pdca_enable_interrupt_reload_counter_zero(MS3_SSC_TX_PDCA_CHANNEL); // Unmute all channels // ms3_write_reg(MS3_MUTE_VOL_CTRL, 0xA0); // Enable SSC interface gpio_enable_module(MS3_GPIO_MAP, sizeof(MS3_GPIO_MAP) / sizeof(MS3_GPIO_MAP[0])); } }
void aic23b_dac_flush(void) { pdca_disable_interrupt_transfer_complete(AIC23B_SSC_TX_PDCA_CHANNEL); pdca_disable_interrupt_reload_counter_zero(AIC23B_SSC_TX_PDCA_CHANNEL); while (!(pdca_get_transfer_status(AIC23B_SSC_TX_PDCA_CHANNEL) & PDCA_TRANSFER_COMPLETE)); }
__interrupt #endif static void aic23b_ssc_rx_pdca_int_handler(void) { if (pdca_get_transfer_status(AIC23B_SSC_RX_PDCA_CHANNEL) & PDCA_TRANSFER_COMPLETE) { pdca_disable_interrupt_transfer_complete(AIC23B_SSC_RX_PDCA_CHANNEL); if (aic23b_output_params.callback_opt & AUDIO_ADC_OUT_OF_SAMPLE_CB) aic23b_output_params.callback(AUDIO_ADC_OUT_OF_SAMPLE_CB); } if (pdca_get_transfer_status(AIC23B_SSC_RX_PDCA_CHANNEL) & PDCA_TRANSFER_COUNTER_RELOAD_IS_ZERO) { pdca_disable_interrupt_reload_counter_zero(AIC23B_SSC_RX_PDCA_CHANNEL); if (aic23b_output_params.callback_opt & AUDIO_ADC_RELOAD_CB) aic23b_output_params.callback(AUDIO_ADC_RELOAD_CB); } }
__interrupt #endif static void ms3_ssc_tx_pdca_int_handler(void) { if (pdca_get_transfer_status(MS3_SSC_TX_PDCA_CHANNEL) & PDCA_TRANSFER_COMPLETE) { pdca_disable_interrupt_transfer_complete(MS3_SSC_TX_PDCA_CHANNEL); if (ms3_output_params.callback_opt & AUDIO_DAC_OUT_OF_SAMPLE_CB) ms3_output_params.callback(AUDIO_DAC_OUT_OF_SAMPLE_CB); } if (pdca_get_transfer_status(MS3_SSC_TX_PDCA_CHANNEL) & PDCA_TRANSFER_COUNTER_RELOAD_IS_ZERO) { pdca_disable_interrupt_reload_counter_zero(MS3_SSC_TX_PDCA_CHANNEL); if (ms3_output_params.callback_opt & AUDIO_DAC_RELOAD_CB) ms3_output_params.callback(AUDIO_DAC_RELOAD_CB); } }
bool aic23b_adc_input(void *sample_buffer, size_t sample_length) { if (!(pdca_get_transfer_status(AIC23B_SSC_RX_PDCA_CHANNEL) & PDCA_TRANSFER_COUNTER_RELOAD_IS_ZERO)) return false; if (sample_length) { pdca_reload_channel(AIC23B_SSC_RX_PDCA_CHANNEL, sample_buffer, sample_length * 2); pdca_get_reload_size(AIC23B_SSC_RX_PDCA_CHANNEL); if (aic23b_output_params.callback_opt & AUDIO_ADC_OUT_OF_SAMPLE_CB) pdca_enable_interrupt_transfer_complete(AIC23B_SSC_RX_PDCA_CHANNEL); if (aic23b_output_params.callback_opt & AUDIO_ADC_RELOAD_CB) pdca_enable_interrupt_reload_counter_zero(AIC23B_SSC_RX_PDCA_CHANNEL); } return true; }
void aic23b_dac_start(uint32_t sample_rate_hz, uint8_t num_channels, uint8_t bits_per_sample, bool swap_channels, void (*callback)(uint32_t arg), uint32_t callback_opt, uint32_t pba_hz) { #if AIC23B_CTRL_INTERFACE == AIC23B_CTRL_INTERFACE_SPI static const spi_options_t AIC23B_SPI_OPTIONS = { .reg = AIC23B_SPI_NPCS, .baudrate = AIC23B_SPI_MASTER_SPEED, .bits = AIC23B_CTRL_SIZE, .spck_delay = 0, .trans_delay = 0, .stay_act = 0, .spi_mode = 3, .modfdis = 1 }; spi_setupChipReg(AIC23B_SPI, &AIC23B_SPI_OPTIONS, pba_hz); #endif aic23b_dac_stop(); gpio_enable_module(AIC23B_SSC_DAC_GPIO_MAP, sizeof(AIC23B_SSC_DAC_GPIO_MAP) / sizeof(AIC23B_SSC_DAC_GPIO_MAP[0])); aic23b_pdc_t pdc; pdc.data = AIC23B_DEFAULT(AIC23B_PDC); pdc.off = 0; pdc.clk = 0; pdc.osc = 0; pdc.out = 0; pdc.dac = 0; pdc.adc = 1; pdc.mic = 1; pdc.line = 1; aic23b_set_power_down_state(pdc); aic23b_dac_setup(sample_rate_hz, num_channels, bits_per_sample, swap_channels, callback, callback_opt, pba_hz); aic23b_aapc_t aapc; aapc.data = AIC23B_DEFAULT(AIC23B_AAPC); aapc.ste = 0; aapc.dac = 1; aapc.byp = 0; aapc.micm = 1; aapc.micb = 0; aic23b_set_analog_audio_path(aapc); aic23b_dapc_t dapc; dapc.data = AIC23B_DEFAULT(AIC23B_DAPC); dapc.dacm = 0; dapc.deemp = AIC23B_DAPC_DEEMP_NONE; dapc.adchp = 1; aic23b_set_digital_audio_path(dapc); // set an acceptable start volume aic23b_set_headphone_volume(AIC23B_LEFT_CHANNEL | AIC23B_RIGHT_CHANNEL, -30, true); aic23b_activate_dig_audio(true); INTC_register_interrupt(&aic23b_ssc_tx_pdca_int_handler, AIC23B_SSC_TX_PDCA_IRQ, AIC23B_SSC_TX_PDCA_INT_LEVEL); } void aic23b_dac_setup(uint32_t sample_rate_hz, uint8_t num_channels, uint8_t bits_per_sample, bool swap_channels, void (*callback)(uint32_t arg), uint32_t callback_opt, uint32_t pba_hz) { #if defined(AIC23B_DAC_USE_RX_CLOCK) && AIC23B_DAC_USE_RX_CLOCK == true #if defined(AIC23B_DAC_RX_CLOCK_SET_CALLBACK) AIC23B_DAC_RX_CLOCK_SET_CALLBACK(2 * sample_rate_hz * ((bits_per_sample <= 16) ? 16 : (bits_per_sample <= 20) ? 20 : (bits_per_sample <= 24) ? 24 : 32)); #endif ssc_i2s_init(AIC23B_SSC, sample_rate_hz, bits_per_sample, (bits_per_sample <= 16) ? 16 : (bits_per_sample <= 20) ? 20 : (bits_per_sample <= 24) ? 24 : 32, SSC_I2S_MODE_STEREO_OUT_EXT_CLK, pba_hz); #else ssc_i2s_init(AIC23B_SSC, sample_rate_hz, bits_per_sample, (bits_per_sample <= 16) ? 16 : (bits_per_sample <= 20) ? 20 : (bits_per_sample <= 24) ? 24 : 32, SSC_I2S_MODE_STEREO_OUT, pba_hz); #endif pdca_channel_options_t aic23b_ssc_pdca_options = { .addr = NULL, .size = 0, .r_addr = NULL, .r_size = 0, .pid = AIC23B_SSC_TX_PDCA_PID, .transfer_size = (bits_per_sample <= 8) ? PDCA_TRANSFER_SIZE_BYTE : (bits_per_sample <= 16) ? PDCA_TRANSFER_SIZE_HALF_WORD : PDCA_TRANSFER_SIZE_WORD }; pdca_init_channel(AIC23B_SSC_TX_PDCA_CHANNEL, &aic23b_ssc_pdca_options); pdca_enable(AIC23B_SSC_TX_PDCA_CHANNEL); #if !defined(AIC23B_DAC_USE_RX_CLOCK) || AIC23B_DAC_USE_RX_CLOCK == false || \ !defined(AIC23B_DAC_RX_CLOCK_SET_CALLBACK) // Set DAC frequency aic23b_configure_freq(AIC23B_MCLK_HZ, sample_rate_hz); #endif aic23b_daif_t daif; daif.data = AIC23B_DEFAULT(AIC23B_DAIF); daif.ms = AIC23B_DAIF_MS_SLAVE; daif.lrswap = swap_channels; daif.lrp = 0; daif.iwl = (bits_per_sample <= 16) ? AIC23B_DAIF_IWL_16 : (bits_per_sample <= 20) ? AIC23B_DAIF_IWL_20 : (bits_per_sample <= 24) ? AIC23B_DAIF_IWL_24 : AIC23B_DAIF_IWL_32; daif.fmt = AIC23B_DAIF_FMT_I2S; aic23b_write_reg(AIC23B_DAIF, daif.data); aic23b_output_params.num_channels = num_channels; aic23b_output_params.callback = callback; aic23b_output_params.callback_opt = callback_opt; } #endif bool aic23b_dac_output(void *sample_buffer, size_t sample_length) { bool global_interrupt_enabled; if (!(pdca_get_transfer_status(AIC23B_SSC_TX_PDCA_CHANNEL) & PDCA_TRANSFER_COUNTER_RELOAD_IS_ZERO)) return false; if (sample_length) { if (aic23b_output_params.num_channels == 1) { int16_t *s16_sample_buffer = sample_buffer; int i; for (i = sample_length - 1; i >= 0; i--) { s16_sample_buffer[2 * i + 1] = s16_sample_buffer[2 * i] = s16_sample_buffer[i]; } } // The PDCA is not able to synchronize its start of transfer with the SSC // start of period, so this has to be done by polling the TF pin. // Not doing so may result in channels being swapped randomly. if ((global_interrupt_enabled = Is_global_interrupt_enabled())) Disable_global_interrupt(); if (pdca_get_transfer_status(AIC23B_SSC_TX_PDCA_CHANNEL) & PDCA_TRANSFER_COMPLETE) { while (gpio_get_pin_value(AIC23B_SSC_TX_FRAME_SYNC_PIN)); while (!gpio_get_pin_value(AIC23B_SSC_TX_FRAME_SYNC_PIN)); } pdca_reload_channel(AIC23B_SSC_TX_PDCA_CHANNEL, sample_buffer, sample_length * 2); pdca_get_reload_size(AIC23B_SSC_TX_PDCA_CHANNEL); if (global_interrupt_enabled) Enable_global_interrupt(); if (aic23b_output_params.callback_opt & AUDIO_DAC_OUT_OF_SAMPLE_CB) pdca_enable_interrupt_transfer_complete(AIC23B_SSC_TX_PDCA_CHANNEL); if (aic23b_output_params.callback_opt & AUDIO_DAC_RELOAD_CB) pdca_enable_interrupt_reload_counter_zero(AIC23B_SSC_TX_PDCA_CHANNEL); } return true; }
void idle(void) { while(1) { uint8_t tempmode=0; while(tempmode==0) //wait until a command has been received { if(lcdinit==false) //check for LCD { if(detect_lcd()==true) { usart_write_line(LCD_USART, "play modesel\r\n"); lcdinit=true; } } tempmode=idle_getmode(); } uint8_t tempsd=check_SD(); switch(tempmode) { case start_hostmode: if(tempsd!=SD_card_valid) { usart_write_line(USB_USART, "bad SD card\n"); } else { usart_write_line(USB_USART, "good SD card\n"); hostmode_run(); //go to host execution } break; case select_standalone: if(tempsd==SD_card_valid) { //valid SD card detected //retrieve experiment from SD card my_SD_read_experiment_PDCA(experiment_base_address,(uint32_t)(&experiment.MODE), (uint32_t)(&bank0[0]), sizeof(experiment), blocks_per_cluster); if(validate_sequences()==false) { //sequence was not valid usart_write_line(LCD_USART, "play badexp\r\n"); while(strcmp(get_LCD_cmd(),"BR2\r")!=0); usart_write_line(LCD_USART, "play modesel\r\n"); } else { //sequence was valid usart_write_line(LCD_USART, "play goodexp\r\n"); while(strcmp(get_LCD_cmd(),"BR2\r")!=0); standalone_mode_run(); //re-enable USB USART to receive commands from host pdca_load_channel(USB_USART_RX_PDCA_CHANNEL, (&host_USART_buffer),(uint32_t)(sizeof(host_USART_buffer))); pdca_enable(USB_USART_RX_PDCA_CHANNEL); USB_USART->cr|=AVR32_USART_CR_STTTO_MASK; //set to not start counting again until after new character is received USB_USART->rtor=15000; //baud rate is 3mbaud, so 15000 gives 5ms timeout usart_write_line(LCD_USART, "play modesel\r\n"); //will eventually have branch here to cancel, examine experiment, or proceed } } else if(tempsd==SD_card_not_inserted) { //no SD card inserted usart_write_line(LCD_USART, "play noSD\r\n"); while(strcmp(get_LCD_cmd(),"BR2\r")!=0); usart_write_line(LCD_USART, "play modesel\r\n"); } else if(tempsd==SD_card_init_failed) { //SD card failed to init usart_write_line(LCD_USART, "play SDerr\r\n"); while(strcmp(get_LCD_cmd(),"BR2\r")!=0); usart_write_line(LCD_USART, "play modesel\r\n"); } else if(tempsd==SD_card_invalid) { //SD card init but not valid usart_write_line(LCD_USART, "play badSD\r\n"); while(strcmp(get_LCD_cmd(),"BR2\r")!=0); usart_write_line(LCD_USART, "play modesel\r\n"); } break; case select_checkSD: switch (tempsd) { case SD_card_valid: usart_write_line(LCD_USART, "play goodSD\r\n"); while(strcmp(get_LCD_cmd(),"BR2\r")!=0); usart_write_line(LCD_USART, "play modesel\r\n"); break; case SD_card_not_inserted: usart_write_line(LCD_USART, "play noSD\r\n"); while(strcmp(get_LCD_cmd(),"BR2\r")!=0); usart_write_line(LCD_USART, "play modesel\r\n"); break; case SD_card_init_failed: usart_write_line(LCD_USART, "play SDerr\r\n"); while(strcmp(get_LCD_cmd(),"BR2\r")!=0); usart_write_line(LCD_USART, "play modesel\r\n"); break; case SD_card_invalid: usart_write_line(LCD_USART, "play badSD\r\n"); while(strcmp(get_LCD_cmd(),"BR2\r")!=0); usart_write_line(LCD_USART, "play modesel\r\n"); break; } break; case program_experiment: if(tempsd!=SD_card_valid) { usart_write_line(USB_USART, "bad SD card\n"); } else { usart_write_line(USB_USART, "good SD card\n"); get_experiment_from_host_to_SD(); my_SD_read_experiment_PDCA(experiment_base_address,(uint32_t)(&experiment.MODE), (uint32_t)(&bank1[0]), sizeof(experiment), blocks_per_cluster); if(validate_sequences()==true) { usart_write_line(USB_USART, "goodexp\n"); } else { usart_write_line(USB_USART, "badexp\n"); } } break; case get_data: if(tempsd!=SD_card_valid) { usart_write_line(USB_USART, "bad SD card\n"); //if SD card is bad, say so and return } else {//if SD card is good, say so. Then read the experiment and validate it usart_write_line(USB_USART, "good SD card\n"); //this will read in entire first cluster of SD my_SD_read_experiment_PDCA(experiment_base_address,(uint32_t)(&experiment.MODE), (uint32_t)(&bank1[0]), sizeof(experiment), blocks_per_cluster); if(validate_sequences()==true) { //if experiment is valid, say so, then get true experiment usart_write_line(USB_USART, "goodexperiment\n"); gettruesequence(); //send entire cluster's worth of data to host. this will start with experiment and also include other "stuff" in the first cluster pdca_disable(USB_USART_TX_PDCA_CHANNEL);//goin to set up PDCA to send all of experiment, then start reading out bank1 until an entire cluster has been written my_pdca_init_channel(USB_USART_TX_PDCA_CHANNEL, (uint32_t)(&experiment.MODE),(uint32_t)(sizeof(experiment)), USB_USART_TX_PDCA_PID, (uint32_t)(&bank1[0]), (blocks_per_cluster*512-(uint32_t)(sizeof(experiment))), PDCA_TRANSFER_SIZE_BYTE); pdca_enable(USB_USART_TX_PDCA_CHANNEL); while(!(pdca_get_transfer_status(USB_USART_TX_PDCA_CHANNEL) & AVR32_PDCA_TRC_MASK)); //wait until transfer is done pdca_disable(USB_USART_TX_PDCA_CHANNEL); for(uint8_t i=0;i<Nsequences_max;i++) { usart_putchar(USB_USART,(uint8_t)(t_experiment.t_sequence[i].clusters_per_sequence)); } uint32_t SD_read_ptr=data_base_address; //now need to send actual data for(uint8_t i=0;i<t_experiment.N_experiments;i++) { for(uint8_t j=0;j<t_experiment.N_sequences;j++) { while(strcmp(get_HOST_cmd(),"SEND SEQUENCE\n")!=0); //wait for host to ask for each sequence send_data_to_host(SD_read_ptr,t_experiment.t_sequence[j].clusters_per_sequence); SD_read_ptr+=t_experiment.t_sequence[j].clusters_per_sequence*blocks_per_cluster*bytes_per_block; } } } else { usart_write_line(USB_USART, "badexperiment\n"); } } break; } } }
void ms3_dac_setup(U32 sample_rate_hz, U8 num_channels, U8 bits_per_sample, bool swap_channels, void (*callback)(U32 arg), U32 callback_opt, U32 pba_hz) { //configure clock if (sample_rate_hz < (8000 + 8021) / 2) { usb_stream_resync_frequency = 4096000; cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, CS2200_FREF)); } else if (sample_rate_hz < (8021 + 22050) / 2) { usb_stream_resync_frequency = 4106752; cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, CS2200_FREF)); } else if (sample_rate_hz < (22050 + 32000) / 2) { usb_stream_resync_frequency = 11289600; cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, CS2200_FREF)); } else if (sample_rate_hz < (32000 + 44100) / 2) { usb_stream_resync_frequency = 16384000; cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, CS2200_FREF)); } else if (sample_rate_hz < (44100 + 48000) / 2) { usb_stream_resync_frequency = 22579200; cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, CS2200_FREF)); } else if (sample_rate_hz < (48000 + 88200) / 2) { usb_stream_resync_frequency = 24576000; cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, CS2200_FREF)); } //configure ssc to use clock on TX_CLOCK pin AVR32_SSC.tcmr = (0 << AVR32_SSC_TCMR_CKO_OFFSET) | (1 << AVR32_SSC_TCMR_STTDLY_OFFSET) | (2 << AVR32_SSC_TCMR_CKS_OFFSET) | (7 << AVR32_SSC_TCMR_START_OFFSET) | (0x1f << AVR32_SSC_TCMR_PERIOD_OFFSET); AVR32_SSC.tfmr = (0xf << AVR32_SSC_TFMR_DATLEN_OFFSET) | (1 << AVR32_SSC_TFMR_MSBF_OFFSET) | (1 << AVR32_SSC_TFMR_FSOS_OFFSET) | (1 << AVR32_SSC_TFMR_FSLENHI_OFFSET) | (0xf << AVR32_SSC_TFMR_FSLEN_OFFSET); AVR32_SSC.cr = AVR32_SSC_CR_TXEN_MASK; //configure DMA pdca_channel_options_t ms3_ssc_pdca_options = { .addr = NULL, .size = 0, .r_addr = NULL, .r_size = 0, .pid = AVR32_PDCA_PID_SSC_TX, .transfer_size = (bits_per_sample <= 8)?PDCA_TRANSFER_SIZE_BYTE: (bits_per_sample <= 16)?PDCA_TRANSFER_SIZE_HALF_WORD: PDCA_TRANSFER_SIZE_WORD }; pdca_init_channel(MS3_SSC_TX_PDCA_CHANNEL, &ms3_ssc_pdca_options); pdca_enable(MS3_SSC_TX_PDCA_CHANNEL); //configure audio parameters ms3_output_params.num_channels = num_channels; ms3_output_params.callback = callback; ms3_output_params.callback_opt = callback_opt; } bool ms3_dac_output(void *sample_buffer, size_t sample_length) { bool global_interrupt_enabled; if (!(pdca_get_transfer_status(MS3_SSC_TX_PDCA_CHANNEL) & PDCA_TRANSFER_COUNTER_RELOAD_IS_ZERO)) return false; if (sample_length) { if (ms3_output_params.num_channels == 1) { S16 *s16_sample_buffer = sample_buffer; int i; for (i = sample_length - 1; i >= 0; i--) { s16_sample_buffer[2 * i + 1] = s16_sample_buffer[2 * i] = s16_sample_buffer[i]; } } // The PDCA is not able to synchronize its start of transfer with the SSC // start of period, so this has to be done by polling the TF pin. // Not doing so may result in channels being swapped randomly. if ((global_interrupt_enabled = Is_global_interrupt_enabled())) Disable_global_interrupt(); if (pdca_get_transfer_status(MS3_SSC_TX_PDCA_CHANNEL) & PDCA_TRANSFER_COMPLETE) { while (gpio_get_pin_value(MS3_SSC_TX_FRAME_SYNC_PIN)); while (!gpio_get_pin_value(MS3_SSC_TX_FRAME_SYNC_PIN)); } pdca_reload_channel(MS3_SSC_TX_PDCA_CHANNEL, sample_buffer, sample_length * 2); pdca_get_reload_size(MS3_SSC_TX_PDCA_CHANNEL); if (global_interrupt_enabled) Enable_global_interrupt(); if (ms3_output_params.callback_opt & AUDIO_DAC_OUT_OF_SAMPLE_CB) pdca_enable_interrupt_transfer_complete(MS3_SSC_TX_PDCA_CHANNEL); if (ms3_output_params.callback_opt & AUDIO_DAC_RELOAD_CB) pdca_enable_interrupt_reload_counter_zero(MS3_SSC_TX_PDCA_CHANNEL); } return true; }
void aic23b_codec_start(uint32_t sample_rate_hz, uint8_t num_channels, uint8_t bits_per_sample, bool swap_channels, void (*callback)(uint32_t arg), uint32_t callback_opt, uint32_t pba_hz) { #if AIC23B_CTRL_INTERFACE == AIC23B_CTRL_INTERFACE_SPI static const spi_options_t AIC23B_SPI_OPTIONS = { .reg = AIC23B_SPI_NPCS, .baudrate = AIC23B_SPI_MASTER_SPEED, .bits = AIC23B_CTRL_SIZE, .spck_delay = 0, .trans_delay = 0, .stay_act = 0, .spi_mode = 3, .modfdis = 1 }; spi_setupChipReg(AIC23B_SPI, &AIC23B_SPI_OPTIONS, pba_hz); #endif aic23b_codec_stop(); gpio_enable_module(AIC23B_SSC_CODEC_GPIO_MAP, sizeof(AIC23B_SSC_CODEC_GPIO_MAP) / sizeof(AIC23B_SSC_CODEC_GPIO_MAP[0])); aic23b_pdc_t pdc; pdc.data = AIC23B_DEFAULT(AIC23B_PDC); pdc.off = 0; pdc.clk = 0; pdc.osc = 0; pdc.out = 0; pdc.dac = 0; pdc.adc = 0; #if (AIC23B_INPUT==AIC23B_INPUT_LINE) pdc.mic = 1; pdc.line = 0; #elif (AIC23B_INPUT==AIC23B_INPUT_MIC) pdc.mic = 0; pdc.line = 1; #else #error No Input defined in file 'conf_tlv320aic23b.h' #endif aic23b_set_power_down_state(pdc); aic23b_codec_setup(sample_rate_hz, num_channels, bits_per_sample, swap_channels, callback, callback_opt, pba_hz); aic23b_aapc_t aapc; aapc.data = AIC23B_DEFAULT(AIC23B_AAPC); #if (AIC23B_INPUT==AIC23B_INPUT_LINE) aapc.ste = 0; aapc.dac = 1; aapc.byp = 0; aapc.insel = 0; aapc.micm = 0; aapc.micb = 1; #elif (AIC23B_INPUT==AIC23B_INPUT_MIC) aapc.ste = 0; aapc.dac = 1; aapc.sta = 4; aapc.byp = 0; aapc.insel = 1; aapc.micm = 0; aapc.micb = 1; #else #error No Input defined in file 'conf_tlv320aic23b.h' #endif aic23b_set_analog_audio_path(aapc); aic23b_dapc_t dapc; dapc.data = AIC23B_DEFAULT(AIC23B_DAPC); dapc.dacm = 0; dapc.deemp = AIC23B_DAPC_DEEMP_NONE; dapc.adchp = 0; aic23b_set_digital_audio_path(dapc); aic23b_llicvc_t llivc; llivc.data = AIC23B_DEFAULT(AIC23B_LLICVC); llivc.liv = 20; llivc.lim = 0; llivc.lrs = 1; aic23b_write_reg(AIC23B_LLICVC, llivc.data); aic23b_rlicvc_t rlivc; rlivc.data = AIC23B_DEFAULT(AIC23B_RLICVC); rlivc.riv = 20; rlivc.rim = 0; rlivc.rls = 1; aic23b_write_reg(AIC23B_RLICVC, rlivc.data); INTC_register_interrupt(&aic23b_ssc_rx_pdca_int_handler, AIC23B_SSC_RX_PDCA_IRQ, AIC23B_SSC_RX_PDCA_INT_LEVEL); // set an acceptable start volume aic23b_set_headphone_volume(AIC23B_LEFT_CHANNEL | AIC23B_RIGHT_CHANNEL, -30, true); aic23b_activate_dig_audio(true); INTC_register_interrupt(&aic23b_ssc_tx_pdca_int_handler, AIC23B_SSC_TX_PDCA_IRQ, AIC23B_SSC_TX_PDCA_INT_LEVEL); } void aic23b_codec_setup(uint32_t sample_rate_hz, uint8_t num_channels, uint8_t bits_per_sample, bool swap_channels, void (*callback)(uint32_t opt), uint32_t callback_opt, uint32_t pba_hz) { uint32_t master_clock = AIC23B_MCLK_HZ; // default configuration // Change the CPU frequency // //Disable_global_interrupt(); // Switch to OSC0 during OSC1 transition //pm_switch_to_osc0(&AVR32_PM, FOSC0, OSC0_STARTUP); // Switch to PLL0 as the master clock //pm_switch_to_clock(&AVR32_PM, AVR32_PM_MCCTRL_MCSEL_PLL0); if (sample_rate_hz < (8000 + 8021) / 2) { // 8000 Hz } else if (sample_rate_hz < (8021 + 32000) / 2) { // 8021 Hz } else if (sample_rate_hz < (32000 + 44100) / 2) { // 32000 Hz master_clock = usb_stream_resync_frequency = 8192000; cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, FOSC0)); pba_hz = FCPU_HZ = FHSB_HZ = FPBA_HZ = FPBB_HZ = FMCK_HZ(8192000); } else if (sample_rate_hz < (44100 + 48000) / 2) { // 44100 Hz master_clock = usb_stream_resync_frequency = 11289600; cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, FOSC0)); pba_hz = FCPU_HZ = FHSB_HZ = FPBA_HZ = FPBB_HZ = FMCK_HZ(11289600); } else if (sample_rate_hz < (48000 + 88200) / 2) { // 48000 Hz master_clock = usb_stream_resync_frequency = 12288000; cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, FOSC0)); pba_hz = FCPU_HZ = FHSB_HZ = FPBA_HZ = FPBB_HZ = FMCK_HZ(12288000); } else if (sample_rate_hz < (88200 + 96000) / 2) { // 88200 Hz } else { // 96000 Hz } //Enable_global_interrupt(); ssc_i2s_init(AIC23B_SSC, sample_rate_hz, bits_per_sample, (bits_per_sample <= 16) ? 16 : (bits_per_sample <= 20) ? 20 : (bits_per_sample <= 24) ? 24 : 32, SSC_I2S_MODE_STEREO_OUT_STEREO_IN, pba_hz); pdca_channel_options_t aic23b_ssc_pdca_options_rx = { .addr = NULL, .size = 0, .r_addr = NULL, .r_size = 0, .pid = AIC23B_SSC_RX_PDCA_PID, .transfer_size = (bits_per_sample <= 8) ? PDCA_TRANSFER_SIZE_BYTE : (bits_per_sample <= 16) ? PDCA_TRANSFER_SIZE_HALF_WORD : PDCA_TRANSFER_SIZE_WORD }; pdca_init_channel(AIC23B_SSC_RX_PDCA_CHANNEL, &aic23b_ssc_pdca_options_rx); pdca_enable(AIC23B_SSC_RX_PDCA_CHANNEL); pdca_channel_options_t aic23b_ssc_pdca_options_tx = { .addr = NULL, .size = 0, .r_addr = NULL, .r_size = 0, .pid = AIC23B_SSC_TX_PDCA_PID, .transfer_size = (bits_per_sample <= 8) ? PDCA_TRANSFER_SIZE_BYTE : (bits_per_sample <= 16) ? PDCA_TRANSFER_SIZE_HALF_WORD : PDCA_TRANSFER_SIZE_WORD }; pdca_init_channel(AIC23B_SSC_TX_PDCA_CHANNEL, &aic23b_ssc_pdca_options_tx); pdca_enable(AIC23B_SSC_TX_PDCA_CHANNEL); // Set codec frequency aic23b_configure_freq(master_clock, sample_rate_hz); aic23b_daif_t daif; daif.data = AIC23B_DEFAULT(AIC23B_DAIF); daif.ms = AIC23B_DAIF_MS_SLAVE; daif.lrswap = swap_channels; daif.lrp = 0; daif.iwl = (bits_per_sample <= 16) ? AIC23B_DAIF_IWL_16 : (bits_per_sample <= 20) ? AIC23B_DAIF_IWL_20 : (bits_per_sample <= 24) ? AIC23B_DAIF_IWL_24 : AIC23B_DAIF_IWL_32; daif.fmt = AIC23B_DAIF_FMT_I2S; aic23b_write_reg(AIC23B_DAIF, daif.data); aic23b_output_params.num_channels = num_channels; aic23b_output_params.callback = callback; aic23b_output_params.callback_opt = callback_opt; } void aic23b_codec_flush(void) { pdca_disable_interrupt_transfer_complete(AIC23B_SSC_RX_PDCA_CHANNEL); while (!(pdca_get_transfer_status(AIC23B_SSC_RX_PDCA_CHANNEL) & PDCA_TRANSFER_COMPLETE)); pdca_disable_interrupt_transfer_complete(AIC23B_SSC_TX_PDCA_CHANNEL); while (!(pdca_get_transfer_status(AIC23B_SSC_TX_PDCA_CHANNEL) & PDCA_TRANSFER_COMPLETE)); } void aic23b_codec_stop(void) { aic23b_codec_flush(); aic23b_reset(); aic23b_pdc_t pdc; pdc.data = AIC23B_DEFAULT(AIC23B_PDC); pdc.off = 1; pdc.clk = 1; pdc.osc = 1; pdc.out = 1; pdc.dac = 1; pdc.adc = 1; pdc.mic = 1; pdc.line = 1; aic23b_set_power_down_state(pdc); pdca_disable(AIC23B_SSC_RX_PDCA_CHANNEL); pdca_disable(AIC23B_SSC_TX_PDCA_CHANNEL); ssc_i2s_reset(AIC23B_SSC); gpio_enable_gpio(AIC23B_SSC_CODEC_GPIO_MAP, sizeof(AIC23B_SSC_CODEC_GPIO_MAP) / sizeof(AIC23B_SSC_CODEC_GPIO_MAP[0])); aic23b_output_params.num_channels = 0; aic23b_output_params.callback = NULL; aic23b_output_params.callback_opt = 0; }
/*! \brief Sets the DACs up with new settings. * * \note The DACs must have been started beforehand. */ void tpa6130_dac_setup(uint32_t sample_rate_hz, uint8_t num_channels, uint8_t bits_per_sample, bool swap_channels, void (*callback)(uint32_t arg), uint32_t callback_opt, uint32_t pba_hz) { // save input parameters to local driver data tpa6130_output_param.num_channels = num_channels; tpa6130_output_param.callback = callback; tpa6130_output_param.callback_opt = callback_opt; /* Probe for amplifier and initialize it */ tpa6130_init(); #if defined(TPA6130_DAC_CLOCK_SET_CALLBACK) TPA6130_DAC_CLOCK_SET_CALLBACK(sample_rate_hz); #else /* ABDAC configuration * The ABDAC needs the input frequency of its generic clock (bus_hz) * Here we use the configuration value from the conf_tpa6130.h file * (TPA6130_ABDAC_GCLK_INPUT_HZ). * The sample rate specifies the desired sample rate for the ABDAC. * The generic clock input must be greater than 256*sample_rate_hz * or the setup of the ABDAC will fail silently here. * TODO we could add asserts here to detect wrong settings during * compile time. */ if(!abdac_set_dac_sample_rate(sample_rate_hz)) { // if it is not possible to set correctly the sample rate // Use default set function abdac_set_dac_hz(TPA6130_ABDAC, TPA6130_ABDAC_GCLK_INPUT_HZ,sample_rate_hz); } #endif if(swap_channels) { abdac_swap_channels(TPA6130_ABDAC); } abdac_enable(TPA6130_ABDAC); /* PDCA setup */ /*FIXME we use only word as transfer size for now. * half-word transfer size will only write to channel0 * of the ABDAC, this can be used to implement mono */ pdca_channel_options_t tpa6130_abdac_pdca_options = { .addr = NULL, .size = 0, .r_addr = 0, .r_size = 0, .pid = TPA6130_ABDAC_PDCA_PID, .transfer_size = PDCA_TRANSFER_SIZE_WORD }; /* Initialize the PCDA for the ABDAC * The channel number can be set in the configuration file * with the define TPA6130_ABDAC_PDCA_CHANNEL. */ pdca_init_channel(TPA6130_ABDAC_PDCA_CHANNEL, &tpa6130_abdac_pdca_options); /* Enable the PDCA channel. Since we did not provide any data * yet the channel is in idle mode */ pdca_enable(TPA6130_ABDAC_PDCA_CHANNEL); } /*! \brief Outputs a sample buffer to the DACs. * The input requires a sample buffer that consists of words (32-bit) * which contain two (16-bit) samples, one for each channel. * * \note The DACs must have been started beforehand. */ bool tpa6130_dac_output(void *sample_buffer, size_t sample_length) { //int global_interrupt_enabled; /*Wait until the PDCA loads the reload value to its transfer * counter register(TCRR=0). Then we are ready to set up a new * transfer */ if(!(pdca_get_transfer_status(TPA6130_ABDAC_PDCA_CHANNEL) & PDCA_TRANSFER_COUNTER_RELOAD_IS_ZERO)) { return false; } /* Nothing to do if we get no data. */ if(sample_length) { /*TODO Do we really need to adjust the buffer for mono*/ /* While reloading the PDC we do not need any active interrupt*/ //if((global_interrupt_enabled = cpu_irq_is_enabled())) // cpu_irq_disable(); /*FIXME This assumes a stereo 16-bit sample size */ // one sample here consists of 2x16-bit (16-bit stereo) pdca_reload_channel(TPA6130_ABDAC_PDCA_CHANNEL, sample_buffer, sample_length); //if(global_interrupt_enabled) // cpu_irq_enable(); /*TODO enable transfer complete interrupt * Is it possible to move this to setup or other places?*/ if(tpa6130_output_param.callback_opt & AUDIO_DAC_OUT_OF_SAMPLE_CB) pdca_enable_interrupt_transfer_complete(TPA6130_ABDAC_PDCA_CHANNEL); if (tpa6130_output_param.callback_opt & AUDIO_DAC_RELOAD_CB) pdca_enable_interrupt_reload_counter_zero(TPA6130_ABDAC_PDCA_CHANNEL); } return true; } bool tpa6130_dac_is_volume_muted(void) { return false; } void tpa6130_dac_mute(bool mute) { // //1st Version Mute Audio for Play/Pause /* int volume=tpa6130_get_volume(); if(mute==true) { //Mute volume volume= volume|MUTE_L|MUTE_R; } else { //Unmute volume volume= volume&(~(MUTE_L|MUTE_R)); } tpa6130_write_data(TPA6130_VOLUME_AND_MUTE,volume); */ //2n Version Stop PDCA >> No lost of audio when pause /* if(mute==true) { pdca_disable(TPA6130_ABDAC_PDCA_CHANNEL); } else { pdca_enable(TPA6130_ABDAC_PDCA_CHANNEL); } */ // 3rd Version wait until the current buffers are empty and disable the interrupts int8_t volume = tpa6130_get_volume(); if (mute) { uint32_t save_dac_reload_callback_opt; // Mute the audio stream volume = volume | MUTE_L | MUTE_R; tpa6130_write_data(TPA6130_VOLUME_AND_MUTE, volume); // Disable the reload channel of the interrupt save_dac_reload_callback_opt = tpa6130_output_param.callback_opt; tpa6130_output_param.callback_opt = 0; // Disable the reload interruption and wait until the transfer is complete pdca_disable_interrupt_reload_counter_zero(TPA6130_ABDAC_PDCA_CHANNEL); while (!(pdca_get_transfer_status(TPA6130_ABDAC_PDCA_CHANNEL) & PDCA_TRANSFER_COMPLETE)); // Restore the reload callback function tpa6130_output_param.callback_opt = save_dac_reload_callback_opt; } else { // Re-enable the interrupts pdca_enable_interrupt_reload_counter_zero(TPA6130_ABDAC_PDCA_CHANNEL); // Un-mute the audio stream volume = volume & (~(MUTE_L | MUTE_R)); tpa6130_write_data(TPA6130_VOLUME_AND_MUTE, volume); } }
uint8_t check_SD(void) { if(SD_card_inserted()==false) { return SD_card_not_inserted; } spi_options_t SD_spiOptions = { .reg = SD_MMC_SPI_NPCS, .baudrate = SD_SPI_SPEED, // Defined in conf_sd_mmc_spi.h. .bits = 8, // Defined in conf_sd_mmc_spi.h. .spck_delay = 0, .trans_delay = 0, .stay_act = 1, .spi_mode = 0, .modfdis = 1 }; if(sd_mmc_spi_init(SD_spiOptions, PBA_SPEED)==false) { return SD_card_init_failed; } if(card_type!=SD_CARD_2_SDHC) { return SD_card_invalid; } return SD_card_valid; } bool SD_card_inserted(void) { if(gpio_get_pin_value(SD_detect_pin)==0) { return true; } else { return false; } } uint8_t hostmode_run(void) { //first receive and verify full experiment //set USB PDCA to store experiment USB_USART->rtor=0; //disable timeout pdca_disable(USB_USART_RX_PDCA_CHANNEL); my_pdca_init_channel(USB_USART_RX_PDCA_CHANNEL, (uint32_t)(&experiment.MODE),(uint32_t)(sizeof(experiment)), USB_USART_RX_PDCA_PID, 0, 0, PDCA_TRANSFER_SIZE_BYTE); pdca_enable(USB_USART_RX_PDCA_CHANNEL); while(!(pdca_get_transfer_status(USB_USART_RX_PDCA_CHANNEL) & AVR32_PDCA_TRC_MASK)); //wait until transfer is done if(validate_sequences()==false) { usart_write_line(USB_USART, "badexp\n"); usart_putchar(USB_USART,(uint8_t)(get_experiment_problem())); my_pdca_init_channel(USB_USART_RX_PDCA_CHANNEL, (uint32_t)(&host_USART_buffer),(uint32_t)(sizeof(host_USART_buffer)),USB_USART_RX_PDCA_PID,0,0, PDCA_TRANSFER_SIZE_BYTE); pdca_enable(USB_USART_RX_PDCA_CHANNEL); USB_USART->cr|=AVR32_USART_CR_STTTO_MASK; //set timeout to stop until new character is received USB_USART->rtor=15000; //set to timeout in 1ms return 0; } usart_write_line(USB_USART, "goodexp\n"); pdca_disable(USB_USART_TX_PDCA_CHANNEL); gettruesequence(); my_pdca_init_channel(USB_USART_TX_PDCA_CHANNEL, (uint32_t)(&experiment.MODE),(uint32_t)(sizeof(experiment)), USB_USART_TX_PDCA_PID, 0, 0, PDCA_TRANSFER_SIZE_BYTE); pdca_enable(USB_USART_TX_PDCA_CHANNEL); while(!(pdca_get_transfer_status(USB_USART_TX_PDCA_CHANNEL) & AVR32_PDCA_TRC_MASK)); //wait until transfer is done pdca_disable(USB_USART_TX_PDCA_CHANNEL); //change back USB USART to accept command tokens my_pdca_init_channel(USB_USART_RX_PDCA_CHANNEL, (uint32_t)(&host_USART_buffer),(uint32_t)(sizeof(host_USART_buffer)),USB_USART_RX_PDCA_PID,0,0, PDCA_TRANSFER_SIZE_BYTE); pdca_enable(USB_USART_RX_PDCA_CHANNEL); for(uint8_t i=0;i<Nsequences_max;i++) { usart_putchar(USB_USART,(uint8_t)(t_experiment.t_sequence[i].clusters_per_sequence)); } USB_USART->cr|=AVR32_USART_CR_STTTO_MASK; //set timeout to stop until new character is received USB_USART->rtor=15000; //set to timeout in 1ms reset_SD_sink_ptr(); uint32_t SD_read_ptr=data_base_address; DAC1->dr0=t_experiment.t_Vgain; //set gain of RF amp while(1) //once in host mode, this will run until a restart command is received { char *HOSTCMD="false"; while(strcmp(HOSTCMD,"false")==0) { HOSTCMD=get_HOST_cmd(); if(strcmp((HOSTCMD+1),"sequencetoken")==0) { uint8_t sequenceindex=*HOSTCMD; t_currentsequence=t_experiment.t_sequence[sequenceindex]; executesequence_SDstorage_multiprep_combined(); if(did_data_fail()) { usart_write_line(USB_USART, "fail\n"); usart_putchar(USB_USART,(uint8_t)(get_failure_cause())); usart_putchar(USB_USART,(uint8_t)(get_saved_r1())); } else { usart_write_line(USB_USART, "good\n"); send_data_to_host(SD_read_ptr,t_currentsequence.clusters_per_sequence); } SD_read_ptr+=t_currentsequence.clusters_per_sequence*blocks_per_cluster*bytes_per_block; //set back to command mode pdca_disable(USB_USART_RX_PDCA_CHANNEL); my_pdca_init_channel(USB_USART_RX_PDCA_CHANNEL, (uint32_t)(&host_USART_buffer),(uint32_t)(sizeof(host_USART_buffer)),USB_USART_RX_PDCA_PID,0,0, PDCA_TRANSFER_SIZE_BYTE); pdca_enable(USB_USART_RX_PDCA_CHANNEL); USB_USART->cr|=AVR32_USART_CR_STTTO_MASK; //set timeout to stop until new character is received USB_USART->rtor=15000; //set to timeout in 1ms } else if(strcmp((HOSTCMD),"RESTART\n")==0) { //want to handle start of new host mode experiment return 1; } } } return 1; }
void aic23b_adc_start(uint32_t sample_rate_hz, uint8_t num_channels, uint8_t bits_per_sample, bool swap_channels, void (*callback)(uint32_t arg), uint32_t callback_opt, uint32_t pba_hz) { #if AIC23B_CTRL_INTERFACE == AIC23B_CTRL_INTERFACE_SPI static const spi_options_t AIC23B_SPI_OPTIONS = { .reg = AIC23B_SPI_NPCS, .baudrate = AIC23B_SPI_MASTER_SPEED, .bits = AIC23B_CTRL_SIZE, .spck_delay = 0, .trans_delay = 0, .stay_act = 0, .spi_mode = 3, .modfdis = 1 }; spi_setupChipReg(AIC23B_SPI, &AIC23B_SPI_OPTIONS, pba_hz); #endif aic23b_adc_stop(); gpio_enable_module(AIC23B_SSC_ADC_GPIO_MAP, sizeof(AIC23B_SSC_ADC_GPIO_MAP) / sizeof(AIC23B_SSC_ADC_GPIO_MAP[0])); aic23b_pdc_t pdc; pdc.data = AIC23B_DEFAULT(AIC23B_PDC); pdc.off = 0; pdc.clk = 0; pdc.osc = 0; pdc.out = 0; pdc.dac = 1; pdc.adc = 0; #if (AIC23B_INPUT==AIC23B_INPUT_LINE) pdc.mic = 1; pdc.line = 0; #elif (AIC23B_INPUT==AIC23B_INPUT_MIC) pdc.mic = 0; pdc.line = 1; #else #error No Input defined in file 'conf_tlv320aic23b.h' #endif aic23b_set_power_down_state(pdc); aic23b_adc_setup(sample_rate_hz, num_channels, bits_per_sample, swap_channels, callback, callback_opt, pba_hz); aic23b_aapc_t aapc; aapc.data = AIC23B_DEFAULT(AIC23B_AAPC); #if (AIC23B_INPUT==AIC23B_INPUT_LINE) aapc.ste = 0; aapc.dac = 0; aapc.byp = 0; aapc.insel = 0; aapc.micm = 0; aapc.micb = 0; #elif (AIC23B_INPUT==AIC23B_INPUT_MIC) aapc.ste = 0; aapc.dac = 0; aapc.byp = 0; aapc.insel = 1; aapc.micm = 0; aapc.micb = 0; #else #error No Input defined in file 'conf_tlv320aic23b.h' #endif aic23b_set_analog_audio_path(aapc); aic23b_dapc_t dapc; dapc.data = AIC23B_DEFAULT(AIC23B_DAPC); dapc.dacm = 0; dapc.deemp = AIC23B_DAPC_DEEMP_NONE; dapc.adchp = 0; aic23b_set_digital_audio_path(dapc); aic23b_llicvc_t llivc; llivc.data = AIC23B_DEFAULT(AIC23B_LLICVC); llivc.liv = 20; llivc.lim = 0; llivc.lrs = 1; aic23b_write_reg(AIC23B_LLICVC, llivc.data); aic23b_rlicvc_t rlivc; rlivc.data = AIC23B_DEFAULT(AIC23B_RLICVC); rlivc.riv = 20; rlivc.rim = 0; rlivc.rls = 1; aic23b_write_reg(AIC23B_RLICVC, rlivc.data); INTC_register_interrupt(&aic23b_ssc_rx_pdca_int_handler, AIC23B_SSC_RX_PDCA_IRQ, AIC23B_SSC_RX_PDCA_INT_LEVEL); aic23b_activate_dig_audio(true); } void aic23b_adc_setup(uint32_t sample_rate_hz, uint8_t num_channels, uint8_t bits_per_sample, bool swap_channels, void (*callback)(uint32_t arg), callback_opt, uint32_t pba_hz) { ssc_i2s_init(AIC23B_SSC, sample_rate_hz, bits_per_sample, (bits_per_sample <= 16) ? 16 : (bits_per_sample <= 20) ? 20 : (bits_per_sample <= 24) ? 24 : 32, SSC_I2S_MODE_STEREO_IN, pba_hz); pdca_channel_options_t aic23b_ssc_pdca_options = { .addr = NULL, .size = 0, .r_addr = NULL, .r_size = 0, .pid = AIC23B_SSC_RX_PDCA_PID, .transfer_size = (bits_per_sample <= 8) ? PDCA_TRANSFER_SIZE_BYTE : (bits_per_sample <= 16) ? PDCA_TRANSFER_SIZE_HALF_WORD : PDCA_TRANSFER_SIZE_WORD }; pdca_init_channel(AIC23B_SSC_RX_PDCA_CHANNEL, &aic23b_ssc_pdca_options); pdca_enable(AIC23B_SSC_RX_PDCA_CHANNEL); // Set ADC frequency aic23b_configure_freq(AIC23B_MCLK_HZ, sample_rate_hz); aic23b_daif_t daif; daif.data = AIC23B_DEFAULT(AIC23B_DAIF); daif.ms = AIC23B_DAIF_MS_SLAVE; daif.lrswap = swap_channels; daif.lrp = 0; daif.iwl = (bits_per_sample <= 16) ? AIC23B_DAIF_IWL_16 : (bits_per_sample <= 20) ? AIC23B_DAIF_IWL_20 : (bits_per_sample <= 24) ? AIC23B_DAIF_IWL_24 : AIC23B_DAIF_IWL_32; daif.fmt = AIC23B_DAIF_FMT_I2S; aic23b_write_reg(AIC23B_DAIF, daif.data); aic23b_output_params.num_channels = num_channels; aic23b_output_params.callback = callback; aic23b_output_params.callback_opt = callback_opt; } void aic23b_adc_flush(void) { pdca_disable_interrupt_transfer_complete(AIC23B_SSC_RX_PDCA_CHANNEL); while (!(pdca_get_transfer_status(AIC23B_SSC_RX_PDCA_CHANNEL) & PDCA_TRANSFER_COMPLETE)); }
/****************************************************************************** rn42_init *//** @brief Initializes RN42 driver. @brief usart Pointer to the USART hardware structure the RN42 is on. @brief irq IRQ number to process interrupts on. @brief gpio_pin Pin connected to the RN42's status output. ******************************************************************************/ void rn42_init( volatile avr32_usart_t *usart, uint32_t irq, uint32_t gpio_pin) { static usart_options_t usart_options = { .baudrate = 115200, .charlength = 8, .paritytype = USART_NO_PARITY, .stopbits = USART_1_STOPBIT, .channelmode = USART_NORMAL_CHMODE }; static pdca_channel_options_t pdca_rx_options = { .pid = AVR32_PDCA_PID_USART3_RX, .addr = NULL, .size = 0, .r_addr = NULL, .r_size = 0, .transfer_size = PDCA_TRANSFER_SIZE_BYTE }; static pdca_channel_options_t pdca_tx_options = { .pid = AVR32_PDCA_PID_USART3_TX, .addr = NULL, .size = 0, .r_addr = NULL, .r_size = 0, .transfer_size = PDCA_TRANSFER_SIZE_BYTE }; /* Initialize the USART to use hardware handshaking. Without the handshaking, the RN42 has trouble keeping up when continuosly sending fairly small amounts of data. Note that when hardware handshaking is enabled, the PDCA must be used for receiving data. */ rn42_usart = usart; usart_serial_init(rn42_usart, &usart_options); rn42_usart->mr = (rn42_usart->mr & ~0xf) | 0x02; /* Register the ISR for USART's DMA completion IRQs. */ pdca_init_channel(PDCA_CHANNEL_RX, &pdca_rx_options); pdca_init_channel(PDCA_CHANNEL_TX, &pdca_tx_options); irq_register_handler(usart_isr, PDCA_IRQ, 0); setup_usart_rx_dma(bt_buf, sizeof(command_t)); usart_irq_enable(); pdca_enable(PDCA_CHANNEL_RX); pdca_enable(PDCA_CHANNEL_TX); /* Configure RN42 status GPIO. */ gpio_configure_pin(gpio_pin, GPIO_DIR_INPUT | GPIO_PULL_DOWN); gpio_disable_pin_pull_up(gpio_pin); rn42_status_pin = gpio_pin; } /****************************************************************************** rn42_connected *//** @brief Returns whether the RN42 is connected by examining the status GPIO. The RN42's status line appears to bounce, so this function takes care of debouncing it. ******************************************************************************/ static bool rn42_connected(void) { bool connected1; bool connected2; do { connected1 = gpio_pin_is_high(rn42_status_pin); delay_ms(50); connected2 = gpio_pin_is_high(rn42_status_pin); } while (connected1 != connected2); return connected1 & connected2; } /****************************************************************************** rn42_send_data *//** @brief Transmits data to a Bluetooth peer over the RN42 module. @param[in] buf Pointer to the data that should be sent. @param[in] size Number of bytes to send. ******************************************************************************/ void rn42_send_data(uint8_t *buf, uint32_t size) { uint32_t status; setup_usart_tx_dma(buf, size); while (true) { status = pdca_get_transfer_status(PDCA_CHANNEL_TX); if (status & PDCA_TRANSFER_COMPLETE) { break; } } } /****************************************************************************** send_response *//** @brief Sends a response packet to the host. @param[in] cmd_id The command ID we're responding to. @param[in] status The status code. @param[in] data Pointer to data to send to the PC. @param[in] data_length Number of bytes to send. ******************************************************************************/ static void send_response( uint8_t cmd_id, uint8_t status, uint8_t *data, uint32_t data_length) { response_t response = { {'C', 'C', 'M', 'D'}, cmd_id, status, }; storeBigU32(&response.data_length, data_length); rn42_send_data((uint8_t*) &response, sizeof(response)); rn42_send_data(data, data_length); }