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

Thread: Spififo

  1. #1
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin, TX
    Posts
    112

    Spififo

    Will SPIFIFO be able to work with multiple devices without doing begin() between them?

    SPIFIFO seems to be taking less than 2u to send and receive two bytes.
    SPI4Teensy3 and the SdFat code I've been using take just over 5us to do the same.
    I'm trying to do a lot of SPI communication and wavetable synthesis inside an (approximately) audio rate timer so a couple of us are very important.

    Here's the SPI code I lifted from SdFat. You just have to put a digitalWriteFast before and after spiSend or spiRec.

    I'm using an external DAC as I need two channels along with an ADC and serial flash, which I've made a library for.
    I haven't jumped to Audio.h as I've got a lot invested in the silly way I'm doing it.

    Aaaand here's some code form this video I made when testing the internal DAC on the 3.1.

    Code:
    #include <SPIFIFO.h> 
    int drymix,wetmix,dealy_in;
    IntervalTimer timer0;
    uint32_t j,todac;
    long prev2,d,t;
    static long LMSIZE =16;
    uint32_t accumulator[9]={};
    uint32_t increment[9]={};
    uint16_t out[9]={};
    uint32_t freq[9]={};
    int waveindex[9]={};
    byte tick;
    int dds_rate=25;
    long dds_tune;
    int raw;
    
    void setup() {
    
      SPIFIFO.begin(10,SPI_CLOCK_24MHz);
      timer0.begin(DDS, dds_rate);
      dds_tune=1/(dds_rate*.000001);
      analogWriteResolution(12);
      delay(100);
    }
    
    
    void DDS() 
    {
      t=micros();
    
      n2f(0,500^j);
      int vt0 =  vtri_voice(0,512,255);
      n2f(1,1000&j);
      int vt1 =  vtri_voice(1,j,255);
      n2f(2,1200*j);
      int vt2 =  vtri_voice(2,j,128);
      n2f(3,250);
      int vt3 =  vtri_voice(3,j,255);
      n2f(4,125/2);
      int vt4 =  vtri_voice(4,j,255);
      n2f(5,3000&j);
      int vt5 =  vtri_voice(5,j,255);  
    
    /*
      n2f(0,64|j);
      int vt0 =  vtri_voice(0,512,255);
      n2f(1,128|vt0);
      int vt1 =  vtri_voice(1,j,255);
      n2f(2,256|j);
      int vt2 =  vtri_voice(2,j,128);
      n2f(3,512|vt2);
      int vt3 =  vtri_voice(3,j,255);
      n2f(4,1024|vt3);
      int vt4 =  vtri_voice(4,j,128);
      n2f(5,6000/j);
      int vt5 =  vtri_voice(5,j,255);  
      */
       drymix=(vt0+vt1+vt2+vt3+vt4+vt5)>>3;
    
      // todac = (1 << 15) | (1 << 14) | (1<< 13) | (1 << 12) | ( outmix ); 
      // SPIFIFO.write16(todac);
    
          analogWrite(A14, drymix);
          
    
      d=micros()-t;
    
    
    }
    
    void loop() {
    
      if ((millis()-prev2)>5){
        j++;
        j%=1024;
    
        prev2=millis();
        Serial.print(d);       
        Serial.print( " " );
        Serial.println(drymix);       
      }
    
    }
    
    
    
    uint16_t vtri_voice(volatile byte vn, int16_t knee, byte amp){
      int16_t tempout;
      int waveamp=4095;
      int wavelength=1024;
      accumulator[vn] += increment[vn]; 
      waveindex[vn]=((accumulator[vn]) >> 22); 
      //   out[vn]= pgm_read_word(&tempout);  
    
      if (waveindex[vn]<knee){
        tempout=((waveindex[vn])*waveamp)/knee;
      }
    
      if (waveindex[vn]>=knee){
        tempout=((((waveindex[vn]-knee)*waveamp)/(wavelength-knee))*-1)+waveamp;
      }
      return  (tempout*amp)>>8;
    
    } 
    
    void n2f(byte n, long freq){
      increment[n] = ((65535*(freq))/(dds_tune))<<16 ; 
    
    }
    John-Mike
    bleeplabs.com
    Last edited by john-mike; 01-17-2014 at 06:05 AM.

  2. #2
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin, TX
    Posts
    112
    There must have been something odd in my previous speed test code as when I tried SPIFIFO again it was considerably faster.

    On the 3.0 it takes under 2.5us to change the CS and send and receive 2 bytes.
    The 3.1 takes under 2.25.

    Here's the unconnected test code. The speeds are similar when it's hooked up to a few DACs.

    Code:
    #include <SPIFIFO.h>
    IntervalTimer timer0;
    long prev2,d,t;
    
    void setup() {
      timer0.begin(DDS, 25);
    }
    
    
    void DDS() 
    {
    int temp1=65000;
      t=micros();
    
      SPIFIFO.begin(9,SPI_CLOCK_24MHz);
      SPIFIFO.write16(temp1);
      int temp = SPIFIFO.read();
    
      SPIFIFO.begin(10,SPI_CLOCK_24MHz);
      SPIFIFO.write16(temp1);
      temp = SPIFIFO.read();
    
      SPIFIFO.begin(20,SPI_CLOCK_24MHz);
      SPIFIFO.write16(temp1);
      temp = SPIFIFO.read();
    
      SPIFIFO.begin(23,SPI_CLOCK_24MHz);
      SPIFIFO.write16(temp1);
      temp = SPIFIFO.read();
    
      d=micros()-t;
    }
    
    void loop() {
    
       // j++;
       // j%=1024;
       if ((millis()-prev2)>100){
        prev2=millis();
        Serial.println(d);       
        Serial.print( " " );
    
      }
    
    }
    Last edited by john-mike; 01-17-2014 at 05:26 PM.

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    25,073
    Yes, a call to begin() is needed to switch to a different chip.

    Maybe it ought to have a way to rapidly change to a different chip without affecting the other settings?

  4. #4
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin, TX
    Posts
    112
    Quote Originally Posted by PaulStoffregen View Post
    .... without affecting the other settings?
    Yes that's what I mean. Is there a lot of overhead being wasted?

    Thanks!

Posting Permissions

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