drv_dmic.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. /*
  2. * File : drv_dmic.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2015-11-19 Urey the first version
  23. */
  24. #include <rthw.h>
  25. #include <rtthread.h>
  26. #include <rtdevice.h>
  27. #include <drivers/audio.h>
  28. #ifdef RT_USING_FINSH
  29. # include <finsh.h>
  30. #endif
  31. #include "board.h"
  32. #include "drv_gpio.h"
  33. #include "drv_dma.h"
  34. #include "drv_aic.h"
  35. #include "drv_clock.h"
  36. #include "drv_dmic.h"
  37. #include "dma.h"
  38. #include "audio_pipe.h"
  39. #define DMIC_DEBUG 0
  40. #if DMIC_DEBUG
  41. # define DMIC_DBG(...) rt_kprintf("[DMIC]"),rt_kprintf(__VA_ARGS__)
  42. #else
  43. # define DMIC_DBG(...)
  44. #endif
  45. #define DMIC_DMA_RX_CHAN 4
  46. #define DMIC_FIFO_DEPTH 64
  47. #define JZ_DMIC_FORMATS 16
  48. #define JZ_DMIC_RATE (8000)
  49. ALIGN(32) rt_uint32_t _g_dmic_dma_buffer[DMIC_DMA_PAGE_NUM*DMIC_DMA_PAGE_SIZE/sizeof(rt_uint32_t)];
  50. static struct jz_dmic _g_jz_dmic=
  51. {
  52. .io_base = DMIC_BASE,
  53. .dma_buf = (rt_uint8_t *)_g_dmic_dma_buffer,
  54. .dma_offset = 0,
  55. };
  56. static void dump_dmic_registers(void)
  57. {
  58. struct jz_dmic *jz_dmic = &_g_jz_dmic;
  59. rt_kprintf("DMICCR0 %p : 0x%08x\n", (jz_dmic->io_base+DMICCR0),dmic_read_reg(jz_dmic, DMICCR0));
  60. rt_kprintf("DMICGCR %p : 0x%08x\n", (jz_dmic->io_base+DMICGCR),dmic_read_reg(jz_dmic, DMICGCR));
  61. rt_kprintf("DMICIMR %p : 0x%08x\n", (jz_dmic->io_base+DMICIMR),dmic_read_reg(jz_dmic, DMICIMR));
  62. rt_kprintf("DMICINTCR %p : 0x%08x\n", (jz_dmic->io_base+DMICINTCR),dmic_read_reg(jz_dmic, DMICINTCR));
  63. rt_kprintf("DMICTRICR %p : 0x%08x\n", (jz_dmic->io_base+DMICTRICR),dmic_read_reg(jz_dmic, DMICTRICR));
  64. rt_kprintf("DMICTHRH %p : 0x%08x\n", (jz_dmic->io_base+DMICTHRH),dmic_read_reg(jz_dmic, DMICTHRH));
  65. rt_kprintf("DMICTHRL %p : 0x%08x\n", (jz_dmic->io_base+DMICTHRL),dmic_read_reg(jz_dmic, DMICTHRL));
  66. rt_kprintf("DMICTRIMMAX %p : 0x%08x\n", (jz_dmic->io_base+DMICTRIMMAX),dmic_read_reg(jz_dmic, DMICTRIMMAX));
  67. rt_kprintf("DMICTRINMAX %p : 0x%08x\n", (jz_dmic->io_base+DMICTRINMAX),dmic_read_reg(jz_dmic, DMICTRINMAX));
  68. rt_kprintf("DMICDR %p : 0x%08x\n", (jz_dmic->io_base+DMICDR),dmic_read_reg(jz_dmic, DMICDR));
  69. rt_kprintf("DMICFTHR %p : 0x%08x\n", (jz_dmic->io_base+DMICFTHR),dmic_read_reg(jz_dmic, DMICFTHR));
  70. rt_kprintf("DMICFSR %p : 0x%08x\n", (jz_dmic->io_base+DMICFSR),dmic_read_reg(jz_dmic, DMICFSR));
  71. rt_kprintf("DMICCGDIS %p : 0x%08x\n", (jz_dmic->io_base+DMICCGDIS),dmic_read_reg(jz_dmic, DMICCGDIS));
  72. return;
  73. }
  74. MSH_CMD_EXPORT(dump_dmic_registers,"dump dmic regs...\n");
  75. int jz_dmic_set_rate(struct jz_dmic* dmic, int rate)
  76. {
  77. // rt_kprintf("rate = %d\n",rate);
  78. switch (rate)
  79. {
  80. case 8000:
  81. __dmic_set_sr_8k(dmic);
  82. break;
  83. case 16000:
  84. __dmic_set_sr_16k(dmic);
  85. break;
  86. case 48000:
  87. __dmic_set_sr_48k(dmic);
  88. break;
  89. default:
  90. DMIC_DBG("dmic unsupport rate %d\n", rate);
  91. }
  92. return 0;
  93. }
  94. int jz_dmic_set_channels(struct jz_dmic* dmic, int channels)
  95. {
  96. if (channels > 4)
  97. channels = 4;
  98. if (channels <= 1)
  99. channels = 1;
  100. __dmic_set_chnum(dmic,channels - 1);
  101. }
  102. int jz_dmic_set_record_volume(struct jz_dmic* dmic, int vol)
  103. {
  104. if(vol >= 32)
  105. vol = 31;
  106. __dmic_set_gcr(dmic,vol);
  107. dmic->record_gain = vol;
  108. }
  109. static void jz_dmic_dma_complete(struct rt_dma_channel *dmac, struct dma_message *msg)
  110. {
  111. rt_base_t level;
  112. if(msg->complete_cb)
  113. msg->complete_cb(msg->complete_arg,msg->dst_addr);
  114. /* restart DMA Job */
  115. rt_dma_trans_message(dmac,msg);
  116. }
  117. void jz_dmic_start_recv(struct jz_dmic* dmic,void (*rx_callback)(void *,void *), void *rx_arg)
  118. {
  119. rt_base_t level;
  120. rt_uint32_t i;
  121. struct dma_message message;
  122. __dmic_enable_rdms(dmic);
  123. __dmic_enable(dmic);
  124. level = rt_hw_interrupt_disable();
  125. dmic->dma_offset = 0;
  126. dmic->dma_buf = (rt_uint8_t *)_g_dmic_dma_buffer;
  127. for (i = 0; i < DMIC_DMA_PAGE_NUM; ++i)
  128. {
  129. message.src_addr = (uint8_t *) (DMIC_BASE + DMICDR);
  130. message.src_option = RT_DMA_ADDR_FIX;
  131. message.dst_addr = (uint8_t *) (dmic->dma_buf + DMIC_DMA_PAGE_SIZE * i);
  132. message.dst_option = RT_DMA_ADDR_INC;
  133. message.t_size = DMIC_DMA_PAGE_SIZE;
  134. message.t_mode = JZDMA_REQ_DMIC_RX;
  135. /* init callback */
  136. message.complete_cb = rx_callback;
  137. message.complete_arg = rx_arg;
  138. rt_dma_trans_message(dmic->rx_dmac,&message);
  139. }
  140. rt_hw_interrupt_enable(level);
  141. return ;
  142. }
  143. void jz_dmic_stop_recv(struct jz_dmic* dmic)
  144. {
  145. if (__dmic_is_enable_rdms(dmic))
  146. {
  147. __dmic_disable_rdms(dmic);
  148. }
  149. __dmic_disable(dmic);
  150. }
  151. void dmic_rx_complete(void *data,void *pbuf)
  152. {
  153. struct jz_dmic *dmic = (struct jz_dmic *)data;
  154. rt_device_write(RT_DEVICE(&dmic->pipe),0,pbuf,DMIC_DMA_PAGE_SIZE);
  155. }
  156. #define CFG_DMIC_PIPE_SIZE (2 * 1024)
  157. struct jz_dmic* rt_hw_dmic_init(void)
  158. {
  159. struct jz_dmic *dmic = &_g_jz_dmic;
  160. //init pipe for record
  161. {
  162. rt_uint8_t *buf = rt_malloc(CFG_DMIC_PIPE_SIZE);
  163. if(buf == RT_NULL)
  164. {
  165. rt_kprintf("request pipe memory error\n");
  166. return RT_NULL;
  167. }
  168. rt_audio_pipe_init(&dmic->pipe,"recdmic",RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD,buf,(CFG_DMIC_PIPE_SIZE));
  169. rt_device_open(RT_DEVICE(&dmic->pipe),RT_DEVICE_OFLAG_RDONLY);
  170. }
  171. /* GPIO config
  172. * PB05 -> FUNC1 DMIC1_IN
  173. * PB21 -> FUNC0 DMIC_CLK
  174. * PB22 -> FUNC0 DMIC0_IN
  175. * */
  176. gpio_set_func(GPIO_PORT_B,GPIO_Pin_5,GPIO_FUNC_1);
  177. gpio_set_func(GPIO_PORT_B,GPIO_Pin_21,GPIO_FUNC_0);
  178. gpio_set_func(GPIO_PORT_B,GPIO_Pin_22,GPIO_FUNC_0);
  179. /* enable clock */
  180. dmic->clk_gate = clk_get("dmic");
  181. if (dmic->clk_gate == RT_NULL)
  182. {
  183. DMIC_DBG("Failed to get dmic gate clock \n");
  184. return RT_NULL;
  185. }
  186. clk_enable(dmic->clk_gate);
  187. /*gain: 0, ..., e*/
  188. __dmic_reset(dmic);
  189. while (__dmic_get_reset(dmic)) ;
  190. jz_dmic_set_rate(dmic, 8000);
  191. __dmic_set_chnum(dmic,0); //mono
  192. __dmic_enable_hpf1(dmic);
  193. __dmic_set_gcr(dmic, 27);
  194. __dmic_mask_all_int(dmic);
  195. __dmic_enable_pack(dmic);
  196. __dmic_enable_sw_lr(dmic);
  197. __dmic_enable_lp(dmic);
  198. __dmic_disable_lp(dmic);
  199. __dmic_set_request(dmic, 48);
  200. __dmic_enable_hpf2(dmic);
  201. __dmic_set_thr_high(dmic, 32);
  202. __dmic_set_thr_low(dmic, 16);
  203. __dmic_enable_tri(dmic);
  204. //config DMA
  205. {
  206. int trigger;
  207. /* DMA config */
  208. struct dma_config config;
  209. dmic->rx_dmac = rt_dma_get_channel(DMIC_DMA_RX_CHAN);
  210. if (dmic->rx_dmac != RT_NULL)
  211. {
  212. DMIC_DBG("config dmic dma rx channel...\n");
  213. config.direction = RT_DMA_DEV_TO_MEM;
  214. config.src_addr_width = RT_DMA_BUSWIDTH_2_BYTES;
  215. config.src_maxburst = (DMIC_FIFO_DEPTH * RT_DMA_BUSWIDTH_2_BYTES) / 2;
  216. config.dst_addr_width = RT_DMA_BUSWIDTH_2_BYTES;
  217. config.dst_maxburst = (64 * 1024);
  218. rt_dma_configture(dmic->rx_dmac, &config);
  219. dmic->rx_dmac->start = RT_NULL;
  220. dmic->rx_dmac->complete = jz_dmic_dma_complete;
  221. }
  222. trigger = config.src_maxburst / config.src_addr_width;
  223. __dmic_set_request(dmic, trigger);
  224. }
  225. jz_dmic_start_recv(dmic,dmic_rx_complete,dmic);
  226. return dmic;
  227. _error_exit:
  228. __dmic_disable(dmic);
  229. rt_audio_pipe_detach(&dmic->pipe);
  230. clk_disable(dmic->clk_gate);
  231. return RT_NULL;
  232. }
  233. //INIT_ENV_EXPORT(rt_hw_dmic_init);
  234. struct speech_wav_header
  235. {
  236. char riff_id[4]; //"RIFF"
  237. uint32_t size0; //file len - 8
  238. char wave_fmt[8]; //"WAVEfmt "
  239. uint32_t size1; //0x10
  240. uint16_t fmttag; //0x01
  241. uint16_t channel; //1
  242. uint32_t samplespersec; //8000
  243. uint32_t bytepersec; //8000 * 2
  244. uint16_t blockalign; //1 * 16 / 8
  245. uint16_t bitpersamples; //16
  246. char data_id[4]; //"data"
  247. uint32_t size2; //file len - 44
  248. };
  249. static void speech_wav_init_header(struct speech_wav_header *header,rt_uint16_t Channels,int SamplesPerSec,int BitsPerSample)
  250. {
  251. strcpy(header->riff_id, "RIFF");
  252. header->size0 = 0; // Final file size not known yet, write 0
  253. strcpy(header->wave_fmt, "WAVEfmt ");
  254. header->size1 = 16; // Sub-chunk size, 16 for PCM
  255. header->fmttag = 1; // AudioFormat, 1 for PCM
  256. header->channel = Channels; // Number of channels, 1 for mono, 2 for stereo
  257. header->samplespersec = SamplesPerSec; // Sample rate
  258. header->bytepersec = SamplesPerSec * BitsPerSample * Channels / 8; //Byte rate
  259. header->blockalign = Channels * BitsPerSample / 8; // Block align, NumberOfChannels*BitsPerSample/8
  260. header->bitpersamples = BitsPerSample;
  261. strcpy(header->data_id, "data");
  262. header->size2 = 0;
  263. }
  264. static void speech_wav_upgrade_size(struct speech_wav_header *header,rt_uint32_t paylodSize)
  265. {
  266. header->size0 = paylodSize + 36;
  267. header->size2 = paylodSize;
  268. }
  269. #include <finsh.h>
  270. #include <dfs_posix.h>
  271. rt_uint8_t rec_buff[2048];
  272. int dmic_record(int samplingrates)
  273. {
  274. struct jz_dmic *dmic = &_g_jz_dmic;
  275. rt_device_t dmic_pipe;
  276. struct speech_wav_header wav_header;
  277. rt_uint32_t wav_len = 0;
  278. char *file_name;
  279. int fd;
  280. int i = 0;
  281. int rdlen, wrlen;
  282. rt_kprintf("samplingrates = %d\n",samplingrates);
  283. if((samplingrates != 8000) && (samplingrates != 16000))
  284. {
  285. rt_kprintf("un-support this samplingrates\n");
  286. return -RT_EIO;
  287. }
  288. dmic_pipe = rt_device_find("recdmic");
  289. if(dmic_pipe == RT_NULL)
  290. {
  291. rt_kprintf("can't find the record device\n");
  292. return -RT_ERROR ;
  293. }
  294. rt_kprintf("pls hold WAKE key to start record...\n");
  295. while(gpio_get_value(GPIO_PORT_B, GPIO_Pin_31) == 1)
  296. rt_thread_delay(100);
  297. rt_kprintf("OK,start record....\n");
  298. if(samplingrates == 8000)
  299. file_name = "/appfs/dmic8k.wav";
  300. else
  301. file_name = "/appfs/dmic16k.wav";
  302. fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0);
  303. if (fd < 0)
  304. {
  305. rt_kprintf("open file for write failed\n");
  306. return -RT_EIO;
  307. }
  308. speech_wav_init_header(&wav_header,1,samplingrates,16);
  309. write(fd, &wav_header, wav_len);
  310. jz_dmic_set_rate(dmic,samplingrates);
  311. wav_len = 0;
  312. while(i++ < 1000)
  313. {
  314. rdlen = rt_device_read(dmic_pipe,0,rec_buff,sizeof(rec_buff));
  315. wrlen = write(fd, rec_buff, rdlen);
  316. if (wrlen != rdlen)
  317. {
  318. rt_kprintf("write data failed\n");
  319. close(fd);
  320. return -RT_EIO;
  321. }
  322. wav_len += wrlen;
  323. if(gpio_get_value(GPIO_PORT_B, GPIO_Pin_31) == 1)
  324. break;
  325. }
  326. rt_kprintf("record complete...\n");
  327. //upgrage wav header
  328. lseek(fd,0,SEEK_SET);
  329. speech_wav_upgrade_size(&wav_header,wav_len);
  330. write(fd, &wav_header, sizeof(struct speech_wav_header));
  331. close(fd);
  332. rt_kprintf("WAV file saved ok!\n");
  333. }
  334. FINSH_FUNCTION_EXPORT(dmic_record,dmic record test);
  335. #if 0
  336. int dmic_test(void)
  337. {
  338. rt_device_t device;
  339. int i = 0;
  340. device = rt_device_find("recdmic");
  341. if(device == RT_NULL)
  342. {
  343. rt_kprintf("can't find the record device\n");
  344. return -RT_ERROR ;
  345. }
  346. audio_device_set_rate(8000);
  347. while(i++ < 1000)
  348. {
  349. int len;
  350. uint8_t *sendBuf;
  351. sendBuf = audio_device_get_buffer(&len);
  352. len = rt_device_read(device,0,sendBuf,len);
  353. audio_device_write(sendBuf,len);
  354. }
  355. rt_kprintf("dmic test complete...\n");
  356. return 0;
  357. }
  358. MSH_CMD_EXPORT(dmic_test,dmic test ....);
  359. #endif