Senior Design: Sound Monitor / BSP

Dependencies:   CMSIS_STM32L4xx CMSIS_DSP_401 STM32L4xx_HAL_Driver

Dependents:   DiscoAudioRecord

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.1
00006   * @date    16-September-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 /* Uncomment this line to enable verifying data sent to codec after each write 
00067    operation (for debug purpose) */
00068 #if !defined (VERIFY_WRITTENDATA)  
00069 /* #define VERIFY_WRITTENDATA */
00070 #endif /* VERIFY_WRITTENDATA */
00071 /**
00072   * @}
00073   */ 
00074 
00075 /** @defgroup CS43L22_Private_Macros
00076   * @{
00077   */
00078 
00079 /**
00080   * @}
00081   */ 
00082   
00083 /** @defgroup CS43L22_Private_Variables
00084   * @{
00085   */
00086 
00087 /* Audio codec driver structure initialization */  
00088 AUDIO_DrvTypeDef cs43l22_drv = 
00089 {
00090   cs43l22_Init,
00091   cs43l22_DeInit,
00092   cs43l22_ReadID,
00093 
00094   cs43l22_Play,
00095   cs43l22_Pause,
00096   cs43l22_Resume,
00097   cs43l22_Stop,  
00098   
00099   cs43l22_SetFrequency,  
00100   cs43l22_SetVolume,
00101   cs43l22_SetMute,  
00102   cs43l22_SetOutputMode,
00103   cs43l22_Reset,
00104 };
00105 
00106 static uint8_t Is_cs43l22_Stop = 1;
00107 
00108 volatile uint8_t OutputDev = 0;
00109 
00110 /**
00111   * @}
00112   */ 
00113 
00114 /** @defgroup CS43L22_Function_Prototypes
00115   * @{
00116   */
00117 static uint8_t CODEC_IO_Write(uint8_t Addr, uint8_t Reg, uint8_t Value);
00118 /**
00119   * @}
00120   */ 
00121 
00122 /** @defgroup CS43L22_Private_Functions
00123   * @{
00124   */ 
00125 
00126 /**
00127   * @brief Initializes the audio codec and the control interface.
00128   * @param DeviceAddr: Device address on communication Bus.   
00129   * @param OutputDevice: can be OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
00130   *                       OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO .
00131   * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max))
00132   * @retval 0 if correct communication, else wrong communication
00133   */
00134 uint32_t cs43l22_Init(uint16_t DeviceAddr, uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
00135 {
00136   uint32_t counter = 0;
00137   
00138   /* Initialize the Control interface of the Audio Codec */
00139   AUDIO_IO_Init();     
00140     
00141   /* Keep Codec powered OFF */
00142   counter += CODEC_IO_Write(DeviceAddr, 0x02, 0x01);  
00143   
00144   /*Save Output device for mute ON/OFF procedure*/
00145   switch (OutputDevice)
00146   {
00147   case OUTPUT_DEVICE_SPEAKER:
00148     OutputDev = 0xFA;
00149     break;
00150     
00151   case OUTPUT_DEVICE_HEADPHONE:
00152     OutputDev = 0xAF;
00153     break;
00154     
00155   case OUTPUT_DEVICE_BOTH:
00156     OutputDev = 0xAA;
00157     break;
00158     
00159   case OUTPUT_DEVICE_AUTO:
00160     OutputDev = 0x05;
00161     break;    
00162     
00163   default:
00164     OutputDev = 0x05;
00165     break;    
00166   }
00167   
00168   counter += CODEC_IO_Write(DeviceAddr, 0x04, OutputDev);
00169   
00170   /* Clock configuration: Auto detection */  
00171   counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x81);
00172   
00173   /* Set the Slave Mode and the audio Standard */  
00174   counter += CODEC_IO_Write(DeviceAddr, 0x06, CODEC_STANDARD);
00175   
00176   /* Set the Master volume */
00177   counter += cs43l22_SetVolume(DeviceAddr, Volume);
00178   
00179   /* If the Speaker is enabled, set the Mono mode and volume attenuation level */
00180   if(OutputDevice != OUTPUT_DEVICE_HEADPHONE)
00181   {
00182     /* Set the Speaker Mono mode */  
00183     counter += CODEC_IO_Write(DeviceAddr, 0x0F , 0x06);
00184     
00185     /* Set the Speaker attenuation level */  
00186     counter += CODEC_IO_Write(DeviceAddr, 0x24, 0x00);
00187     counter += CODEC_IO_Write(DeviceAddr, 0x25, 0x00);
00188   }
00189   
00190   /* Additional configuration for the CODEC. These configurations are done to reduce
00191   the time needed for the Codec to power off. If these configurations are removed, 
00192   then a long delay should be added between powering off the Codec and switching 
00193   off the I2S peripheral MCLK clock (which is the operating clock for Codec).
00194   If this delay is not inserted, then the codec will not shut down properly and
00195   it results in high noise after shut down. */
00196   
00197   /* Disable the analog soft ramp */
00198   counter += CODEC_IO_Write(DeviceAddr, 0x0A, 0x00);
00199   /* Disable the digital soft ramp */
00200   counter += CODEC_IO_Write(DeviceAddr, 0x0E, 0x04);
00201   /* Disable the limiter attack level */
00202   counter += CODEC_IO_Write(DeviceAddr, 0x27, 0x00);
00203   /* Adjust Bass and Treble levels */
00204   counter += CODEC_IO_Write(DeviceAddr, 0x1F, 0x0F);
00205   /* Adjust PCM volume level */
00206   counter += CODEC_IO_Write(DeviceAddr, 0x1A, 0x0A);
00207   counter += CODEC_IO_Write(DeviceAddr, 0x1B, 0x0A);
00208   
00209   /* Return communication control value */
00210   return counter;  
00211 }
00212 
00213 /**
00214   * @brief  Deinitializes the audio codec.
00215   * @param  None
00216   * @retval  None
00217   */
00218 void cs43l22_DeInit(void)
00219 {
00220   /* Deinitialize Audio Codec interface */
00221   AUDIO_IO_DeInit();
00222 }
00223 
00224 /**
00225   * @brief  Get the CS43L22 ID.
00226   * @param DeviceAddr: Device address on communication Bus.   
00227   * @retval The CS43L22 ID 
00228   */
00229 uint32_t cs43l22_ReadID(uint16_t DeviceAddr)
00230 {
00231   uint8_t Value;
00232   /* Initialize the Control interface of the Audio Codec */
00233   AUDIO_IO_Init(); 
00234   
00235   Value = AUDIO_IO_Read(DeviceAddr, CS43L22_CHIPID_ADDR);
00236   Value = (Value & CS43L22_ID_MASK);
00237   
00238   return((uint32_t) Value);
00239 }
00240 
00241 /**
00242   * @brief Start the audio Codec play feature.
00243   * @note For this codec no Play options are required.
00244   * @param DeviceAddr: Device address on communication Bus.   
00245   * @retval 0 if correct communication, else wrong communication
00246   */
00247 uint32_t cs43l22_Play(uint16_t DeviceAddr, uint16_t* pBuffer, uint16_t Size)
00248 {
00249   uint32_t counter = 0;
00250   
00251   if(Is_cs43l22_Stop == 1)
00252   {
00253     /* Enable the digital soft ramp */
00254     counter += CODEC_IO_Write(DeviceAddr, 0x0E, 0x06);
00255   
00256     /* Enable Output device */  
00257     counter += cs43l22_SetMute(DeviceAddr, AUDIO_MUTE_OFF);
00258     
00259     /* Power on the Codec */
00260     counter += CODEC_IO_Write(DeviceAddr, 0x02, 0x9E);  
00261     Is_cs43l22_Stop = 0;
00262   }
00263   
00264   /* Return communication control value */
00265   return counter;  
00266 }
00267 
00268 /**
00269   * @brief Pauses playing on the audio codec.
00270   * @param DeviceAddr: Device address on communication Bus. 
00271   * @retval 0 if correct communication, else wrong communication
00272   */
00273 uint32_t cs43l22_Pause(uint16_t DeviceAddr)
00274 {  
00275   uint32_t counter = 0;
00276  
00277   /* Pause the audio file playing */
00278   /* Mute the output first */
00279   counter += cs43l22_SetMute(DeviceAddr, AUDIO_MUTE_ON);
00280   
00281   /* Put the Codec in Power save mode */    
00282   counter += CODEC_IO_Write(DeviceAddr,0x02, 0x01);
00283  
00284   return counter;
00285 }
00286 
00287 /**
00288   * @brief Resumes playing on the audio codec.
00289   * @param DeviceAddr: Device address on communication Bus. 
00290   * @retval 0 if correct communication, else wrong communication
00291   */
00292 uint32_t cs43l22_Resume(uint16_t DeviceAddr)
00293 {
00294   uint32_t counter = 0;
00295   volatile uint32_t index = 0x00;
00296   /* Resumes the audio file playing */  
00297   /* Unmute the output first */
00298   counter += cs43l22_SetMute(DeviceAddr, AUDIO_MUTE_OFF);
00299 
00300   for(index = 0x00; index < 0xFF; index++);
00301   
00302   counter += CODEC_IO_Write(DeviceAddr,0x04, OutputDev);
00303 
00304   /* Exit the Power save mode */
00305   counter += CODEC_IO_Write(DeviceAddr,0x02, 0x9E); 
00306   
00307   return counter;
00308 }
00309 
00310 /**
00311   * @brief Stops audio Codec playing. It powers down the codec.
00312   * @param DeviceAddr: Device address on communication Bus. 
00313   * @param CodecPdwnMode: selects the  power down mode.
00314   *          - CODEC_PDWN_HW: Physically power down the codec. When resuming from this
00315   *                           mode, the codec is set to default configuration 
00316   *                           (user should re-Initialize the codec in order to 
00317   *                            play again the audio stream).
00318   * @retval 0 if correct communication, else wrong communication
00319   */
00320 uint32_t cs43l22_Stop(uint16_t DeviceAddr, uint32_t CodecPdwnMode)
00321 {
00322   uint32_t counter = 0;
00323   
00324   /* Mute the output first */
00325   counter += cs43l22_SetMute(DeviceAddr, AUDIO_MUTE_ON);
00326 
00327   /* Disable the digital soft ramp */
00328   counter += CODEC_IO_Write(DeviceAddr, 0x0E, 0x04);
00329   
00330   /* Power down the DAC and the speaker (PMDAC and PMSPK bits)*/
00331   counter += CODEC_IO_Write(DeviceAddr, 0x02, 0x9F);
00332   
00333   Is_cs43l22_Stop = 1;
00334   return counter;    
00335 }
00336 
00337 /**
00338   * @brief Sets higher or lower the codec volume level.
00339   * @param DeviceAddr: Device address on communication Bus.   
00340   * @param Volume: a byte value from 0 to 255 (refer to codec registers 
00341   *         description for more details).
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(Volume > 0xE6)
00350   {
00351     /* Set the Master volume */
00352     counter += CODEC_IO_Write(DeviceAddr, 0x20, convertedvol - 0xE7); 
00353     counter += CODEC_IO_Write(DeviceAddr, 0x21, convertedvol - 0xE7);     
00354   }
00355   else
00356   {
00357     /* Set the Master volume */
00358     counter += CODEC_IO_Write(DeviceAddr, 0x20, convertedvol + 0x19); 
00359     counter += CODEC_IO_Write(DeviceAddr, 0x21, 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, 0x04, 0xFF);
00391     counter += CODEC_IO_Write(DeviceAddr, 0x22, 0x01);
00392     counter += CODEC_IO_Write(DeviceAddr, 0x23, 0x01);
00393   }
00394   else /* AUDIO_MUTE_OFF Disable the Mute */
00395   {
00396     counter += CODEC_IO_Write(DeviceAddr, 0x22, 0x00);
00397     counter += CODEC_IO_Write(DeviceAddr, 0x23, 0x00);
00398     counter += CODEC_IO_Write(DeviceAddr, 0x04, 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, 0x04, 0xFA); /* SPK always ON & HP always OFF */
00420       OutputDev = 0xFA;
00421       break;
00422       
00423     case OUTPUT_DEVICE_HEADPHONE:
00424       counter += CODEC_IO_Write(DeviceAddr, 0x04, 0xAF); /* SPK always OFF & HP always ON */
00425       OutputDev = 0xAF;
00426       break;
00427       
00428     case OUTPUT_DEVICE_BOTH:
00429       counter += CODEC_IO_Write(DeviceAddr, 0x04, 0xAA); /* SPK always ON & HP always ON */
00430       OutputDev = 0xAA;
00431       break;
00432       
00433     case OUTPUT_DEVICE_AUTO:
00434       counter += CODEC_IO_Write(DeviceAddr, 0x04, 0x05); /* Detect the HP or the SPK automatically */
00435       OutputDev = 0x05;
00436       break;    
00437       
00438     default:
00439       counter += CODEC_IO_Write(DeviceAddr, 0x04, 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****/
00494