Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 9 of 9

Thread: Writing Directly to DAC (pt8211)

  1. #1
    Junior Member
    Join Date
    Oct 2019
    Posts
    5

    Writing Directly to DAC (pt8211)

    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 by snowday; 10-30-2019 at 01:52 AM.

  2. #2
    Junior Member
    Join Date
    Oct 2019
    Posts
    5
    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 by snowday; 10-31-2019 at 09:39 PM.

  3. #3
    Senior Member
    Join Date
    Nov 2017
    Location
    Belgium
    Posts
    164
    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.

  4. #4
    Junior Member
    Join Date
    Oct 2019
    Posts
    5
    Quote Originally Posted by neurofun View Post
    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?

  5. #5
    Senior Member
    Join Date
    Nov 2017
    Location
    Belgium
    Posts
    164
    Quote Originally Posted by snowday View Post
    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?
    At the bottom of this page,
    https://www.pjrc.com/teensy/td_libs_...ewObjects.html

  6. #6
    Snowday, I haven’t had luck finding how to wire up the PT8211 with T4. Can you tell me?

    Thanks

  7. #7
    Junior Member
    Join Date
    Oct 2019
    Posts
    5
    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() {}

  8. #8
    Senior Member
    Join Date
    Nov 2017
    Location
    Belgium
    Posts
    164
    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

  9. #9
    Junior Member
    Join Date
    Oct 2019
    Posts
    5
    Quote Originally Posted by tele_player View Post
    Snowday, I havenít had luck finding how to wire up the PT8211 with T4. Can you tell me?

    Thanks
    Here's the updated pinout:

    BCK: 21
    DIN: 7
    WS: 20
    3.3V and GND as before

    as seen here: forum.pjrc.com

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •