drv_sound.c 15 KB

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