aboutsummaryrefslogtreecommitdiff
path: root/circuitpython/lib/mp3/examples/DMA_play_from_SD
diff options
context:
space:
mode:
Diffstat (limited to 'circuitpython/lib/mp3/examples/DMA_play_from_SD')
-rw-r--r--circuitpython/lib/mp3/examples/DMA_play_from_SD/.due.test.skip0
-rw-r--r--circuitpython/lib/mp3/examples/DMA_play_from_SD/.esp32.test.skip0
-rw-r--r--circuitpython/lib/mp3/examples/DMA_play_from_SD/.esp8266.test.skip0
-rw-r--r--circuitpython/lib/mp3/examples/DMA_play_from_SD/.leonardo.test.skip0
-rw-r--r--circuitpython/lib/mp3/examples/DMA_play_from_SD/.mega2560.test.skip0
-rw-r--r--circuitpython/lib/mp3/examples/DMA_play_from_SD/.uno.test.skip0
-rw-r--r--circuitpython/lib/mp3/examples/DMA_play_from_SD/.zero.test.skip0
-rw-r--r--circuitpython/lib/mp3/examples/DMA_play_from_SD/DMA_play_from_SD.ino248
8 files changed, 248 insertions, 0 deletions
diff --git a/circuitpython/lib/mp3/examples/DMA_play_from_SD/.due.test.skip b/circuitpython/lib/mp3/examples/DMA_play_from_SD/.due.test.skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/circuitpython/lib/mp3/examples/DMA_play_from_SD/.due.test.skip
diff --git a/circuitpython/lib/mp3/examples/DMA_play_from_SD/.esp32.test.skip b/circuitpython/lib/mp3/examples/DMA_play_from_SD/.esp32.test.skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/circuitpython/lib/mp3/examples/DMA_play_from_SD/.esp32.test.skip
diff --git a/circuitpython/lib/mp3/examples/DMA_play_from_SD/.esp8266.test.skip b/circuitpython/lib/mp3/examples/DMA_play_from_SD/.esp8266.test.skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/circuitpython/lib/mp3/examples/DMA_play_from_SD/.esp8266.test.skip
diff --git a/circuitpython/lib/mp3/examples/DMA_play_from_SD/.leonardo.test.skip b/circuitpython/lib/mp3/examples/DMA_play_from_SD/.leonardo.test.skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/circuitpython/lib/mp3/examples/DMA_play_from_SD/.leonardo.test.skip
diff --git a/circuitpython/lib/mp3/examples/DMA_play_from_SD/.mega2560.test.skip b/circuitpython/lib/mp3/examples/DMA_play_from_SD/.mega2560.test.skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/circuitpython/lib/mp3/examples/DMA_play_from_SD/.mega2560.test.skip
diff --git a/circuitpython/lib/mp3/examples/DMA_play_from_SD/.uno.test.skip b/circuitpython/lib/mp3/examples/DMA_play_from_SD/.uno.test.skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/circuitpython/lib/mp3/examples/DMA_play_from_SD/.uno.test.skip
diff --git a/circuitpython/lib/mp3/examples/DMA_play_from_SD/.zero.test.skip b/circuitpython/lib/mp3/examples/DMA_play_from_SD/.zero.test.skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/circuitpython/lib/mp3/examples/DMA_play_from_SD/.zero.test.skip
diff --git a/circuitpython/lib/mp3/examples/DMA_play_from_SD/DMA_play_from_SD.ino b/circuitpython/lib/mp3/examples/DMA_play_from_SD/DMA_play_from_SD.ino
new file mode 100644
index 0000000..a97f6b2
--- /dev/null
+++ b/circuitpython/lib/mp3/examples/DMA_play_from_SD/DMA_play_from_SD.ino
@@ -0,0 +1,248 @@
+/*
+ * Play an MP3 file from an SD card
+ */
+#include "Adafruit_MP3.h"
+#include <SPI.h>
+#include <SD.h>
+
+#include <Adafruit_ZeroDMA.h>
+#include "utility/dma.h"
+
+#define VOLUME_MAX 2047
+const char *filename = "test3.mp3";
+const int chipSelect = 10;
+
+Adafruit_ZeroDMA leftDMA;
+Adafruit_ZeroDMA rightDMA;
+ZeroDMAstatus stat; // DMA status codes returned by some functions
+File dataFile;
+Adafruit_MP3_DMA player;
+DmacDescriptor *desc;
+
+//the output data buffers
+int16_t *ping, *pong;
+
+//this gets called when the player wants more data
+int getMoreData(uint8_t *writeHere, int thisManyBytes){
+ int bytesRead = 0;
+ while(dataFile.available() && bytesRead < thisManyBytes){
+ *writeHere = dataFile.read();
+ writeHere++;
+ bytesRead++;
+ }
+ return bytesRead;
+}
+
+
+//this will get called when data has been decoded
+void decodeCallback(int16_t *data, int len){
+ for(int i=0; i<len; i++){
+ int val = map(*data, -32768, 32767, 0, VOLUME_MAX);
+ *data++ = val;
+ }
+}
+
+void dma_callback(Adafruit_ZeroDMA *dma) {
+
+ digitalWrite(13, HIGH);
+ //try to fill the next buffer
+ if(player.fill()){
+ //stop
+ leftDMA.abort();
+ rightDMA.abort();
+ }
+ digitalWrite(13, LOW);
+}
+
+void doNothing(Adafruit_ZeroDMA *dma) {
+
+}
+
+void initMonoDMA(){
+ //set up the DMA channels
+ leftDMA.setTrigger(MP3_DMA_TRIGGER);
+ leftDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
+ stat = leftDMA.allocate();
+
+ //ask for the buffers we're going to use
+ player.getBuffers(&ping, &pong);
+
+ //make the descriptors
+ desc = leftDMA.addDescriptor(
+ ping, // move data from here
+ (void *)(&DAC->DATA[0]), // to here (M4)
+ MP3_OUTBUF_SIZE,
+ DMA_BEAT_SIZE_HWORD, // bytes/hword/words
+ true, // increment source addr?
+ false);
+ desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT;
+
+ desc = leftDMA.addDescriptor(
+ pong, // move data from here
+ (void *)(&DAC->DATA[0]), // to here (M4)
+ MP3_OUTBUF_SIZE,
+ DMA_BEAT_SIZE_HWORD, // bytes/hword/words
+ true, // increment source addr?
+ false); // increment dest addr?
+ desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT;
+
+ //make the descriptor list loop
+ leftDMA.loop(true);
+ leftDMA.setCallback(dma_callback);
+
+ rightDMA.setTrigger(MP3_DMA_TRIGGER);
+ rightDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
+ stat = rightDMA.allocate();
+
+ //make the descriptors
+ desc = rightDMA.addDescriptor(
+ ping + 1, // move data from here
+ (void *)(&DAC->DATA[1]), // to here (M4)
+ MP3_OUTBUF_SIZE, // this many...
+ DMA_BEAT_SIZE_HWORD, // bytes/hword/words
+ true, // increment source addr?
+ false); // increment dest addr?
+ desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT;
+
+ desc = rightDMA.addDescriptor(
+ pong + 1, // move data from here
+ (void *)(&DAC->DATA[1]), // to here (M4)
+ MP3_OUTBUF_SIZE, // this many...
+ DMA_BEAT_SIZE_HWORD, // bytes/hword/words
+ true, // increment source addr?
+ false); // increment dest addr?
+ desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT;
+
+ //make the descriptor list loop
+ rightDMA.loop(true);
+ rightDMA.setCallback(doNothing);
+}
+
+void initStereoDMA(){
+ //######### LEFT CHANNEL DMA ##############//
+
+ //set up the DMA channels
+ leftDMA.setTrigger(MP3_DMA_TRIGGER);
+ leftDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
+ stat = leftDMA.allocate();
+
+ //ask for the buffers we're going to use
+ player.getBuffers(&ping, &pong);
+
+ //make the descriptors
+ desc = leftDMA.addDescriptor(
+ ping, // move data from here
+ (void *)(&DAC->DATA[0]), // to here (M4)
+ MP3_OUTBUF_SIZE >> 1, // this many...
+ DMA_BEAT_SIZE_HWORD, // bytes/hword/words
+ true, // increment source addr?
+ false,
+ DMA_ADDRESS_INCREMENT_STEP_SIZE_2,
+ DMA_STEPSEL_SRC); // increment dest addr?
+
+ desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT;
+
+ desc = leftDMA.addDescriptor(
+ pong, // move data from here
+ (void *)(&DAC->DATA[0]), // to here (M4)
+ MP3_OUTBUF_SIZE >> 1, // this many...
+ DMA_BEAT_SIZE_HWORD, // bytes/hword/words
+ true, // increment source addr?
+ false,
+ DMA_ADDRESS_INCREMENT_STEP_SIZE_2,
+ DMA_STEPSEL_SRC); // increment dest addr?
+
+ desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT;
+
+ //make the descriptor list loop
+ leftDMA.loop(true);
+ leftDMA.setCallback(dma_callback);
+
+ //######### RIGHT CHANNEL DMA ##############//
+
+ rightDMA.setTrigger(MP3_DMA_TRIGGER);
+ rightDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
+ stat = rightDMA.allocate();
+
+ //make the descriptors
+ desc = rightDMA.addDescriptor(
+ ping + 1, // move data from here
+ (void *)(&DAC->DATA[1]), // to here (M4)
+ MP3_OUTBUF_SIZE >> 1, // this many...
+ DMA_BEAT_SIZE_HWORD, // bytes/hword/words
+ true, // increment source addr?
+ false,
+ DMA_ADDRESS_INCREMENT_STEP_SIZE_2,
+ DMA_STEPSEL_SRC); // increment dest addr?
+ desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT;
+
+ desc = rightDMA.addDescriptor(
+ pong + 1, // move data from here
+ (void *)(&DAC->DATA[1]), // to here (M4)
+ MP3_OUTBUF_SIZE >> 1, // this many...
+ DMA_BEAT_SIZE_HWORD, // bytes/hword/words
+ true, // increment source addr?
+ false,
+ DMA_ADDRESS_INCREMENT_STEP_SIZE_2,
+ DMA_STEPSEL_SRC); // increment dest addr?
+ desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT;
+
+ //make the descriptor list loop
+ rightDMA.loop(true);
+ rightDMA.setCallback(doNothing);
+}
+
+// the setup routine runs once when you press reset:
+void setup() {
+ pinMode(13, OUTPUT);
+ Serial.begin(9600);
+ while(!Serial);
+
+
+ while (!SD.begin(12000000, chipSelect)) {
+ Serial.println("Card failed, or not present");
+ delay(2000);
+ }
+ Serial.println("card initialized.");
+
+ dataFile = SD.open(filename);
+ if(!dataFile){
+ Serial.println("could not open file!");
+ while(1);
+ }
+
+ //set the DAC to the center of the range
+ analogWrite(A0, 2048);
+ analogWrite(A1, 2048);
+
+ //begin the player
+ player.begin();
+
+ //this will be how the player asks for data
+ player.setBufferCallback(getMoreData);
+
+ //this will be how the player asks you to clean the data
+ player.setDecodeCallback(decodeCallback);
+
+ player.play(); //this will automatically fill the first buffer and get the channel info
+
+ if(player.numChannels == 1)
+ initMonoDMA(); //this is a mono file
+
+ else if(player.numChannels == 2)
+ initStereoDMA(); //this is a stereo file
+
+ else{
+ Serial.println("only mono and stereo files are supported");
+ while(1);
+ }
+
+ //the DMA controller will dictate what happens from here on out
+ rightDMA.startJob();
+ leftDMA.startJob();
+}
+
+// the loop routine runs over and over again forever:
+void loop() {
+ //do nothing
+}