Felipe Gomes / BSP_DISCO_F469NI

Dependents:   Aprendendo Final_v3

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