From 51797757e1d13aa44fad3c6e3bfd0776eb10ac88 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Sat, 29 Sep 2012 00:12:25 +0200 Subject: [PATCH] Audio library improved. (experiments with PDC) --- .../arduino/sam/libraries/Audio/Audio.cpp | 110 +++++------------- hardware/arduino/sam/libraries/Audio/Audio.h | 6 +- hardware/arduino/sam/libraries/Audio/DAC.cpp | 14 +-- 3 files changed, 32 insertions(+), 98 deletions(-) diff --git a/hardware/arduino/sam/libraries/Audio/Audio.cpp b/hardware/arduino/sam/libraries/Audio/Audio.cpp index bd8d99186..64a418b7c 100644 --- a/hardware/arduino/sam/libraries/Audio/Audio.cpp +++ b/hardware/arduino/sam/libraries/Audio/Audio.cpp @@ -10,126 +10,68 @@ #include "Audio.h" -class LockDAC { -public: - LockDAC(DACClass *_dac) : dac(_dac) - { dac->disableInterrupts(); }; - ~LockDAC() { dac->enableInterrupts(); }; - DACClass *dac; -}; - void AudioClass::begin(uint32_t sampleRate, uint32_t msPreBuffer) { // Allocate a buffer to keep msPreBuffer milliseconds of audio bufferSize = msPreBuffer * sampleRate / 1000; - if (bufferSize < 2048) - bufferSize = 2048; + if (bufferSize < 1024) + bufferSize = 1024; buffer = (uint32_t *) malloc(bufferSize * sizeof(uint32_t)); + half = buffer + bufferSize / 2; last = buffer + bufferSize; // Buffering starts from the beginning - running = last; - current = buffer; + running = buffer; next = buffer; - // Run DAC + // Start DAC dac->begin(VARIANT_MCK / sampleRate); dac->setOnTransmitEnd_CB(onTransmitEnd, this); } void AudioClass::end() { dac->end(); - free(buffer); + free( buffer); } size_t AudioClass::write(const uint32_t *data, size_t size) { - LockDAC lock(dac); - //Serial1.print("WRI("); const uint32_t TAG = 0x10000000; int i; - for (i=0; i < size && next != running; i++) { + for (i = 0; i < size; i++) { *next = data[i] | TAG; next++; - // Wrap around circular buffer - if (next == last) - next = buffer; + if (next == half || next == last) { + enqueue(); + while (next == running) + ; + } } - debug(); - if (dac->canQueue()) { - enqueue(); - debug(); - } - //Serial1.print(")"); + return i; } void AudioClass::enqueue() { - if (!dac->canQueue()) + if (!dac->canQueue()) { // DMA queue full return; - - if (current == next) - // No data to enqueue - return; - - // If wrapping happened - if (next < current) { - - uint32_t size = last - current; - - if (size < 1024) { - // enqueue the last part of the circular buffer - dac->queueBuffer(current, size); - current = buffer; - next = buffer; - } else { - // Enqueue only a block of 512 - dac->queueBuffer(current, 512); - current += 512; - } - return; } - bool aboutToWrap = (last - next) < 512; - uint32_t size = next - current; - - // If buffered data is less than 512 bytes - if (size < 512) { - - // Enqueue all - dac->queueBuffer(current, size); - - if (aboutToWrap) - next = buffer; - current = next; - + if (next == half) { + // Enqueue the first half + dac->queueBuffer(buffer, bufferSize / 2); } else { - - if (aboutToWrap && size < 1024) { - // Enqueue all - dac->queueBuffer(current, size); - next = buffer; - current = buffer; - } else { - // Enqueue only a block of 512 - dac->queueBuffer(current, 512); - current += 512; - } - + // Enqueue the second half + dac->queueBuffer(half, bufferSize / 2); + next = buffer; // wrap around } } -void AudioClass::onTransmitEnd(void *me) { - AudioClass *audio = reinterpret_cast(me); - - //Serial1.print("INT("); - audio->enqueue(); - - // Update running pointer - audio->running = audio->dac->getCurrentQueuePointer(); - - audio->debug(); - //Serial1.print(")"); +void AudioClass::onTransmitEnd(void *_me) { + AudioClass *me = reinterpret_cast (_me); + if (me->running == me->buffer) + me->running = me->half; + else + me->running = me->buffer; } AudioClass Audio(DAC); diff --git a/hardware/arduino/sam/libraries/Audio/Audio.h b/hardware/arduino/sam/libraries/Audio/Audio.h index 93ae0e780..cb49295d1 100644 --- a/hardware/arduino/sam/libraries/Audio/Audio.h +++ b/hardware/arduino/sam/libraries/Audio/Audio.h @@ -41,10 +41,10 @@ private: static void onTransmitEnd(void *me); uint32_t bufferSize; uint32_t *buffer; + uint32_t *half; uint32_t *last; - uint32_t * volatile running; - uint32_t * volatile current; - uint32_t * volatile next; + uint32_t *volatile running; + uint32_t *volatile next; uint32_t *cook(const uint32_t *buffer, size_t size); diff --git a/hardware/arduino/sam/libraries/Audio/DAC.cpp b/hardware/arduino/sam/libraries/Audio/DAC.cpp index 766d7e4c4..f827d2f27 100644 --- a/hardware/arduino/sam/libraries/Audio/DAC.cpp +++ b/hardware/arduino/sam/libraries/Audio/DAC.cpp @@ -85,11 +85,7 @@ void DACClass::end() { } bool DACClass::canQueue() { - if ((dac->DACC_TCR == 0) && (dac->DACC_TNCR == 0)) - return true; - if (dac->DACC_TNCR == 0) - return true; - return false; + return (dac->DACC_TNCR == 0); } size_t DACClass::queueBuffer(const uint32_t *buffer, size_t size) { @@ -117,10 +113,6 @@ size_t DACClass::queueBuffer(const uint32_t *buffer, size_t size) { return 0; } -uint32_t *DACClass::getCurrentQueuePointer() { - return reinterpret_cast(dac->DACC_TPR); -} - void DACClass::setOnTransmitEnd_CB(OnTransmitEnd_CB _cb, void *_data) { cb = _cb; cbData = _data; @@ -130,12 +122,12 @@ void DACClass::setOnTransmitEnd_CB(OnTransmitEnd_CB _cb, void *_data) { void DACClass::onService() { uint32_t sr = dac->DACC_ISR; -// if (sr & DACC_ISR_ENDTX) { + if (sr & DACC_ISR_ENDTX) { // There is a free slot, enqueue data dacc_disable_interrupt(dac, DACC_IDR_ENDTX); if (cb) cb(cbData); -// } + } } DACClass DAC(DACC_INTERFACE, DACC_INTERFACE_ID, DACC_ISR_ID);