void CodecController::init(ApplicationSettings& settings){ // void CodecController::init(uint32_t frequency, I2SProtocol protocol, I2SFormat format, bool master){ // setPin(GPIOA, GPIO_Pin_6); // DEBUG // settings.audio_samplingrate = frequency; // settings.audio_protocol = protocol; // settings.audio_format = format; // settings.audio_codec_master = master; /* configure codec */ setCodecMaster(settings.audio_codec_master); setCodecProtocol(settings.audio_codec_protocol); setCodecFormat(settings.audio_codec_format); /* Configure the I2S peripheral */ if(Codec_AudioInterface_Init(settings.audio_samplingrate, settings.audio_codec_master, settings.audio_codec_protocol, settings.audio_codec_format) != 0) assert_param(false); setInputGainLeft(settings.inputGainLeft); setInputGainRight(settings.inputGainRight); setOutputGainLeft(settings.outputGainLeft); setOutputGainRight(settings.outputGainRight); I2S_Block_Init(); // clearPin(GPIOA, GPIO_Pin_6); // DEBUG }
/** * @brief Calls lower layer update functions. * @param Opt0: The value of this parameter depend on the lower layer implementation. * @param Opt1: The value of this parameter depend on the lower layer implementation. * @param Opt2: The value of this parameter depend on the lower layer implementation. * @param Opt3: The value of this parameter depend on the lower layer implementation. * @retval None */ uint32_t AUDIO_CORR_Out_Update (uint32_t Opt0, uint32_t Opt1, uint32_t Opt2, uint32_t Opt3) { uint32_t result = 0; #if (AUDIO_SYNCHRO_CLKSYNTH_ENABLED == 1) if (OutActiveMethod == SYNCH_EXTCLK) { /* Update the hardware with the new configuration */ Codec_AudioInterface_Init(Opt0, (uint32_t)(Opt0 * 256 * 4)); result += OutMethTab[OutActiveMethod]->Update((uint32_t)(Opt0 * 256 * 4), Opt1, Opt2, Opt3); } else { #endif /* AUDIO_SYNCHRO_CLKSYNTH_ENABLED */ /* Update the hardware with the new configuration */ Codec_AudioInterface_Init(Opt0, 0); #if (AUDIO_SYNCHRO_CLKSYNTH_ENABLED == 1) } #endif /* AUDIO_SYNCHRO_CLKSYNTH_ENABLED */ return result; }
/** * @brief Stops audio stream playing on the used Media. * @param None. * @retval None. */ void Audio_MAL_Stop(void) { /* Stop the Transfer on the I2S side: Stop and disable the DMA stream */ DMA_Cmd(AUDIO_MAL_DMA_CHANNEL, DISABLE); /* Clear all the DMA flags for the next transfer */ DMA_ClearFlag(AUDIO_MAL_DMA_FLAG_ALL); /* Stop the current DMA request by resetting the I2S cell */ Codec_AudioInterface_DeInit(); /* Re-configure the I2S interface for the next paly operation */ Codec_AudioInterface_Init(I2S_InitStructure.I2S_AudioFreq); }
/** * @brief Stops audio stream playing on the used Media. * @param None. * @retval None. */ void Audio_MAL_Stop(void) { /* Stop the Transfer on the I2S side: Stop and disable the DMA stream */ DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE); /* Clear all the DMA flags for the next transfer */ DMA_ClearFlag(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TC |AUDIO_MAL_DMA_FLAG_HT | \ AUDIO_MAL_DMA_FLAG_FE | AUDIO_MAL_DMA_FLAG_TE); /* Wait the DMA Stream to be effectively disabled */ while (DMA_GetCmdStatus(AUDIO_MAL_DMA_STREAM) != DISABLE) {} /* Stop the current DMA request by resetting the I2S cell */ Codec_AudioInterface_DeInit(); /* Re-configure the I2S interface for the next paly operation */ Codec_AudioInterface_Init(I2S_InitStructure.I2S_AudioFreq); }
void CodecController::init(ApplicationSettings& settings){ // setPin(GPIOA, GPIO_Pin_6); // DEBUG /* configure codec */ setCodecMaster(settings.audio_codec_master); setCodecProtocol(settings.audio_codec_protocol); setCodecFormat(settings.audio_codec_format); /* Configure the I2S peripheral */ if(Codec_AudioInterface_Init(settings.audio_samplingrate, settings.audio_codec_master, settings.audio_codec_protocol, settings.audio_codec_format) != 0) assert_param(false); setInputGainLeft(settings.inputGainLeft); setInputGainRight(settings.inputGainRight); setOutputGainLeft(settings.outputGainLeft); setOutputGainRight(settings.outputGainRight); I2S_Block_Init(tx_buffer, rx_buffer, settings.audio_blocksize); setBlocksize(settings.audio_blocksize); // clearPin(GPIOA, GPIO_Pin_6); // DEBUG }
/** * @brief Pauses or Resumes the audio stream playing from the Media. * @param Cmd: AUDIO_PAUSE (or 0) to pause, AUDIO_RESUME (or any value different * from 0) to resume. * @param Addr: Address from/at which the audio stream should resume/pause. * @param Size: Number of data to be configured for next resume. * @retval None. */ void Audio_MAL_PauseResume(uint32_t Cmd, uint32_t Addr, uint32_t Size) { /* Pause the audio file playing */ if (Cmd == AUDIO_PAUSE) { /* Stop the current DMA request by resetting the I2S cell */ Codec_AudioInterface_DeInit(); /* Re-configure the I2S interface for the next resume operation */ Codec_AudioInterface_Init(I2S_InitStructure.I2S_AudioFreq); /* Disable the DMA Stream */ DMA_Cmd(AUDIO_MAL_DMA_CHANNEL, DISABLE); /* Clear the Interrupt flag */ DMA_ClearFlag(AUDIO_MAL_DMA_FLAG_ALL); } else /* AUDIO_RESUME */ { /* Configure the buffer address and size */ DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Addr; DMA_InitStructure.DMA_BufferSize = (uint32_t)(Size*2); /* Configure the DMA Stream with the new parameters */ DMA_Init(AUDIO_MAL_DMA_CHANNEL, &DMA_InitStructure); /* Enable the I2S DMA Stream*/ DMA_Cmd(AUDIO_MAL_DMA_CHANNEL, ENABLE); /* If the I2S peripheral is still not enabled, enable it */ if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0) { I2S_Cmd(CODEC_I2S, ENABLE); } } }
/** * @brief Initializes the audio codec and all related interfaces (control * interface: I2C and audio interface: I2S) * @param OutputDevice: can be OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, * OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO . * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) * @param AudioFreq: Audio frequency used to paly the audio stream. * @retval o if correct communication, else wrong communication */ uint32_t Codec_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) { uint32_t counter = 0; /* Configure the Codec related IOs */ Codec_GPIO_Init(); /* Reset the Codec Registers */ Codec_Reset(); /* Initialize the Control interface of the Audio Codec */ Codec_CtrlInterface_Init(); /* Keep Codec powered OFF */ counter += Codec_WriteRegister(0x02, 0x01); switch (OutputDevice) { case OUTPUT_DEVICE_SPEAKER: counter += Codec_WriteRegister(0x04, 0xFA); /* SPK always ON & HP always OFF */ OutputDev = 0xFA; break; case OUTPUT_DEVICE_HEADPHONE: counter += Codec_WriteRegister(0x04, 0xAF); /* SPK always OFF & HP always ON */ OutputDev = 0xAF; break; case OUTPUT_DEVICE_BOTH: counter += Codec_WriteRegister(0x04, 0xAA); /* SPK always ON & HP always ON */ OutputDev = 0xAA; break; case OUTPUT_DEVICE_AUTO: counter += Codec_WriteRegister(0x04, 0x05); /* Detect the HP or the SPK automatically */ OutputDev = 0x05; break; default: counter += Codec_WriteRegister(0x04, 0x05); /* Detect the HP or the SPK automatically */ OutputDev = 0x05; break; } /* Clock configuration: Auto detection */ counter += Codec_WriteRegister(0x05, 0x81); /* Set the Slave Mode and the audio Standard */ counter += Codec_WriteRegister(0x06, CODEC_STANDARD); /* Set the Master volume */ Codec_VolumeCtrl(Volume); /* If the Speaker is enabled, set the Mono mode and volume attenuation level */ if (OutputDevice != OUTPUT_DEVICE_HEADPHONE) { /* Set the Speaker Mono mode */ counter += Codec_WriteRegister(0x0F , 0x06); /* Set the Speaker attenuation level */ counter += Codec_WriteRegister(0x24, 0x00); counter += Codec_WriteRegister(0x25, 0x00); } /* Power on the Codec */ counter += Codec_WriteRegister(0x02, 0x9E); /* Additional configuration for the CODEC. These configurations are done to reduce the time needed for the Codec to power off. If these configurations are removed, then a long delay should be added between powering off the Codec and switching off the I2S peripheral MCLK clock (which is the operating clock for Codec). If this delay is not inserted, then the codec will not shut down propoerly and it results in high noise after shut down. */ /* Disable the analog soft ramp */ counter += Codec_WriteRegister(0x0A, 0x00); /* Disable the digital soft ramp */ counter += Codec_WriteRegister(0x0E, 0x04); /* Disable the limiter attack level */ counter += Codec_WriteRegister(0x27, 0x00); /* Adjust Bass and Treble levels */ counter += Codec_WriteRegister(0x1F, 0x0F); /* Adjust PCM volume level */ counter += Codec_WriteRegister(0x1A, 0x0A); counter += Codec_WriteRegister(0x1B, 0x0A); /* Configure the I2S peripheral */ Codec_AudioInterface_Init(AudioFreq); /* Return communication control value */ return counter; }
/** * @brief Initializes the audio codec and all related interfaces (control * interface: I2C and audio interface: I2S) * @param OutputDevice: can be OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, * OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO . * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) * @param AudioFreq: Audio frequency used to play the audio stream. * @retval 0 if correct communication, else wrong communication */ static uint32_t Codec_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) { uint32_t counter = 0; /* Configure the Codec related IOs */ Codec_GPIO_Init(); /* Reset the Codec Registers */ // Codec_Reset(); /* Initialize the Control interface of the Audio Codec */ // Codec_CtrlInterface_Init(); /* Keep Codec powered OFF */ counter += Codec_WriteRegister(0x02, 0x01); counter += Codec_WriteRegister(0x04, 0xAF); /* SPK always OFF & HP always ON */ OutputDev = 0xAF; /* Clock configuration: Auto detection */ counter += Codec_WriteRegister(0x05, 0x81); /* Set the Slave Mode and the audio Standard */ counter += Codec_WriteRegister(0x06, CODEC_STANDARD); /* Set the Master volume */ Codec_VolumeCtrl(Volume); if (CurrAudioInterface == AUDIO_INTERFACE_DAC) { /* Enable the PassThrough on AIN1A and AIN1B */ counter += Codec_WriteRegister(0x08, 0x01); counter += Codec_WriteRegister(0x09, 0x01); /* Route the analog input to the HP line */ counter += Codec_WriteRegister(0x0E, 0xC0); /* Set the Passthough volume */ counter += Codec_WriteRegister(0x14, 0x00); counter += Codec_WriteRegister(0x15, 0x00); } /*Set the Beep Frequency, time and volume*/ counter += Codec_WriteRegister(0x1C, 0x71); counter += Codec_WriteRegister(0x1D, 0x20); /* Power on the Codec */ counter += Codec_WriteRegister(0x02, 0x9E); /* Additional configuration for the CODEC. These configurations are done to reduce the time needed for the Codec to power off. If these configurations are removed, then a long delay should be added between powering off the Codec and switching off the I2S peripheral MCLK clock (which is the operating clock for Codec). If this delay is not inserted, then the codec will not shut down properly and it results in high noise after shut down. */ /* Disable the analog soft ramp */ counter += Codec_WriteRegister(0x0A, 0x00); if (CurrAudioInterface != AUDIO_INTERFACE_DAC) { /* Disable the digital soft ramp */ counter += Codec_WriteRegister(0x0E, 0x04); } /* Disable the limiter attack level */ counter += Codec_WriteRegister(0x27, 0x00); /* Adjust Bass and Treble levels */ counter += Codec_WriteRegister(0x1F, 0x0F); /* Adjust PCM volume level */ counter += Codec_WriteRegister(0x1A, 0x0A); counter += Codec_WriteRegister(0x1B, 0x0A); /* Configure the I2S peripheral */ Codec_AudioInterface_Init(AudioFreq); /* Return communication control value */ return counter; }
/** * @brief Initializes the audio codec and all related interfaces (control * interface: I2C and audio interface: I2S) * @param OutputDevice: can be OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, * OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO . * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) * @param AudioFreq: Audio frequency used to play the audio stream. * @retval 0 if correct communication, else wrong communication */ static uint32_t Codec_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) { uint32_t counter = 0; /* Configure the Codec related IOs */ Codec_GPIO_Init(); /* Reset the Codec Registers */ Codec_Reset(); /* Initialize the Control interface of the Audio Codec */ Codec_CtrlInterface_Init(); /* Keep Codec powered OFF */ counter += Codec_WriteRegister(0x02, 0x01); switch (OutputDevice) { case OUTPUT_DEVICE_SPEAKER: counter += Codec_WriteRegister(0x04, 0xFA); /* SPK always ON & HP always OFF */ OutputDev = 0xFA; break; case OUTPUT_DEVICE_HEADPHONE: counter += Codec_WriteRegister(0x04, 0xAF); /* SPK always OFF & HP always ON */ OutputDev = 0xAF; break; case OUTPUT_DEVICE_BOTH: counter += Codec_WriteRegister(0x04, 0xAA); /* SPK always ON & HP always ON */ OutputDev = 0xAA; break; case OUTPUT_DEVICE_AUTO: counter += Codec_WriteRegister(0x04, 0x05); /* Detect the HP or the SPK automatically */ OutputDev = 0x05; break; default: counter += Codec_WriteRegister(0x04, 0x05); /* Detect the HP or the SPK automatically */ OutputDev = 0x05; break; } /* Clock configuration: Auto detection */ counter += Codec_WriteRegister(0x05, 0x81); /* Set the Slave Mode and the audio Standard */ counter += Codec_WriteRegister(0x06, CODEC_STANDARD); /* Set the Master volume */ Codec_VolumeCtrl(Volume); /* If the Speaker is enabled, set the Mono mode and volume attenuation level */ if (OutputDevice != OUTPUT_DEVICE_HEADPHONE) { /* Set the Speaker Mono mode */ counter += Codec_WriteRegister(0x0F , 0x06); /* Set the Speaker attenuation level */ counter += Codec_WriteRegister(0x24, 0xF0); counter += Codec_WriteRegister(0x25, 0xF0); } /* Power on the Codec */ counter += Codec_WriteRegister(0x02, 0x9E); /* Configure the I2S peripheral */ Codec_AudioInterface_Init(AudioFreq); /* Return communication control value */ return counter; }
/** * @brief Pauses or Resumes the audio stream playing from the Media. * @param Cmd: AUDIO_PAUSE (or 0) to pause, AUDIO_RESUME (or any value different * from 0) to resume. * @param Addr: Address from/at which the audio stream should resume/pause. * @param Size: Number of data to be configured for next resume. * @retval None. */ void Audio_MAL_PauseResume(uint32_t Cmd, uint32_t Addr, uint32_t Size) { /* Pause the audio file playing */ if (Cmd == AUDIO_PAUSE) { #ifdef USE_DMA_PAUSE_FEATURE /* Disable the I2S peripheral */ I2S_Cmd(CODEC_I2S, DISABLE); /* Pause the I2S DMA Stream Note. For the STM32F4xx devices, the DMA implements a pause feature, by disabling the stream, all configuration is preserved and data transfer is paused till the next enable of the stream. This feature is not available on STM32F1xx devices. */ DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE); #else /* #if !defined(USE_DMA_PAUSE_FEATURE) */ /* Stop the current DMA request by resetting the I2S cell */ Codec_AudioInterface_DeInit(); /* Re-configure the I2S interface for the next resume operation */ Codec_AudioInterface_Init(I2S_InitStructure.I2S_AudioFreq); /* Disable the DMA Stream */ DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE); /* Wait the DMA Stream to be effectively disabled */ while (DMA_GetCmdStatus(AUDIO_MAL_DMA_STREAM) != DISABLE) {} /* Clear the Interrupt flag */ DMA_ClearFlag(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_ALL); #endif /* USE_DMA_PAUSE_FEATURE */ } else /* AUDIO_RESUME */ { #ifdef USE_DMA_PAUSE_FEATURE /* Resume the I2S DMA Stream Note. For the STM32F4xx devices, the DMA implements a pause feature, by disabling the stream, all configuration is preserved and data transfer is paused till the next enable of the stream. This feature is not available on STM32F1xx devices. */ DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE); #else /* Configure the buffer address and size */ DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Addr; DMA_InitStructure.DMA_BufferSize = (uint32_t)(Size*2); /* Configure the DMA Stream with the new parameters */ DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure); /* Enable the I2S DMA Stream*/ DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE); #endif /* USE_DMA_PAUSE_FEATURE */ /* If the I2S peripheral is still not enabled, enable it */ if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0) { I2S_Cmd(CODEC_I2S, ENABLE); } } }