parent
b400897ca2
commit
7df080ee92
2 changed files with 57 additions and 19 deletions
|
|
@ -38,6 +38,7 @@ public:
|
|||
|
||||
//PORTENTA_H7 min -12 max 51
|
||||
//NANO 33 BLE SENSe min 0 max 80
|
||||
//NICLA_VISION min 0 max 8
|
||||
void setGain(int gain);
|
||||
void setBufferSize(int bufferSize);
|
||||
size_t getBufferSize();
|
||||
|
|
@ -56,6 +57,8 @@ private:
|
|||
int _gain;
|
||||
int _init;
|
||||
|
||||
int _cutSamples;
|
||||
|
||||
// Hardware peripherals used
|
||||
uint _dmaChannel;
|
||||
PIO _pio;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ uint8_t rawBuffer1[RAW_BUFFER_SIZE];
|
|||
uint8_t* rawBuffer[2] = {rawBuffer0, rawBuffer1};
|
||||
volatile int rawBufferIndex = 0;
|
||||
|
||||
int decimation = 64;
|
||||
int decimation = 128;
|
||||
|
||||
// final buffer is the one to be filled with PCM data
|
||||
int16_t* volatile finalBuffer;
|
||||
|
|
@ -45,6 +45,7 @@ PDMClass::PDMClass(int dinPin, int clkPin, int pwrPin) :
|
|||
_channels(-1),
|
||||
_samplerate(-1),
|
||||
_init(-1),
|
||||
_cutSamples(100),
|
||||
_dmaChannel(0),
|
||||
_pio(nullptr),
|
||||
_smIdx(-1),
|
||||
|
|
@ -55,6 +56,12 @@ PDMClass::~PDMClass() {
|
|||
}
|
||||
|
||||
int PDMClass::begin(int channels, int sampleRate) {
|
||||
|
||||
if (_init == 1) {
|
||||
//ERROR: please call end first
|
||||
return 0;
|
||||
}
|
||||
|
||||
//_channels = channels; // only one channel available
|
||||
|
||||
// clear the final buffers
|
||||
|
|
@ -63,6 +70,18 @@ int PDMClass::begin(int channels, int sampleRate) {
|
|||
int finalBufferLength = _doubleBuffer.availableForWrite() / sizeof(int16_t);
|
||||
_doubleBuffer.swap(0);
|
||||
|
||||
// The mic accepts an input clock from 1.2 to 3.25 Mhz
|
||||
// Setup the decimation factor accordingly
|
||||
if ((sampleRate * decimation * 2) > 3250000) {
|
||||
decimation = 64;
|
||||
}
|
||||
|
||||
// Sanity check, abort if still over 3.25Mhz
|
||||
if ((sampleRate * decimation * 2) > 3250000) {
|
||||
//ERROR: Sample rate too high, the mic would glitch
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rawBufferLength = RAW_BUFFER_SIZE / (decimation / 8);
|
||||
// Saturate number of samples. Remaining bytes are dropped.
|
||||
if (rawBufferLength > finalBufferLength) {
|
||||
|
|
@ -71,6 +90,7 @@ int PDMClass::begin(int channels, int sampleRate) {
|
|||
|
||||
/* Initialize Open PDM library */
|
||||
filter.Fs = sampleRate;
|
||||
filter.MaxVolume = 1;
|
||||
filter.nSamples = rawBufferLength;
|
||||
filter.LP_HZ = sampleRate / 2;
|
||||
filter.HP_HZ = 10;
|
||||
|
|
@ -88,7 +108,7 @@ int PDMClass::begin(int channels, int sampleRate) {
|
|||
|
||||
if (!_pdmPgm.prepare(&_pio, &_smIdx, &_pgmOffset)) {
|
||||
// ERROR, no free slots
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
pdm_pio_program_init(_pio, _smIdx, _pgmOffset, _clkPin, _dinPin, clkDiv);
|
||||
|
||||
|
|
@ -118,14 +138,29 @@ int PDMClass::begin(int channels, int sampleRate) {
|
|||
true // Start immediately
|
||||
);
|
||||
|
||||
_cutSamples = 100;
|
||||
|
||||
_init = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void PDMClass::end() {
|
||||
|
||||
if (_init != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
dma_channel_set_irq0_enabled(_dmaChannel, false);
|
||||
dma_channel_abort(_dmaChannel);
|
||||
dma_channel_unclaim(_dmaChannel);
|
||||
irq_remove_handler(DMA_IRQ_0, dmaHandler);
|
||||
pio_sm_unclaim(_pio, _smIdx);
|
||||
pinMode(_clkPin, INPUT);
|
||||
rawBufferIndex = 0;
|
||||
_pgmOffset = -1;
|
||||
|
||||
_init = 0;
|
||||
}
|
||||
|
||||
int PDMClass::available() {
|
||||
|
|
@ -163,7 +198,6 @@ void PDMClass::setBufferSize(int bufferSize) {
|
|||
}
|
||||
|
||||
void PDMClass::IrqHandler(bool halftranfer) {
|
||||
static int cutSamples = 100;
|
||||
|
||||
// Clear the interrupt request.
|
||||
dma_hw->ints0 = 1u << _dmaChannel;
|
||||
|
|
@ -171,24 +205,25 @@ void PDMClass::IrqHandler(bool halftranfer) {
|
|||
int shadowIndex = rawBufferIndex ^ 1;
|
||||
dma_channel_set_write_addr(_dmaChannel, rawBuffer[shadowIndex], true);
|
||||
|
||||
if (_doubleBuffer.available()) {
|
||||
// buffer overflow, stop
|
||||
return end();
|
||||
if (!_doubleBuffer.available()) {
|
||||
// fill final buffer with PCM samples
|
||||
if (filter.Decimation == 128) {
|
||||
Open_PDM_Filter_128(rawBuffer[rawBufferIndex], finalBuffer, 1, &filter);
|
||||
} else {
|
||||
Open_PDM_Filter_64(rawBuffer[rawBufferIndex], finalBuffer, 1, &filter);
|
||||
}
|
||||
|
||||
if (_cutSamples) {
|
||||
memset(finalBuffer, 0, _cutSamples);
|
||||
_cutSamples = 0;
|
||||
}
|
||||
|
||||
// swap final buffer and raw buffers' indexes
|
||||
finalBuffer = (int16_t*)_doubleBuffer.data();
|
||||
_doubleBuffer.swap(filter.nSamples * sizeof(int16_t));
|
||||
rawBufferIndex = shadowIndex;
|
||||
}
|
||||
|
||||
// fill final buffer with PCM samples
|
||||
Open_PDM_Filter_64(rawBuffer[rawBufferIndex], finalBuffer, 1, &filter);
|
||||
|
||||
if (cutSamples) {
|
||||
memset(finalBuffer, 0, cutSamples);
|
||||
cutSamples = 0;
|
||||
}
|
||||
|
||||
// swap final buffer and raw buffers' indexes
|
||||
finalBuffer = (int16_t*)_doubleBuffer.data();
|
||||
_doubleBuffer.swap(filter.nSamples * sizeof(int16_t));
|
||||
rawBufferIndex = shadowIndex;
|
||||
|
||||
if (_onReceive) {
|
||||
_onReceive();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue