/ examples / DMA_play_from_header / DMA_play_from_header.ino
DMA_play_from_header.ino
  1  #include "Adafruit_MP3.h"
  2  #include "sine.h"
  3  
  4  #include <Adafruit_ZeroDMA.h>
  5  #include "utility/dma.h"
  6  
  7  #define VOLUME_MAX 2047
  8  
  9  Adafruit_ZeroDMA myDMA;
 10  ZeroDMAstatus    stat; // DMA status codes returned by some functions
 11  Adafruit_MP3_DMA player;
 12  DmacDescriptor *desc;
 13  
 14  //the output data buffers
 15  int16_t *ping, *pong;
 16  
 17  uint8_t *currentPtr;
 18  uint32_t thisManyBytesLeft;
 19  
 20  //this gets called when the player wants more data
 21  int getMoreData(uint8_t *writeHere, int thisManyBytes){
 22    int toWrite = min(thisManyBytesLeft, thisManyBytes);
 23    memcpy(writeHere, currentPtr, toWrite);
 24    currentPtr += toWrite;
 25    thisManyBytesLeft -= toWrite;
 26    return toWrite;
 27  }
 28  
 29  
 30  //this will get called when data has been decoded
 31  void decodeCallback(int16_t *data, int len){
 32    for(int i=0; i<len; i++){
 33      int val = map(*data, -32768, 32767, 0, VOLUME_MAX);
 34      *data++ = val;
 35    }
 36  }
 37  
 38  
 39  void dma_callback(Adafruit_ZeroDMA *dma) {
 40  
 41    //try to fill the next buffer
 42    if(player.fill()){
 43      //stop
 44      myDMA.abort();
 45    }
 46  }
 47  
 48  // the setup routine runs once when you press reset:
 49  void setup() {
 50  
 51    //set up the DMA channel
 52    myDMA.setTrigger(MP3_DMA_TRIGGER);
 53    myDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
 54    stat = myDMA.allocate();
 55  
 56    //ask for the buffers we're going to use
 57    player.getBuffers(&ping, &pong);
 58  
 59    //make the descriptors
 60    desc = myDMA.addDescriptor(
 61      ping,                    // move data from here
 62      (void *)(&DAC->DATA[0]), // to here (M4)
 63    MP3_OUTBUF_SIZE,                      // this many...
 64      DMA_BEAT_SIZE_HWORD,               // bytes/hword/words
 65      true,                             // increment source addr?
 66      false);                           // increment dest addr?
 67    desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT;
 68  
 69    desc = myDMA.addDescriptor(
 70      pong,                    // move data from here
 71      (void *)(&DAC->DATA[0]), // to here (M4)
 72    MP3_OUTBUF_SIZE,                      // this many...
 73      DMA_BEAT_SIZE_HWORD,               // bytes/hword/words
 74      true,                             // increment source addr?
 75      false);                           // increment dest addr?
 76    desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT;
 77  
 78    //make the descriptor list loop
 79    myDMA.loop(true);
 80    myDMA.setCallback(dma_callback);
 81  
 82    //set the DAC to the center of the range
 83    analogWrite(A0, 2048);
 84  
 85    currentPtr = (uint8_t*)sine_mp3;
 86    thisManyBytesLeft = sizeof(sine_mp3);
 87  
 88    //begin the player
 89    player.begin();
 90  
 91    //this will be how the player asks for data
 92    player.setBufferCallback(getMoreData);
 93  
 94    //this will be how the player asks you to clean the data
 95    player.setDecodeCallback(decodeCallback);
 96  
 97    player.play(); //this will automatically fill the first buffer
 98  
 99    //the DMA controller will dictate what happens from here on out
100    myDMA.startJob();
101  }
102  
103  // the loop routine runs over and over again forever:
104  void loop() {
105  
106  }