ST / BSP_DISCO_L4R9I

Dependents:   DISCO_L4R9I-LCD-demo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cs42l51.c Source File

cs42l51.c

Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    cs42l51.c
00004   * @author  MCD Application Team
00005   * @brief   This file provides the CS42L51 Audio Codec driver.   
00006   ******************************************************************************
00007   * @attention
00008   *
00009   * <h2><center>&copy; Copyright (c) 2017 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 "cs42l51.h"
00022 
00023 /** @addtogroup BSP
00024   * @{
00025   */
00026   
00027 /** @addtogroup Components
00028   * @{
00029   */ 
00030 
00031 /** @addtogroup CS42L51
00032   * @brief     This file provides a set of functions needed to drive the 
00033   *            CS42L51 audio codec.
00034   * @{
00035   */
00036 
00037 /** @defgroup CS42L51_Exported_Variables
00038   * @{
00039   */
00040 
00041 /* Audio codec driver structure initialization */  
00042 AUDIO_DrvTypeDef cs42l51_drv = 
00043 {
00044   cs42l51_Init,
00045   cs42l51_DeInit,
00046   cs42l51_ReadID,
00047 
00048   cs42l51_Play,
00049   cs42l51_Pause,
00050   cs42l51_Resume,
00051   cs42l51_Stop,  
00052   
00053   cs42l51_SetFrequency,  
00054   cs42l51_SetVolume,
00055   cs42l51_SetMute,  
00056   cs42l51_SetOutputMode,
00057   cs42l51_Reset,
00058 };
00059   
00060 /**
00061   * @}
00062   */ 
00063 
00064 /** @defgroup CS42L51_Private_Types
00065   * @{
00066   */
00067 
00068 /**
00069   * @}
00070   */ 
00071   
00072 /** @defgroup CS42L51_Private_Defines
00073   * @{
00074   */
00075 /* Uncomment this line to enable verifying data sent to codec after each write 
00076    operation (for debug purpose) */
00077 #if !defined (VERIFY_WRITTENDATA)  
00078 #define VERIFY_WRITTENDATA
00079 #endif /* VERIFY_WRITTENDATA */
00080 /**
00081   * @}
00082   */ 
00083 
00084 /** @defgroup CS42L51_Private_Macros
00085   * @{
00086   */
00087 
00088 /**
00089   * @}
00090   */ 
00091   
00092 /** @defgroup CS42L51_Private_Variables
00093   * @{
00094   */
00095 
00096 static uint8_t Is_CS42L51_Initialized = 0;
00097 static uint8_t Is_CS42L51_Stop        = 1;
00098 
00099 static uint16_t CS42L51_Device = OUTPUT_DEVICE_HEADPHONE;
00100   
00101 /**
00102   * @}
00103   */ 
00104 
00105 /** @defgroup CS42L51_Private_Functions
00106   * @{
00107   */
00108 static uint8_t CODEC_IO_Write(uint8_t Addr, uint8_t Reg, uint8_t Value);
00109 /**
00110   * @}
00111   */ 
00112 
00113 /** @addtogroup CS42L51_Exported_Functions
00114   * @{
00115   */ 
00116 
00117 /**
00118   * @brief Initialize the audio codec and the control interface.
00119   * @param DeviceAddr: Device address on communication bus.
00120   * @param Device:     Can be combination values of OUTPUT_DEVICE_HEADPHONE and
00121   *                       INPUT_DEVICE_MIC1.
00122   * @param Volume:     Initial output volume level (from 0 (-100dB) to 100 (0dB)).
00123   * @param AudioFreq:  Initial audio frequency (currently not used).
00124   * @retval 0 if correct communication, else wrong communication.
00125   */
00126 uint32_t cs42l51_Init(uint16_t DeviceAddr, uint16_t Device, uint8_t Volume, uint32_t AudioFreq)
00127 {
00128   uint32_t counter = 0;
00129   uint8_t  Value;
00130   
00131   /* Check if codec is already initialized */
00132   if(Is_CS42L51_Initialized == 0)
00133   {
00134     /* Initialize the Control interface of the Audio Codec */
00135     AUDIO_IO_Init();
00136 
00137     Is_CS42L51_Initialized = 1;
00138   }
00139   else
00140   {
00141     /* Set all power down bits to 1 exept PDN to mute ADCs and DACs*/
00142     counter += CODEC_IO_Write(DeviceAddr, 0x02, 0x7E);
00143     Value = AUDIO_IO_Read(DeviceAddr, 0x03);
00144     counter += CODEC_IO_Write(DeviceAddr, 0x03, (Value | 0x0E));
00145     
00146     /* Disable zero cross and soft ramp */
00147     Value = AUDIO_IO_Read(DeviceAddr, 0x09);
00148     counter += CODEC_IO_Write(DeviceAddr, 0x09, (Value & 0xFC));
00149     
00150     /* Power control : Enter standby (PDN = 1) */
00151     Value = AUDIO_IO_Read(DeviceAddr, 0x02);
00152     counter += CODEC_IO_Write(DeviceAddr, 0x02, (Value | 0x01));
00153   }
00154 
00155   /* Mic Power and Speed Control : Auto detect on, Speed mode SSM, tri state off, MCLK divide by 2 off */
00156   Value = AUDIO_IO_Read(DeviceAddr, 0x03);
00157   counter += CODEC_IO_Write(DeviceAddr, 0x03, ((Value & 0x0E) | 0xA0));
00158 
00159   /* Interface control : Loopback off, Slave, I2S (SDIN and SOUT), Digital mix off, Mic mix off */
00160   counter += CODEC_IO_Write(DeviceAddr, 0x04, 0x0C);
00161   
00162   /* Mic control : ADC single volume off, ADCB boost off, ADCA boost off, MicBias on AIN3B/MICIN2 pin, MicBias level 0.8xVA, MICB boost 16db, MICA boost 16dB */
00163   counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x00);
00164 
00165   /* ADC control : ADCB HPF off, ADCB HPF freeze off, ADCA HPF off, ADCA HPF freeze off, Soft ramp B off, Zero cross B off, Soft ramp A off, Zero cross A off */
00166   counter += CODEC_IO_Write(DeviceAddr, 0x06, 0x00);
00167 
00168   /* ADC Input Select, Invert and Mute : AIN1B to PGAB, AIN3A to PreAmp to PGAA, ADCB invert off, ADCA invert off, ADCB mute on, ADCA mute off */
00169   counter += CODEC_IO_Write(DeviceAddr, 0x07, 0x32);
00170   
00171   /* DAC output control : HP Gain to 1, Single volume control off, PCM invert signals polarity off, DAC channels mute on */
00172   counter += CODEC_IO_Write(DeviceAddr, 0x08, 0xC3);
00173 
00174   /* DAC control : Signal processing to DAC, Freeze off, De-emphasis off, Analog output auto mute off, DAC soft ramp */
00175   counter += CODEC_IO_Write(DeviceAddr, 0x09, 0x42);
00176 
00177   /* ALCA and PGAA Control : ALCA soft ramp disable on, ALCA zero cross disable on, PGA A Gain 0dB */  
00178   counter += CODEC_IO_Write(DeviceAddr, 0x0A, 0xC0);
00179 
00180   /* ALCB and PGAB Control : ALCB soft ramp disable on, ALCB zero cross disable on, PGA B Gain 0dB */  
00181   counter += CODEC_IO_Write(DeviceAddr, 0x0B, 0xC0);
00182   
00183   /* ADCA Attenuator : 0dB */
00184   counter += CODEC_IO_Write(DeviceAddr, 0x0C, 0x00);
00185 
00186   /* ADCB Attenuator : 0dB */
00187   counter += CODEC_IO_Write(DeviceAddr, 0x0D, 0x00);
00188 
00189   /* ADCA mixer volume control : ADCA mixer channel mute on, ADCA mixer volume 0dB */
00190   counter += CODEC_IO_Write(DeviceAddr, 0x0E, 0x80);
00191   
00192   /* ADCB mixer volume control : ADCB mixer channel mute on, ADCB mixer volume 0dB */
00193   counter += CODEC_IO_Write(DeviceAddr, 0x0F, 0x80);
00194   
00195   /* PCMA mixer volume control : PCMA mixer channel mute off, PCMA mixer volume 0dB */
00196   counter += CODEC_IO_Write(DeviceAddr, 0x10, 0x00);
00197 
00198   /* PCMB mixer volume control : PCMB mixer channel mute off, PCMB mixer volume 0dB */
00199   counter += CODEC_IO_Write(DeviceAddr, 0x11, 0x00);
00200 
00201   /* PCM channel mixer : AOUTA Left, AOUTB Right */
00202   counter += CODEC_IO_Write(DeviceAddr, 0x18, 0x00);
00203 
00204   if(Device & OUTPUT_DEVICE_HEADPHONE)
00205   {
00206     Value = VOLUME_CONVERT(Volume);
00207     /* AOUTA volume control : AOUTA volume */
00208     counter += CODEC_IO_Write(DeviceAddr, 0x16, Value);
00209     /* AOUTB volume control : AOUTB volume */
00210     counter += CODEC_IO_Write(DeviceAddr, 0x17, Value);
00211   }
00212   
00213   /* Store device */
00214   CS42L51_Device = Device;
00215   
00216   /* Return communication control value */
00217   return counter;  
00218 }
00219 
00220 /**
00221   * @brief  Deinitialize the audio codec.
00222   * @param  None
00223   * @retval  None
00224   */
00225 void cs42l51_DeInit(void)
00226 {
00227   /* Deinitialize Audio Codec interface */
00228   AUDIO_IO_DeInit();
00229   
00230   Is_CS42L51_Initialized = 0;
00231 }
00232 
00233 /**
00234   * @brief  Get the CS42L51 ID.
00235   * @param DeviceAddr: Device address on communication Bus.   
00236   * @retval The CS42L51 ID 
00237   */
00238 uint32_t cs42l51_ReadID(uint16_t DeviceAddr)
00239 {
00240   uint8_t Value;
00241   
00242   if(Is_CS42L51_Initialized == 0)
00243   {
00244     /* Initialize the Control interface of the Audio Codec */
00245     AUDIO_IO_Init(); 
00246     
00247     Value = AUDIO_IO_Read(DeviceAddr, CS42L51_CHIPID_ADDR);
00248     Value = (Value & CS42L51_ID_MASK);
00249 
00250     /* Deinitialize Audio Codec interface */
00251     AUDIO_IO_DeInit();
00252   }
00253   else
00254   {
00255     Value = AUDIO_IO_Read(DeviceAddr, CS42L51_CHIPID_ADDR);
00256     Value = (Value & CS42L51_ID_MASK);
00257   }
00258   
00259   return((uint32_t) Value);
00260 }
00261 
00262 /**
00263   * @brief Start the audio Codec play feature.
00264   * @note For this codec no Play options are required.
00265   * @param DeviceAddr: Device address on communication Bus.   
00266   * @retval 0 if correct communication, else wrong communication
00267   */
00268 uint32_t cs42l51_Play(uint16_t DeviceAddr, uint16_t* pBuffer, uint16_t Size)
00269 {
00270   uint32_t counter = 0;
00271   uint8_t  Value;
00272   
00273   if(Is_CS42L51_Stop == 1)
00274   {
00275     /* Unmute output device */  
00276     counter += cs42l51_SetMute(DeviceAddr, AUDIO_MUTE_OFF);
00277 
00278     if(CS42L51_Device & OUTPUT_DEVICE_HEADPHONE)
00279     {
00280       /* DAC control : Signal processing to DAC, Freeze off, De-emphasis off, Analog output auto mute off, DAC soft ramp */
00281       counter += CODEC_IO_Write(DeviceAddr, 0x09, 0x42);
00282 
00283       /* Power control 1 : PDN_DACA, PDN_DACB disable. */
00284       Value = AUDIO_IO_Read(DeviceAddr, 0x02);
00285       counter += CODEC_IO_Write(DeviceAddr, 0x02, (Value & 0x9F));
00286     }
00287 
00288     if(CS42L51_Device & INPUT_DEVICE_MIC1)
00289     {
00290       /* Power control 1 : PDN_PGAA, PDN_ADCA disable. */
00291       Value = AUDIO_IO_Read(DeviceAddr, 0x02);
00292       counter += CODEC_IO_Write(DeviceAddr, 0x02, (Value & 0xF5));
00293       
00294       /* Mic Power and Speed Control : PDN_MICA, PDN_MIC_BIAS disable. */
00295       Value = AUDIO_IO_Read(DeviceAddr, 0x03);
00296       counter += CODEC_IO_Write(DeviceAddr, 0x03, (Value & 0xF9));
00297     }
00298     
00299     /* Power control : Exit standby (PDN = 0) */
00300     Value = AUDIO_IO_Read(DeviceAddr, 0x02);
00301     counter += CODEC_IO_Write(DeviceAddr, 0x02, (Value & 0xFE));
00302 
00303     Is_CS42L51_Stop = 0;
00304   }
00305   
00306   /* Return communication control value */
00307   return counter;  
00308 }
00309 
00310 /**
00311   * @brief Pause playing on the audio codec.
00312   * @param DeviceAddr: Device address on communication Bus. 
00313   * @retval 0 if correct communication, else wrong communication
00314   */
00315 uint32_t cs42l51_Pause(uint16_t DeviceAddr)
00316 {  
00317   uint32_t counter = 0;
00318  
00319   /* Pause the audio file playing */
00320   /* Mute the output first */
00321   counter += cs42l51_SetMute(DeviceAddr, AUDIO_MUTE_ON);
00322    
00323   return counter;
00324 }
00325 
00326 /**
00327   * @brief Resume playing on the audio codec.
00328   * @param DeviceAddr: Device address on communication Bus. 
00329   * @retval 0 if correct communication, else wrong communication
00330   */
00331 uint32_t cs42l51_Resume(uint16_t DeviceAddr)
00332 {
00333   uint32_t counter = 0;
00334 
00335   /* Unmute the output  */
00336   counter += cs42l51_SetMute(DeviceAddr, AUDIO_MUTE_OFF);
00337   
00338   return counter;
00339 }
00340 
00341 /**
00342   * @brief Stop audio Codec playing. It powers down the codec.
00343   * @param DeviceAddr: Device address on communication Bus. 
00344   * @param CodecPdwnMode: selects the  power down mode (currently not used).
00345   * @retval 0 if correct communication, else wrong communication
00346   */
00347 uint32_t cs42l51_Stop(uint16_t DeviceAddr, uint32_t CodecPdwnMode)
00348 {
00349   uint32_t counter = 0;
00350   uint8_t  Value;
00351   
00352   /* Set all power down bits to 1 exept PDN to mute ADCs and DACs*/
00353   counter += CODEC_IO_Write(DeviceAddr, 0x02, 0x7E);
00354   Value = AUDIO_IO_Read(DeviceAddr, 0x03);
00355   counter += CODEC_IO_Write(DeviceAddr, 0x03, (Value | 0x0E));
00356   
00357   /* Disable zero cross and soft ramp */
00358   Value = AUDIO_IO_Read(DeviceAddr, 0x09);
00359   counter += CODEC_IO_Write(DeviceAddr, 0x09, (Value & 0xFC));
00360 
00361   /* Power control : Enter standby (PDN = 1) */
00362   Value = AUDIO_IO_Read(DeviceAddr, 0x02);
00363   counter += CODEC_IO_Write(DeviceAddr, 0x02, (Value | 0x01));
00364 
00365   Is_CS42L51_Stop = 1;
00366   return counter;
00367 }
00368 
00369 /**
00370   * @brief Set higher or lower the codec volume level.
00371   * @param DeviceAddr: Device address on communication Bus.   
00372   * @param Volume: output volume level (from 0 (-100dB) to 100 (0dB)).
00373   * @retval 0 if correct communication, else wrong communication
00374   */
00375 uint32_t cs42l51_SetVolume(uint16_t DeviceAddr, uint8_t Volume)
00376 {
00377   uint32_t counter = 0;
00378   uint8_t  convertedvol = VOLUME_CONVERT(Volume);
00379 
00380   /* AOUTA volume control : AOUTA volume */
00381   counter += CODEC_IO_Write(DeviceAddr, 0x16, convertedvol);
00382   /* AOUTB volume control : AOUTB volume */
00383   counter += CODEC_IO_Write(DeviceAddr, 0x17, convertedvol);
00384 
00385   return counter;
00386 }
00387 
00388 /**
00389   * @brief Set new frequency.
00390   * @param DeviceAddr: Device address on communication Bus.   
00391   * @param AudioFreq: Audio frequency used to play the audio stream.
00392   * @retval 0 if correct communication, else wrong communication
00393   */
00394 uint32_t cs42l51_SetFrequency(uint16_t DeviceAddr, uint32_t AudioFreq)
00395 {
00396   return 0;
00397 }
00398 
00399 /**
00400   * @brief Enable or disable the mute feature on the audio codec.
00401   * @param DeviceAddr: Device address on communication Bus.   
00402   * @param Cmd: AUDIO_MUTE_ON to enable the mute or AUDIO_MUTE_OFF to disable the
00403   *             mute mode.
00404   * @retval 0 if correct communication, else wrong communication
00405   */
00406 uint32_t cs42l51_SetMute(uint16_t DeviceAddr, uint32_t Cmd)
00407 {
00408   uint32_t counter = 0;
00409   uint8_t  Value;
00410   
00411   /* Read DAC output control register */
00412   Value = AUDIO_IO_Read(DeviceAddr, 0x08);
00413 
00414   /* Set the Mute mode */
00415   if(Cmd == AUDIO_MUTE_ON)
00416   {
00417     /* Mute DAC channels */
00418     counter += CODEC_IO_Write(DeviceAddr, 0x08, (Value | 0x03));
00419   }
00420   else /* AUDIO_MUTE_OFF Disable the Mute */
00421   {
00422     /* Unmute DAC channels */
00423     counter += CODEC_IO_Write(DeviceAddr, 0x08, (Value & 0xFC));
00424   }
00425   return counter;
00426 }
00427 
00428 /**
00429   * @brief Switch dynamically (while audio file is played) the output target 
00430   *         (speaker, headphone, etc).
00431   * @note This function is currently not used (only headphone output device).
00432   * @param DeviceAddr: Device address on communication Bus.
00433   * @param Output: specifies the audio output device target. 
00434   * @retval 0 if correct communication, else wrong communication
00435   */
00436 uint32_t cs42l51_SetOutputMode(uint16_t DeviceAddr, uint8_t Output)
00437 {
00438   return 0;
00439 }
00440 
00441 /**
00442   * @brief Reset CS42L51 registers.
00443   * @param DeviceAddr: Device address on communication Bus. 
00444   * @retval 0 if correct communication, else wrong communication
00445   */
00446 uint32_t cs42l51_Reset(uint16_t DeviceAddr)
00447 {
00448   if(Is_CS42L51_Initialized == 1)
00449   {
00450     /* Deinitialize Audio Codec interface */
00451     AUDIO_IO_DeInit();
00452 
00453     /* Initialize the Control interface of the Audio Codec */
00454     AUDIO_IO_Init();
00455   }
00456   return 0;
00457 }
00458 
00459 /**
00460   * @}
00461   */
00462 
00463 /** @addtogroup CS42L51_Private_Functions
00464   * @{
00465   */ 
00466 
00467 /**
00468   * @brief  Write and optionally read back a single data.
00469   * @param  Addr: I2C address
00470   * @param  Reg: Reg address 
00471   * @param  Value: Data to be written
00472   * @retval None
00473   */
00474 static uint8_t CODEC_IO_Write(uint8_t Addr, uint8_t Reg, uint8_t Value)
00475 {
00476   uint32_t result = 0;
00477   
00478   AUDIO_IO_Write(Addr, Reg, Value);
00479   
00480 #ifdef VERIFY_WRITTENDATA
00481   /* Verify that the data has been correctly written */  
00482   result = (AUDIO_IO_Read(Addr, Reg) == Value)? 0:1;
00483 #endif /* VERIFY_WRITTENDATA */
00484   
00485   return result;
00486 }
00487 
00488 /**
00489   * @}
00490   */
00491 
00492 /**
00493   * @}
00494   */
00495 
00496 /**
00497   * @}
00498   */
00499 
00500 /**
00501   * @}
00502   */
00503 
00504 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/