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) { 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(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_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; }
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; }