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 * 2017-12-04 Haley the first version
9 */
10
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include "am_mcu_apollo.h"
14
15 #ifdef RT_USING_PDM
16
17 /* messagequeue define */
18 struct rt_messagequeue pdm_mq;
19
20 static rt_uint8_t am_pdm_buffer_pool[1024];
21
22 #define NWA_FRAME_SAMPLES 160 /* 8k, 16bit, mono audio data */
23 #define PDM_FIFO_THRESHOLD NWA_FRAME_SAMPLES
24
25 #define PDM_GPIO_CLK 22
26 #define PDM_GPIO_CFG_CLK AM_HAL_PIN_22_PDM_CLK
27 #define PDM_GPIO_DATA 23
28 #define PDM_GPIO_CFG_DATA AM_HAL_PIN_23_PDM_DATA
29
30 static am_hal_pdm_config_t g_sPDMConfig =
31 {
32 AM_HAL_PDM_PCFG_LRSWAP_DISABLE | AM_HAL_PDM_PCFG_RIGHT_PGA_0DB | AM_HAL_PDM_PCFG_LEFT_PGA_0DB
33 | AM_HAL_PDM_PCFG_MCLKDIV_DIV1 | AM_HAL_PDM_PCFG_SINC_RATE(48) | AM_HAL_PDM_PCFG_ADCHPD_ENABLE
34 | AM_HAL_PDM_PCFG_HPCUTOFF(0x1) | AM_HAL_PDM_PCFG_CYCLES(0x1) | AM_HAL_PDM_PCFG_SOFTMUTE_DISABLE
35 | AM_HAL_PDM_PCFG_PDMCORE_ENABLE, /* Set the PDM configuration */
36 AM_HAL_PDM_IOCLK_750KHZ | AM_HAL_PDM_VCFG_RSTB_NORMAL | AM_HAL_PDM_VCFG_PDMCLK_ENABLE
37 | AM_HAL_PDM_VCFG_I2SMODE_DISABLE | AM_HAL_PDM_VCFG_BCLKINV_DISABLE | AM_HAL_PDM_VCFG_DMICDEL_DISABLE
38 | AM_HAL_PDM_VCFG_SELAP_INTERNAL | AM_HAL_PDM_VCFG_PACK_DISABLE | AM_HAL_PDM_VCFG_CHANNEL_LEFT, /* Set the Voice Configuration */
39 PDM_FIFO_THRESHOLD, /* Select the FIFO PCM sample threshold 0~256 */
40 };
41
42 /**
43 * @brief Get the pdm data.
44 *
45 * @param None.
46 *
47 * This function Get the pdm data.
48 *
49 * @return None.
50 */
am_pdm_data_get(rt_uint8_t * buff,rt_uint16_t size)51 rt_uint8_t am_pdm_data_get(rt_uint8_t *buff, rt_uint16_t size)
52 {
53 rt_uint8_t pdm_rbufftemp[340];
54
55 /* wait pdm message forever */
56 rt_mq_recv(&pdm_mq, pdm_rbufftemp, 340, RT_WAITING_FOREVER);
57
58 /* copy the data */
59 rt_memcpy(buff, (char *)pdm_rbufftemp, size);
60
61 return 0;
62 }
63
64 /**
65 * @brief Start the pdm.
66 *
67 * @param None.
68 *
69 * This function Start the pdm.
70 *
71 * @return None.
72 */
am_pdm_start(void)73 void am_pdm_start(void)
74 {
75 /* Enable PDM */
76 am_hal_interrupt_enable(AM_HAL_INTERRUPT_PDM);
77 am_hal_pdm_enable();
78 }
79
80 /**
81 * @brief Stop the pdm.
82 *
83 * @param None.
84 *
85 * This function Stop the pdm.
86 *
87 * @return None.
88 */
am_pdm_stop(void)89 void am_pdm_stop(void)
90 {
91 /* Disable PDM */
92 am_hal_interrupt_disable(AM_HAL_INTERRUPT_PDM);
93 am_hal_pdm_disable();
94 }
95
96 /**
97 * @brief Get the pdm left gain.
98 *
99 * @param None.
100 *
101 * This function Get the pdm left gain.
102 *
103 * @return gain_val.
104 */
am_pdm_left_gain_get(void)105 uint8_t am_pdm_left_gain_get(void)
106 {
107 /* get the left gain */
108 return am_hal_pdm_left_gain_get();
109 }
110
111 /**
112 * @brief Set the pdm left gain.
113 *
114 * @param gain_val.
115 *
116 * This function Set the pdm left gain.
117 *
118 * @return None.
119 */
am_pdm_left_gain_set(uint8_t gain_val)120 void am_pdm_left_gain_set(uint8_t gain_val)
121 {
122 /* set the left gain */
123 am_hal_pdm_left_gain_set(gain_val);
124 }
125
126 /**
127 * @brief Get the pdm right gain.
128 *
129 * @param None.
130 *
131 * This function Get the pdm right gain.
132 *
133 * @return gain_val.
134 */
am_pdm_right_gain_get(void)135 uint8_t am_pdm_right_gain_get(void)
136 {
137 /* get the right gain */
138 return am_hal_pdm_right_gain_get();
139 }
140
141 /**
142 * @brief Set the pdm right gain.
143 *
144 * @param gain_val.
145 *
146 * This function Set the pdm right gain.
147 *
148 * @return None.
149 */
am_pdm_right_gain_set(uint8_t gain_val)150 void am_pdm_right_gain_set(uint8_t gain_val)
151 {
152 /* set the right gain */
153 am_hal_pdm_right_gain_set(gain_val);
154 }
155
156 /**
157 * @brief Interrupt handler for the PDM
158 *
159 * This function is Interrupt handler for the PDM
160 *
161 * @return None.
162 */
am_pdm_isr(void)163 void am_pdm_isr (void)
164 {
165 int i;
166 rt_int16_t pdm_sbufftemp[160];
167
168 /* Clear the PDM interrupt */
169 am_hal_pdm_int_clear(AM_HAL_PDM_INT_UNDFL | AM_HAL_PDM_INT_OVF | AM_HAL_PDM_INT_FIFO);
170
171 for (i = 0; i < PDM_FIFO_THRESHOLD; i++) /* adjust as needed */
172 {
173 pdm_sbufftemp[i] = (rt_int16_t)am_hal_pdm_fifo_data_read();
174 }
175
176 /* send the message */
177 rt_mq_send(&pdm_mq, pdm_sbufftemp, PDM_FIFO_THRESHOLD*sizeof(rt_int16_t));
178 }
179
180 /**
181 * @brief Initialize the PDM
182 *
183 * This function initialize the PDM
184 *
185 * @return None.
186 */
rt_hw_pdm_init(void)187 int rt_hw_pdm_init(void)
188 {
189 /* Enable power to modules used */
190 am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PDM);
191
192 /* Enable the PDM clock and data */
193 am_hal_gpio_pin_config(PDM_GPIO_CLK, PDM_GPIO_CFG_CLK | AM_HAL_GPIO_HIGH_DRIVE);
194 am_hal_gpio_pin_config(PDM_GPIO_DATA, PDM_GPIO_CFG_DATA );
195
196 /* PDM setting */
197 am_hal_pdm_config(&g_sPDMConfig);
198
199 /* Enable PDM interrupts */
200 am_hal_pdm_int_enable(AM_HAL_PDM_INT_FIFO);
201
202 /* Clear PDM interrupts */
203 am_hal_pdm_int_clear(AM_HAL_PDM_INT_UNDFL | AM_HAL_PDM_INT_OVF | AM_HAL_PDM_INT_FIFO);
204
205 /* messagequeue init */
206 rt_mq_init(&pdm_mq, "mq_pdm",
207 &am_pdm_buffer_pool[0],
208 340 - sizeof(void*),
209 sizeof(am_pdm_buffer_pool),
210 RT_IPC_FLAG_FIFO);
211
212 //rt_kprintf("pdm_init!\n");
213
214 return 0;
215 }
216 #ifdef RT_USING_COMPONENTS_INIT
217 INIT_BOARD_EXPORT(rt_hw_pdm_init);
218 #endif
219
220 #endif
221
222 /*@}*/
223