Home | History | Annotate | Download | only in apollo3
      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