STM32L476G-Discovery board drivers V1.0.0

Dependents:   DiscoLogger DISCO_L476VG_GlassLCD DISCO_L476VG_MicrophoneRecorder DISCO_L476VG_UART ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cs43l22.c Source File

cs43l22.c

Go to the documentation of this file.
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>&copy; 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****/