From 6695518cffb527ec58417aceb8b131cb98da3e5e Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 18 Jun 2012 01:53:53 +0200 Subject: [PATCH] Audio library: improved DMA transfers. Stereo output. --- .../arduino/sam/libraries/Audio/Audio.cpp | 56 +++++++++++++++---- hardware/arduino/sam/libraries/Audio/Audio.h | 24 +++++++- 2 files changed, 67 insertions(+), 13 deletions(-) diff --git a/hardware/arduino/sam/libraries/Audio/Audio.cpp b/hardware/arduino/sam/libraries/Audio/Audio.cpp index 23051045d..0831d1876 100644 --- a/hardware/arduino/sam/libraries/Audio/Audio.cpp +++ b/hardware/arduino/sam/libraries/Audio/Audio.cpp @@ -1,3 +1,12 @@ +/* + * Copyright (c) 2012 by Cristian Maglie + * Audio library for Arduino Due. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ #include "Audio.h" @@ -49,19 +58,31 @@ void AudioClass::begin(uint32_t sampleRate) { // Configure Timer Counter to trigger DAC // -------------------------------------- - pmc_enable_periph_clk(ID_TC0); + pmc_enable_periph_clk(ID_TC1); TC_Configure(TC0, 1, - TC_CMR_TCCLKS_TIMER_CLOCK2 | - TC_CMR_WAVE | // Waveform mode - TC_CMR_WAVSEL_UP_RC | // Counter running up and reset when equals to RC + TC_CMR_TCCLKS_TIMER_CLOCK2 | // Clock at MCR/8 + TC_CMR_WAVE | // Waveform mode + TC_CMR_WAVSEL_UP_RC | // Counter running up and reset when equals to RC TC_CMR_ACPA_SET | TC_CMR_ACPC_CLEAR); const uint32_t TC = VARIANT_MCK / 8 / sampleRate; TC_SetRA(TC0, 1, TC / 2); TC_SetRC(TC0, 1, TC); TC_Start(TC0, 1); - // Configure clock source for DAC (1 = TC0 Output Chan. 1) - dacc_set_trigger(dac, 1); + // Configure clock source for DAC (2 = TC0 Output Chan. 1) + dacc_set_trigger(dac, 2); + + // Configure pins + PIO_Configure(g_APinDescription[DA0].pPort, + g_APinDescription[DA0].ulPinType, + g_APinDescription[DA0].ulPin, + g_APinDescription[DA0].ulPinConfiguration); + PIO_Configure(g_APinDescription[DA1].pPort, + g_APinDescription[DA1].ulPinType, + g_APinDescription[DA1].ulPin, + g_APinDescription[DA1].ulPinConfiguration); + + currentBuffer = 0; } void AudioClass::end() { @@ -70,11 +91,10 @@ void AudioClass::end() { dacc_disable_channel(dac, 1); } -size_t AudioClass::write(const uint8_t *buffer, size_t size) { - +size_t AudioClass::write(const uint32_t *buffer, size_t size) { // Try the first PDC buffer if ((dac->DACC_TCR == 0) && (dac->DACC_TNCR == 0)) { - dac->DACC_TPR = (uint32_t) buffer; + dac->DACC_TPR = (uint32_t) cook(buffer, size); dac->DACC_TCR = size; dac->DACC_PTCR = DACC_PTCR_TXTEN; return size; @@ -82,7 +102,7 @@ size_t AudioClass::write(const uint8_t *buffer, size_t size) { // Try the second PDC buffer if (dac->DACC_TNCR == 0) { - dac->DACC_TNPR = (uint32_t) buffer; + dac->DACC_TNPR = (uint32_t) cook(buffer, size); dac->DACC_TNCR = size; dac->DACC_PTCR = DACC_PTCR_TXTEN; return size; @@ -92,6 +112,22 @@ size_t AudioClass::write(const uint8_t *buffer, size_t size) { return 0; } +uint32_t *AudioClass::cook(const uint32_t *buffer, size_t size) { + if (currentBuffer == 0) { + // Use buffer0 + for (int i = 0; i < size; i++) + buffer0[i] = buffer[i] | 0x10000000; + currentBuffer = 1; + return buffer0; + } else { + // Use buffer1 + for (int i = 0; i < size; i++) + buffer1[i] = buffer[i] | 0x10000000; + currentBuffer = 0; + return buffer1; + } +} + AudioClass Audio(DACC_INTERFACE, DACC_INTERFACE_ID); //void DACC_IrqHandler(void) { diff --git a/hardware/arduino/sam/libraries/Audio/Audio.h b/hardware/arduino/sam/libraries/Audio/Audio.h index aae6f1363..39f0f289e 100644 --- a/hardware/arduino/sam/libraries/Audio/Audio.h +++ b/hardware/arduino/sam/libraries/Audio/Audio.h @@ -1,8 +1,17 @@ +/* + * Copyright (c) 2012 by Cristian Maglie + * Audio library for Arduino Due. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + #ifndef AUDIO_H #define AUDIO_H #include "Arduino.h" -//#include #include "Print.h" class AudioClass : public Print { @@ -11,10 +20,19 @@ public: void begin(uint32_t sampleRate); void end(); - virtual size_t write(uint8_t c) { write(&c, 1); }; - virtual size_t write(const uint8_t *buffer, size_t size); + virtual size_t write(uint8_t c) { /* not implemented */ }; + virtual size_t write(const uint8_t *buffer, size_t size) { return write((uint32_t*) buffer, size/4) * 4; }; + virtual size_t write(const uint16_t *buffer, size_t size) { return write((uint32_t*) buffer, size/2) * 2; }; + virtual size_t write(const int16_t *buffer, size_t size) { return write((uint32_t*) buffer, size/2) * 2; }; + virtual size_t write(const uint32_t *buffer, size_t size); private: + uint32_t buffer0[1024]; + uint32_t buffer1[1024]; + int currentBuffer; + + uint32_t *cook(const uint32_t *buffer, size_t size); + Dacc *dac; uint32_t dacId; };