1 /* Copyright 2018 The TensorFlow Authors. All Rights Reserved. 2 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 ==============================================================================*/ 15 16 /* This file is a modification of the Tensorflow Micro Lite file _main.c */ 17 18 #include <stdint.h> 19 #include "am_bsp.h" 20 #include "am_mcu_apollo.h" // Defines AM_CMSIS_REGS 21 #include "am_util.h" 22 23 #define ARM_MATH_CM4 24 #include <arm_math.h> 25 26 //***************************************************************************** 27 // Parameters 28 // 29 // Total number of bytes transferred = 320*50*2 = 32000 30 //***************************************************************************** 31 32 #define FRAME_SIZE 320 // Capture one 320-sample (20-ms) frame at a time 33 #define NUM_FRAMES 50 // Number of frames in 1 second 34 35 //***************************************************************************** 36 // GLOBALS 37 //***************************************************************************** 38 39 volatile int16_t g_numFramesCaptured = 0; 40 volatile bool g_bPDMDataReady = false; 41 int16_t 42 captured_data[FRAME_SIZE * NUM_FRAMES]; // Location of 1-second data buffer 43 extern uint8_t g_silence_score; 44 extern uint8_t g_unknown_score; 45 extern uint8_t g_yes_score; 46 extern uint8_t g_no_score; 47 q7_t g_scores[4] = {0}; 48 49 //***************************************************************************** 50 // The entry point for the application. 51 //***************************************************************************** 52 extern int main(int argc, char** argv); 53 54 void DebugLog(const char* s) { am_util_stdio_printf("%s", s); } 55 void DebugLogInt32(int32_t i) { am_util_stdio_printf("%d", i); } 56 void DebugLogUInt32(uint32_t i) { am_util_stdio_printf("%d", i); } 57 void DebugLogHex(uint32_t i) { am_util_stdio_printf("0x%8x", i); } 58 void DebugLogFloat(float i) { am_util_stdio_printf("%f", i); } 59 60 //***************************************************************************** 61 // PDM configuration information. 62 //***************************************************************************** 63 void* PDMHandle; 64 65 am_hal_pdm_config_t g_sPdmConfig = { 66 .eClkDivider = AM_HAL_PDM_MCLKDIV_1, 67 .eLeftGain = AM_HAL_PDM_GAIN_P225DB, 68 .eRightGain = AM_HAL_PDM_GAIN_P225DB, 69 .ui32DecimationRate = 70 48, // OSR = 1500/16 = 96 = 2*SINCRATE --> SINC_RATE = 48 71 .bHighPassEnable = 0, 72 .ui32HighPassCutoff = 0xB, 73 .ePDMClkSpeed = AM_HAL_PDM_CLK_1_5MHZ, 74 .bInvertI2SBCLK = 0, 75 .ePDMClkSource = AM_HAL_PDM_INTERNAL_CLK, 76 .bPDMSampleDelay = 0, 77 .bDataPacking = 1, 78 .ePCMChannels = AM_HAL_PDM_CHANNEL_RIGHT, 79 .bLRSwap = 0, 80 }; 81 82 //***************************************************************************** 83 // BUTTON0 pin configuration settings. 84 //***************************************************************************** 85 const am_hal_gpio_pincfg_t g_deepsleep_button0 = { 86 .uFuncSel = 3, 87 .eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI, 88 .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE, 89 }; 90 91 //***************************************************************************** 92 // PDM initialization. 93 //***************************************************************************** 94 void pdm_init(void) { 95 // 96 // Initialize, power-up, and configure the PDM. 97 // 98 am_hal_pdm_initialize(0, &PDMHandle); 99 am_hal_pdm_power_control(PDMHandle, AM_HAL_PDM_POWER_ON, false); 100 am_hal_pdm_configure(PDMHandle, &g_sPdmConfig); 101 am_hal_pdm_enable(PDMHandle); 102 103 // 104 // Configure the necessary pins. 105 // 106 am_hal_gpio_pincfg_t sPinCfg = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 107 108 // ARPIT 181019 109 // sPinCfg.uFuncSel = AM_HAL_PIN_10_PDMCLK; 110 // am_hal_gpio_pinconfig(10, sPinCfg); 111 sPinCfg.uFuncSel = AM_HAL_PIN_12_PDMCLK; 112 am_hal_gpio_pinconfig(12, sPinCfg); 113 114 sPinCfg.uFuncSel = AM_HAL_PIN_11_PDMDATA; 115 am_hal_gpio_pinconfig(11, sPinCfg); 116 117 // am_hal_gpio_state_write(14, AM_HAL_GPIO_OUTPUT_CLEAR); 118 // am_hal_gpio_pinconfig(14, g_AM_HAL_GPIO_OUTPUT); 119 120 // 121 // Configure and enable PDM interrupts (set up to trigger on DMA 122 // completion). 123 // 124 am_hal_pdm_interrupt_enable(PDMHandle, 125 (AM_HAL_PDM_INT_DERR | AM_HAL_PDM_INT_DCMP | 126 AM_HAL_PDM_INT_UNDFL | AM_HAL_PDM_INT_OVF)); 127 128 #if AM_CMSIS_REGS 129 NVIC_EnableIRQ(PDM_IRQn); 130 #else 131 am_hal_interrupt_enable(AM_HAL_INTERRUPT_PDM); 132 #endif 133 } 134 135 //***************************************************************************** 136 // 137 // Start a transaction to get some number of bytes from the PDM interface. 138 // 139 //***************************************************************************** 140 void pdm_data_get(void) { 141 // 142 // Configure DMA and target address. 143 // 144 am_hal_pdm_transfer_t sTransfer; 145 sTransfer.ui32TargetAddr = 146 (uint32_t)(&captured_data[FRAME_SIZE * g_numFramesCaptured]); 147 sTransfer.ui32TotalCount = 2 * FRAME_SIZE; // Each sample is 2 bytes 148 149 // 150 // Start the data transfer. 151 // 152 am_hal_pdm_dma_start(PDMHandle, &sTransfer); 153 } 154 155 //***************************************************************************** 156 // 157 // PDM interrupt handler. 158 // 159 //***************************************************************************** 160 void am_pdm0_isr(void) { 161 uint32_t ui32Status; 162 // 163 // Read the interrupt status. 164 // 165 am_hal_pdm_interrupt_status_get(PDMHandle, &ui32Status, true); 166 am_hal_pdm_interrupt_clear(PDMHandle, ui32Status); 167 168 // 169 // Once our DMA transaction completes, send a flag to the main routine 170 // 171 if (ui32Status & AM_HAL_PDM_INT_DCMP) g_bPDMDataReady = true; 172 } 173 174 //***************************************************************************** 175 // GPIO ISR 176 // Will enable the PDM, set number of frames transferred to 0, and turn on LED 177 //***************************************************************************** 178 void am_gpio_isr(void) { 179 // 180 // Delay for debounce. 181 // 182 am_util_delay_ms(200); 183 184 // 185 // Clear the GPIO Interrupt (write to clear). 186 // 187 am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(AM_BSP_GPIO_BUTTON0)); 188 189 // Start audio transfer 190 am_hal_pdm_fifo_flush(PDMHandle); 191 pdm_data_get(); 192 am_hal_pdm_enable(PDMHandle); 193 194 // 195 // Turn on LED 0 196 // 197 am_devices_led_on(am_bsp_psLEDs, 0); 198 } 199 200 int _main(void) { 201 am_util_id_t sIdDevice; 202 uint32_t ui32StrBuf; 203 204 // 205 // Set the clock frequency. 206 // 207 am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0); 208 209 // 210 // Set the default cache configuration 211 // 212 am_hal_cachectrl_config(&am_hal_cachectrl_defaults); 213 am_hal_cachectrl_enable(); 214 215 // 216 // Configure the board for low power operation. 217 // 218 am_bsp_low_power_init(); 219 220 #if defined(AM_BSP_NUM_BUTTONS) && defined(AM_BSP_NUM_LEDS) 221 // 222 // Configure the button pin. 223 // 224 am_hal_gpio_pinconfig(AM_BSP_GPIO_BUTTON0, g_deepsleep_button0); 225 226 // 227 // Clear the GPIO Interrupt (write to clear). 228 // 229 am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(AM_BSP_GPIO_BUTTON0)); 230 231 // 232 // Enable the GPIO/button interrupt. 233 // 234 am_hal_gpio_interrupt_enable(AM_HAL_GPIO_BIT(AM_BSP_GPIO_BUTTON0)); 235 236 // 237 // Configure the LEDs. 238 // 239 am_devices_led_array_init(am_bsp_psLEDs, AM_BSP_NUM_LEDS); 240 241 // 242 // Turn the LEDs off 243 // 244 for (int ix = 0; ix < AM_BSP_NUM_LEDS; ix++) { 245 am_devices_led_off(am_bsp_psLEDs, ix); 246 } 247 248 // am_devices_led_on(am_bsp_psLEDs, 1); 249 #endif // defined(AM_BSP_NUM_BUTTONS) && defined(AM_BSP_NUM_LEDS) 250 251 #if AM_CMSIS_REGS 252 NVIC_EnableIRQ(GPIO_IRQn); 253 #else // AM_CMSIS_REGS 254 am_hal_interrupt_enable(AM_HAL_INTERRUPT_GPIO); 255 #endif // AM_CMSIS_REGS 256 257 // 258 // Enable interrupts to the core. 259 // 260 am_hal_interrupt_master_enable(); 261 262 // Turn on PDM 263 pdm_init(); 264 265 // 266 // Initialize the printf interface for UART output 267 // 268 am_bsp_uart_printf_enable(); 269 270 // 271 // Print the banner. 272 // 273 am_util_stdio_terminal_clear(); 274 am_util_stdio_printf("Starting streaming test\n\n"); 275 276 // Score variables 277 q7_t max_score = 0; 278 uint32_t max_score_index = 0; 279 280 while (1) { 281 am_hal_interrupt_master_disable(); 282 283 if (g_bPDMDataReady) { 284 g_bPDMDataReady = false; 285 g_numFramesCaptured++; 286 287 if (g_numFramesCaptured < NUM_FRAMES) { 288 pdm_data_get(); // Start converting the next set of PCM samples. 289 } 290 291 else { 292 g_numFramesCaptured = 0; 293 // am_hal_pdm_disable(PDMHandle); 294 am_devices_led_off(am_bsp_psLEDs, 0); 295 296 main(0, NULL); 297 298 g_scores[0] = (q7_t)g_silence_score - 128; 299 g_scores[1] = (q7_t)g_unknown_score - 128; 300 g_scores[2] = (q7_t)g_yes_score - 128; 301 g_scores[3] = (q7_t)g_no_score - 128; 302 303 am_devices_led_off( 304 am_bsp_psLEDs, 305 max_score_index + 1); // Turn off LED for previous max score 306 arm_max_q7(g_scores, 4, &max_score, &max_score_index); 307 am_devices_led_on( 308 am_bsp_psLEDs, 309 max_score_index + 1); // Turn on LED for new max score 310 } 311 } 312 313 // 314 // Go to Deep Sleep. 315 // 316 am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP); 317 318 am_hal_interrupt_master_enable(); 319 } 320 321 // main(0, NULL); 322 } 323