drv_sound.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-11-14 ZeroFree first implementation
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #include <rthw.h>
  13. #include <stdint.h>
  14. #include <string.h>
  15. #include "drv_audio.h"
  16. #include "drv_wm8978.h"
  17. #include <stm32f4xx.h>
  18. #define DBG_LEVEL DBG_LOG
  19. #define DBG_SECTION_NAME "Sound"
  20. #include <rtdbg.h>
  21. /**
  22. * Audio Memory Node Manage
  23. */
  24. struct rt_data_node
  25. {
  26. char *data_ptr;
  27. rt_uint32_t data_size;
  28. };
  29. struct rt_data_node_list
  30. {
  31. struct rt_data_node *node;
  32. rt_uint32_t size;
  33. rt_uint32_t read_index, write_index;
  34. rt_uint32_t data_offset;
  35. void (*read_complete)(struct rt_data_node *node, void *user_data);
  36. void *user_data;
  37. };
  38. int rt_data_node_init(struct rt_data_node_list **node_list, rt_uint32_t size)
  39. {
  40. int result = RT_EOK;
  41. struct rt_data_node_list *list = RT_NULL;
  42. struct rt_data_node *node = RT_NULL;
  43. list = rt_malloc(sizeof(struct rt_data_node_list));
  44. if (list == RT_NULL)
  45. {
  46. result = -RT_ENOMEM;
  47. goto __exit;
  48. }
  49. memset(list, 0, sizeof(struct rt_data_node_list));
  50. node = rt_malloc(sizeof(struct rt_data_node) * size);
  51. if (size == RT_NULL)
  52. {
  53. result = -RT_ENOMEM;
  54. goto __exit;
  55. }
  56. memset(node, 0, sizeof(struct rt_data_node));
  57. list->node = node;
  58. list->size = size;
  59. list->read_index = 0;
  60. list->write_index = 0;
  61. list->data_offset = 0;
  62. list->read_complete = RT_NULL;
  63. list->user_data = 0;
  64. *node_list = list;
  65. return result;
  66. __exit:
  67. if (list)
  68. rt_free(list);
  69. if (node)
  70. rt_free(node);
  71. return result;
  72. }
  73. int rt_data_node_is_empty(struct rt_data_node_list *node_list)
  74. {
  75. rt_uint32_t read_index, write_index;
  76. rt_base_t level;
  77. level = rt_hw_interrupt_disable();
  78. read_index = node_list->read_index;
  79. write_index = node_list->write_index;
  80. rt_hw_interrupt_enable(level);
  81. if (read_index == write_index)
  82. {
  83. return RT_TRUE;
  84. }
  85. else
  86. {
  87. return RT_FALSE;
  88. }
  89. }
  90. void wait_node_free(struct rt_data_node_list *node_list)
  91. {
  92. while (node_list->read_index != node_list->write_index)
  93. rt_thread_mdelay(5);
  94. }
  95. int rt_data_node_write(struct rt_data_node_list *node_list, void *buffer, rt_uint32_t size)
  96. {
  97. struct rt_data_node *node = RT_NULL;
  98. rt_uint32_t read_index, write_index, next_index;
  99. rt_base_t level;
  100. level = rt_hw_interrupt_disable();
  101. read_index = node_list->read_index;
  102. write_index = node_list->write_index;
  103. rt_hw_interrupt_enable(level);
  104. next_index = write_index + 1;
  105. if (next_index >= node_list->size)
  106. next_index = 0;
  107. if (next_index == read_index)
  108. {
  109. rt_kprintf("[node]:node list full, write index = %d, read index = %d \n", write_index, read_index);
  110. return -RT_ERROR;
  111. }
  112. level = rt_hw_interrupt_disable();
  113. /* set node attribute */
  114. node = &node_list->node[write_index];
  115. node->data_ptr = (char *) buffer;
  116. node->data_size = size;
  117. node_list->write_index = next_index;
  118. rt_hw_interrupt_enable(level);
  119. return size;
  120. }
  121. int rt_data_node_read(struct rt_data_node_list *node_list, void *buffer, rt_uint32_t size)
  122. {
  123. struct rt_data_node *node = RT_NULL;
  124. rt_uint32_t read_index, write_index, next_index;
  125. rt_int32_t remain_len, copy_size;
  126. rt_uint32_t read_offset, data_offset;
  127. rt_base_t level;
  128. rt_uint32_t result = size;
  129. level = rt_hw_interrupt_disable();
  130. read_index = node_list->read_index;
  131. write_index = node_list->write_index;
  132. rt_hw_interrupt_enable(level);
  133. read_offset = 0;
  134. if (read_index == write_index)
  135. {
  136. result = 0;
  137. }
  138. else
  139. {
  140. do
  141. {
  142. node = &node_list->node[node_list->read_index];
  143. data_offset = node_list->data_offset;
  144. remain_len = node->data_size - data_offset;
  145. if (size - read_offset > remain_len)
  146. {
  147. /* Full*/
  148. copy_size = remain_len;
  149. }
  150. else
  151. {
  152. /* reamain buffer */
  153. copy_size = size - read_offset;
  154. }
  155. memcpy((char *)buffer + read_offset, node->data_ptr + data_offset, copy_size);
  156. read_offset += copy_size;
  157. data_offset += copy_size;
  158. node_list->data_offset = data_offset;
  159. if (data_offset >= node->data_size)
  160. {
  161. /* notify transmitted complete. */
  162. if (node_list->read_complete != RT_NULL)
  163. {
  164. node_list->read_complete(node, node_list->user_data);
  165. }
  166. level = rt_hw_interrupt_disable();
  167. read_index = node_list->read_index;
  168. write_index = node_list->write_index;
  169. rt_hw_interrupt_enable(level);
  170. next_index = read_index + 1;
  171. if (next_index >= node_list->size)
  172. next_index = 0;
  173. level = rt_hw_interrupt_disable();
  174. node_list->read_index = next_index;
  175. node_list->data_offset = 0;
  176. rt_hw_interrupt_enable(level);
  177. if (next_index == write_index)
  178. {
  179. result = read_offset;
  180. break;
  181. }
  182. }
  183. }
  184. while (read_offset < size);
  185. }
  186. return result;
  187. }
  188. static void data_node_read_complete(struct rt_data_node *node, void *user_data)
  189. {
  190. struct rt_device *dev = RT_NULL;
  191. dev = (struct rt_device *)user_data;
  192. if (dev->tx_complete != RT_NULL)
  193. {
  194. dev->tx_complete(dev, node->data_ptr);
  195. }
  196. }
  197. /**
  198. * RT-Thread Audio Device Driver
  199. */
  200. struct sound_device
  201. {
  202. struct rt_device parent;
  203. struct rt_data_node_list *node_list;
  204. /* i2c mode */
  205. struct rt_i2c_bus_device *i2c_device;
  206. char *send_fifo;
  207. };
  208. #define AUDIO_SEND_BUFFER_SIZE (2048 * 2)
  209. SAI_HandleTypeDef SAI1B_Handler;
  210. DMA_HandleTypeDef SAI1_RXDMA_Handler;
  211. SAI_HandleTypeDef SAI1A_Handler;
  212. DMA_HandleTypeDef SAI1_TXDMA_Handler;
  213. static struct sound_device *sound;
  214. static void SAIA_Init(void)
  215. {
  216. HAL_SAI_DeInit(&SAI1A_Handler);
  217. // SAI1A_Handler.Init.AudioFrequency = 44100;
  218. SAI1A_Handler.Instance = SAI1_Block_A;
  219. SAI1A_Handler.Init.AudioMode = SAI_MODEMASTER_TX;
  220. SAI1A_Handler.Init.Synchro = SAI_ASYNCHRONOUS;
  221. SAI1A_Handler.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
  222. SAI1A_Handler.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
  223. SAI1A_Handler.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
  224. SAI1A_Handler.Init.ClockSource = SAI_CLKSOURCE_PLLI2S;
  225. SAI1A_Handler.Init.MonoStereoMode = SAI_STEREOMODE;
  226. SAI1A_Handler.Init.Protocol = SAI_FREE_PROTOCOL;
  227. SAI1A_Handler.Init.DataSize = SAI_DATASIZE_16;
  228. SAI1A_Handler.Init.FirstBit = SAI_FIRSTBIT_MSB;
  229. SAI1A_Handler.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
  230. SAI1A_Handler.FrameInit.FrameLength = 64;
  231. SAI1A_Handler.FrameInit.ActiveFrameLength = 32;
  232. SAI1A_Handler.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
  233. SAI1A_Handler.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
  234. SAI1A_Handler.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
  235. SAI1A_Handler.SlotInit.FirstBitOffset = 0;
  236. SAI1A_Handler.SlotInit.SlotSize = SAI_SLOTSIZE_32B;
  237. SAI1A_Handler.SlotInit.SlotNumber = 2;
  238. SAI1A_Handler.SlotInit.SlotActive = SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1;
  239. HAL_SAI_Init(&SAI1A_Handler);
  240. __HAL_SAI_ENABLE(&SAI1A_Handler);
  241. /* DMA Configuration */
  242. SAIA_TX_DMAx_CLK_ENABLE();
  243. __HAL_LINKDMA(&SAI1A_Handler, hdmatx, SAI1_TXDMA_Handler);
  244. SAI1_TXDMA_Handler.Instance = SAIA_TX_DMAx_STREAM;
  245. SAI1_TXDMA_Handler.Init.Channel = SAIA_TX_DMAx_CHANNEL;
  246. SAI1_TXDMA_Handler.Init.Direction = DMA_MEMORY_TO_PERIPH;
  247. SAI1_TXDMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;
  248. SAI1_TXDMA_Handler.Init.MemInc = DMA_MINC_ENABLE;
  249. SAI1_TXDMA_Handler.Init.PeriphDataAlignment = SAIA_TX_DMAx_PERIPH_DATA_SIZE;
  250. SAI1_TXDMA_Handler.Init.MemDataAlignment = SAIA_TX_DMAx_MEM_DATA_SIZE;
  251. SAI1_TXDMA_Handler.Init.Mode = DMA_CIRCULAR;
  252. SAI1_TXDMA_Handler.Init.Priority = DMA_PRIORITY_HIGH;
  253. SAI1_TXDMA_Handler.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
  254. SAI1_TXDMA_Handler.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL;
  255. SAI1_TXDMA_Handler.Init.MemBurst = DMA_MBURST_SINGLE;
  256. SAI1_TXDMA_Handler.Init.PeriphBurst = DMA_PBURST_SINGLE;
  257. HAL_DMA_DeInit(&SAI1_TXDMA_Handler);
  258. HAL_DMA_Init(&SAI1_TXDMA_Handler);
  259. HAL_NVIC_SetPriority(SAIA_TX_DMAx_IRQ, 0, 0);
  260. HAL_NVIC_EnableIRQ(SAIA_TX_DMAx_IRQ);
  261. }
  262. const uint16_t SAI_PSC_TBL[][5] =
  263. {
  264. {800, 344, 7, 0, 12},
  265. {1102, 429, 2, 18, 2},
  266. {1600, 344, 7, 0, 6},
  267. {2205, 429, 2, 18, 1},
  268. {3200, 344, 7, 0, 3},
  269. {4410, 429, 2, 18, 0},
  270. {4800, 344, 7, 0, 2},
  271. {8820, 271, 2, 2, 1},
  272. {9600, 344, 7, 0, 1},
  273. {17640, 271, 2, 2, 0},
  274. {19200, 344, 7, 0, 0},
  275. };
  276. void SAIA_DMA_Enable(void)
  277. {
  278. SAI1_Block_A->CR1 |= SAI_xCR1_DMAEN;
  279. }
  280. void SAIA_DMA_Disable(void)
  281. {
  282. SAI1_Block_A->CR1 &= ~SAI_xCR1_DMAEN;
  283. }
  284. int SAIA_SampleRate_Set(uint32_t samplerate)
  285. {
  286. uint16_t i = 0;
  287. RCC_PeriphCLKInitTypeDef RCCSAI1_Sture;
  288. for (i = 0; i < (sizeof(SAI_PSC_TBL) / 10); i++)
  289. {
  290. if ((samplerate / 10) == SAI_PSC_TBL[i][0])
  291. break;
  292. }
  293. if (i == (sizeof(SAI_PSC_TBL) / 10))
  294. return -RT_ERROR;
  295. RCCSAI1_Sture.PeriphClockSelection = RCC_PERIPHCLK_SAI_PLLI2S;
  296. RCCSAI1_Sture.PLLI2S.PLLI2SN = (uint32_t)SAI_PSC_TBL[i][1];
  297. RCCSAI1_Sture.PLLI2S.PLLI2SQ = (uint32_t)SAI_PSC_TBL[i][2];
  298. RCCSAI1_Sture.PLLI2SDivQ = SAI_PSC_TBL[i][3] + 1;
  299. HAL_RCCEx_PeriphCLKConfig(&RCCSAI1_Sture);
  300. __HAL_RCC_SAI_BLOCKACLKSOURCE_CONFIG(RCC_SAIACLKSOURCE_PLLI2S);
  301. __HAL_SAI_DISABLE(&SAI1A_Handler);
  302. SAIA_DMA_Disable();
  303. SAI1A_Handler.Init.AudioFrequency = samplerate;
  304. HAL_SAI_Init(&SAI1A_Handler);
  305. SAIA_DMA_Enable();
  306. __HAL_SAI_ENABLE(&SAI1A_Handler);
  307. return RT_EOK;
  308. }
  309. void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
  310. {
  311. GPIO_InitTypeDef GPIO_Initure;
  312. __HAL_RCC_SAI1_CLK_ENABLE();
  313. __HAL_RCC_GPIOE_CLK_ENABLE();
  314. GPIO_Initure.Pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6;
  315. GPIO_Initure.Mode = GPIO_MODE_AF_PP;
  316. GPIO_Initure.Pull = GPIO_PULLUP;
  317. GPIO_Initure.Speed = GPIO_SPEED_HIGH;
  318. GPIO_Initure.Alternate = GPIO_AF6_SAI1;
  319. HAL_GPIO_Init(GPIOE, &GPIO_Initure);
  320. }
  321. void SAIA_TX_DMAx_IRQHandler(void)
  322. {
  323. HAL_DMA_IRQHandler(&SAI1_TXDMA_Handler);
  324. }
  325. void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
  326. {
  327. int result;
  328. struct sound_device *snd = sound;
  329. if (hsai == &SAI1A_Handler)
  330. {
  331. result = rt_data_node_is_empty(snd->node_list);
  332. if (result)
  333. {
  334. rt_kprintf("# ");
  335. memset(snd->send_fifo, 0, AUDIO_SEND_BUFFER_SIZE / 2);
  336. }
  337. else
  338. {
  339. memset(snd->send_fifo, 0, AUDIO_SEND_BUFFER_SIZE / 2);
  340. rt_data_node_read(snd->node_list, snd->send_fifo, AUDIO_SEND_BUFFER_SIZE / 2);
  341. }
  342. }
  343. }
  344. void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
  345. {
  346. int result;
  347. struct sound_device *snd = sound;
  348. if (hsai == &SAI1A_Handler)
  349. {
  350. result = rt_data_node_is_empty(snd->node_list);
  351. if (result)
  352. {
  353. rt_kprintf("* ");
  354. memset(snd->send_fifo + (AUDIO_SEND_BUFFER_SIZE / 2), 0, AUDIO_SEND_BUFFER_SIZE / 2);
  355. }
  356. else
  357. {
  358. memset(snd->send_fifo + (AUDIO_SEND_BUFFER_SIZE / 2), 0, AUDIO_SEND_BUFFER_SIZE / 2);
  359. rt_data_node_read(snd->node_list, snd->send_fifo + (AUDIO_SEND_BUFFER_SIZE / 2), AUDIO_SEND_BUFFER_SIZE / 2);
  360. }
  361. }
  362. }
  363. void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
  364. {
  365. rt_kprintf("x ");
  366. }
  367. static rt_err_t sound_init(rt_device_t dev)
  368. {
  369. int result;
  370. struct sound_device *snd = (struct sound_device *)dev;
  371. SAIA_Init();
  372. result = wm8978_init(snd->i2c_device);
  373. return result;
  374. }
  375. static rt_err_t sound_open(rt_device_t dev, rt_uint16_t oflag)
  376. {
  377. int result = RT_EOK;
  378. struct sound_device *snd = (struct sound_device *)dev;
  379. LOG_I("Open Sound Device!");
  380. /* Configure DMA transmit */
  381. result = HAL_SAI_Transmit_DMA(&SAI1A_Handler, (uint8_t *)(snd->send_fifo), AUDIO_SEND_BUFFER_SIZE / 2);
  382. if (result != HAL_OK)
  383. {
  384. LOG_E("Start DMA Transmit Failed!");
  385. result = -RT_ERROR;
  386. }
  387. return result;
  388. }
  389. static rt_err_t sound_control(rt_device_t dev, int cmd, void *args)
  390. {
  391. int value, result = RT_EOK;
  392. struct sound_device *snd = (struct sound_device *)dev;
  393. switch (cmd)
  394. {
  395. case CODEC_CMD_SET_VOLUME:
  396. value = *(int *)args;
  397. if (value < 0 || value > 99)
  398. {
  399. LOG_W("Please volume level 0 ~ 99");
  400. result = -RT_EINVAL;
  401. }
  402. else
  403. {
  404. LOG_I("Set volume level to %d", value);
  405. wm8978_set_volume(snd->i2c_device, value);
  406. result = RT_EOK;
  407. }
  408. break;
  409. case CODEC_CMD_SAMPLERATE:
  410. value = *(int *)args;
  411. LOG_I("Set Samplerate %d", value);
  412. SAIA_SampleRate_Set(value);
  413. break;
  414. default:
  415. result = RT_EOK;
  416. }
  417. return result;
  418. }
  419. static rt_size_t sound_write(rt_device_t dev, rt_off_t pos,
  420. const void *buffer, rt_size_t size)
  421. {
  422. int result = RT_EOK;
  423. struct sound_device *snd = (struct sound_device *)dev;
  424. result = rt_data_node_write(snd->node_list, (void *)buffer, size);
  425. return result;
  426. }
  427. static rt_err_t sound_close(rt_device_t dev)
  428. {
  429. HAL_SAI_DMAStop(&SAI1A_Handler);
  430. LOG_I("Close Sound Device!");
  431. return RT_EOK;
  432. }
  433. int rt_hw_sound_hw_init(char *i2c_bus_name)
  434. {
  435. int result = RT_EOK;
  436. if (sound != RT_NULL)
  437. return RT_EOK;
  438. HAL_SAI_MspInit(NULL);
  439. sound = rt_malloc(sizeof(struct sound_device));
  440. if (sound == RT_NULL)
  441. {
  442. LOG_E("malloc memory for sound device failed!");
  443. result = -RT_ENOMEM;
  444. goto __exit;
  445. }
  446. memset(sound, 0, sizeof(struct sound_device));
  447. sound->i2c_device = rt_i2c_bus_device_find(i2c_bus_name);
  448. if (sound->i2c_device == RT_NULL)
  449. {
  450. LOG_E("i2c bus device %s not found!", i2c_bus_name);
  451. result = -RT_ENOSYS;
  452. goto __exit;
  453. }
  454. sound->send_fifo = rt_malloc(AUDIO_SEND_BUFFER_SIZE);
  455. if (sound->send_fifo == RT_NULL)
  456. {
  457. result = -RT_ENOMEM;
  458. goto __exit;
  459. }
  460. memset(sound->send_fifo, 0, AUDIO_SEND_BUFFER_SIZE);
  461. rt_data_node_init(&sound->node_list, 10);
  462. sound->node_list->read_complete = data_node_read_complete;
  463. sound->node_list->user_data = sound;
  464. sound->parent.type = RT_Device_Class_Sound;
  465. sound->parent.init = sound_init;
  466. sound->parent.open = sound_open;
  467. sound->parent.control = sound_control;
  468. sound->parent.write = sound_write;
  469. sound->parent.read = RT_NULL;
  470. sound->parent.close = sound_close;
  471. sound->parent.user_data = sound;
  472. /* register the device */
  473. rt_device_register(&sound->parent, "sound", RT_DEVICE_FLAG_WRONLY | RT_DEVICE_FLAG_DMA_TX);
  474. rt_device_init(&sound->parent);
  475. return RT_EOK;
  476. __exit:
  477. if (sound->send_fifo != RT_NULL)
  478. {
  479. rt_free(sound->send_fifo);
  480. sound->send_fifo = RT_NULL;
  481. }
  482. if (sound != RT_NULL)
  483. {
  484. rt_free(sound);
  485. sound = RT_NULL;
  486. }
  487. return result;
  488. }
  489. extern int rt_hw_micphone_init(char *i2c_bus_name);
  490. int rt_hw_audio_init(char *i2c_bus_name)
  491. {
  492. rt_hw_sound_hw_init(i2c_bus_name);
  493. rt_hw_micphone_init(i2c_bus_name);
  494. return RT_EOK;
  495. }