-
-
Save justiceamoh/4c3033b2c5afbbe1d5c54cf4a1bf8235 to your computer and use it in GitHub Desktop.
Queued PDM Streaming on Artemis Boards
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define ARM_MATH_CM4 //ARM Math library needed for FFT | |
#include <arm_math.h> | |
#include "am_bsp.h" | |
#include <CircularBuffer.h> | |
#define ledPin LED_BUILTIN | |
// ---------------- | |
// Global Variables | |
// ---------------- | |
#define BUFFSIZE 512 | |
#define FRMESIZE 128 | |
uint32_t PDMDataBuffer[BUFFSIZE]; | |
int16_t *pi16Buffer = (int16_t *) PDMDataBuffer; | |
int16_t FrameBuffer[FRMESIZE]={0}; | |
// Audio Buffer | |
CircularBuffer<int16_t,2048> AudioQueue; | |
am_hal_pdm_transfer_t sTransfer; | |
// Global Vars | |
int fidx = 0; // Buffer read pointer | |
// ----------------- | |
// PDM Configuration | |
// ----------------- | |
void *PDMHandle = NULL; | |
am_hal_pdm_config_t newConfig = { | |
.eClkDivider = AM_HAL_PDM_MCLKDIV_1, | |
.eLeftGain = AM_HAL_PDM_GAIN_0DB, | |
.eRightGain = AM_HAL_PDM_GAIN_0DB, | |
.ui32DecimationRate = 24, | |
.bHighPassEnable = 0, | |
.ui32HighPassCutoff = 0xB, | |
.ePDMClkSpeed = AM_HAL_PDM_CLK_750KHZ, //we get 768,000 Hz using 49.152 MHz clock | |
.bInvertI2SBCLK = 0, | |
.ePDMClkSource = AM_HAL_PDM_INTERNAL_CLK, | |
.bPDMSampleDelay = 0, | |
.bDataPacking = 0, | |
.ePCMChannels = AM_HAL_PDM_CHANNEL_RIGHT, | |
.ui32GainChangeDelay = 1, | |
.bI2SEnable = 0, | |
.bSoftMute = 0, | |
.bLRSwap = 0, | |
}; | |
// ----------------- | |
// PDM Configuration | |
// ----------------- | |
void pdm_init(void){ | |
// Initialize, power-up and configure PDM | |
am_hal_pdm_initialize(0,&PDMHandle); | |
am_hal_pdm_power_control(PDMHandle, AM_HAL_PDM_POWER_ON,false); | |
am_hal_pdm_configure(PDMHandle,&newConfig); | |
am_hal_pdm_enable(PDMHandle); | |
// Configure PDM pins | |
am_hal_gpio_pinconfig(AM_BSP_PDM_DATA, g_AM_BSP_PDM_DATA); | |
am_hal_gpio_pinconfig(AM_BSP_PDM_CLOCK, g_AM_BSP_PDM_CLOCK); | |
// Configure PDM interrupts - set to trigger on DMA completion | |
am_hal_pdm_interrupt_enable(PDMHandle,(AM_HAL_PDM_INT_DERR | |
| AM_HAL_PDM_INT_DCMP | |
| AM_HAL_PDM_INT_UNDFL | |
| AM_HAL_PDM_INT_OVF)); | |
// Enable PDM interrupt | |
NVIC_EnableIRQ(PDM_IRQn); | |
} | |
// ---------------------------- | |
// Get Data from PDM Microphone | |
// ---------------------------- | |
void pdm_data_start(void){ | |
// Configure DMA and target address. | |
sTransfer.ui32TargetAddr = (uint32_t ) PDMDataBuffer; | |
sTransfer.ui32TotalCount = BUFFSIZE * 2; | |
// Start the data transfer. | |
am_hal_pdm_enable(PDMHandle); | |
am_util_delay_ms(100); | |
am_hal_pdm_fifo_flush(PDMHandle); | |
am_hal_pdm_dma_start(PDMHandle, &sTransfer); | |
} | |
void pdm_data_stop(void){ | |
am_hal_pdm_disable(PDMHandle); | |
} | |
// ----------------------------- | |
// PDM Interrupt Service Routine | |
// ----------------------------- | |
extern "C" void am_pdm_isr(void){ | |
uint32_t ui32Status; | |
// Read the interrupt status. | |
am_hal_pdm_interrupt_status_get(PDMHandle, &ui32Status, true); | |
am_hal_pdm_interrupt_clear(PDMHandle, ui32Status); | |
// Once DMA transaction completes, move to Queue & Start next conversion | |
if (ui32Status & AM_HAL_PDM_INT_DCMP){ | |
for (int i=0; i<BUFFSIZE;i++){ | |
AudioQueue.push(pi16Buffer[i]); | |
} | |
// Start next conversion | |
am_hal_pdm_dma_start(PDMHandle, &sTransfer); | |
} | |
} | |
void setup() { | |
pinMode(ledPin, OUTPUT); | |
Serial.begin(115200); | |
delay(1000); | |
pdm_init(); | |
pdm_data_start(); | |
} | |
void loop() { | |
processFrame(); | |
} | |
void processFrame(){ | |
if(!AudioQueue.isEmpty()){ | |
FrameBuffer[fidx] = AudioQueue.pop(); | |
fidx+=1; | |
//When frame is full, dump to serial | |
if(fidx==FRMESIZE){ | |
Serial.write((uint8_t*)FrameBuffer, sizeof(FrameBuffer)); | |
fidx = 0; | |
delay(2); | |
} | |
} | |
} | |
// Blink n times | |
void blink(int n){ | |
for (int i = 0; i < n; ++i) { | |
digitalWrite(ledPin, LOW); | |
delay(100); | |
digitalWrite(ledPin, HIGH); | |
delay(100); | |
digitalWrite(ledPin, LOW); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment