Introduction
In order to feed the AI recognition for detect the dog bites either cloud AWS or locally by TensorFlow lite, first we must make the sound card work, unfortunately the sound card and mic do not work out of board as easy as like Linux, PSOC6 require extensive of hardware and software knowledge for make it smooth, as those tiny and small device design for iOT which provide downsizing and ultra low power application together with relative lower cost, developer should very careful using of resources under small size of memory and restricted power. However, Cypress provide HAL layer and rich open source support which help develop meet their target.
In this topic, i could introudce how the pioneer kit embedded PDM mic and Sound card can be uilized under Mbed, how we can echo the mic to sound card so we can listen our voice from the phone, I also discuss use the DMA for reduce CPU loading and free for other tasks. On next blog, we will explore the FRAM which is new type of high reliability and endurnace non-volatile memory suitable to store frequency change data such as our sound data.
Hardware
The TFT shielder included a Knowles MEMS and AKM 4954A sound codec for evaluate, the Cypress
https://github.com/cypresssemiconductorco/mtb-example-psoc6-i2s and https://github.com/cypresssemiconductorco/mtb-example-psoc6-pdm-to-i2s
examples provide good startup of how to use those parts, however no Mbed example, so we are working for that. We also use the driver of AK4954a.
UART and I2S Codec under Mbed
The Mbed will hang the system when booting if you try to config the I2S under Device Configurator, it is because the kit UART used by Mbed for console debug is share as I2S port (P5_0),
instead of fully close of UART without console data, I programming for temporary close UART when sound playing. Instead of using Device Configurator, i fully manual startup of I2S, PDM mic and setup DMA by the code.
BUFFER
We use two small buffer, each with 256 samples, one for playback, another for record, after each cycles, role of buffer will fliping to provide continue sound steam.
The DMA will trigged interrupt after finish read 256 data, and we start another cycle by change of Dsc/Src Address of DMA.
DMA
The CPU with two separate DMA direct memory access, our echo use both of them, which DM1 for Mic input and DM0 for codec, we also use the interrupt DMA to flipping the record and playback buffer. The I2S require stereo signal, we use 2D DMA at codec TX DMA, which every address will read twice before shift to other.
Based on the timing for PDM Mic we selected MONO LEFT input, as I2S require Left/Right signal, just every cycle DMA Codec read some address twice for duplicate left and right. The Mic DMA just write once, the DMA run all those process without use CPU resources.
The descriptor help us to play with that, for PDM input, simple 1D Xincrement 1 and xCount set to 256, as PDM config .chanSelect CY_PDM_PCM_OUT_CHAN_LEFT only Mono data will feed to buffer for save memory.
The descriptor of I2S we config to 2D srcXincrement set 0 and xCount set to 2 to stand some address twice, and outer (Y) loop srcYincrement set 1 and Count to 256 to feed both left/right some samples.
We also set trigger type to CY_DMA_DESCR, so after each descriptor finish we have chance for change of address.
Because we only need change the dsc/src address between every descriptor, very low overhead is require for background playback, as this is the reason why DMA save CPU time and power.
WHD WIFI
The DMA is share with other periphial such as WIFI, as the WIFI heavy use of DMA resource when init,
suggest startup the sound card and mic after WIFI init to avoid init timeout of WIFI, which the DMA able to handle both task.
Sound Format
In our application, which detect dog voices, don't require audiophile quality, instead we set the mic and codec under 22khz 16bit which is sufficient our need, as internal SRAM/Flash not enough for few seconds capture, next blog will discuss how to save data to FRAM.
Our format I2S 16bit format, DMA will auto transfer 16bit data (halfword) to 32bit (P) feed of codec.
Clock
The clock of mic and codec should match of format, reference the TPM document for detail, as Cypress example use MCLK generated by PWM, instead we use coder self PLL, we found that use AK4954A's PLL get better reason, it may because the P5_0 ports is shared with UART.
The Sample Code
Demo with explain have been under our git site.
Under sound.cpp, the sound_init function is the initial process of PDM, I2S, sound card and DMA, follow setup the DMA descriptor and address.
After that enable the DMA and DMA channel, initialise the DMAs Interrupt, set the priority to 3 for lower.
The callback of interrupt just flip the address to another buffer.
Cy_DMA_Channel_ClearInterrupt(CYBSP_DMA_PDM_HW, CYBSP_DMA_PDM_CHANNEL); /*Flip Buffer*/ if (Cy_DMA_Descriptor_GetDstAddress(&CYBSP_DMA_PDM_Descriptor_0)==(void*)record_buffer[0][0]) Cy_DMA_Descriptor_SetDstAddress(&CYBSP_DMA_PDM_Descriptor_0, (void*)record_buffer[1][0]); else Cy_DMA_Descriptor_SetDstAddress(&CYBSP_DMA_PDM_Descriptor_0, (void*)record_buffer[0][0]); /* Enable channel for start next cycle */ Cy_DMA_Channel_Enable(CYBSP_DMA_PDM_HW, CYBSP_DMA_PDM_CHANNEL);
The Demo echo the mic sound to sound card 60s and close all resource fully, plug a earphone to listen self voice.
https://github.com/sicreative/mbed-os-cypress-echo
Next
The internal SRAM / Flash is too small for save few seconds data for future use, as we will study how to save voice to external FRAM (QSPI).