drv_mic.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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 <rthw.h>
  12. #include <rtdevice.h>
  13. #include <string.h>
  14. #include "drv_audio.h"
  15. #include "drv_wm8978.h"
  16. #include <stm32f4xx.h>
  17. #define DBG_LEVEL DBG_INFO
  18. #define DBG_SECTION_NAME "MIC"
  19. #include <rtdbg.h>
  20. struct micphone_device
  21. {
  22. struct rt_device parent;
  23. rt_uint16_t *recv_fifo;
  24. struct rt_audio_pipe record_pipe;
  25. /* i2c mode */
  26. struct rt_i2c_bus_device *i2c_device;
  27. };
  28. #define AUDIO_RECV_BUFFER_SIZE (2048)
  29. extern SAI_HandleTypeDef SAI1B_Handler;
  30. extern DMA_HandleTypeDef SAI1_RXDMA_Handler;
  31. extern SAI_HandleTypeDef SAI1A_Handler;
  32. extern DMA_HandleTypeDef SAI1_TXDMA_Handler;
  33. static struct micphone_device micphone;
  34. static uint16_t send_fifo[2] = {0, 0};
  35. static void SAIB_Init(void)
  36. {
  37. HAL_SAI_DeInit(&SAI1B_Handler);
  38. SAI1B_Handler.Instance = SAI1_Block_B;
  39. SAI1B_Handler.Init.AudioMode = SAI_MODESLAVE_RX;
  40. SAI1B_Handler.Init.Synchro = SAI_SYNCHRONOUS;
  41. SAI1B_Handler.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
  42. SAI1B_Handler.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
  43. SAI1B_Handler.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
  44. SAI1B_Handler.Init.ClockSource = SAI_CLKSOURCE_PLLI2S;
  45. SAI1B_Handler.Init.MonoStereoMode = SAI_MONOMODE;
  46. SAI1B_Handler.Init.Protocol = SAI_FREE_PROTOCOL;
  47. SAI1B_Handler.Init.DataSize = SAI_DATASIZE_16;
  48. SAI1B_Handler.Init.FirstBit = SAI_FIRSTBIT_MSB;
  49. SAI1B_Handler.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
  50. SAI1B_Handler.FrameInit.FrameLength = 64;
  51. SAI1B_Handler.FrameInit.ActiveFrameLength = 32;
  52. SAI1B_Handler.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
  53. SAI1B_Handler.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
  54. SAI1B_Handler.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
  55. SAI1B_Handler.SlotInit.FirstBitOffset = 0;
  56. SAI1B_Handler.SlotInit.SlotSize = SAI_SLOTSIZE_32B;
  57. SAI1B_Handler.SlotInit.SlotNumber = 2;
  58. SAI1B_Handler.SlotInit.SlotActive = SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1;
  59. HAL_SAI_Init(&SAI1B_Handler);
  60. __HAL_SAI_ENABLE(&SAI1B_Handler);
  61. SAIA_RX_DMAx_CLK_ENABLE();
  62. __HAL_LINKDMA(&SAI1B_Handler, hdmarx, SAI1_RXDMA_Handler);
  63. SAI1_RXDMA_Handler.Instance = SAIA_RX_DMAx_STREAM;
  64. SAI1_RXDMA_Handler.Init.Channel = SAIA_RX_DMAx_CHANNEL;
  65. SAI1_RXDMA_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY;
  66. SAI1_RXDMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;
  67. SAI1_RXDMA_Handler.Init.MemInc = DMA_MINC_ENABLE;
  68. SAI1_RXDMA_Handler.Init.PeriphDataAlignment = SAIA_RX_DMAx_PERIPH_DATA_SIZE;
  69. SAI1_RXDMA_Handler.Init.MemDataAlignment = SAIA_RX_DMAx_MEM_DATA_SIZE;
  70. SAI1_RXDMA_Handler.Init.Mode = DMA_CIRCULAR;
  71. SAI1_RXDMA_Handler.Init.Priority = DMA_PRIORITY_MEDIUM;
  72. SAI1_RXDMA_Handler.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  73. SAI1_RXDMA_Handler.Init.MemBurst = DMA_MBURST_SINGLE;
  74. SAI1_RXDMA_Handler.Init.PeriphBurst = DMA_PBURST_SINGLE;
  75. HAL_DMA_DeInit(&SAI1_RXDMA_Handler);
  76. HAL_DMA_Init(&SAI1_RXDMA_Handler);
  77. HAL_NVIC_SetPriority(SAIA_RX_DMAx_IRQ, 0, 1);
  78. HAL_NVIC_EnableIRQ(SAIA_RX_DMAx_IRQ);
  79. }
  80. void SAIA_RX_DMAx_IRQHandler(void)
  81. {
  82. HAL_DMA_IRQHandler(&SAI1_RXDMA_Handler);
  83. }
  84. void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
  85. {
  86. if (hsai == &SAI1B_Handler)
  87. {
  88. rt_device_write(&micphone.record_pipe.parent, 0, micphone.recv_fifo, AUDIO_RECV_BUFFER_SIZE / 2);
  89. }
  90. }
  91. void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
  92. {
  93. if (hsai == &SAI1B_Handler)
  94. {
  95. rt_device_write(&micphone.record_pipe.parent, 0, micphone.recv_fifo + (AUDIO_RECV_BUFFER_SIZE / 4), AUDIO_RECV_BUFFER_SIZE / 2);
  96. }
  97. }
  98. static rt_err_t micphone_init(rt_device_t dev)
  99. {
  100. SAIB_Init();
  101. return RT_EOK;
  102. }
  103. static rt_err_t micphone_open(rt_device_t dev, rt_uint16_t oflag)
  104. {
  105. struct micphone_device *mic = RT_NULL;
  106. mic = (struct micphone_device *)dev;
  107. if (oflag & RT_DEVICE_OFLAG_RDONLY)
  108. {
  109. LOG_I("Open Micphone Device!");
  110. rt_device_open(&mic->record_pipe.parent, RT_DEVICE_OFLAG_RDONLY);
  111. /* Disable DMA Interruption */
  112. __HAL_DMA_DISABLE_IT(&SAI1_TXDMA_Handler, DMA_IT_TC | DMA_IT_HT);
  113. HAL_DMA_Start(&SAI1_TXDMA_Handler, (uint32_t)&send_fifo[0], (uint32_t)&SAI1_Block_A->DR, 2);
  114. /* Start RX DMA */
  115. HAL_SAI_Receive_DMA(&SAI1B_Handler, (uint8_t *)(micphone.recv_fifo), AUDIO_RECV_BUFFER_SIZE / 2);
  116. }
  117. return RT_EOK;
  118. }
  119. static rt_size_t micphone_read(rt_device_t dev, rt_off_t pos,
  120. void *buffer, rt_size_t size)
  121. {
  122. struct micphone_device *mic = RT_NULL;
  123. mic = (struct micphone_device *)dev;
  124. return rt_device_read(&mic->record_pipe.parent, pos, buffer, size);
  125. }
  126. static rt_err_t micphone_control(rt_device_t dev, int cmd, void *args)
  127. {
  128. rt_err_t value, result = RT_EOK;
  129. switch (cmd)
  130. {
  131. case CODEC_CMD_SET_VOLUME:
  132. {
  133. // TODO
  134. break;
  135. }
  136. case CODEC_CMD_SAMPLERATE:
  137. {
  138. value = *(int *)args;
  139. LOG_I("Set Samplerate %d", value);
  140. result = SAIA_SampleRate_Set(value);
  141. break;
  142. }
  143. default:
  144. break;
  145. }
  146. return result;
  147. }
  148. static rt_err_t micphone_close(rt_device_t dev)
  149. {
  150. struct micphone_device *mic = RT_NULL;
  151. mic = (struct micphone_device *)dev;
  152. HAL_SAI_DMAStop(&SAI1A_Handler);
  153. HAL_SAI_DMAStop(&SAI1B_Handler);
  154. rt_device_close(&mic->record_pipe.parent);
  155. LOG_I("Close Micphone Device!");
  156. return RT_EOK;
  157. }
  158. int rt_hw_micphone_init(char *i2c_bus_name)
  159. {
  160. int result = RT_EOK;
  161. struct micphone_device *mic = &micphone;
  162. if (mic->recv_fifo != RT_NULL)
  163. {
  164. return RT_EOK;
  165. }
  166. mic->recv_fifo = rt_malloc(AUDIO_RECV_BUFFER_SIZE);
  167. if (mic->recv_fifo == RT_NULL)
  168. {
  169. result = -RT_ENOMEM;
  170. goto __exit;
  171. }
  172. memset(mic->recv_fifo, 0, AUDIO_RECV_BUFFER_SIZE);
  173. mic->parent.type = RT_Device_Class_Sound;
  174. mic->parent.init = micphone_init;
  175. mic->parent.open = micphone_open;
  176. mic->parent.control = micphone_control;
  177. mic->parent.write = RT_NULL;
  178. mic->parent.read = micphone_read;
  179. mic->parent.close = micphone_close;
  180. mic->parent.user_data = mic;
  181. /* register the device */
  182. rt_device_register(&mic->parent, "mic", RT_DEVICE_FLAG_RDONLY | RT_DEVICE_FLAG_DMA_RX);
  183. rt_device_init(&mic->parent);
  184. {
  185. rt_uint8_t *buffer = rt_malloc(AUDIO_RECV_BUFFER_SIZE);
  186. if (buffer == RT_NULL)
  187. {
  188. result = -RT_ENOMEM;
  189. goto __exit;
  190. }
  191. memset(buffer, 0, AUDIO_RECV_BUFFER_SIZE);
  192. rt_audio_pipe_init(&mic->record_pipe,
  193. "voice",
  194. RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD,
  195. buffer,
  196. AUDIO_RECV_BUFFER_SIZE);
  197. }
  198. return RT_EOK;
  199. __exit:
  200. if (mic->recv_fifo)
  201. {
  202. rt_free(mic->recv_fifo);
  203. mic->recv_fifo = RT_NULL;
  204. }
  205. return result;
  206. }