cs43l22.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. /**
  2. ******************************************************************************
  3. * @file cs43l22.c
  4. * @author MCD Application Team
  5. * @version V2.0.2
  6. * @date 06-October-2015
  7. * @brief This file provides the CS43L22 Audio Codec driver.
  8. ******************************************************************************
  9. * @attention
  10. *
  11. * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
  12. *
  13. * Redistribution and use in source and binary forms, with or without modification,
  14. * are permitted provided that the following conditions are met:
  15. * 1. Redistributions of source code must retain the above copyright notice,
  16. * this list of conditions and the following disclaimer.
  17. * 2. Redistributions in binary form must reproduce the above copyright notice,
  18. * this list of conditions and the following disclaimer in the documentation
  19. * and/or other materials provided with the distribution.
  20. * 3. Neither the name of STMicroelectronics nor the names of its contributors
  21. * may be used to endorse or promote products derived from this software
  22. * without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  25. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  27. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  28. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  30. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  31. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  32. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  33. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. ******************************************************************************
  36. */
  37. /* Includes ------------------------------------------------------------------*/
  38. #include "cs43l22.h"
  39. /** @addtogroup BSP
  40. * @{
  41. */
  42. /** @addtogroup Components
  43. * @{
  44. */
  45. /** @addtogroup CS43L22
  46. * @brief This file provides a set of functions needed to drive the
  47. * CS43L22 audio codec.
  48. * @{
  49. */
  50. /** @defgroup CS43L22_Private_Types
  51. * @{
  52. */
  53. /**
  54. * @}
  55. */
  56. /** @defgroup CS43L22_Private_Defines
  57. * @{
  58. */
  59. #define VOLUME_CONVERT(Volume) (((Volume) > 100)? 100:((uint8_t)(((Volume) * 255) / 100)))
  60. /* Uncomment this line to enable verifying data sent to codec after each write
  61. operation (for debug purpose) */
  62. #if !defined (VERIFY_WRITTENDATA)
  63. /* #define VERIFY_WRITTENDATA */
  64. #endif /* VERIFY_WRITTENDATA */
  65. /**
  66. * @}
  67. */
  68. /** @defgroup CS43L22_Private_Macros
  69. * @{
  70. */
  71. /**
  72. * @}
  73. */
  74. /** @defgroup CS43L22_Private_Variables
  75. * @{
  76. */
  77. /* Audio codec driver structure initialization */
  78. AUDIO_DrvTypeDef cs43l22_drv =
  79. {
  80. cs43l22_Init,
  81. cs43l22_DeInit,
  82. cs43l22_ReadID,
  83. cs43l22_Play,
  84. cs43l22_Pause,
  85. cs43l22_Resume,
  86. cs43l22_Stop,
  87. cs43l22_SetFrequency,
  88. cs43l22_SetVolume,
  89. cs43l22_SetMute,
  90. cs43l22_SetOutputMode,
  91. cs43l22_Reset,
  92. };
  93. static uint8_t Is_cs43l22_Stop = 1;
  94. volatile uint8_t OutputDev = 0;
  95. /**
  96. * @}
  97. */
  98. /** @defgroup CS43L22_Function_Prototypes
  99. * @{
  100. */
  101. static uint8_t CODEC_IO_Write(uint8_t Addr, uint8_t Reg, uint8_t Value);
  102. /**
  103. * @}
  104. */
  105. /** @defgroup CS43L22_Private_Functions
  106. * @{
  107. */
  108. /**
  109. * @brief Initializes the audio codec and the control interface.
  110. * @param DeviceAddr: Device address on communication Bus.
  111. * @param OutputDevice: can be OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
  112. * OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO .
  113. * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max))
  114. * @retval 0 if correct communication, else wrong communication
  115. */
  116. uint32_t cs43l22_Init(uint16_t DeviceAddr, uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
  117. {
  118. uint32_t counter = 0;
  119. /* Initialize the Control interface of the Audio Codec */
  120. AUDIO_IO_Init();
  121. /* Keep Codec powered OFF */
  122. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL1, 0x01);
  123. /*Save Output device for mute ON/OFF procedure*/
  124. switch (OutputDevice)
  125. {
  126. case OUTPUT_DEVICE_SPEAKER:
  127. OutputDev = 0xFA;
  128. break;
  129. case OUTPUT_DEVICE_HEADPHONE:
  130. OutputDev = 0xAF;
  131. break;
  132. case OUTPUT_DEVICE_BOTH:
  133. OutputDev = 0xAA;
  134. break;
  135. case OUTPUT_DEVICE_AUTO:
  136. OutputDev = 0x05;
  137. break;
  138. default:
  139. OutputDev = 0x05;
  140. break;
  141. }
  142. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, OutputDev);
  143. /* Clock configuration: Auto detection */
  144. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_CLOCKING_CTL, 0x81);
  145. /* Set the Slave Mode and the audio Standard */
  146. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_INTERFACE_CTL1, CODEC_STANDARD);
  147. /* Set the Master volume */
  148. counter += cs43l22_SetVolume(DeviceAddr, Volume);
  149. /* If the Speaker is enabled, set the Mono mode and volume attenuation level */
  150. if(OutputDevice != OUTPUT_DEVICE_HEADPHONE)
  151. {
  152. /* Set the Speaker Mono mode */
  153. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_PLAYBACK_CTL2, 0x06);
  154. /* Set the Speaker attenuation level */
  155. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_SPEAKER_A_VOL, 0x00);
  156. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_SPEAKER_B_VOL, 0x00);
  157. }
  158. /* Additional configuration for the CODEC. These configurations are done to reduce
  159. the time needed for the Codec to power off. If these configurations are removed,
  160. then a long delay should be added between powering off the Codec and switching
  161. off the I2S peripheral MCLK clock (which is the operating clock for Codec).
  162. If this delay is not inserted, then the codec will not shut down properly and
  163. it results in high noise after shut down. */
  164. /* Disable the analog soft ramp */
  165. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_ANALOG_ZC_SR_SETT, 0x00);
  166. /* Disable the digital soft ramp */
  167. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MISC_CTL, 0x04);
  168. /* Disable the limiter attack level */
  169. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_LIMIT_CTL1, 0x00);
  170. /* Adjust Bass and Treble levels */
  171. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_TONE_CTL, 0x0F);
  172. /* Adjust PCM volume level */
  173. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_PCMA_VOL, 0x0A);
  174. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_PCMB_VOL, 0x0A);
  175. /* Return communication control value */
  176. return counter;
  177. }
  178. /**
  179. * @brief Deinitializes the audio codec.
  180. * @param None
  181. * @retval None
  182. */
  183. void cs43l22_DeInit(void)
  184. {
  185. /* Deinitialize Audio Codec interface */
  186. AUDIO_IO_DeInit();
  187. }
  188. /**
  189. * @brief Get the CS43L22 ID.
  190. * @param DeviceAddr: Device address on communication Bus.
  191. * @retval The CS43L22 ID
  192. */
  193. uint32_t cs43l22_ReadID(uint16_t DeviceAddr)
  194. {
  195. uint8_t Value;
  196. /* Initialize the Control interface of the Audio Codec */
  197. AUDIO_IO_Init();
  198. Value = AUDIO_IO_Read(DeviceAddr, CS43L22_CHIPID_ADDR);
  199. Value = (Value & CS43L22_ID_MASK);
  200. return((uint32_t) Value);
  201. }
  202. /**
  203. * @brief Start the audio Codec play feature.
  204. * @note For this codec no Play options are required.
  205. * @param DeviceAddr: Device address on communication Bus.
  206. * @retval 0 if correct communication, else wrong communication
  207. */
  208. uint32_t cs43l22_Play(uint16_t DeviceAddr, uint16_t* pBuffer, uint16_t Size)
  209. {
  210. uint32_t counter = 0;
  211. if(Is_cs43l22_Stop == 1)
  212. {
  213. /* Enable the digital soft ramp */
  214. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MISC_CTL, 0x06);
  215. /* Enable Output device */
  216. counter += cs43l22_SetMute(DeviceAddr, AUDIO_MUTE_OFF);
  217. /* Power on the Codec */
  218. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL1, 0x9E);
  219. Is_cs43l22_Stop = 0;
  220. }
  221. /* Return communication control value */
  222. return counter;
  223. }
  224. /**
  225. * @brief Pauses playing on the audio codec.
  226. * @param DeviceAddr: Device address on communication Bus.
  227. * @retval 0 if correct communication, else wrong communication
  228. */
  229. uint32_t cs43l22_Pause(uint16_t DeviceAddr)
  230. {
  231. uint32_t counter = 0;
  232. /* Pause the audio file playing */
  233. /* Mute the output first */
  234. counter += cs43l22_SetMute(DeviceAddr, AUDIO_MUTE_ON);
  235. /* Put the Codec in Power save mode */
  236. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL1, 0x01);
  237. return counter;
  238. }
  239. /**
  240. * @brief Resumes playing on the audio codec.
  241. * @param DeviceAddr: Device address on communication Bus.
  242. * @retval 0 if correct communication, else wrong communication
  243. */
  244. uint32_t cs43l22_Resume(uint16_t DeviceAddr)
  245. {
  246. uint32_t counter = 0;
  247. volatile uint32_t index = 0x00;
  248. /* Resumes the audio file playing */
  249. /* Unmute the output first */
  250. counter += cs43l22_SetMute(DeviceAddr, AUDIO_MUTE_OFF);
  251. for(index = 0x00; index < 0xFF; index++);
  252. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, OutputDev);
  253. /* Exit the Power save mode */
  254. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL1, 0x9E);
  255. return counter;
  256. }
  257. /**
  258. * @brief Stops audio Codec playing. It powers down the codec.
  259. * @param DeviceAddr: Device address on communication Bus.
  260. * @param CodecPdwnMode: selects the power down mode.
  261. * - CODEC_PDWN_HW: Physically power down the codec. When resuming from this
  262. * mode, the codec is set to default configuration
  263. * (user should re-Initialize the codec in order to
  264. * play again the audio stream).
  265. * @retval 0 if correct communication, else wrong communication
  266. */
  267. uint32_t cs43l22_Stop(uint16_t DeviceAddr, uint32_t CodecPdwnMode)
  268. {
  269. uint32_t counter = 0;
  270. /* Mute the output first */
  271. counter += cs43l22_SetMute(DeviceAddr, AUDIO_MUTE_ON);
  272. /* Disable the digital soft ramp */
  273. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MISC_CTL, 0x04);
  274. /* Power down the DAC and the speaker (PMDAC and PMSPK bits)*/
  275. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL1, 0x9F);
  276. Is_cs43l22_Stop = 1;
  277. return counter;
  278. }
  279. /**
  280. * @brief Sets higher or lower the codec volume level.
  281. * @param DeviceAddr: Device address on communication Bus.
  282. * @param Volume: a byte value from 0 to 255 (refer to codec registers
  283. * description for more details).
  284. * @retval 0 if correct communication, else wrong communication
  285. */
  286. uint32_t cs43l22_SetVolume(uint16_t DeviceAddr, uint8_t Volume)
  287. {
  288. uint32_t counter = 0;
  289. uint8_t convertedvol = VOLUME_CONVERT(Volume);
  290. if(Volume > 0xE6)
  291. {
  292. /* Set the Master volume */
  293. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MASTER_A_VOL, convertedvol - 0xE7);
  294. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MASTER_B_VOL, convertedvol - 0xE7);
  295. }
  296. else
  297. {
  298. /* Set the Master volume */
  299. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MASTER_A_VOL, convertedvol + 0x19);
  300. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_MASTER_B_VOL, convertedvol + 0x19);
  301. }
  302. return counter;
  303. }
  304. /**
  305. * @brief Sets new frequency.
  306. * @param DeviceAddr: Device address on communication Bus.
  307. * @param AudioFreq: Audio frequency used to play the audio stream.
  308. * @retval 0 if correct communication, else wrong communication
  309. */
  310. uint32_t cs43l22_SetFrequency(uint16_t DeviceAddr, uint32_t AudioFreq)
  311. {
  312. return 0;
  313. }
  314. /**
  315. * @brief Enables or disables the mute feature on the audio codec.
  316. * @param DeviceAddr: Device address on communication Bus.
  317. * @param Cmd: AUDIO_MUTE_ON to enable the mute or AUDIO_MUTE_OFF to disable the
  318. * mute mode.
  319. * @retval 0 if correct communication, else wrong communication
  320. */
  321. uint32_t cs43l22_SetMute(uint16_t DeviceAddr, uint32_t Cmd)
  322. {
  323. uint32_t counter = 0;
  324. /* Set the Mute mode */
  325. if(Cmd == AUDIO_MUTE_ON)
  326. {
  327. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0xFF);
  328. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_HEADPHONE_A_VOL, 0x01);
  329. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_HEADPHONE_B_VOL, 0x01);
  330. }
  331. else /* AUDIO_MUTE_OFF Disable the Mute */
  332. {
  333. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_HEADPHONE_A_VOL, 0x00);
  334. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_HEADPHONE_B_VOL, 0x00);
  335. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, OutputDev);
  336. }
  337. return counter;
  338. }
  339. /**
  340. * @brief Switch dynamically (while audio file is played) the output target
  341. * (speaker or headphone).
  342. * @note This function modifies a global variable of the audio codec driver: OutputDev.
  343. * @param DeviceAddr: Device address on communication Bus.
  344. * @param Output: specifies the audio output target: OUTPUT_DEVICE_SPEAKER,
  345. * OUTPUT_DEVICE_HEADPHONE, OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO
  346. * @retval 0 if correct communication, else wrong communication
  347. */
  348. uint32_t cs43l22_SetOutputMode(uint16_t DeviceAddr, uint8_t Output)
  349. {
  350. uint32_t counter = 0;
  351. switch (Output)
  352. {
  353. case OUTPUT_DEVICE_SPEAKER:
  354. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0xFA); /* SPK always ON & HP always OFF */
  355. OutputDev = 0xFA;
  356. break;
  357. case OUTPUT_DEVICE_HEADPHONE:
  358. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0xAF); /* SPK always OFF & HP always ON */
  359. OutputDev = 0xAF;
  360. break;
  361. case OUTPUT_DEVICE_BOTH:
  362. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0xAA); /* SPK always ON & HP always ON */
  363. OutputDev = 0xAA;
  364. break;
  365. case OUTPUT_DEVICE_AUTO:
  366. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0x05); /* Detect the HP or the SPK automatically */
  367. OutputDev = 0x05;
  368. break;
  369. default:
  370. counter += CODEC_IO_Write(DeviceAddr, CS43L22_REG_POWER_CTL2, 0x05); /* Detect the HP or the SPK automatically */
  371. OutputDev = 0x05;
  372. break;
  373. }
  374. return counter;
  375. }
  376. /**
  377. * @brief Resets cs43l22 registers.
  378. * @param DeviceAddr: Device address on communication Bus.
  379. * @retval 0 if correct communication, else wrong communication
  380. */
  381. uint32_t cs43l22_Reset(uint16_t DeviceAddr)
  382. {
  383. return 0;
  384. }
  385. /**
  386. * @brief Writes/Read a single data.
  387. * @param Addr: I2C address
  388. * @param Reg: Reg address
  389. * @param Value: Data to be written
  390. * @retval None
  391. */
  392. static uint8_t CODEC_IO_Write(uint8_t Addr, uint8_t Reg, uint8_t Value)
  393. {
  394. uint32_t result = 0;
  395. AUDIO_IO_Write(Addr, Reg, Value);
  396. #ifdef VERIFY_WRITTENDATA
  397. /* Verify that the data has been correctly written */
  398. result = (AUDIO_IO_Read(Addr, Reg) == Value)? 0:1;
  399. #endif /* VERIFY_WRITTENDATA */
  400. return result;
  401. }
  402. /**
  403. * @}
  404. */
  405. /**
  406. * @}
  407. */
  408. /**
  409. * @}
  410. */
  411. /**
  412. * @}
  413. */
  414. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/