void dsp_process_init(int cpu_hz, int hsb_hz, int pba_hz, int pbb_hz) { // Initialize TPA6130 tpa6130_init(); // Initialize DAC that send audio to TPA6130 tpa6130_dac_start(DAC_SAMPLING_RATE, DAC_NUM_CHANNELS, DAC_BITS_PER_SAMPLE, DAC_SWAP_CHANNELS, audio_callback, AUDIO_DAC_RELOAD_CB, FOSC0); tpa6130_set_volume(0x20); tpa6130_get_volume(); signal_source_init(&signal1_generator, 433, 20000); signal_source_init(&signal2_generator, 2000, 10000); current_stereo_out_buf = stereo_out_buf1; signal_in_buf = signal_pre_filter_buf + FIR_NUM_COEF; filter_restore_default(); /* Fill the initial buffer for the hamming window with ones. This buffer * will then be multiplied by the hamming window. */ dsp16_gen_step(fft_window, BUFFER_LENGTH, DSP16_Q(1.), DSP16_Q(1.), 0); dsp16_win_hamm(fft_window, fft_window, BUFFER_LENGTH); /* Run the interrupt handler manually once to start the ABDAC */ dac_reload_callback(); }
/*! \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); } }
/*! main function */ int main(void) { init_sys_clocks(); // Initialize RS232 debug text output. init_dbg_rs232(FOSC0); print_dbg(MSG_WELCOME); // Enable LED0 and LED1 gpio_enable_gpio_pin(LED0_GPIO); gpio_enable_gpio_pin(LED1_GPIO); // Configure TWI as master twi_init(); // Initialize TPA6130 tpa6130_init(); // Initialize DAC that send audio to TPA6130 tpa6130_dac_start(DEFAULT_DAC_SAMPLE_RATE_HZ, DEFAULT_DAC_NUM_CHANNELS, DEFAULT_DAC_BITS_PER_SAMPLE, DEFAULT_DAC_SWAP_CHANNELS, master_callback, AUDIO_DAC_OUT_OF_SAMPLE_CB | AUDIO_DAC_RELOAD_CB, FOSC0); tpa6130_set_volume(0x2F); tpa6130_get_volume(); int count = 0; int i=0; while(true) { count = 0; // Store sample from the sound_table array while(count < (SOUND_SAMPLES)){ samples[count++] = ((uint8_t)sound_table[i]+0x80) << 8; samples[count++] = ((uint8_t)sound_table[i]+0x80) << 8; i++; if (i >= sizeof(sound_table)) i = 0; } gpio_set_gpio_pin(LED0_GPIO); gpio_clr_gpio_pin(LED1_GPIO); // Play buffer tpa6130_dac_output((void *) samples,SOUND_SAMPLES/2); gpio_clr_gpio_pin(LED0_GPIO); gpio_set_gpio_pin(LED1_GPIO); /* Wait until the reload register is empty. * This means that one transmission is still ongoing * but we are already able to set up the next transmission */ while(!tpa6130_dac_output(NULL, 0)); } }