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 Decreases the output volume of the amplifier by one step. * * Stops at the lowest possible volume. */ void tpa6130_dac_decrease_volume(void) { int8_t volume = tpa6130_get_volume()& (~(MUTE_L | MUTE_R));; if( volume > TPA6130_VOL_MIN ) --volume; tpa6130_set_volume( volume ); }
/*! \brief Increases the output volume of the amplifier by one step. * Stops at the maximum volume and thus does not wrap to the * lowest volume. */ void tpa6130_dac_increase_volume(void) { int8_t volume = tpa6130_get_volume()& (~(MUTE_L | MUTE_R)); if( volume < TPA6130_VOL_MIN ) volume = TPA6130_VOL_MIN; tpa6130_set_volume(volume+1); }
/*! \brief Returns the current volume of the DAC. * The volume is in the range 0 - 255 */ uint8_t tpa6130_dac_get_volume(void) { // return volume is num display step for LCD // volume scale is between 10 and 245 // 0 is -100db // 245 is max volume uint16_t raw_volume; raw_volume = (tpa6130_get_volume() & (~(MUTE_L | MUTE_R))); return (uint8_t) ((raw_volume * 255) / TPA6130_VOL_MAX); }
static bool state_machine_idle(enum state_function *state) { uint32_t frame_rate_ms; S8 volume; const S8 volume_inc = (TPA6130_VOL_MAX - TPA6130_VOL_MIN) / 20; switch (*state) { case STATE_FCT_IDLE: if (new_state_fct) { gui_set_selection(GUI_NO_SEL); gui_text_print(GUI_COMMENT_ID, TEXT_IDLE); } else { if (controller_wheel_right(1) || controller_wheel_left(1)) switch_state(STATE_SOURCE1); return false; } break; // Frame rate case STATE_FCT_FUNCTION1: frame_rate_ms = gui_get_update_fs(); if (controller_wheel_left(1) && frame_rate_ms < 1000) { if (!frame_rate_ms) frame_rate_ms = 40; else frame_rate_ms = 1000 / ((1000 / frame_rate_ms) - 1); new_state_fct = true; } else if (controller_wheel_right(1)) { if (frame_rate_ms <= 40) frame_rate_ms = 0; else frame_rate_ms = 1000 / ((1000 / frame_rate_ms) + 1); new_state_fct = true; } if (new_state_fct) { gui_change_update_fs(frame_rate_ms); if (frame_rate_ms) { gui_text_printf(GUI_COMMENT_ID, TEXT_FUNC1 "\n%i Frame(s)/s\n\n\n\n" TEXT_WHEEL, (1000 / frame_rate_ms)); } else gui_text_print(GUI_COMMENT_ID, TEXT_FUNC1 "\nMAX Frame(s)/s\n\n\n\n" TEXT_WHEEL); } break; // Volume case STATE_FCT_FUNCTION2: volume = tpa6130_get_volume(); if (volume < TPA6130_VOL_MIN) volume = TPA6130_VOL_MIN; if (controller_wheel_right(1)) { if (volume < TPA6130_VOL_MAX - volume_inc) volume += volume_inc; else volume = TPA6130_VOL_MAX; new_state_fct = true; } else if (controller_wheel_left(1)) { if (volume > TPA6130_VOL_MIN + volume_inc) volume -= volume_inc; else volume = TPA6130_VOL_MIN; new_state_fct = true; } if (new_state_fct) { tpa6130_set_volume(volume); gui_text_printf(GUI_COMMENT_ID, TEXT_FUNC2 "\nVolume %i%%\n\n\n\n" TEXT_WHEEL, ((int) volume * 100) / (TPA6130_VOL_MAX - TPA6130_VOL_MIN)); } break; /* extern U8 tpa6130_get_volume(void); extern void tpa6130_set_volume(U8 volume); */ case STATE_FCT_FUNCTION3: if (new_state_fct) gui_text_print(GUI_COMMENT_ID, TEXT_FUNC_NOT_IMPLEMENTED); else if (controller_wheel_right(1) || controller_wheel_left(1)) { switch_state(STATE_SOURCE1); return false; } break; case STATE_FCT_ZOOM: break; } return true; }
/*! \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)); } }