drv_mic.c 7.0 KB

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