drv_sound.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Date Author Notes
  7. * 2019-07-31 Zero-Free first implementation
  8. */
  9. #include <board.h>
  10. #include "drv_sound.h"
  11. #include "drv_es8388.h"
  12. #define DBG_TAG "drv.sound"
  13. #define DBG_LVL DBG_LOG
  14. #include <rtdbg.h>
  15. #define TX_FIFO_SIZE (2048)
  16. struct sound_device
  17. {
  18. struct rt_audio_device audio;
  19. struct rt_audio_configure replay_config;
  20. rt_uint8_t *tx_fifo;
  21. rt_uint8_t volume;
  22. };
  23. static struct sound_device snd_dev = {0};
  24. static I2S_HandleTypeDef I2S3_Handler = {0};
  25. static DMA_HandleTypeDef I2S3_TXDMA_Handler = {0};
  26. /**
  27. * 采样率计算公式:Fs=I2SxCLK/[256*(2*I2SDIV+ODD)]
  28. * I2SxCLK=(HSE/pllm)*PLLI2SN/PLLI2SR
  29. * 一般HSE=8Mhz
  30. * pllm:在Sys_Clock_Set设置的时候确定,一般是8
  31. * PLLI2SN:一般是192~432
  32. * PLLI2SR:2~7
  33. * I2SDIV:2~255
  34. * ODD:0/1
  35. * I2S分频系数表@pllm=8,HSE=8Mhz,即vco输入频率为1Mhz
  36. * 表格式:采样率/10,PLLI2SN,PLLI2SR,I2SDIV,ODD
  37. */
  38. const uint16_t I2S_PSC_TBL[][5]=
  39. {
  40. { 800, 256, 5, 12, 1 }, /* 8Khz采样率 */
  41. { 1102, 429, 4, 19, 0 }, /* 11.025Khz采样率 */
  42. { 1600, 213, 2, 13, 0 }, /* 16Khz采样率 */
  43. { 2205, 429, 4, 9, 1 }, /* 22.05Khz采样率 */
  44. { 3200, 213, 2, 6, 1 }, /* 32Khz采样率 */
  45. { 4410, 271, 2, 6, 0 }, /* 44.1Khz采样率 */
  46. { 4800, 258, 3, 3, 1 }, /* 48Khz采样率 */
  47. { 8820, 316, 2, 3, 1 }, /* 88.2Khz采样率 */
  48. { 9600, 344, 2, 3, 1 }, /* 96Khz采样率 */
  49. { 17640, 361, 2, 2, 0 }, /* 176.4Khz采样率 */
  50. { 19200, 393, 2, 2, 0 }, /* 192Khz采样率 */
  51. };
  52. static void I2S3_Init(void)
  53. {
  54. RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
  55. PeriphClkInitStruct.PeriphClockSelection |= RCC_PERIPHCLK_I2S;
  56. PeriphClkInitStruct.PLLI2S.PLLI2SN = 192;
  57. PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
  58. if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  59. {
  60. Error_Handler();
  61. }
  62. HAL_I2S_DeInit(&I2S3_Handler);
  63. I2S3_Handler.Instance = SPI3;
  64. I2S3_Handler.Init.Mode = I2S_MODE_MASTER_TX;
  65. I2S3_Handler.Init.Standard = I2S_STANDARD_PHILIPS;
  66. I2S3_Handler.Init.DataFormat = I2S_DATAFORMAT_16B;
  67. I2S3_Handler.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
  68. I2S3_Handler.Init.AudioFreq = I2S_AUDIOFREQ_44K;
  69. I2S3_Handler.Init.CPOL = I2S_CPOL_LOW;
  70. I2S3_Handler.Init.ClockSource = I2S_CLOCK_PLL;
  71. I2S3_Handler.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_ENABLE;
  72. if (HAL_I2S_Init(&I2S3_Handler) != HAL_OK)
  73. {
  74. Error_Handler();
  75. }
  76. SET_BIT(I2S3_Handler.Instance->CR2, SPI_CR2_TXDMAEN);
  77. __HAL_I2S_ENABLE(&I2S3_Handler);
  78. /* Configure DMA used for I2S3 */
  79. __HAL_RCC_DMA1_CLK_ENABLE();
  80. I2S3_TXDMA_Handler.Instance = DMA1_Stream7;
  81. I2S3_TXDMA_Handler.Init.Channel = DMA_CHANNEL_0;
  82. I2S3_TXDMA_Handler.Init.Direction = DMA_MEMORY_TO_PERIPH;
  83. I2S3_TXDMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;
  84. I2S3_TXDMA_Handler.Init.MemInc = DMA_MINC_ENABLE;
  85. I2S3_TXDMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
  86. I2S3_TXDMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
  87. I2S3_TXDMA_Handler.Init.Mode = DMA_CIRCULAR;
  88. I2S3_TXDMA_Handler.Init.Priority = DMA_PRIORITY_HIGH;
  89. I2S3_TXDMA_Handler.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  90. __HAL_LINKDMA(&I2S3_Handler,hdmatx,I2S3_TXDMA_Handler);
  91. HAL_DMA_DeInit(&I2S3_TXDMA_Handler);
  92. HAL_DMA_Init(&I2S3_TXDMA_Handler);
  93. // __HAL_DMA_ENABLE(&I2S3_TXDMA_Handler);
  94. __HAL_DMA_DISABLE(&I2S3_TXDMA_Handler);
  95. __HAL_DMA_ENABLE_IT(&I2S3_TXDMA_Handler, DMA_IT_TC); /* 开启传输完成中断 */
  96. __HAL_DMA_CLEAR_FLAG(&I2S3_TXDMA_Handler, DMA_FLAG_TCIF0_4);
  97. HAL_NVIC_SetPriority(DMA1_Stream7_IRQn, 0, 0);
  98. HAL_NVIC_EnableIRQ(DMA1_Stream7_IRQn);
  99. }
  100. void DMA1_Stream7_IRQHandler(void)
  101. {
  102. rt_audio_tx_complete(&snd_dev.audio);
  103. HAL_DMA_IRQHandler(&I2S3_TXDMA_Handler);
  104. }
  105. //void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
  106. //{
  107. // if (hsai == &SAI1A_Handler)
  108. // {
  109. // rt_audio_tx_complete(&snd_dev.audio);
  110. // }
  111. //}
  112. //void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
  113. //{
  114. // if (hsai == &SAI1A_Handler)
  115. // {
  116. // rt_audio_tx_complete(&snd_dev.audio);
  117. // }
  118. //}
  119. void I2S_Frequency_Set(uint32_t samplerate)
  120. {
  121. // uint8_t i = 0;
  122. // uint32_t tempreg = 0;
  123. // RCC_PeriphCLKInitTypeDef rcc_i2s_clkinit_struct;
  124. // for (i = 0; i < (sizeof(I2S_PSC_TBL) / 10); i++) /* 看看改采样率是否可以支持 */
  125. // {
  126. // if ((samplerate / 10) == I2S_PSC_TBL[i][0])
  127. // {
  128. // break;
  129. // }
  130. // }
  131. // if (i == (sizeof(I2S_PSC_TBL) / 10))
  132. // {
  133. // LOG_E("samplerate not supported.");
  134. // // return 1; /* 找不到 */
  135. // }
  136. // rcc_i2s_clkinit_struct.PeriphClockSelection = RCC_PERIPHCLK_I2S; /* 外设时钟源选择 */
  137. // rcc_i2s_clkinit_struct.PLLI2S.PLLI2SN = (uint32_t)I2S_PSC_TBL[i][1]; /* 设置PLLI2SN */
  138. // rcc_i2s_clkinit_struct.PLLI2S.PLLI2SR = (uint32_t)I2S_PSC_TBL[i][2]; /* 设置PLLI2SR */
  139. // HAL_RCCEx_PeriphCLKConfig(&rcc_i2s_clkinit_struct); /* 设置时钟 */
  140. // RCC->CR |= 1 << 26; /* 开启I2S时钟 */
  141. // while((RCC->CR & 1 << 27) == 0); /* 等待I2S时钟开启成功. */
  142. // tempreg = I2S_PSC_TBL[i][3] << 0; /* 设置I2SDIV */
  143. // tempreg |= I2S_PSC_TBL[i][4] << 8; /* 设置ODD位 */
  144. // tempreg |= 1 << 9; /* 使能MCKOE位,输出MCK */
  145. // I2S3_Handler.Instance->I2SPR = tempreg; /* 设置I2SPR寄存器 */
  146. // return 0;
  147. // RCC_PeriphCLKInitTypeDef PeriphClkInit;
  148. // HAL_RCCEx_GetPeriphCLKConfig(&PeriphClkInit);
  149. // if ((frequency == SAI_AUDIO_FREQUENCY_11K) || (frequency == SAI_AUDIO_FREQUENCY_22K) || (frequency == SAI_AUDIO_FREQUENCY_44K))
  150. // {
  151. // /* Configure and enable PLLSAI1 clock to generate 45.714286MHz */
  152. // PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
  153. // PeriphClkInit.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI2;
  154. // PeriphClkInit.PLLSAI2.PLLSAI2Source = RCC_PLLSOURCE_HSE;
  155. // PeriphClkInit.PLLSAI2.PLLSAI2M = 1;
  156. // PeriphClkInit.PLLSAI2.PLLSAI2N = 40;
  157. // PeriphClkInit.PLLSAI2.PLLSAI2ClockOut = RCC_PLLSAI2_SAI2CLK;
  158. // HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
  159. // }
  160. // else
  161. // {
  162. // /* Configure and enable PLLSAI1 clock to generate 49.142857MHz */
  163. // PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
  164. // PeriphClkInit.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI2;
  165. // PeriphClkInit.PLLSAI2.PLLSAI2Source = RCC_PLLSOURCE_HSE;
  166. // PeriphClkInit.PLLSAI2.PLLSAI2M = 1;
  167. // PeriphClkInit.PLLSAI2.PLLSAI2N = 43;
  168. // PeriphClkInit.PLLSAI2.PLLSAI2P = RCC_PLLP_DIV7;
  169. // PeriphClkInit.PLLSAI2.PLLSAI2ClockOut = RCC_PLLSAI2_SAI2CLK;
  170. // HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
  171. // }
  172. // /* Disable SAI peripheral to allow access to SAI internal registers */
  173. // __HAL_SAI_DISABLE(&SAI1A_Handler);
  174. // /* Update the SAI audio frequency configuration */
  175. // SAI1A_Handler.Init.AudioFrequency = frequency;
  176. // HAL_SAI_Init(&SAI1A_Handler);
  177. // /* Enable SAI peripheral to generate MCLK */
  178. // __HAL_SAI_ENABLE(&SAI1A_Handler);
  179. }
  180. void SAIA_Channels_Set(uint8_t channels)
  181. {
  182. // if (channels == 1)
  183. // {
  184. // SAI1A_Handler.Init.MonoStereoMode = SAI_MONOMODE;
  185. // }
  186. // else
  187. // {
  188. // SAI1A_Handler.Init.MonoStereoMode = SAI_STEREOMODE;
  189. // }
  190. // __HAL_SAI_DISABLE(&SAI1A_Handler);
  191. // HAL_SAI_Init(&SAI1A_Handler);
  192. // __HAL_SAI_ENABLE(&SAI1A_Handler);
  193. }
  194. /**
  195. * RT-Thread Audio Device Driver Interface
  196. */
  197. static rt_err_t sound_getcaps(struct rt_audio_device *audio, struct rt_audio_caps *caps)
  198. {
  199. rt_err_t result = RT_EOK;
  200. struct sound_device *snd_dev;
  201. RT_ASSERT(audio != RT_NULL);
  202. snd_dev = (struct sound_device *)audio->parent.user_data;
  203. switch (caps->main_type)
  204. {
  205. case AUDIO_TYPE_QUERY: /* qurey the types of hw_codec device */
  206. {
  207. switch (caps->sub_type)
  208. {
  209. case AUDIO_TYPE_QUERY:
  210. caps->udata.mask = AUDIO_TYPE_OUTPUT | AUDIO_TYPE_MIXER;
  211. break;
  212. default:
  213. result = -RT_ERROR;
  214. break;
  215. }
  216. break;
  217. }
  218. case AUDIO_TYPE_OUTPUT: /* Provide capabilities of OUTPUT unit */
  219. {
  220. switch (caps->sub_type)
  221. {
  222. case AUDIO_DSP_PARAM:
  223. caps->udata.config.samplerate = snd_dev->replay_config.samplerate;
  224. caps->udata.config.channels = snd_dev->replay_config.channels;
  225. caps->udata.config.samplebits = snd_dev->replay_config.samplebits;
  226. break;
  227. case AUDIO_DSP_SAMPLERATE:
  228. caps->udata.config.samplerate = snd_dev->replay_config.samplerate;
  229. break;
  230. case AUDIO_DSP_CHANNELS:
  231. caps->udata.config.channels = snd_dev->replay_config.channels;
  232. break;
  233. case AUDIO_DSP_SAMPLEBITS:
  234. caps->udata.config.samplebits = snd_dev->replay_config.samplebits;
  235. break;
  236. default:
  237. result = -RT_ERROR;
  238. break;
  239. }
  240. break;
  241. }
  242. case AUDIO_TYPE_MIXER: /* report the Mixer Units */
  243. {
  244. switch (caps->sub_type)
  245. {
  246. case AUDIO_MIXER_QUERY:
  247. caps->udata.mask = AUDIO_MIXER_VOLUME;
  248. break;
  249. case AUDIO_MIXER_VOLUME:
  250. caps->udata.value = es8388_volume_get();
  251. break;
  252. default:
  253. result = -RT_ERROR;
  254. break;
  255. }
  256. break;
  257. }
  258. default:
  259. result = -RT_ERROR;
  260. break;
  261. }
  262. return result;
  263. }
  264. static rt_err_t sound_configure(struct rt_audio_device *audio, struct rt_audio_caps *caps)
  265. {
  266. rt_err_t result = RT_EOK;
  267. struct sound_device *snd_dev;
  268. RT_ASSERT(audio != RT_NULL);
  269. snd_dev = (struct sound_device *)audio->parent.user_data;
  270. switch (caps->main_type)
  271. {
  272. case AUDIO_TYPE_MIXER:
  273. {
  274. switch (caps->sub_type)
  275. {
  276. case AUDIO_MIXER_VOLUME:
  277. {
  278. rt_uint8_t volume = caps->udata.value;
  279. es8388_volume_set(volume);
  280. snd_dev->volume = volume;
  281. LOG_D("set volume %d", volume);
  282. break;
  283. }
  284. default:
  285. result = -RT_ERROR;
  286. break;
  287. }
  288. break;
  289. }
  290. case AUDIO_TYPE_OUTPUT:
  291. {
  292. switch (caps->sub_type)
  293. {
  294. case AUDIO_DSP_PARAM:
  295. {
  296. /* set samplerate */
  297. I2S_Frequency_Set(caps->udata.config.samplerate);
  298. /* set channels */
  299. SAIA_Channels_Set(caps->udata.config.channels);
  300. /* save configs */
  301. snd_dev->replay_config.samplerate = caps->udata.config.samplerate;
  302. snd_dev->replay_config.channels = caps->udata.config.channels;
  303. snd_dev->replay_config.samplebits = caps->udata.config.samplebits;
  304. LOG_D("set samplerate %d", snd_dev->replay_config.samplerate);
  305. break;
  306. }
  307. case AUDIO_DSP_SAMPLERATE:
  308. {
  309. I2S_Frequency_Set(caps->udata.config.samplerate);
  310. snd_dev->replay_config.samplerate = caps->udata.config.samplerate;
  311. LOG_D("set samplerate %d", snd_dev->replay_config.samplerate);
  312. break;
  313. }
  314. case AUDIO_DSP_CHANNELS:
  315. {
  316. SAIA_Channels_Set(caps->udata.config.channels);
  317. snd_dev->replay_config.channels = caps->udata.config.channels;
  318. LOG_D("set channels %d", snd_dev->replay_config.channels);
  319. break;
  320. }
  321. case AUDIO_DSP_SAMPLEBITS:
  322. {
  323. /* not support */
  324. snd_dev->replay_config.samplebits = caps->udata.config.samplebits;
  325. break;
  326. }
  327. default:
  328. result = -RT_ERROR;
  329. break;
  330. }
  331. break;
  332. }
  333. default:
  334. break;
  335. }
  336. return result;
  337. }
  338. static rt_err_t sound_init(struct rt_audio_device *audio)
  339. {
  340. rt_err_t result = RT_EOK;
  341. struct sound_device *snd_dev;
  342. RT_ASSERT(audio != RT_NULL);
  343. snd_dev = (struct sound_device *)audio->parent.user_data;
  344. es8388_init("i2c2", RT_NULL);
  345. I2S3_Init();
  346. LOG_I("ES8388 init success.");
  347. /* set default params */
  348. I2S_Frequency_Set(snd_dev->replay_config.samplerate);
  349. SAIA_Channels_Set(snd_dev->replay_config.channels);
  350. return result;
  351. }
  352. static rt_err_t sound_start(struct rt_audio_device *audio, int stream)
  353. {
  354. struct sound_device *snd_dev;
  355. RT_ASSERT(audio != RT_NULL);
  356. snd_dev = (struct sound_device *)audio->parent.user_data;
  357. if (stream == AUDIO_STREAM_REPLAY)
  358. {
  359. LOG_D("sound start.");
  360. es8388_start(ES_MODE_DAC);
  361. HAL_I2S_Transmit_DMA(&I2S3_Handler, (uint16_t*)snd_dev->tx_fifo, TX_FIFO_SIZE / 2);
  362. }
  363. return RT_EOK;
  364. }
  365. static rt_err_t sound_stop(struct rt_audio_device *audio, int stream)
  366. {
  367. RT_ASSERT(audio != RT_NULL);
  368. if (stream == AUDIO_STREAM_REPLAY)
  369. {
  370. HAL_I2S_DMAStop(&I2S3_Handler);
  371. es8388_stop(ES_MODE_DAC);
  372. LOG_D("sound stop.");
  373. }
  374. return RT_EOK;
  375. }
  376. static void sound_buffer_info(struct rt_audio_device *audio, struct rt_audio_buf_info *info)
  377. {
  378. struct sound_device *snd_dev;
  379. RT_ASSERT(audio != RT_NULL);
  380. snd_dev = (struct sound_device *)audio->parent.user_data;
  381. /**
  382. * TX_FIFO
  383. * +----------------+----------------+
  384. * | block1 | block2 |
  385. * +----------------+----------------+
  386. * \ block_size /
  387. */
  388. info->buffer = snd_dev->tx_fifo;
  389. info->total_size = TX_FIFO_SIZE;
  390. info->block_size = TX_FIFO_SIZE / 2;
  391. info->block_count = 2;
  392. }
  393. static struct rt_audio_ops snd_ops =
  394. {
  395. .getcaps = sound_getcaps,
  396. .configure = sound_configure,
  397. .init = sound_init,
  398. .start = sound_start,
  399. .stop = sound_stop,
  400. .transmit = RT_NULL,
  401. .buffer_info = sound_buffer_info,
  402. };
  403. int rt_hw_sound_init(void)
  404. {
  405. rt_uint8_t *tx_fifo;
  406. if (snd_dev.tx_fifo)
  407. return RT_EOK;
  408. tx_fifo = rt_malloc(TX_FIFO_SIZE);
  409. if (tx_fifo == RT_NULL)
  410. return -RT_ENOMEM;
  411. rt_memset(tx_fifo, 0, TX_FIFO_SIZE);
  412. snd_dev.tx_fifo = tx_fifo;
  413. /* init default configuration */
  414. {
  415. snd_dev.replay_config.samplerate = 44100;
  416. snd_dev.replay_config.channels = 2;
  417. snd_dev.replay_config.samplebits = 16;
  418. snd_dev.volume = 55;
  419. }
  420. /* register sound device */
  421. snd_dev.audio.ops = &snd_ops;
  422. rt_audio_register(&snd_dev.audio, "sound0", RT_DEVICE_FLAG_WRONLY, &snd_dev);
  423. return RT_EOK;
  424. }
  425. // INIT_DEVICE_EXPORT(rt_hw_sound_init);