drv_mic.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. /*
  2. * Copyright (c) 2006-2021, 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_es8388.h"
  11. #define DBG_TAG "drv.mic"
  12. #define DBG_LVL DBG_INFO
  13. #include <rtdbg.h>
  14. #define RX_FIFO_SIZE (1024)
  15. struct mic_device
  16. {
  17. struct rt_audio_device audio;
  18. struct rt_audio_configure record_config;
  19. rt_uint8_t *rx_fifo;
  20. rt_uint8_t volume;
  21. };
  22. static struct mic_device mic_dev = {0};
  23. static rt_uint16_t zero_frame[2] = {0};
  24. static SAI_HandleTypeDef SAI1B_Handler = {0};
  25. static DMA_HandleTypeDef SAI1_RXDMA_Handler = {0};
  26. extern SAI_HandleTypeDef SAI1A_Handler;
  27. extern DMA_HandleTypeDef SAI1_RXDMA_Handler;
  28. extern void SAIA_Frequency_Set(uint32_t frequency);
  29. void SAIB_Init(void)
  30. {
  31. HAL_SAI_DeInit(&SAI1B_Handler);
  32. SAI1B_Handler.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_44K;
  33. SAI1B_Handler.Instance = SAI1_Block_B;
  34. SAI1B_Handler.Init.AudioMode = SAI_MODESLAVE_RX;
  35. SAI1B_Handler.Init.Synchro = SAI_SYNCHRONOUS;
  36. SAI1B_Handler.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
  37. SAI1B_Handler.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
  38. SAI1B_Handler.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
  39. SAI1B_Handler.Init.MonoStereoMode = SAI_MONOMODE;
  40. SAI1B_Handler.Init.Protocol = SAI_FREE_PROTOCOL;
  41. SAI1B_Handler.Init.DataSize = SAI_DATASIZE_16;
  42. SAI1B_Handler.Init.FirstBit = SAI_FIRSTBIT_MSB;
  43. SAI1B_Handler.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
  44. SAI1B_Handler.FrameInit.FrameLength = 64;
  45. SAI1B_Handler.FrameInit.ActiveFrameLength = 32;
  46. SAI1B_Handler.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
  47. SAI1B_Handler.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
  48. SAI1B_Handler.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
  49. SAI1B_Handler.SlotInit.FirstBitOffset = 0;
  50. SAI1B_Handler.SlotInit.SlotSize = SAI_SLOTSIZE_32B;
  51. SAI1B_Handler.SlotInit.SlotNumber = 2;
  52. SAI1B_Handler.SlotInit.SlotActive = SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1;
  53. HAL_SAI_Init(&SAI1B_Handler);
  54. __HAL_SAI_ENABLE(&SAI1B_Handler);
  55. /* Configure DMA used for SAI1 */
  56. __HAL_RCC_DMA2_CLK_ENABLE();
  57. SAI1_RXDMA_Handler.Init.Request = DMA_REQUEST_1;
  58. SAI1_RXDMA_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY;
  59. SAI1_RXDMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;
  60. SAI1_RXDMA_Handler.Init.MemInc = DMA_MINC_ENABLE;
  61. SAI1_RXDMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
  62. SAI1_RXDMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
  63. SAI1_RXDMA_Handler.Init.Mode = DMA_CIRCULAR;
  64. SAI1_RXDMA_Handler.Init.Priority = DMA_PRIORITY_HIGH;
  65. SAI1_RXDMA_Handler.Instance = DMA2_Channel2;
  66. __HAL_LINKDMA(&SAI1B_Handler, hdmarx, SAI1_RXDMA_Handler);
  67. HAL_DMA_DeInit(&SAI1_RXDMA_Handler);
  68. HAL_DMA_Init(&SAI1_RXDMA_Handler);
  69. __HAL_DMA_ENABLE(&SAI1_RXDMA_Handler);
  70. HAL_NVIC_SetPriority(DMA2_Channel2_IRQn, 0x01, 0);
  71. HAL_NVIC_EnableIRQ(DMA2_Channel2_IRQn);
  72. }
  73. void SAIB_Channels_Set(uint8_t channels)
  74. {
  75. if (channels == 1)
  76. {
  77. SAI1B_Handler.Init.MonoStereoMode = SAI_MONOMODE;
  78. }
  79. else
  80. {
  81. SAI1B_Handler.Init.MonoStereoMode = SAI_STEREOMODE;
  82. }
  83. __HAL_SAI_DISABLE(&SAI1B_Handler);
  84. HAL_SAI_Init(&SAI1B_Handler);
  85. __HAL_SAI_ENABLE(&SAI1B_Handler);
  86. }
  87. void DMA2_Channel2_IRQHandler(void)
  88. {
  89. HAL_DMA_IRQHandler(&SAI1_RXDMA_Handler);
  90. }
  91. void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
  92. {
  93. rt_audio_rx_done(&mic_dev.audio, &mic_dev.rx_fifo[0], RX_FIFO_SIZE / 2);
  94. }
  95. void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
  96. {
  97. rt_audio_rx_done(&mic_dev.audio, &mic_dev.rx_fifo[RX_FIFO_SIZE / 2], RX_FIFO_SIZE / 2);
  98. }
  99. static rt_err_t mic_getcaps(struct rt_audio_device *audio, struct rt_audio_caps *caps)
  100. {
  101. rt_err_t result = RT_EOK;
  102. struct mic_device *mic_dev;
  103. RT_ASSERT(audio != RT_NULL);
  104. mic_dev = (struct mic_device *)audio->parent.user_data;
  105. switch (caps->main_type)
  106. {
  107. case AUDIO_TYPE_QUERY: /* qurey the types of hw_codec device */
  108. {
  109. switch (caps->sub_type)
  110. {
  111. case AUDIO_TYPE_QUERY:
  112. caps->udata.mask = AUDIO_TYPE_INPUT | AUDIO_TYPE_MIXER;
  113. break;
  114. default:
  115. result = -RT_ERROR;
  116. break;
  117. }
  118. break;
  119. }
  120. case AUDIO_TYPE_INPUT: /* Provide capabilities of INPUT unit */
  121. {
  122. switch (caps->sub_type)
  123. {
  124. case AUDIO_DSP_PARAM:
  125. caps->udata.config.samplerate = mic_dev->record_config.samplerate;
  126. caps->udata.config.channels = mic_dev->record_config.channels;
  127. caps->udata.config.samplebits = mic_dev->record_config.samplebits;
  128. break;
  129. case AUDIO_DSP_SAMPLERATE:
  130. caps->udata.config.samplerate = mic_dev->record_config.samplerate;
  131. break;
  132. case AUDIO_DSP_CHANNELS:
  133. caps->udata.config.channels = mic_dev->record_config.channels;
  134. break;
  135. case AUDIO_DSP_SAMPLEBITS:
  136. caps->udata.config.samplebits = mic_dev->record_config.samplebits;
  137. break;
  138. default:
  139. result = -RT_ERROR;
  140. break;
  141. }
  142. break;
  143. }
  144. case AUDIO_TYPE_MIXER: /* report the Mixer Units */
  145. {
  146. switch (caps->sub_type)
  147. {
  148. case AUDIO_MIXER_QUERY:
  149. caps->udata.mask = AUDIO_MIXER_VOLUME | AUDIO_MIXER_LINE;
  150. break;
  151. case AUDIO_MIXER_VOLUME:
  152. caps->udata.value = mic_dev->volume;
  153. break;
  154. case AUDIO_MIXER_LINE:
  155. break;
  156. default:
  157. result = -RT_ERROR;
  158. break;
  159. }
  160. break;
  161. }
  162. default:
  163. result = -RT_ERROR;
  164. break;
  165. }
  166. return result;
  167. }
  168. static rt_err_t mic_configure(struct rt_audio_device *audio, struct rt_audio_caps *caps)
  169. {
  170. rt_err_t result = RT_EOK;
  171. struct mic_device *mic_dev;
  172. RT_ASSERT(audio != RT_NULL);
  173. mic_dev = (struct mic_device *)audio->parent.user_data;
  174. switch (caps->main_type)
  175. {
  176. case AUDIO_TYPE_MIXER:
  177. {
  178. switch (caps->sub_type)
  179. {
  180. case AUDIO_MIXER_VOLUME:
  181. {
  182. rt_uint32_t volume = caps->udata.value;
  183. mic_dev->volume = volume;
  184. LOG_D("set volume %d", volume);
  185. break;
  186. }
  187. default:
  188. result = -RT_ERROR;
  189. break;
  190. }
  191. break;
  192. }
  193. case AUDIO_TYPE_INPUT:
  194. {
  195. switch (caps->sub_type)
  196. {
  197. case AUDIO_DSP_PARAM:
  198. {
  199. SAIA_Frequency_Set(caps->udata.config.samplerate);
  200. HAL_SAI_DMAStop(&SAI1B_Handler);
  201. SAIB_Channels_Set(caps->udata.config.channels);
  202. HAL_SAI_Transmit(&SAI1A_Handler, (uint8_t *)&zero_frame[0], 2, 0);
  203. HAL_SAI_Receive_DMA(&SAI1B_Handler, mic_dev->rx_fifo, RX_FIFO_SIZE / 2);
  204. /* save configs */
  205. mic_dev->record_config.samplerate = caps->udata.config.samplerate;
  206. mic_dev->record_config.channels = caps->udata.config.channels;
  207. mic_dev->record_config.samplebits = caps->udata.config.samplebits;
  208. LOG_D("set samplerate %d", mic_dev->record_config.samplerate);
  209. LOG_D("set channels %d", mic_dev->record_config.channels);
  210. break;
  211. }
  212. case AUDIO_DSP_SAMPLERATE:
  213. {
  214. mic_dev->record_config.samplerate = caps->udata.config.samplerate;
  215. LOG_D("set channels %d", mic_dev->record_config.channels);
  216. break;
  217. }
  218. case AUDIO_DSP_CHANNELS:
  219. {
  220. mic_dev->record_config.channels = caps->udata.config.channels;
  221. LOG_D("set channels %d", mic_dev->record_config.channels);
  222. break;
  223. }
  224. default:
  225. break;
  226. }
  227. break;
  228. }
  229. default:
  230. break;
  231. }
  232. return result;
  233. }
  234. static rt_err_t mic_init(struct rt_audio_device *audio)
  235. {
  236. struct mic_device *mic_dev;
  237. RT_ASSERT(audio != RT_NULL);
  238. mic_dev = (struct mic_device *)audio->parent.user_data;
  239. SAIB_Init();
  240. /* set default params */
  241. SAIB_Channels_Set(mic_dev->record_config.channels);
  242. return RT_EOK;
  243. }
  244. static rt_err_t mic_start(struct rt_audio_device *audio, int stream)
  245. {
  246. struct mic_device *mic_dev;
  247. RT_ASSERT(audio != RT_NULL);
  248. mic_dev = (struct mic_device *)audio->parent.user_data;
  249. if (stream == AUDIO_STREAM_RECORD)
  250. {
  251. es8388_start(ES_MODE_ADC);
  252. HAL_SAI_Transmit(&SAI1A_Handler, (uint8_t *)&zero_frame[0], 2, 0);
  253. HAL_SAI_Receive_DMA(&SAI1B_Handler, mic_dev->rx_fifo, RX_FIFO_SIZE / 2);
  254. }
  255. return RT_EOK;
  256. }
  257. static rt_err_t mic_stop(struct rt_audio_device *audio, int stream)
  258. {
  259. if (stream == AUDIO_STREAM_RECORD)
  260. {
  261. HAL_SAI_DMAStop(&SAI1B_Handler);
  262. HAL_SAI_Abort(&SAI1A_Handler);
  263. es8388_stop(ES_MODE_ADC);
  264. }
  265. return RT_EOK;
  266. }
  267. static struct rt_audio_ops mic_ops =
  268. {
  269. .getcaps = mic_getcaps,
  270. .configure = mic_configure,
  271. .init = mic_init,
  272. .start = mic_start,
  273. .stop = mic_stop,
  274. .transmit = RT_NULL,
  275. .buffer_info = RT_NULL,
  276. };
  277. int rt_hw_mic_init(void)
  278. {
  279. rt_uint8_t *rx_fifo;
  280. if (mic_dev.rx_fifo)
  281. return RT_EOK;
  282. rx_fifo = rt_malloc(RX_FIFO_SIZE);
  283. if (rx_fifo == RT_NULL)
  284. return -RT_ENOMEM;
  285. rt_memset(rx_fifo, 0, RX_FIFO_SIZE);
  286. mic_dev.rx_fifo = rx_fifo;
  287. /* init default configuration */
  288. {
  289. mic_dev.record_config.samplerate = 44100;
  290. mic_dev.record_config.channels = 2;
  291. mic_dev.record_config.samplebits = 16;
  292. mic_dev.volume = 55;
  293. }
  294. /* register sound device */
  295. mic_dev.audio.ops = &mic_ops;
  296. rt_audio_register(&mic_dev.audio, "mic0", RT_DEVICE_FLAG_RDONLY, &mic_dev);
  297. return RT_EOK;
  298. }
  299. INIT_DEVICE_EXPORT(rt_hw_mic_init);