Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: Configurable_Robots DISCO-F469NI_LCD_demo DISCO-F469NI_SD_demo DISCO-F469NI_EEPROM_demo ... more
cs43l22.c
00001 /** 00002 ****************************************************************************** 00003 * @file cs43l22.c 00004 * @author MCD Application Team 00005 * @brief This file provides the CS43L22 Audio Codec driver. 00006 ****************************************************************************** 00007 * @attention 00008 * 00009 * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2> 00010 * 00011 * Redistribution and use in source and binary forms, with or without modification, 00012 * are permitted provided that the following conditions are met: 00013 * 1. Redistributions of source code must retain the above copyright notice, 00014 * this list of conditions and the following disclaimer. 00015 * 2. Redistributions in binary form must reproduce the above copyright notice, 00016 * this list of conditions and the following disclaimer in the documentation 00017 * and/or other materials provided with the distribution. 00018 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00019 * may be used to endorse or promote products derived from this software 00020 * without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00023 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00024 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00025 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00026 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00027 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00028 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00030 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00031 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 * 00033 ****************************************************************************** 00034 */ 00035 00036 /* Includes ------------------------------------------------------------------*/ 00037 #include "cs43l22.h" 00038 00039 /** @addtogroup BSP 00040 * @{ 00041 */ 00042 00043 /** @addtogroup Components 00044 * @{ 00045 */ 00046 00047 /** @addtogroup CS43L22 00048 * @brief This file provides a set of functions needed to drive the 00049 * CS43L22 audio codec. 00050 * @{ 00051 */ 00052 00053 /** @defgroup CS43L22_Private_Types 00054 * @{ 00055 */ 00056 00057 /** 00058 * @} 00059 */ 00060 00061 /** @defgroup CS43L22_Private_Defines 00062 * @{ 00063 */ 00064 #define VOLUME_CONVERT(Volume) (((Volume) > 100)? 255:((uint8_t)(((Volume) * 255) / 100))) 00065 /* Uncomment this line to enable verifying data sent to codec after each write 00066 operation (for debug purpose) */ 00067 #if !defined (VERIFY_WRITTENDATA) 00068 /* #define VERIFY_WRITTENDATA */ 00069 #endif /* VERIFY_WRITTENDATA */ 00070 /** 00071 * @} 00072 */ 00073 00074 /** @defgroup CS43L22_Private_Macros 00075 * @{ 00076 */ 00077 00078 /** 00079 * @} 00080 */ 00081 00082 /** @defgroup CS43L22_Private_Variables 00083 * @{ 00084 */ 00085 00086 /* Audio codec driver structure initialization */ 00087 AUDIO_DrvTypeDef cs43l22_drv = 00088 { 00089 cs43l22_Init, 00090 cs43l22_DeInit, 00091 cs43l22_ReadID, 00092 00093 cs43l22_Play, 00094 cs43l22_Pause, 00095 cs43l22_Resume, 00096 cs43l22_Stop, 00097 00098 cs43l22_SetFrequency, 00099 cs43l22_SetVolume, 00100 cs43l22_SetMute, 00101 cs43l22_SetOutputMode, 00102 cs43l22_Reset, 00103 }; 00104 00105 static uint8_t Is_cs43l22_Stop = 1; 00106 00107 volatile uint8_t OutputDev = 0; 00108 00109 /** 00110 * @} 00111 */ 00112 00113 /** @defgroup CS43L22_Function_Prototypes 00114 * @{ 00115 */ 00116 static uint8_t CODEC_IO_Write(uint8_t Addr, uint8_t Reg, uint8_t Value); 00117 /** 00118 * @} 00119 */ 00120 00121 /** @defgroup CS43L22_Private_Functions 00122 * @{ 00123 */ 00124 00125 /** 00126 * @brief Initializes the audio codec and the control interface. 00127 * @param DeviceAddr: Device address on communication Bus. 00128 * @param OutputDevice: can be OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00129 * OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO . 00130 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 00131 * @retval 0 if correct communication, else wrong communication 00132 */ 00133 uint32_t cs43l22_Init(uint16_t DeviceAddr, uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) 00134 { 00135 uint32_t counter = 0; 00136 00137 /* Initialize the Control interface of the Audio Codec */ 00138 AUDIO_IO_Init(); 00139 00140 /* Keep Codec powered OFF */ 00141 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL1, 0x01); 00142 00143 /*Save Output device for mute ON/OFF procedure*/ 00144 switch (OutputDevice) 00145 { 00146 case OUTPUT_DEVICE_SPEAKER: 00147 OutputDev = 0xFA; 00148 break; 00149 00150 case OUTPUT_DEVICE_HEADPHONE: 00151 OutputDev = 0xAF; 00152 break; 00153 00154 case OUTPUT_DEVICE_BOTH: 00155 OutputDev = 0xAA; 00156 break; 00157 00158 case OUTPUT_DEVICE_AUTO: 00159 OutputDev = 0x05; 00160 break; 00161 00162 default: 00163 OutputDev = 0x05; 00164 break; 00165 } 00166 00167 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, OutputDev); 00168 00169 /* Clock configuration: Auto detection */ 00170 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_CLOCKING_CTL, 0x81); 00171 00172 /* Set the Slave Mode and the audio Standard */ 00173 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_INTERFACE_CTL1, CODEC_STANDARD); 00174 00175 /* Set the Master volume */ 00176 counter += cs43l22_SetVolume(DeviceAddr, Volume); 00177 00178 /* If the Speaker is enabled, set the Mono mode and volume attenuation level */ 00179 if(OutputDevice != OUTPUT_DEVICE_HEADPHONE) 00180 { 00181 /* Set the Speaker Mono mode */ 00182 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_PLAYBACK_CTL2, 0x06); 00183 00184 /* Set the Speaker attenuation level */ 00185 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_SPEAKER_A_VOL, 0x00); 00186 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_SPEAKER_B_VOL, 0x00); 00187 } 00188 00189 /* Additional configuration for the CODEC. These configurations are done to reduce 00190 the time needed for the Codec to power off. If these configurations are removed, 00191 then a long delay should be added between powering off the Codec and switching 00192 off the I2S peripheral MCLK clock (which is the operating clock for Codec). 00193 If this delay is not inserted, then the codec will not shut down properly and 00194 it results in high noise after shut down. */ 00195 00196 /* Disable the analog soft ramp */ 00197 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_ANALOG_ZC_SR_SETT, 0x00); 00198 /* Disable the digital soft ramp */ 00199 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MISC_CTL, 0x04); 00200 /* Disable the limiter attack level */ 00201 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_LIMIT_CTL1, 0x00); 00202 /* Adjust Bass and Treble levels */ 00203 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_TONE_CTL, 0x0F); 00204 /* Adjust PCM volume level */ 00205 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_PCMA_VOL, 0x0A); 00206 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_PCMB_VOL, 0x0A); 00207 00208 /* Return communication control value */ 00209 return counter; 00210 } 00211 00212 /** 00213 * @brief Deinitializes the audio codec. 00214 * @param None 00215 * @retval None 00216 */ 00217 void cs43l22_DeInit(void) 00218 { 00219 /* Deinitialize Audio Codec interface */ 00220 AUDIO_IO_DeInit(); 00221 } 00222 00223 /** 00224 * @brief Get the CS43L22 ID. 00225 * @param DeviceAddr: Device address on communication Bus. 00226 * @retval The CS43L22 ID 00227 */ 00228 uint32_t cs43l22_ReadID(uint16_t DeviceAddr) 00229 { 00230 uint8_t Value; 00231 /* Initialize the Control interface of the Audio Codec */ 00232 AUDIO_IO_Init(); 00233 00234 Value = AUDIO_IO_Read(DeviceAddr, CS43L22_CHIPID_ADDR); 00235 Value = (Value & CS43L22_ID_MASK); 00236 00237 return((uint32_t) Value); 00238 } 00239 00240 /** 00241 * @brief Start the audio Codec play feature. 00242 * @note For this codec no Play options are required. 00243 * @param DeviceAddr: Device address on communication Bus. 00244 * @retval 0 if correct communication, else wrong communication 00245 */ 00246 uint32_t cs43l22_Play(uint16_t DeviceAddr, uint16_t* pBuffer, uint16_t Size) 00247 { 00248 uint32_t counter = 0; 00249 00250 if(Is_cs43l22_Stop == 1) 00251 { 00252 /* Enable the digital soft ramp */ 00253 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MISC_CTL, 0x06); 00254 00255 /* Enable Output device */ 00256 counter += cs43l22_SetMute(DeviceAddr, AUDIO_MUTE_OFF); 00257 00258 /* Power on the Codec */ 00259 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL1, 0x9E); 00260 Is_cs43l22_Stop = 0; 00261 } 00262 00263 /* Return communication control value */ 00264 return counter; 00265 } 00266 00267 /** 00268 * @brief Pauses playing on the audio codec. 00269 * @param DeviceAddr: Device address on communication Bus. 00270 * @retval 0 if correct communication, else wrong communication 00271 */ 00272 uint32_t cs43l22_Pause(uint16_t DeviceAddr) 00273 { 00274 uint32_t counter = 0; 00275 00276 /* Pause the audio file playing */ 00277 /* Mute the output first */ 00278 counter += cs43l22_SetMute(DeviceAddr, AUDIO_MUTE_ON); 00279 00280 /* Put the Codec in Power save mode */ 00281 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL1, 0x01); 00282 00283 return counter; 00284 } 00285 00286 /** 00287 * @brief Resumes playing on the audio codec. 00288 * @param DeviceAddr: Device address on communication Bus. 00289 * @retval 0 if correct communication, else wrong communication 00290 */ 00291 uint32_t cs43l22_Resume(uint16_t DeviceAddr) 00292 { 00293 uint32_t counter = 0; 00294 volatile uint32_t index = 0x00; 00295 /* Resumes the audio file playing */ 00296 /* Unmute the output first */ 00297 counter += cs43l22_SetMute(DeviceAddr, AUDIO_MUTE_OFF); 00298 00299 for(index = 0x00; index < 0xFF; index++); 00300 00301 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, OutputDev); 00302 00303 /* Exit the Power save mode */ 00304 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL1, 0x9E); 00305 00306 return counter; 00307 } 00308 00309 /** 00310 * @brief Stops audio Codec playing. It powers down the codec. 00311 * @param DeviceAddr: Device address on communication Bus. 00312 * @param CodecPdwnMode: selects the power down mode. 00313 * - CODEC_PDWN_HW: Physically power down the codec. When resuming from this 00314 * mode, the codec is set to default configuration 00315 * (user should re-Initialize the codec in order to 00316 * play again the audio stream). 00317 * @retval 0 if correct communication, else wrong communication 00318 */ 00319 uint32_t cs43l22_Stop(uint16_t DeviceAddr, uint32_t CodecPdwnMode) 00320 { 00321 uint32_t counter = 0; 00322 00323 /* Mute the output first */ 00324 counter += cs43l22_SetMute(DeviceAddr, AUDIO_MUTE_ON); 00325 00326 /* Disable the digital soft ramp */ 00327 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MISC_CTL, 0x04); 00328 00329 /* Power down the DAC and the speaker (PMDAC and PMSPK bits)*/ 00330 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL1, 0x9F); 00331 00332 Is_cs43l22_Stop = 1; 00333 return counter; 00334 } 00335 00336 /** 00337 * @brief Sets higher or lower the codec volume level. 00338 * @param DeviceAddr: Device address on communication Bus. 00339 * @param Volume: a byte value from 0 to 255 (refer to codec registers 00340 * description for more details). 00341 * 00342 * @retval 0 if correct communication, else wrong communication 00343 */ 00344 uint32_t cs43l22_SetVolume(uint16_t DeviceAddr, uint8_t Volume) 00345 { 00346 uint32_t counter = 0; 00347 uint8_t convertedvol = VOLUME_CONVERT(Volume); 00348 00349 if(convertedvol > 0xE6) 00350 { 00351 /* Set the Master volume */ 00352 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MASTER_A_VOL, convertedvol - 0xE7); 00353 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MASTER_B_VOL, convertedvol - 0xE7); 00354 } 00355 else 00356 { 00357 /* Set the Master volume */ 00358 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MASTER_A_VOL, convertedvol + 0x19); 00359 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MASTER_B_VOL, convertedvol + 0x19); 00360 } 00361 00362 return counter; 00363 } 00364 00365 /** 00366 * @brief Sets new frequency. 00367 * @param DeviceAddr: Device address on communication Bus. 00368 * @param AudioFreq: Audio frequency used to play the audio stream. 00369 * @retval 0 if correct communication, else wrong communication 00370 */ 00371 uint32_t cs43l22_SetFrequency(uint16_t DeviceAddr, uint32_t AudioFreq) 00372 { 00373 return 0; 00374 } 00375 00376 /** 00377 * @brief Enables or disables the mute feature on the audio codec. 00378 * @param DeviceAddr: Device address on communication Bus. 00379 * @param Cmd: AUDIO_MUTE_ON to enable the mute or AUDIO_MUTE_OFF to disable the 00380 * mute mode. 00381 * @retval 0 if correct communication, else wrong communication 00382 */ 00383 uint32_t cs43l22_SetMute(uint16_t DeviceAddr, uint32_t Cmd) 00384 { 00385 uint32_t counter = 0; 00386 00387 /* Set the Mute mode */ 00388 if(Cmd == AUDIO_MUTE_ON) 00389 { 00390 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0xFF); 00391 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_HEADPHONE_A_VOL, 0x01); 00392 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_HEADPHONE_B_VOL, 0x01); 00393 } 00394 else /* AUDIO_MUTE_OFF Disable the Mute */ 00395 { 00396 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_HEADPHONE_A_VOL, 0x00); 00397 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_HEADPHONE_B_VOL, 0x00); 00398 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, OutputDev); 00399 } 00400 return counter; 00401 } 00402 00403 /** 00404 * @brief Switch dynamically (while audio file is played) the output target 00405 * (speaker or headphone). 00406 * @note This function modifies a global variable of the audio codec driver: OutputDev. 00407 * @param DeviceAddr: Device address on communication Bus. 00408 * @param Output: specifies the audio output target: OUTPUT_DEVICE_SPEAKER, 00409 * OUTPUT_DEVICE_HEADPHONE, OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO 00410 * @retval 0 if correct communication, else wrong communication 00411 */ 00412 uint32_t cs43l22_SetOutputMode(uint16_t DeviceAddr, uint8_t Output) 00413 { 00414 uint32_t counter = 0; 00415 00416 switch (Output) 00417 { 00418 case OUTPUT_DEVICE_SPEAKER: 00419 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0xFA); /* SPK always ON & HP always OFF */ 00420 OutputDev = 0xFA; 00421 break; 00422 00423 case OUTPUT_DEVICE_HEADPHONE: 00424 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0xAF); /* SPK always OFF & HP always ON */ 00425 OutputDev = 0xAF; 00426 break; 00427 00428 case OUTPUT_DEVICE_BOTH: 00429 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0xAA); /* SPK always ON & HP always ON */ 00430 OutputDev = 0xAA; 00431 break; 00432 00433 case OUTPUT_DEVICE_AUTO: 00434 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0x05); /* Detect the HP or the SPK automatically */ 00435 OutputDev = 0x05; 00436 break; 00437 00438 default: 00439 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0x05); /* Detect the HP or the SPK automatically */ 00440 OutputDev = 0x05; 00441 break; 00442 } 00443 return counter; 00444 } 00445 00446 /** 00447 * @brief Resets cs43l22 registers. 00448 * @param DeviceAddr: Device address on communication Bus. 00449 * @retval 0 if correct communication, else wrong communication 00450 */ 00451 uint32_t cs43l22_Reset(uint16_t DeviceAddr) 00452 { 00453 return 0; 00454 } 00455 00456 /** 00457 * @brief Writes/Read a single data. 00458 * @param Addr: I2C address 00459 * @param Reg: Reg address 00460 * @param Value: Data to be written 00461 * @retval None 00462 */ 00463 static uint8_t CODEC_IO_Write(uint8_t Addr, uint8_t Reg, uint8_t Value) 00464 { 00465 uint32_t result = 0; 00466 00467 AUDIO_IO_Write(Addr, Reg, Value); 00468 00469 #ifdef VERIFY_WRITTENDATA 00470 /* Verify that the data has been correctly written */ 00471 result = (AUDIO_IO_Read(Addr, Reg) == Value)? 0:1; 00472 #endif /* VERIFY_WRITTENDATA */ 00473 00474 return result; 00475 } 00476 00477 /** 00478 * @} 00479 */ 00480 00481 /** 00482 * @} 00483 */ 00484 00485 /** 00486 * @} 00487 */ 00488 00489 /** 00490 * @} 00491 */ 00492 00493 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 18:31:51 by
