STM32L476G-Discovery board drivers V1.0.0
Dependents: DiscoLogger DISCO_L476VG_GlassLCD DISCO_L476VG_MicrophoneRecorder DISCO_L476VG_UART ... 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. 00010 * All rights reserved.</center></h2> 00011 * 00012 * This software component is licensed by ST under BSD 3-Clause license, 00013 * the "License"; You may not use this file except in compliance with the 00014 * License. You may obtain a copy of the License at: 00015 * opensource.org/licenses/BSD-3-Clause 00016 * 00017 ****************************************************************************** 00018 */ 00019 00020 /* Includes ------------------------------------------------------------------*/ 00021 #include "cs43l22.h" 00022 00023 /** @addtogroup BSP 00024 * @{ 00025 */ 00026 00027 /** @addtogroup Components 00028 * @{ 00029 */ 00030 00031 /** @addtogroup CS43L22 00032 * @brief This file provides a set of functions needed to drive the 00033 * CS43L22 audio codec. 00034 * @{ 00035 */ 00036 00037 /** @defgroup CS43L22_Private_Types 00038 * @{ 00039 */ 00040 00041 /** 00042 * @} 00043 */ 00044 00045 /** @defgroup CS43L22_Private_Defines 00046 * @{ 00047 */ 00048 #define VOLUME_CONVERT(Volume) (((Volume) > 100)? 255:((uint8_t)(((Volume) * 255) / 100))) 00049 /* Uncomment this line to enable verifying data sent to codec after each write 00050 operation (for debug purpose) */ 00051 #if !defined (VERIFY_WRITTENDATA) 00052 /* #define VERIFY_WRITTENDATA */ 00053 #endif /* VERIFY_WRITTENDATA */ 00054 /** 00055 * @} 00056 */ 00057 00058 /** @defgroup CS43L22_Private_Macros 00059 * @{ 00060 */ 00061 00062 /** 00063 * @} 00064 */ 00065 00066 /** @defgroup CS43L22_Private_Variables 00067 * @{ 00068 */ 00069 00070 /* Audio codec driver structure initialization */ 00071 AUDIO_DrvTypeDef cs43l22_drv = 00072 { 00073 cs43l22_Init, 00074 cs43l22_DeInit, 00075 cs43l22_ReadID, 00076 00077 cs43l22_Play, 00078 cs43l22_Pause, 00079 cs43l22_Resume, 00080 cs43l22_Stop, 00081 00082 cs43l22_SetFrequency, 00083 cs43l22_SetVolume, 00084 cs43l22_SetMute, 00085 cs43l22_SetOutputMode, 00086 cs43l22_Reset, 00087 }; 00088 00089 static uint8_t Is_cs43l22_Stop = 1; 00090 00091 volatile uint8_t OutputDev = 0; 00092 00093 /** 00094 * @} 00095 */ 00096 00097 /** @defgroup CS43L22_Function_Prototypes 00098 * @{ 00099 */ 00100 static uint8_t CODEC_IO_Write(uint8_t Addr, uint8_t Reg, uint8_t Value); 00101 /** 00102 * @} 00103 */ 00104 00105 /** @defgroup CS43L22_Private_Functions 00106 * @{ 00107 */ 00108 00109 /** 00110 * @brief Initializes the audio codec and the control interface. 00111 * @param DeviceAddr: Device address on communication Bus. 00112 * @param OutputDevice: can be OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00113 * OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO . 00114 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 00115 * @retval 0 if correct communication, else wrong communication 00116 */ 00117 uint32_t cs43l22_Init(uint16_t DeviceAddr, uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) 00118 { 00119 uint32_t counter = 0; 00120 00121 /* Initialize the Control interface of the Audio Codec */ 00122 AUDIO_IO_Init(); 00123 00124 /* Keep Codec powered OFF */ 00125 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL1, 0x01); 00126 00127 /*Save Output device for mute ON/OFF procedure*/ 00128 switch (OutputDevice) 00129 { 00130 case OUTPUT_DEVICE_SPEAKER: 00131 OutputDev = 0xFA; 00132 break; 00133 00134 case OUTPUT_DEVICE_HEADPHONE: 00135 OutputDev = 0xAF; 00136 break; 00137 00138 case OUTPUT_DEVICE_BOTH: 00139 OutputDev = 0xAA; 00140 break; 00141 00142 case OUTPUT_DEVICE_AUTO: 00143 OutputDev = 0x05; 00144 break; 00145 00146 default: 00147 OutputDev = 0x05; 00148 break; 00149 } 00150 00151 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, OutputDev); 00152 00153 /* Clock configuration: Auto detection */ 00154 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_CLOCKING_CTL, 0x81); 00155 00156 /* Set the Slave Mode and the audio Standard */ 00157 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_INTERFACE_CTL1, CODEC_STANDARD); 00158 00159 /* Set the Master volume */ 00160 counter += cs43l22_SetVolume(DeviceAddr, Volume); 00161 00162 /* If the Speaker is enabled, set the Mono mode and volume attenuation level */ 00163 if(OutputDevice != OUTPUT_DEVICE_HEADPHONE) 00164 { 00165 /* Set the Speaker Mono mode */ 00166 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_PLAYBACK_CTL2, 0x06); 00167 00168 /* Set the Speaker attenuation level */ 00169 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_SPEAKER_A_VOL, 0x00); 00170 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_SPEAKER_B_VOL, 0x00); 00171 } 00172 00173 /* Additional configuration for the CODEC. These configurations are done to reduce 00174 the time needed for the Codec to power off. If these configurations are removed, 00175 then a long delay should be added between powering off the Codec and switching 00176 off the I2S peripheral MCLK clock (which is the operating clock for Codec). 00177 If this delay is not inserted, then the codec will not shut down properly and 00178 it results in high noise after shut down. */ 00179 00180 /* Disable the analog soft ramp */ 00181 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_ANALOG_ZC_SR_SETT, 0x00); 00182 /* Disable the digital soft ramp */ 00183 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MISC_CTL, 0x04); 00184 /* Disable the limiter attack level */ 00185 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_LIMIT_CTL1, 0x00); 00186 /* Adjust Bass and Treble levels */ 00187 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_TONE_CTL, 0x0F); 00188 /* Adjust PCM volume level */ 00189 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_PCMA_VOL, 0x0A); 00190 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_PCMB_VOL, 0x0A); 00191 00192 /* Return communication control value */ 00193 return counter; 00194 } 00195 00196 /** 00197 * @brief Deinitializes the audio codec. 00198 * @param None 00199 * @retval None 00200 */ 00201 void cs43l22_DeInit(void) 00202 { 00203 /* Deinitialize Audio Codec interface */ 00204 AUDIO_IO_DeInit(); 00205 } 00206 00207 /** 00208 * @brief Get the CS43L22 ID. 00209 * @param DeviceAddr: Device address on communication Bus. 00210 * @retval The CS43L22 ID 00211 */ 00212 uint32_t cs43l22_ReadID(uint16_t DeviceAddr) 00213 { 00214 uint8_t Value; 00215 /* Initialize the Control interface of the Audio Codec */ 00216 AUDIO_IO_Init(); 00217 00218 Value = AUDIO_IO_Read(DeviceAddr, CS43L22_CHIPID_ADDR); 00219 Value = (Value & CS43L22_ID_MASK); 00220 00221 return((uint32_t) Value); 00222 } 00223 00224 /** 00225 * @brief Start the audio Codec play feature. 00226 * @note For this codec no Play options are required. 00227 * @param DeviceAddr: Device address on communication Bus. 00228 * @retval 0 if correct communication, else wrong communication 00229 */ 00230 uint32_t cs43l22_Play(uint16_t DeviceAddr, uint16_t* pBuffer, uint16_t Size) 00231 { 00232 uint32_t counter = 0; 00233 00234 if(Is_cs43l22_Stop == 1) 00235 { 00236 /* Enable the digital soft ramp */ 00237 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MISC_CTL, 0x06); 00238 00239 /* Enable Output device */ 00240 counter += cs43l22_SetMute(DeviceAddr, AUDIO_MUTE_OFF); 00241 00242 /* Power on the Codec */ 00243 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL1, 0x9E); 00244 Is_cs43l22_Stop = 0; 00245 } 00246 00247 /* Return communication control value */ 00248 return counter; 00249 } 00250 00251 /** 00252 * @brief Pauses playing on the audio codec. 00253 * @param DeviceAddr: Device address on communication Bus. 00254 * @retval 0 if correct communication, else wrong communication 00255 */ 00256 uint32_t cs43l22_Pause(uint16_t DeviceAddr) 00257 { 00258 uint32_t counter = 0; 00259 00260 /* Pause the audio file playing */ 00261 /* Mute the output first */ 00262 counter += cs43l22_SetMute(DeviceAddr, AUDIO_MUTE_ON); 00263 00264 /* Put the Codec in Power save mode */ 00265 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL1, 0x01); 00266 00267 return counter; 00268 } 00269 00270 /** 00271 * @brief Resumes playing on the audio codec. 00272 * @param DeviceAddr: Device address on communication Bus. 00273 * @retval 0 if correct communication, else wrong communication 00274 */ 00275 uint32_t cs43l22_Resume(uint16_t DeviceAddr) 00276 { 00277 uint32_t counter = 0; 00278 volatile uint32_t index = 0x00; 00279 /* Resumes the audio file playing */ 00280 /* Unmute the output first */ 00281 counter += cs43l22_SetMute(DeviceAddr, AUDIO_MUTE_OFF); 00282 00283 for(index = 0x00; index < 0xFF; index++); 00284 00285 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, OutputDev); 00286 00287 /* Exit the Power save mode */ 00288 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL1, 0x9E); 00289 00290 return counter; 00291 } 00292 00293 /** 00294 * @brief Stops audio Codec playing. It powers down the codec. 00295 * @param DeviceAddr: Device address on communication Bus. 00296 * @param CodecPdwnMode: selects the power down mode. 00297 * - CODEC_PDWN_HW: Physically power down the codec. When resuming from this 00298 * mode, the codec is set to default configuration 00299 * (user should re-Initialize the codec in order to 00300 * play again the audio stream). 00301 * @retval 0 if correct communication, else wrong communication 00302 */ 00303 uint32_t cs43l22_Stop(uint16_t DeviceAddr, uint32_t CodecPdwnMode) 00304 { 00305 uint32_t counter = 0; 00306 00307 /* Mute the output first */ 00308 counter += cs43l22_SetMute(DeviceAddr, AUDIO_MUTE_ON); 00309 00310 /* Disable the digital soft ramp */ 00311 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MISC_CTL, 0x04); 00312 00313 /* Power down the DAC and the speaker (PMDAC and PMSPK bits)*/ 00314 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL1, 0x9F); 00315 00316 Is_cs43l22_Stop = 1; 00317 return counter; 00318 } 00319 00320 /** 00321 * @brief Sets higher or lower the codec volume level. 00322 * @param DeviceAddr: Device address on communication Bus. 00323 * @param Volume: a byte value from 0 to 255 (refer to codec registers 00324 * description for more details). 00325 * 00326 * @retval 0 if correct communication, else wrong communication 00327 */ 00328 uint32_t cs43l22_SetVolume(uint16_t DeviceAddr, uint8_t Volume) 00329 { 00330 uint32_t counter = 0; 00331 uint8_t convertedvol = VOLUME_CONVERT(Volume); 00332 00333 if(convertedvol > 0xE6) 00334 { 00335 /* Set the Master volume */ 00336 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MASTER_A_VOL, convertedvol - 0xE7); 00337 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MASTER_B_VOL, convertedvol - 0xE7); 00338 } 00339 else 00340 { 00341 /* Set the Master volume */ 00342 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MASTER_A_VOL, convertedvol + 0x19); 00343 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MASTER_B_VOL, convertedvol + 0x19); 00344 } 00345 00346 return counter; 00347 } 00348 00349 /** 00350 * @brief Sets new frequency. 00351 * @param DeviceAddr: Device address on communication Bus. 00352 * @param AudioFreq: Audio frequency used to play the audio stream. 00353 * @retval 0 if correct communication, else wrong communication 00354 */ 00355 uint32_t cs43l22_SetFrequency(uint16_t DeviceAddr, uint32_t AudioFreq) 00356 { 00357 return 0; 00358 } 00359 00360 /** 00361 * @brief Enables or disables the mute feature on the audio codec. 00362 * @param DeviceAddr: Device address on communication Bus. 00363 * @param Cmd: AUDIO_MUTE_ON to enable the mute or AUDIO_MUTE_OFF to disable the 00364 * mute mode. 00365 * @retval 0 if correct communication, else wrong communication 00366 */ 00367 uint32_t cs43l22_SetMute(uint16_t DeviceAddr, uint32_t Cmd) 00368 { 00369 uint32_t counter = 0; 00370 00371 /* Set the Mute mode */ 00372 if(Cmd == AUDIO_MUTE_ON) 00373 { 00374 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0xFF); 00375 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_HEADPHONE_A_VOL, 0x01); 00376 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_HEADPHONE_B_VOL, 0x01); 00377 } 00378 else /* AUDIO_MUTE_OFF Disable the Mute */ 00379 { 00380 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_HEADPHONE_A_VOL, 0x00); 00381 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_HEADPHONE_B_VOL, 0x00); 00382 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, OutputDev); 00383 } 00384 return counter; 00385 } 00386 00387 /** 00388 * @brief Switch dynamically (while audio file is played) the output target 00389 * (speaker or headphone). 00390 * @note This function modifies a global variable of the audio codec driver: OutputDev. 00391 * @param DeviceAddr: Device address on communication Bus. 00392 * @param Output: specifies the audio output target: OUTPUT_DEVICE_SPEAKER, 00393 * OUTPUT_DEVICE_HEADPHONE, OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO 00394 * @retval 0 if correct communication, else wrong communication 00395 */ 00396 uint32_t cs43l22_SetOutputMode(uint16_t DeviceAddr, uint8_t Output) 00397 { 00398 uint32_t counter = 0; 00399 00400 switch (Output) 00401 { 00402 case OUTPUT_DEVICE_SPEAKER: 00403 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0xFA); /* SPK always ON & HP always OFF */ 00404 OutputDev = 0xFA; 00405 break; 00406 00407 case OUTPUT_DEVICE_HEADPHONE: 00408 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0xAF); /* SPK always OFF & HP always ON */ 00409 OutputDev = 0xAF; 00410 break; 00411 00412 case OUTPUT_DEVICE_BOTH: 00413 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0xAA); /* SPK always ON & HP always ON */ 00414 OutputDev = 0xAA; 00415 break; 00416 00417 case OUTPUT_DEVICE_AUTO: 00418 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0x05); /* Detect the HP or the SPK automatically */ 00419 OutputDev = 0x05; 00420 break; 00421 00422 default: 00423 counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0x05); /* Detect the HP or the SPK automatically */ 00424 OutputDev = 0x05; 00425 break; 00426 } 00427 return counter; 00428 } 00429 00430 /** 00431 * @brief Resets cs43l22 registers. 00432 * @param DeviceAddr: Device address on communication Bus. 00433 * @retval 0 if correct communication, else wrong communication 00434 */ 00435 uint32_t cs43l22_Reset(uint16_t DeviceAddr) 00436 { 00437 return 0; 00438 } 00439 00440 /** 00441 * @brief Writes/Read a single data. 00442 * @param Addr: I2C address 00443 * @param Reg: Reg address 00444 * @param Value: Data to be written 00445 * @retval None 00446 */ 00447 static uint8_t CODEC_IO_Write(uint8_t Addr, uint8_t Reg, uint8_t Value) 00448 { 00449 uint32_t result = 0; 00450 00451 AUDIO_IO_Write(Addr, Reg, Value); 00452 00453 #ifdef VERIFY_WRITTENDATA 00454 /* Verify that the data has been correctly written */ 00455 result = (AUDIO_IO_Read(Addr, Reg) == Value)? 0:1; 00456 #endif /* VERIFY_WRITTENDATA */ 00457 00458 return result; 00459 } 00460 00461 /** 00462 * @} 00463 */ 00464 00465 /** 00466 * @} 00467 */ 00468 00469 /** 00470 * @} 00471 */ 00472 00473 /** 00474 * @} 00475 */ 00476 00477 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 18:37:21 by 1.7.2