1/* ----------------------------------------------------------------------
2 * Project:      CMSIS DSP Library
3 * Title:        kws.ino
4 * Description:  Very simple Yes detector
5 *
6 * $Date:        16 March 2022
7 *
8 * Target Processor: Cortex-M and Cortex-A cores
9 * -------------------------------------------------------------------- */
10/*
11 * Copyright (C) 2010-2022 ARM Limited or its affiliates. All rights reserved.
12 *
13 * SPDX-License-Identifier: Apache-2.0
14 *
15 * Licensed under the Apache License, Version 2.0 (the License); you may
16 * not use this file except in compliance with the License.
17 * You may obtain a copy of the License at
18 *
19 * www.apache.org/licenses/LICENSE-2.0
20 *
21 * Unless required by applicable law or agreed to in writing, software
22 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
23 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24 * See the License for the specific language governing permissions and
25 * limitations under the License.
26 */
27
28#include <PDM.h>
29#include "arm_math.h"
30#include "coef.h"
31#include "scheduler.h"
32
33// default number of output channels
34static const char channels = 1;
35
36// default PCM output frequency
37static const int frequency = 16000;
38
39// Buffer to read samples into, each sample is 16-bits
40short sampleBuffer[AUDIOBUFFER_LENGTH];
41
42// Number of audio samples read
43volatile int samplesRead=0;
44
45
46void setup() {
47  Serial.begin(9600);
48  while (!Serial);
49
50  Serial.println("Starting ...");
51
52  // Configure the data receive callback
53  PDM.onReceive(onPDMdata);
54
55  // Optionally set the gain
56  // Defaults to 20 on the BLE Sense and 24 on the Portenta Vision Shield
57  // PDM.setGain(30);
58
59  // Initialize PDM with:
60  // - one channel (mono mode)
61  // - a 16 kHz sample rate for the Arduino Nano 33 BLE Sense
62  // - a 32 kHz or 64 kHz sample rate for the Arduino Portenta Vision Shield
63  if (!PDM.begin(channels, frequency)) {
64    Serial.println("Failed to start PDM!");
65    while (1);
66  }
67
68
69}
70
71void loop() {
72  int error;
73  uint32_t nb;
74
75  // Start the CMSIS-DSP generated synchronous scheduling
76
77  Serial.println("Scheduling ...");
78  nb = scheduler(&error,window,coef_q15,coef_shift,intercept_q15,intercept_shift);
79  Serial.println("End of scheduling");
80  Serial.print("Error status = ");
81  Serial.println(error);
82  Serial.print("Nb iterations");
83  Serial.println(nb);
84}
85
86/**
87 * Callback function to process the data from the PDM microphone.
88 * NOTE: This callback is executed as part of an ISR.
89 * Therefore using `Serial` to print messages inside this function isn't supported.
90 * */
91void onPDMdata() {
92  // Query the number of available bytes
93  int bytesAvailable = PDM.available();
94
95  // Get free remaining bytes in the buffer
96  // If real time is respected, there should never be
97  // any overflow.
98  int remainingFreeBytes = AUDIOBUFFER_LENGTH*2 - samplesRead*2;
99
100  if (remainingFreeBytes >= bytesAvailable)
101  {
102     // Read into the sample buffer
103     int nbReadBytes = PDM.read(sampleBuffer+samplesRead, bytesAvailable);
104
105     // 16-bit, 2 bytes per sample
106     samplesRead += nbReadBytes / 2;
107  }
108  else if (remainingFreeBytes > 0)
109  {
110    // Read into the sample buffer
111     int nbReadBytes = PDM.read(sampleBuffer+samplesRead, remainingFreeBytes);
112
113     // 16-bit, 2 bytes per sample
114     samplesRead += nbReadBytes / 2;
115  }
116
117
118}
119