drv_dfsdm.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-07-07 thread-liu first version
  9. */
  10. #include "board.h"
  11. #if defined(BSP_USING_DFSDM)
  12. #include "drv_wm8994.h"
  13. #include "drv_dfsdm.h"
  14. #define DRV_DEBUG
  15. #define LOG_TAG "drv.dfsdm"
  16. #include <drv_log.h>
  17. #define FILTER_FIFO_SIZE (1024)
  18. #if defined(__ARMCC_VERSION)
  19. __attribute__((at(0x2FFC8000))) static rt_int32_t FILTER0_FIFO[FILTER_FIFO_SIZE];
  20. #elif defined ( __GNUC__ )
  21. static rt_int32_t FILTER0_FIFO[FILTER_FIFO_SIZE] __attribute__((section(".Filter0Section")));
  22. #elif defined(__ICCARM__)
  23. #pragma location = 0x2FFC8000
  24. __no_init static rt_int32_t FILTER0_FIFO[FILTER_FIFO_SIZE];
  25. #endif
  26. #if defined(__ARMCC_VERSION)
  27. __attribute__((at(0x2FFC9000))) static rt_int32_t FILTER0_FIFO[FILTER_FIFO_SIZE];
  28. #elif defined ( __GNUC__ )
  29. static rt_int32_t FILTER0_FIFO[FILTER_FIFO_SIZE] __attribute__((section(".Filter1Section")));
  30. #elif defined(__ICCARM__)
  31. #pragma location = 0x2FFC9000
  32. __no_init static rt_int32_t FILTER1_FIFO[FILTER_FIFO_SIZE];
  33. #endif
  34. #define PALY_SIZE 2048
  35. #if defined(__ARMCC_VERSION)
  36. __attribute__((at(0x2FFCA000))) static rt_int16_t PLAY_BUF[PALY_SIZE];
  37. #elif defined ( __GNUC__ )
  38. __attribute__((at(0x2FFCA000))) __attribute__((section(".DfsdmSection")));
  39. #elif defined(__ICCARM__)
  40. #pragma location = 0x2FFCA000
  41. __no_init static rt_int16_t PLAY_BUF[PALY_SIZE];
  42. #endif
  43. static volatile rt_uint8_t DmaLeftRecBuffCplt = 0;
  44. static volatile rt_uint8_t DmaRightRecBuffCplt = 0;
  45. static volatile rt_uint8_t DmaLeftRecHalfBuffCplt = 0;
  46. static volatile rt_uint8_t DmaRightRecHalfBuffCplt = 0;
  47. static DFSDM_Channel_HandleTypeDef hdfsdm1_channel0 = {0}; /* data_in1_right */
  48. static DFSDM_Channel_HandleTypeDef hdfsdm1_channel1 = {0}; /* data_in1_left */
  49. static DFSDM_Filter_HandleTypeDef hdfsdm1_filter0 = {0}; /* data_in1_right */
  50. static DFSDM_Filter_HandleTypeDef hdfsdm1_filter1 = {0}; /* data_in1_left */
  51. extern DMA_HandleTypeDef hdma_dfsdm1_flt0;
  52. extern DMA_HandleTypeDef hdma_dfsdm1_flt1;
  53. static struct rt_device dfsdm_dev = {0};
  54. void DMA2_Stream2_IRQHandler(void)
  55. {
  56. /* enter interrupt */
  57. rt_interrupt_enter();
  58. HAL_DMA_IRQHandler(&hdma_dfsdm1_flt1);
  59. /* leave interrupt */
  60. rt_interrupt_leave();
  61. }
  62. void DMA2_Stream1_IRQHandler(void)
  63. {
  64. /* enter interrupt */
  65. rt_interrupt_enter();
  66. HAL_DMA_IRQHandler(&hdma_dfsdm1_flt0);
  67. /* leave interrupt */
  68. rt_interrupt_leave();
  69. }
  70. void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
  71. {
  72. if(hdfsdm_filter == &hdfsdm1_filter1)
  73. {
  74. DmaLeftRecHalfBuffCplt = 1;
  75. }
  76. else
  77. {
  78. DmaRightRecHalfBuffCplt = 1;
  79. }
  80. }
  81. void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
  82. {
  83. if (hdfsdm_filter == &hdfsdm1_filter1)
  84. {
  85. DmaLeftRecBuffCplt = 1;
  86. }
  87. else
  88. {
  89. DmaRightRecBuffCplt = 1;
  90. }
  91. }
  92. static int rt_hw_dfsdm_init(void)
  93. {
  94. /* DATAIN1_LEFT */
  95. __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hdfsdm1_channel1);
  96. hdfsdm1_channel1.Instance = DFSDM1_Channel1;
  97. hdfsdm1_channel1.Init.OutputClock.Activation = ENABLE;
  98. hdfsdm1_channel1.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_SYSTEM; /* 209MHZ */
  99. hdfsdm1_channel1.Init.OutputClock.Divider = 74; /* 209/74 = 2.82MHZ*/
  100. hdfsdm1_channel1.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS;
  101. hdfsdm1_channel1.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE;
  102. hdfsdm1_channel1.Init.Input.Pins = DFSDM_CHANNEL_SAME_CHANNEL_PINS;
  103. hdfsdm1_channel1.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_RISING ; /* left */
  104. hdfsdm1_channel1.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
  105. hdfsdm1_channel1.Init.Awd.FilterOrder = DFSDM_CHANNEL_FASTSINC_ORDER;
  106. hdfsdm1_channel1.Init.Awd.Oversampling = 10;
  107. hdfsdm1_channel1.Init.Offset = 0;
  108. hdfsdm1_channel1.Init.RightBitShift = 2;
  109. if(HAL_OK != HAL_DFSDM_ChannelInit(&hdfsdm1_channel1))
  110. {
  111. return RT_ERROR;
  112. }
  113. /* DATAIN1_RIGHT */
  114. __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hdfsdm1_channel0);
  115. hdfsdm1_channel0.Instance = DFSDM1_Channel0;
  116. hdfsdm1_channel0.Init.OutputClock.Activation = ENABLE;
  117. hdfsdm1_channel0.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_SYSTEM;
  118. hdfsdm1_channel0.Init.OutputClock.Divider = 74; /* 209/74 = 2.82MHZ*/
  119. hdfsdm1_channel0.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS;
  120. hdfsdm1_channel0.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE;
  121. hdfsdm1_channel0.Init.Input.Pins = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS;
  122. hdfsdm1_channel0.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_FALLING; /* right */
  123. hdfsdm1_channel0.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
  124. hdfsdm1_channel0.Init.Awd.FilterOrder = DFSDM_CHANNEL_FASTSINC_ORDER;
  125. hdfsdm1_channel0.Init.Awd.Oversampling = 10;
  126. hdfsdm1_channel0.Init.Offset = 0;
  127. hdfsdm1_channel0.Init.RightBitShift = 2;
  128. if(HAL_OK != HAL_DFSDM_ChannelInit(&hdfsdm1_channel0))
  129. {
  130. return RT_ERROR;
  131. }
  132. /* Initialize filter 0 (data_in1 right channel) */
  133. __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hdfsdm1_filter0);
  134. hdfsdm1_filter0.Instance = DFSDM1_Filter0;
  135. hdfsdm1_filter0.Init.RegularParam.Trigger = DFSDM_FILTER_SW_TRIGGER;
  136. hdfsdm1_filter0.Init.RegularParam.FastMode = ENABLE;
  137. hdfsdm1_filter0.Init.RegularParam.DmaMode = ENABLE;
  138. hdfsdm1_filter0.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER;
  139. hdfsdm1_filter0.Init.InjectedParam.ScanMode = DISABLE;
  140. hdfsdm1_filter0.Init.InjectedParam.DmaMode = DISABLE;
  141. hdfsdm1_filter0.Init.FilterParam.SincOrder = DFSDM_FILTER_SINC3_ORDER;
  142. hdfsdm1_filter0.Init.FilterParam.Oversampling = 64; /* 209 / ( 74 * 64) = 44.1KHZ*/
  143. hdfsdm1_filter0.Init.FilterParam.IntOversampling = 1;
  144. if (HAL_OK != HAL_DFSDM_FilterInit(&hdfsdm1_filter0))
  145. {
  146. return RT_ERROR;
  147. }
  148. /* Initialize filter 1 (data_in1 left channel) */
  149. __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hdfsdm1_filter1);
  150. hdfsdm1_filter1.Instance = DFSDM1_Filter1;
  151. hdfsdm1_filter1.Init.RegularParam.Trigger = DFSDM_FILTER_SW_TRIGGER;
  152. hdfsdm1_filter1.Init.RegularParam.FastMode = ENABLE;
  153. hdfsdm1_filter1.Init.RegularParam.DmaMode = ENABLE;
  154. hdfsdm1_filter1.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER;
  155. hdfsdm1_filter1.Init.InjectedParam.ScanMode = DISABLE;
  156. hdfsdm1_filter1.Init.InjectedParam.DmaMode = DISABLE;
  157. hdfsdm1_filter1.Init.FilterParam.SincOrder = DFSDM_FILTER_SINC3_ORDER;
  158. hdfsdm1_filter1.Init.FilterParam.Oversampling = 64; /* 209 / ( 74 * 64) = 44.1KHZ*/
  159. hdfsdm1_filter1.Init.FilterParam.IntOversampling = 1;
  160. if (HAL_OK != HAL_DFSDM_FilterInit(&hdfsdm1_filter1))
  161. {
  162. return RT_ERROR;
  163. }
  164. /* Configure regular channel and continuous mode for filter 0 (data_in1 left channel) */
  165. if (HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hdfsdm1_filter1, DFSDM_CHANNEL_1, DFSDM_CONTINUOUS_CONV_ON))
  166. {
  167. return RT_ERROR;
  168. }
  169. /* Configure regular channel and continuous mode for filter 1 (data_in1 right channel) */
  170. if (HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hdfsdm1_filter0, DFSDM_CHANNEL_0, DFSDM_CONTINUOUS_CONV_ON))
  171. {
  172. return RT_ERROR;
  173. }
  174. return RT_EOK;
  175. }
  176. /* dfsdm start coversions */
  177. static rt_err_t rt_hw_dfsdm_open(void)
  178. {
  179. if (HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hdfsdm1_filter0, FILTER0_FIFO, FILTER_FIFO_SIZE))
  180. {
  181. LOG_E("DFSDM DATA_IN1 rifht channel start conversions failed!");
  182. return RT_ERROR;
  183. }
  184. if (HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hdfsdm1_filter1, FILTER1_FIFO, FILTER_FIFO_SIZE))
  185. {
  186. LOG_E("DFSDM DATA_IN1 left channel start conversions failed!");
  187. return RT_ERROR;
  188. }
  189. return RT_EOK;
  190. }
  191. static rt_err_t _init(rt_device_t dev)
  192. {
  193. RT_ASSERT(dev != RT_NULL);
  194. rt_hw_dfsdm_init();
  195. return RT_EOK;
  196. }
  197. static rt_err_t _open(rt_device_t dev, rt_uint16_t oflag)
  198. {
  199. RT_ASSERT(dev != RT_NULL);
  200. rt_hw_dfsdm_open();
  201. return RT_EOK;
  202. }
  203. static rt_err_t _close(rt_device_t dev)
  204. {
  205. RT_ASSERT(dev != RT_NULL);
  206. HAL_DFSDM_FilterRegularStop_DMA(&hdfsdm1_filter0);
  207. HAL_DFSDM_FilterRegularStop_DMA(&hdfsdm1_filter1);
  208. return RT_EOK;
  209. }
  210. static rt_size_t _read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  211. {
  212. RT_ASSERT(dev != RT_NULL);
  213. rt_uint32_t i = 0;
  214. rt_int16_t *p = RT_NULL;
  215. p = (rt_int16_t *)buffer;
  216. if (!pos)
  217. {
  218. for (i = 0; i < 512; i++)
  219. {
  220. p[2*i] = (int16_t)SaturaLH((FILTER0_FIFO[i] >> 8), -32768, 32767);
  221. p[(2*i)+1] = (int16_t)SaturaLH((FILTER1_FIFO[i] >> 8), -32768, 32767);
  222. }
  223. }
  224. else
  225. {
  226. for (i = 512; i < 1024; i++)
  227. {
  228. p[2*i] = (int16_t)SaturaLH((FILTER0_FIFO[i] >> 8), -32768, 32767);
  229. p[(2*i)+1] = (int16_t)SaturaLH((FILTER1_FIFO[i] >> 8), -32768, 32767);
  230. }
  231. }
  232. return size;
  233. }
  234. static rt_size_t _write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  235. {
  236. RT_ASSERT(dev != RT_NULL);
  237. return RT_EOK;
  238. }
  239. static rt_err_t _control(rt_device_t dev, int cmd, void *args)
  240. {
  241. RT_ASSERT(dev != RT_NULL);
  242. return RT_EOK;
  243. }
  244. int dfsdm_init(void)
  245. {
  246. dfsdm_dev.type = RT_Device_Class_Miscellaneous;
  247. dfsdm_dev.init = _init;
  248. dfsdm_dev.open = _open;
  249. dfsdm_dev.close = _close;
  250. dfsdm_dev.read = _read;
  251. dfsdm_dev.write = _write;
  252. dfsdm_dev.control = _control;
  253. dfsdm_dev.user_data = RT_NULL;
  254. rt_device_register(&dfsdm_dev, "dfsdm1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
  255. LOG_I("dfsdm1 init success!");
  256. return RT_EOK;
  257. }
  258. INIT_DEVICE_EXPORT(dfsdm_init);
  259. static int dfsdm_sample(int argc, char **argv)
  260. {
  261. if (argc != 1)
  262. {
  263. rt_kprintf("Usage:\n");
  264. rt_kprintf("dfsdm_sample\n");
  265. return -1;
  266. }
  267. static struct rt_device *dfsdm_dev = RT_NULL;
  268. static struct rt_device *sound_dev = RT_NULL;
  269. rt_uint16_t play_type = OUTPUT_DEVICE_HEADPHONE;
  270. rt_uint16_t tickstart = 0;
  271. extern SAI_HandleTypeDef hsai_BlockA2;
  272. dfsdm_dev = rt_device_find("dfsdm1");
  273. if (dfsdm_dev == RT_NULL)
  274. {
  275. rt_kprintf("no dfsdm device!");
  276. return RT_ERROR;
  277. }
  278. sound_dev = rt_device_find("decoder");
  279. if (sound_dev == RT_NULL)
  280. {
  281. rt_kprintf("no decoder device!");
  282. return RT_ERROR;
  283. }
  284. /* open dfsdm device */
  285. rt_device_open(dfsdm_dev, RT_DEVICE_OFLAG_RDWR);
  286. /* open sound device */
  287. rt_device_open(sound_dev, RT_DEVICE_OFLAG_WRONLY);
  288. rt_device_control(sound_dev, SET_PLAY_TYPE, &play_type);
  289. rt_device_control(sound_dev, START_PLAY, RT_NULL);
  290. rt_memset(PLAY_BUF, 0, PALY_SIZE);
  291. tickstart = rt_tick_get();
  292. if (HAL_SAI_Transmit_DMA(&hsai_BlockA2, (uint8_t *)PLAY_BUF, PALY_SIZE) != HAL_OK)
  293. {
  294. rt_kprintf("sai transmit dma failed!\n");
  295. return RT_ERROR;
  296. }
  297. rt_kprintf("dfsdm audio record test begin!\n");
  298. while (1)
  299. {
  300. if ((rt_tick_get() - tickstart) > 0x1000)
  301. {
  302. HAL_SAI_DMAStop(&hsai_BlockA2);
  303. rt_device_close(dfsdm_dev);
  304. break;
  305. }
  306. if (DmaLeftRecHalfBuffCplt && DmaRightRecHalfBuffCplt)
  307. {
  308. rt_device_read(dfsdm_dev, 0, PLAY_BUF, 512);
  309. DmaLeftRecHalfBuffCplt = 0;
  310. DmaRightRecHalfBuffCplt = 0;
  311. }
  312. else if (DmaLeftRecBuffCplt && DmaRightRecBuffCplt)
  313. {
  314. rt_device_read(dfsdm_dev, 1, PLAY_BUF, 512);
  315. DmaLeftRecBuffCplt = 0;
  316. DmaRightRecBuffCplt = 0;
  317. }
  318. }
  319. rt_kprintf("dfsdm audio record test end!\n");
  320. return RT_EOK;
  321. }
  322. MSH_CMD_EXPORT(dfsdm_sample, dfsdm audiorecord test);
  323. #endif