Writing Directly to DAC (pt8211)

Status
Not open for further replies.

snowday

Member
Is there a way to write directly to the pt8211, utilizing the existing code from the audio library? I was thinking you could inherit the update function from output_PT8211.cp and write the buffers to that directly. Maybe there's some easier way to do it?

For reference: I'm using the Teensy 4.0 with the pt8211 board. It's wired up with the pinouts referenced here: pjrc.com
Both the beep and sine tests work.

My project has two (1s length or so) circular sample buffers that need to interact in a specific way, it doesn't seem like you could necessarily implement them with the audio library's built in queue, it isn't big enough. Furthermore, I already have the code working how I like it as a juce project, so porting it would be easier if I could just write more or less directly to the DAC.

Thanks for the help, let me know if more information is necessary.

Update: I'm probably an idiot, I'll try to implement this with the built in queues.
 
Last edited:
Here's the code as I've got it so far.

OK, I'm feeding the input with a clean sine wave. It passes the sine wave along for a split second, then outputs a sorta clicky version of it. Therefore, I think it's a memory issue. How do I clear the buffers AudioPlayQueue is using?

Btw I'm using the updated Teensy 4.0 ADC library from @bumbler: forum.pjrc.com

Code:
#include <ADC.h>

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

ADC *adc  = new ADC();


// GUItool: begin automatically generated code
AudioPlayQueue           outputQueue;         //xy=733,426
AudioOutputPT8211        pt8211_1;       //xy=919,423
AudioConnection          patchCord2(outputQueue, 0, pt8211_1, 0);
AudioConnection          patchCord3(outputQueue, 0, pt8211_1, 1);
// GUItool: end automatically generated code*/

short int input = 0;
short int outputBuffer[128];

int counter = 0;

void setup() {
  uint32_t freq = 50000;  // try a sampling rate of 50 kHz

  adc->adc0->stopPDB();
  adc->adc0->startSingleRead(A1); // call this to setup everything before the pdb starts, differential is also possible
  adc->enableInterrupts(ADC_0);
  adc->adc0->startPDB(freq); //frequency in Hz


  AudioMemory(30);

  adc->setConversionSpeed(ADC_CONVERSION_SPEED:: VERY_HIGH_SPEED);
  adc->setSamplingSpeed(ADC_SAMPLING_SPEED:: VERY_HIGH_SPEED);
  adc->setAveraging(16);
  adc->setResolution(12);

}


void adc0_isr() {
  cli();
  input = adc->readSingle();
  if (counter == 128){
    getNextOutputBlock();
    counter = 0;
  }
  outputBuffer[counter] = input;
  counter++;
  sei();
}

void adc1_isr() {}

void getNextOutputBlock() {
  if (outputQueue.available() >= 1) {
    int16_t *p = outputQueue.getBuffer();
    memcpy(p, outputBuffer, 256);
    outputQueue.playBuffer();
  }
}

void loop() {}
 
Last edited:
Just a wild guess since I never used the AudioPlayQueue object.

Sample rate mismatch between input(50000Hz) and output(44117.64706Hz)?

The outputQueue is filled faster than it is played. When all 32 available ouputBlocks for the outputQueue are filled, outputQueue.playBuffer() will wait for an ouputBlock to be released or freed, resulting in clicks.
 
Just a wild guess since I never used the AudioPlayQueue object.

Sample rate mismatch between input(50000Hz) and output(44117.64706Hz)?

The outputQueue is filled faster than it is played. When all 32 available ouputBlocks for the outputQueue are filled, outputQueue.playBuffer() will wait for an ouputBlock to be released or freed, resulting in clicks.

Holy moly it worked. Still a little bit of background noise but it sounds pretty good so far. Out of curiosity, where did you find the 44117 number?
 
OK, so now I'm trying to get data in from the other ADC pins to adjust parameters of the delay. The trouble is, if I try and use analogRead, or use another startSingleRead, the input drops out completely. Still a slight clicking but I suspect it's to do with the delay buffer, since the clicking is sort of in time with the delays.

Code:
#include <ADC.h>

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

ADC *adc  = new ADC();
ADC *adc2 = new ADC();

// GUItool: begin automatically generated code
AudioPlayQueue           outputQueue;         //xy=733,426
AudioOutputPT8211        pt8211_1;       //xy=919,423
AudioConnection          patchCord2(outputQueue, 0, pt8211_1, 0);
AudioConnection          patchCord3(outputQueue, 0, pt8211_1, 1);
// GUItool: end automatically generated code*/

float feedback = 0.8;
short int input = 0;
const short int delayMax = 3000;
short int sampleBuffer [delayMax];
short int delayBuffer[delayMax];
short int delayNum = 0;
short int delayRate = 1;
short int outputBuffer[256];

IntervalTimer sampleOut;
int counter = 0;

void setup() {
  uint32_t freq = 22058;  // try a sampling rate of 22.058 kHz (44.117 kHz is base, so we'll do half)

  adc->adc0->stopPDB();
  adc->adc0->startSingleRead(A1); 
  adc->enableInterrupts(ADC_0);
  adc->adc0->startPDB(freq); //frequency in Hz

  adc2->adc1->stopPDB();
  //adc2->adc1->startSingleRead(A9);   // if I uncomment this, input stops entirely, otherwise the feedback input does nothing
  adc2->enableInterrupts(ADC_1);
  adc2->adc1->startPDB(freq); //frequency in Hz

  
  AudioMemory(20);

  for (short int i = 0; i < delayMax; i++) {
    delayBuffer[i] = 0;
    sampleBuffer[i] = 0;
  }

  adc->setConversionSpeed(ADC_CONVERSION_SPEED:: HIGH_SPEED);
  adc->setSamplingSpeed(ADC_SAMPLING_SPEED:: HIGH_SPEED);
  adc->setAveraging(32);
  adc->setResolution(12);
}


void adc0_isr() {
  //cli();
  adc->adc0->readSingle();
  input = (adc->readSingle(A1)) * 2;
  if (counter == 128) {
    getNextOutputBlock();
    counter = 0;
  }
  outputBuffer[counter] = input;
  outputBuffer[counter + 1] = input;
  counter += 2;
 // sei();
}

void adc1_isr() {
  feedback = (float)(adc->readSingle(A9))/8191;
  }

void getNextOutputBlock() {

  //quickly delay buffer, then update output buffer and pass it to DAC
  for (int i = 0; i < 128; i += 2) {
    short int holdNum = outputBuffer[i];
    outputBuffer[i] = outputBuffer[i] + delayBuffer[delayNum];
    //outputBuffer[i] = outputBuffer[i];
    outputBuffer[i + 1] = outputBuffer[i];

    updateDelay(holdNum);
  }

  int16_t *p = outputQueue.getBuffer();
  memcpy(p, outputBuffer, 256);
  outputQueue.playBuffer();
}

void updateDelay(short int in) {
  for (short int i = 0; i < delayRate; i++) {
    if (delayNum >= delayMax)
      delayNum = delayNum - delayMax;
    delayBuffer[delayNum] = ((float)feedback * (float)delayBuffer[delayNum] + in);
    delayNum++;
  }
}

void loop() {}
 
Correction:
Sample rate for T4.0 = 44100Hz
Sample rate for T3.x = 44117.64706Hz

Just figured this out while having a look at AudioStream.h
 
Status
Not open for further replies.
Back
Top