Forum Rule: Always post complete source code & details to reproduce any issue!
Page 5 of 5 FirstFirst ... 3 4 5
Results 101 to 121 of 121

Thread: Quad channel output on Teensy 3.6

  1. #101
    Junior Member
    Join Date
    Jul 2018
    Posts
    15
    OSHPark board (x3) and spare teensy 3.2 ordered
    paul, something I dont understand in your design - you seem to connect pin 1 (the i2c address) to both high AND low, and both resistors seem to be populated in the photos. you mention wanting to be able to configure i2c address - I guess you've just got a divider and can choose which way up it goes? whereas I tied both address pins straight to ground. do you think this could be the source of my woes? its a bit odd, as the i2c side of things works fine but.... I dont think I fully understand why a divider is needed on these pins at all? just trying to flush out all differences between the designs.

  2. #102
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    19,248
    Yeah, those resistors are redundant and unnecessary. The 150 ohm resistor could just be a short, and the 100K is totally unnecessary.

    The way I do these sorts of boards, managing the 2 week wait from OSH Park while juggle lots of other stuff for Teensy, I tend label all the part values when I design the board and then it's "out of sight, out of mind". Two weeks later, when I or someone else actually solders the board (really can't recall if I soldered this one, or if Erin or Brian did it), I don't bother looking at these sorts of things again if the board "just works", as this one did. Of course it didn't immediately spring the life... I had to write the TDM code. But fortunate the hardware worked on the first try.

    If you want to do exact the same as I did, populate both resistors. But there wasn't any reason to use both, other than I wanted the board to be configurable, and when the boards actually arrived the configuration stuff was forgotten and the boards built from the docs I made when I created the layout.

  3. #103
    Junior Member
    Join Date
    Jul 2018
    Posts
    15
    you're a more thorough man than I. while I wait for the oshpark board, I have done the filthy thing and patched a bodge wire from VQ to a spare teensy pin, which I found that a brief 10us high output is enough to kick the codec into normal operation. I feel bad that I dont know why it doesn't work without it, and know that this is definitely not what the chip designers intended, but... at least I can move on and test the rest of the circuit (the bodge cap in the picture was me replacing an SMT 4.7uf with various other sizes, to see if it helped. it didnt). oh well... onwards!
    I'm doing pinMode(3,OUTPUT); digitalWriteFast(3,1); delayMicroseconds(10); pinMode(3,INPUT); to generate the high pulse (ie short VQ to 3v3) and then trying to disable the pin by setting it to INPUT (hi-z); this is ok and works but, since the voltage on the pin then hovers around 2.5v I worry that it'll be toggling the input transistors needlessly. is there a way to fully disable a pin? I searched a bit but kept finding AVR/teensy2 results, so I was unsure. thanks
    Click image for larger version. 

Name:	Dki_48FXsAAvr3c.jpg 
Views:	24 
Size:	113.6 KB 
ID:	14442

  4. #104
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    19,248
    Quote Originally Posted by mmalex View Post
    is there a way to fully disable a pin?
    Yes, INPUT_DISABLE.

  5. #105
    Junior Member
    Join Date
    Jul 2018
    Posts
    15
    fantastic, thanks for prompt reply. I had checked https://www.pjrc.com/teensy/pins.html and misunderstood. cheers!

  6. #106
    Junior Member
    Join Date
    Apr 2017
    Posts
    19
    Quote Originally Posted by mmalex View Post
    [...] - I've moved to an OLED SPI display (but one without a noisy boost converter! avoid the adafruit ones for audio work unless you have really good power supply) .
    Sorry, slightly OT: Mind to share - Which OLED is that, mmalex?

  7. #107
    Junior Member
    Join Date
    Jul 2018
    Posts
    15
    Quote Originally Posted by ubiubu View Post
    Sorry, slightly OT: Mind to share - Which OLED is that, mmalex?
    np, it's this one https://www.soselectronic.com/produc...02-6lga-291087
    photo here in my module: https://twitter.com/mmalex/status/10...931883520?s=21

  8. #108
    Junior Member
    Join Date
    Apr 2017
    Posts
    19
    Quote Originally Posted by mmalex View Post
    Ah, thanks! Figured so, but was looking at the 128x64 version which looked too big. 102x64 ... didn't know that was a thing!

    And one OT follow-up, if I may (sorry, just was working backwards through the thread): You mentioned you had 2x AD5668 DACs working with SPI/DMA. Would you consider sharing the relevant code snippets? I've been trying, but failing, to get a multichannel DAC working via DMA.

  9. #109
    Junior Member
    Join Date
    Jul 2018
    Posts
    15
    Quote Originally Posted by ubiubu View Post
    You mentioned you had 2x AD5668 DACs working with SPI/DMA. Would you consider sharing the relevant code snippets? I've been trying, but failing, to get a multichannel DAC working via DMA.
    sure! I pasted together the code, sorry if I missed a definition in the pasting process. i've added some comments too.
    Code:
    DMAChannel dacdma;
    #define PSPI0_CSDAC0 10 // teensy pin 10 = cs0_0
    #define PSPI0_CSDAC1 9  // teensy pin 9 = cs0_1
    #define DACCS0 (1<<0) // which CS0_x bit the two dacs are on. this is bit 0 
    #define DACCS1 (1<<1) // this is bit 1
    #define DACDMA(data,cs,chan) SPI_PUSHR_CTAS(1) | (1ul<<31) | (cs<<16) | (0x0300) | ((chan)<<4) | ((data)>>12), \
    					    	 SPI_PUSHR_CTAS(1) |           (cs<<16) | (((data)<<4)&0xfff0)
    
    u32 dacdmabuffer[8*4]={
    	DACDMA(32768,DACCS0,0), DACDMA(32768,DACCS1,0),	
    	DACDMA(32768,DACCS0,1), DACDMA(32768,DACCS1,1),	
    	DACDMA(32768,DACCS0,2), DACDMA(32768,DACCS1,2),	
    	DACDMA(32768,DACCS0,3), DACDMA(32768,DACCS1,3),	
    	DACDMA(32768,DACCS0,4), DACDMA(32768,DACCS1,4),	
    	DACDMA(32768,DACCS0,5), DACDMA(32768,DACCS1,5),	
    	DACDMA(32768,DACCS0,6), DACDMA(32768,DACCS1,6),	
    	DACDMA(32768,DACCS0,7), DACDMA(32768,DACCS1,7),	
    };
    
    inline void ClearSPIFinishedFlag() {
    	SPI0_SR = SPI_SR_TCF; // clear spi complete flag	
    }
    
    inline void WaitForSPIFinishedFlag() {
    	while (!(SPI0_SR & SPI_SR_TCF)) yield(); // wait
    }
    
    void InitDAC() {
            // set up DACs
            // NB this setCS() hands the pins to the SPI unit on teensy
            // otherwise the top bits of PUSHR have no effect. crucial! took me a while to find
    	u32 cs0=SPI.setCS(PSPI0_CSDAC0); // PSPI0_CSDACx is a teensy pin number from my design, must be a CS0_x pin
        u32 cs1=SPI.setCS(PSPI0_CSDAC1);
        assert(cs0==DACCS0); // did you set your defines right
        assert(cs1==DACCS1); // did you set your defines right
        u32 cs01=cs0|cs1; // you can even talk to both dacs at the same time...
        SPI.begin();
        SPISettings dacsettings(12*1000*1000,MSBFIRST, SPI_MODE0);
        SPI.beginTransaction(dacsettings);
        const static u32 ref_enable=(1<<27)+1;
        ClearSPIFinishedFlag();
        // uses SPI0 fifo to write two times in one go
        SPI0_PUSHR = SPI_PUSHR_CTAS(1) | (1<<31) | (cs01<<16) | (ref_enable>>16);
        SPI0_PUSHR = SPI_PUSHR_CTAS(1) |           (cs01<<16) | (ref_enable&0xffff);
        WaitForSPIFinishedFlag();
    }
    
    void InitDMA() {
    	dacdma.disable();
        dacdma.destination((volatile uint32_t&)SPI0_PUSHR);
        dacdma.disableOnCompletion();
        dacdma.triggerAtHardwareEvent(DMAMUX_SOURCE_SPI0_TX);
    	dacdma.sourceBuffer(dacdmabuffer, sizeof(dacdmabuffer)); 
    
        // ask for DMA pokes from SPI unit
        SPI0_SR = 0xFF0F0000; // TODO what are these bits
        SPI0_RSER = /*SPI_RSER_RFDF_RE | SPI_RSER_RFDF_DIRS |*/ SPI_RSER_TFFF_RE | SPI_RSER_TFFF_DIRS;
    }
    
    void KickDMABuffer(const u16 anaout[16]) { // a single sample across 16 channels
        const u16 *src=anaout;
    	for (int chan=0;chan<8;++chan) {
    		u16 data0=*src++;
    		u16 data1=*src++;
            // note that I alternate a register-width (2 writes) for dac0, then dac1, then dac0, etc
            // ie alternate chips. also note that the dma buffer high u16 of each PUSHR is already setup
            // so this code only touches the bottom u16 which has the data in it
    
            // that gives each chip a chance to 'breathe' between each 32 bit write
            // alternatively you can set up CS delays I believe via SPI registers
    
    		((u16*)dacdmabuffer)[chan*8+0] = (0x0300) | ((chan)<<4) | ((data0)>>12);
    		((u16*)dacdmabuffer)[chan*8+2] = ((data0)<<4);
    		((u16*)dacdmabuffer)[chan*8+4] = (0x0300) | ((chan)<<4) | ((data1)>>12);
    		((u16*)dacdmabuffer)[chan*8+6] = ((data1)<<4);
    	} 
    	dacdma.enable();
    }
    
    main type thing {
        InitDAC();
        delay(1); // for good measure
        InitDMA();
        //... set up an IntervalTimer to do some DSP and call KickDMABuffer() for each sample. I ran at 32khz
    }

  10. #110
    Junior Member
    Join Date
    Apr 2017
    Posts
    19
    Quote Originally Posted by mmalex View Post
    sure! I pasted together the code, sorry if I missed a definition in the pasting process. i've added some comments too.

    Cool, thanks. This did the trick ... Getting output on all 8 channels now, I guess I must have done something wrong when stuffing the buffer. Now on to trying to hook things up to the PDB / audio library.

    FWIW, here's an .ino-version of mmalex's code above for just one 8-channel DAC (TI DAC8568 in this case. Turns out the input register is almost identical to AD5668). NB: using pin 7 for MOSI.

    Code:
    /* DAC8568 */
    
    #include <DmaChannel.h>
    #include <SPI.h>
    #include "dspinst.h"
    
    #define PSPI0_CSDAC0 15   // teensy pin 15 = cs0_0
    #define LDAC 14
    #define DACCS0 0x10       // ~ pcs (CS = PTC0 = T15)
    
    /* 0  X  X  X  0  0  1  1  A3  A2  A1  A0  [ Data 15 - 0 ]  X  X  X  X */ 
    /* p.37: "Write to Selected DAC Input Register and Update Respective DAC Register" */
        
    #define DAC_CHANNEL_OFFSET 4  // A0-A3
    #define SELECT_UPDATE 0x0300  // C0-C3
    #define INTREF_ENABLE 0x8000001
    #define NUM_CHANNELS 8
    
    #define DACDMA(data,cs,chan) SPI_PUSHR_CTAS(1) | (1ul << 31) | (cs << 16) | SELECT_UPDATE | ((chan) << DAC_CHANNEL_OFFSET) | ((data) >> 12), \
                                 SPI_PUSHR_CTAS(1) | (cs << 16) | (((data) << 4) & 0xFFF0)
                                 
    DMAChannel dacdma;
    IntervalTimer timer;
    const uint32_t timer_rate = 10;
    uint32_t phase_accumulator = 0, phase_increment = 0xFFFFFF;
    
      // plucked from synth_sine.cpp:
      
    static int32_t taylor(uint32_t ph)
    {
      int32_t angle, sum, p1, p2, p3, p5, p7, p9, p11;
    
      if (ph >= 0xC0000000 || ph < 0x40000000) {                            // ph:  0.32
        angle = (int32_t)ph; // valid from -90 to +90 degrees
      } else {
        angle = (int32_t)(0x80000000u - ph);                        // angle: 2.30
      }
      p1 =  multiply_32x32_rshift32_rounded(angle, 1686629713) << 2;        // p1:  2.30
      p2 =  multiply_32x32_rshift32_rounded(p1, p1) << 1;                   // p2:  3.29
      p3 =  multiply_32x32_rshift32_rounded(p2, p1) << 2;                   // p3:  3.29
      sum = multiply_subtract_32x32_rshift32_rounded(p1, p3, 1431655765);   // sum: 2.30
      p5 =  multiply_32x32_rshift32_rounded(p3, p2);                        // p5:  6.26
      sum = multiply_accumulate_32x32_rshift32_rounded(sum, p5, 572662306);
      p7 =  multiply_32x32_rshift32_rounded(p5, p2);                        // p7:  9.23
      sum = multiply_subtract_32x32_rshift32_rounded(sum, p7, 109078534);
      p9 =  multiply_32x32_rshift32_rounded(p7, p2);                        // p9: 12.20
      sum = multiply_accumulate_32x32_rshift32_rounded(sum, p9, 12119837);
      p11 = multiply_32x32_rshift32_rounded(p9, p2);                       // p11: 15.17
      sum = multiply_subtract_32x32_rshift32_rounded(sum, p11, 881443);
      return sum <<= 1;                                                 // return:  1.31
    }
    
    
    void FASTRUN ISR() {
    
      uint16_t buf[NUM_CHANNELS];
      
      uint32_t sample = (taylor(phase_accumulator) >> 16) + 0x8000;
      // fill the buffer
      for (int i = 0; i < NUM_CHANNELS; i++) buf[i] = sample;
      
      KickDMABuffer(buf);
      phase_accumulator += phase_increment;
    }
    
    uint32_t dacdmabuffer[NUM_CHANNELS * 2] = { 
      
      DACDMA(32768,DACCS0,0),  
      DACDMA(32768,DACCS0,1),
      DACDMA(32768,DACCS0,2),
      DACDMA(32768,DACCS0,3),
      DACDMA(32768,DACCS0,4),
      DACDMA(32768,DACCS0,5),
      DACDMA(32768,DACCS0,6),
      DACDMA(32768,DACCS0,7) 
    };
    
    inline void ClearSPIFinishedFlag() {
      SPI0_SR = SPI_SR_TCF; // clear spi complete flag  
    }
    
    inline void WaitForSPIFinishedFlag() {
      while (!(SPI0_SR & SPI_SR_TCF)) 
        yield(); // wait
    }
    
    void InitDAC() {
      
        // set up DAC    
        uint32_t pcs = SPI.setCS(PSPI0_CSDAC0); // must be a CS pin
    
        SPI.setMOSI(7);
        SPI.begin();
        SPISettings dacsettings(30*1000*1000, MSBFIRST, SPI_MODE0);
        SPI.beginTransaction(dacsettings);
        
        uint32_t ref_enable = INTREF_ENABLE;
        ClearSPIFinishedFlag();
        // uses SPI0 fifo to write two times in one go
        SPI0_PUSHR = SPI_PUSHR_CTAS(1) | (1ul << 31) | (pcs << 16) | (ref_enable >> 16);
        SPI0_PUSHR = SPI_PUSHR_CTAS(1) | (pcs << 16) | (ref_enable & 0xFFFF);
        
        WaitForSPIFinishedFlag();
        Serial.println("DAC initialised");
    }
    
    void InitDMA() {
      
        dacdma.disable();
        dacdma.destination((volatile uint32_t&)SPI0_PUSHR);
        dacdma.disableOnCompletion();
        dacdma.triggerAtHardwareEvent(DMAMUX_SOURCE_SPI0_TX);
        dacdma.sourceBuffer(dacdmabuffer, sizeof(dacdmabuffer)); 
    
        // ask for DMA pokes from SPI unit
        SPI0_SR = 0xFF0F0000; // Setup SPI for DMA transfer
        SPI0_RSER = /*SPI_RSER_RFDF_RE | SPI_RSER_RFDF_DIRS |*/ SPI_RSER_TFFF_RE | SPI_RSER_TFFF_DIRS;
        Serial.println("DMA initialised");
    }
    
    void KickDMABuffer(const uint16_t anaout[NUM_CHANNELS]) { // a single sample across 8 channels
      
      const uint16_t *src = anaout;
      
      for (int chan = 0; chan < NUM_CHANNELS; ++chan) {
        
        uint16_t data0 = *src++;
        
        ((uint16_t*)dacdmabuffer)[chan * NUM_CHANNELS/2 + 0] = SELECT_UPDATE | ((chan) << DAC_CHANNEL_OFFSET) | ((data0) >> 12);
        ((uint16_t*)dacdmabuffer)[chan * NUM_CHANNELS/2 + 2] = ((data0) << 4);
      } 
      dacdma.enable();
    }
    
    void setup() {
    
        delay(10);
        // LDAC pin 
        pinMode(LDAC, OUTPUT);
        digitalWrite(LDAC, LOW);
        //
        InitDAC();
        delay(10); // for good measure
        InitDMA();
        timer.priority(64);
        timer.begin(ISR, timer_rate);
    }
    
    void loop() { }
    Last edited by ubiubu; 08-15-2018 at 05:18 PM.

  11. #111
    Junior Member
    Join Date
    Jul 2018
    Posts
    15

    Wink

    Quote Originally Posted by ubiubu View Post
    Cool, thanks. This did the trick ... Getting output on all 8 channels now
    so happy I was able to help someone and not just ask questions

  12. #112
    Junior Member
    Join Date
    Jul 2018
    Posts
    15
    progress! https://twitter.com/mmalex/status/1030925272508456960 :
    with a single (evil) bodge wire, everything seems to work. plus, ive built 2 copies! code atm is just: 10 sine oscs out, and 10 ins graphed on a 'scope'. buttons, leds, encoders all fine. omg. next step - write some audio dsp?
    this is using the cs24228 from this thread to do 6 of the ins and 8 of the outs; the teensy3.6 DACs provide the last 2 outs, and the ADCs (multiplexed) provide the last 4 ins. so it's a mashup of input/output devices to get 10 in, 10 out (+2 digital in, 1 digital out, 8 encoders with 8 RGB leds and 4 illuminated tact switches). now, lots of software ahead...
    the teensy has been amazing to work with. the cs42448, not so much.
    Click image for larger version. 

Name:	Dk6VDLPX4AAKPpR.jpg 
Views:	47 
Size:	175.6 KB 
ID:	14493Click image for larger version. 

Name:	Dk6VDLKX0AUZZWd.jpg 
Views:	45 
Size:	203.1 KB 
ID:	14494

  13. #113
    Junior Member
    Join Date
    Nov 2018
    Posts
    1
    Hi Paul and Co!

    I've enjoyed making projects with my 3.2 for some time now. I wanted to try out the CS42448 board for an audio project and had a question:

    Is it possible to order a fully populated CS42448 board from OSH park or someone on the forum like the Soldering Goddess? I'm a bit confused on how people are getting these completed boards ordered other than through private messaging. I have 0 experience soldering SMD so I'm not sure I could make a working one myself!

    Thanks for your time!

  14. #114
    Junior Member
    Join Date
    Dec 2018
    Posts
    1
    Hello,
    This thread has been most useful!
    i've been working on an audio project with teensy 3.6 for a few weeks now, developed my proof of concept using the audio shield and the 3.6 internal sd card (recording wav files into it) and all was well.
    Now i've upgraded to the CS42448 audio board, all audio is already working properly but the sd card is not saving any files and does not report any error!
    If i remove all the cs42448 related code and leave just my sd card code it works.
    I noticed that pins 11 and 13 are being used for both the cs42448 and internal sd card although it has the comment "// not actually used".
    also removed the SPI.setXXX pins and used the :
    #define SD_SELECT BUILTIN_SDCARD
    and also used this initialization method instead:
    if (!(SD.begin(SD_SELECT))) {
    although this change also worked in my sd card only code it still isn't working on my main project.
    still no errors are reported in the serial monitor...

    i wonder if this is a know issue/incompatibility or something else is breaking...
    any help is greatly appreciated!
    All the very best
    Andre

  15. #115
    Junior Member
    Join Date
    Jan 2019
    Posts
    3
    Hi, I've just soldered a cs42448 board from OSH Park to be used with the teensy 3.6. I'm not sure though if the 5 pins which differ in position from v3.2 (reset, program, ground, 3.3v, vbat), should be connected to the board. It seems that the ground on the OSH board is connected anyway to the common for both v3.6 and v3.2 ground pin, but I've seen people here who connect this anyway. I think the same goes for the 3.3V pin. Do I need to take care of this, or will I fry the IC if I don't, and just hook up the 3.6 neglecting the 5 "horizontal" pins? @__ag how does your setup look like?
    Thanks!

  16. #116
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,579
    Those 5 pins are ignorable generally. Indeed the GND and 3v3 pins are just duplicates, and the other 3 special purpose pins are only selectively needed as labelled.

  17. #117
    Junior Member
    Join Date
    Jan 2019
    Posts
    3
    Great, thanks! There must be something wrong with my soldering then, as all I can hear from a simple passthrough patch is noise. Good thing three boards is the minimum order at OSH

  18. #118
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,579
    Given you have boards a quick tie of the GND and 3v3 from T_3.6 would tell for sure if the extra GND or 3v3 path helps - either the center pins - or the handy extra edge pins.

  19. #119
    Junior Member
    Join Date
    Jan 2019
    Posts
    3
    Thanks for the tip! It seems it's not necessary to connect the extra GND ans 3v3. The noise and other problems I had (working for a few seconds and then dying) were because of my inexperience on soldering something this tiny. The flux I used is apparently conductive, and there was still some leftover after cleaning the board.
    It took me while as well to realize that only the even numbered in/outs of the TDM objects are valid, at least for v3.6 (0-10 for the ins and 0-14 for the outs). And now coding!
    Click image for larger version. 

Name:	IMG_20190117_134659.jpg 
Views:	16 
Size:	75.2 KB 
ID:	15628

  20. #120
    I think I managed to solder the chip onto the board, hurray! Now, next task: solder all the little pieces too.

    Now I wondered: how to recognize the orientation of the capacitors? I just inspected one of the 10uF capacitors. There is a circle going through one of the ends. Does this signify anything? The clearest placement diagram was this of course: https://www.pjrc.com/teensy/beta/cs42448_placement.png. The parts are all readable in the same directions. Yet I would guess the orientation on the left hand side should be the opposite from the right hand side?

  21. #121
    OK, I found an explanation that ceramic capacitors are not polarised.

Posting Permissions

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