Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 4 1 2 3 ... LastLast
Results 1 to 25 of 100

Thread: SPISlave_T4

  1. #1
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,095

    SPISlave_T4

    SPISlave_T4 has been released!

    You may download it at https://github.com/tonton81/SPISlave_T4
    An example is supplied as well.

    It is based on TSPISlave for Teensy 3.x, except it has an additional feature. Not using a callback will print out data being received to serial monitor.

    So far Teensy 4.0/4.1 are supported for SPI only on pins 10, 11, 12, 13. No additional pins needed (well, common ground is obviously a plus).

    I don't have the SPI1 or SPI2 pins broken out, but the library can easily support them as I am accessing the memory blocks directly with calculated offsets, rather than independant register names. Until then, SPI. is only supported.

    My setup consisted of a Teensy LC SPI master sending data to a Teensy 4.0 slave.
    Code:
    Pin layout for SPI:
    
    LC      T4
    
    12      11
    11      12
    10      10
    13      13
    
    
    No alternate pins are broken out for SPI on Teensy 4.0/4.1.
    Slave mode on Teensy 4 supports 8, 16, and 32bit transfers selectable in the constructor. Note that if you set 16 or 32bits, you need to send all the bits. Like for 16 bit you need to send 2x8bit transfers or one transfer16, or 4x 8bit transfers for 32bit or 2x transfer16's for 32bit.

    Enjoy!
    Last edited by tonton81; 02-25-2021 at 02:52 PM.

  2. #2
    Senior Member
    Join Date
    Dec 2013
    Location
    East Stroudsburg PA.
    Posts
    344
    Oh this is looking good
    I am wondering if I can use this to spy on my vintage Atari 1040 STE Microwire Interface (LMC1992 IC).

  3. #3
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,095
    As a spy? just don't hookup the return line so it wont try to send anything to it, it should be able to print out what it sees on the spi bus with the callback disabled

  4. #4
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,095
    Hey that is an interesting idea. We could setup the library to also be an SPI bus sniffer. The T4.x is capable of swapping the MISO/MOSI pins so you can log & sniff data going to and from the SPI devices. The outgoing pin could be disabled in sniff mode as well.

  5. #5
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,095
    Just updated the library. It now supports:

    mySPI.swapPins() --> swaps MISO with MOSI, so you can connect teensies together directly pin-to-pin:
    Code:
    13   13
    12   12
    11   11
    10   10
    and sniffer() : --> disables the slave output pin so it listens to traffic only.

  6. #6
    Junior Member
    Join Date
    Dec 2020
    Posts
    11
    Hi! Thanks for the libary! I have two questions.

    1. How would I go about to make the library work with an active-high setting for the CS? (That is, the CS will go high and then the clock signal will be sent, then CS goes low again).

    2. I had a Teensy 4.1 working as a slave. I was trying to send from the teensy-as-a-slave always the same 5 bits. For example {1, 2, 3, 4, 5} but on the master device I was getting somthing like {2, 3, 4, 5, 1}. I tried leaving the clock and CS connected but made a loopback between the Teensy's MISO and MOSI I would get {3, 4, 5, 1, 2}. There were 3 extra bytes I was getting before what I actually wanted to push, namely: {0, 255, 5}. I thought pushing some extra bytes before starting pushing these with the loop but that was breaking the mySPI.active() early somehow.

    Thanks!

  7. #7
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,095
    1) currently only SPI_MODE0 is supported/hard coded, CS polarity is not changeable yet without editing the source config & testing

    2) the initial 2 bytes are from the SPI slave config FIFO, they must be shifted out before your actual data ends up shifting out of the slave

  8. #8
    Junior Member
    Join Date
    Dec 2020
    Posts
    11

    Quote Originally Posted by tonton81 View Post
    1) currently only SPI_MODE0 is supported/hard coded, CS polarity is not changeable yet without editing the source config & testing

    2) the initial 2 bytes are from the SPI slave config FIFO, they must be shifted out before your actual data ends up shifting out of the slave
    Many thanks!

  9. #9
    Junior Member
    Join Date
    Dec 2020
    Posts
    11
    Quote Originally Posted by tonton81 View Post
    2) the initial 2 bytes are from the SPI slave config FIFO, they must be shifted out before your actual data ends up shifting out of the slave
    How would I go about to shift out the bytes? I was writing some extra bytes to be able to then have the correct order but the output order was not consistent.

    The master is sending the CS and clock and allowing for 5 bytes to come through. For the following code I get consistent output (11, 15, 14, 13, 12). (I am checking the output with a logic analyzer):

    Code:
    #include "SPISlave_T4.h"
    SPISlave_T4<&SPI, SPI_8_BITS> mySPI;
    
    void setup() {
      Serial.begin(115200);
      while (!Serial);
      Serial.println("Begin");
      mySPI.begin();
      mySPI.onReceive(myFunc);
    }
    
    void loop() {
    }
    
    void myFunc() {
      while (mySPI.active()) {
        if (mySPI.available()) {
          mySPI.pushr(15);
          mySPI.pushr(14);
          mySPI.pushr(13);
          mySPI.pushr(12);
          mySPI.pushr(11);
        }
      }
    }

  10. #10
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,095
    just make 2 dummy bytes maybe 0xFF, can be anything, then write them from the master before the actual payload. if you are overriding the pusr with bytes then that will work also

  11. #11
    Junior Member
    Join Date
    Sep 2021
    Posts
    6

    SPI Slave without interrupts??

    Hello,

    Will this only work using interrupts?

    My issue seems to be that the RX Interrupt is happening too fast, and hanging up my Teensy. If I disable the interrupt, will the rx bits get written to the FIFO automatically?

    I am having trouble using the teensy4.0 to receive data from the AD7764 ADC. (https://www.analog.com/media/en/tech...ets/ad7764.pdf)
    I have data coming in at a frequency of about 156kHz, and the clock signal coming in at 20MHz.

    To start I just want to read the latest 32 bit sample, like once a second. So I am not worried about timing, except that I can't slow down the ADC. Using this library as is makes the teensy hang as soon as the interrupts are enabled in the begin() function.

    Thanks for your help!

  12. #12
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,095
    you need to drive pin 10 high to exit the SPI slave ISR. If it is asserted (low) yes the interrupt holds until the CS line de-asserts

  13. #13
    Junior Member
    Join Date
    Sep 2021
    Posts
    6
    Quote Originally Posted by tonton81 View Post
    you need to drive pin 10 high to exit the SPI slave ISR. If it is asserted (low) yes the interrupt holds until the CS line de-asserts
    Pin10 is connected to the frame sync output from the ADC. So it is driven low while the ADC is outputting data. It is driven low for 32 bits at 20MHz (1.6uS) then driven high again.
    I think the issue is that the next time it is driven low again is just about 7uS later. Is 7uS enough time to get out of the ISR and prepare for the next?

  14. #14
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,095
    one way to find out is to slow it down

  15. #15
    Junior Member
    Join Date
    Sep 2021
    Posts
    3
    Hi,

    I am currently using this library to communicate via SPI with an openBCI. The openBCI uses a pic32 as the master that controls SD card, analog to digital converter and a RF module. I would like to add to this board a teensy so I can add more features to the board. Currently I am trying to send the date to the openBCI just to test the implementation.

    Before working with the OpenBCI, I tested the slave code with another teensy that serves as a master. They both worked properly, I sent a command with the teensy#1 (Master), then the teensy #2 (slave) calculated the date and sent it to the master.

    When I do the same with the pic32 the data stream from the pic32 gets corrupted only when I connect the MISO to the board. When I connect the CS, the SCK and the MOSI while checking with the oscilloscope, the MISO sends the data correctly from the teensy (slave) to the oscilloscope. At the moment I connect the MISO to the pic, the pin voltage changes completely (both devices use a 3.3V architecture).

    I am adding some pictures to show the problem.

    Correct (before attaching MISO):
    Click image for larger version. 

Name:	correct.jpg 
Views:	103 
Size:	80.8 KB 
ID:	25882


    Problem (after attaching MISO):

    Click image for larger version. 

Name:	problem.jpg 
Views:	94 
Size:	66.9 KB 
ID:	25883

    I tried just connecting the MISO to the Pic and the same problem happened. I also tried changing the MISO and MOSI pins with the swap Pins functions, that didn't work either. Maybe if someone knows about this problem or something similar. Maybe the voltages are not the same in both ports and are generating a type of shortcircuit.

    Looking forward to your replies and thank you for your responses.

  16. #16
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,095
    Are your common grounds connected?

  17. #17
    Junior Member
    Join Date
    Sep 2021
    Posts
    3
    Quote Originally Posted by tonton81 View Post
    Are your common grounds connected?
    Yes they are connected.

    I was checking the voltages, and the MISO port from the PIC32 is always HIGH and goes down and back again when there is data available. In the Teensy4, the pin is always LOW and when there is data it goes up and down. Could this be the problem? Since the "default" voltages are opposite it might generate a problem?
    Is there a way to change this polarization of the MISO pin? That is the only idea I have at the moment.
    Last edited by fabianG; 09-20-2021 at 08:40 AM.

  18. #18
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,095
    yes it is possible but currently hardcoded this way, future update may add this feature

  19. #19
    Junior Member
    Join Date
    Sep 2021
    Posts
    3
    Could you guide me a bit about where could I change that?
    Is it too complicated to do? Maybe I can try to change it.

  20. #20
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,095
    you can modify the CPOL & CHPA register, check the release manual for the correct value, in slave mode section

  21. #21
    Junior Member
    Join Date
    Oct 2021
    Posts
    8
    Quote Originally Posted by tonton81 View Post
    just make 2 dummy bytes maybe 0xFF, can be anything, then write them from the master before the actual payload. if you are overriding the pusr with bytes then that will work also

    Hi tonton81,

    I tried to use SPISlave_T4 as described above, but I have found it impossible to receive the data in correct order.
    I can send/receive up to 3 bytes correctly, but then when I tried sending more data I got it 'mixed up'.

    My working code is bellow:

    Teensy 4.1 SPI SLAVE
    main.cpp
    Code:
    #include <Arduino.h>
    #include "TeensyThreads.h"
    #include "SPISlave_T4.h"
    
    
    SPISlave_T4<&SPI, SPI_8_BITS> mySPI;
    
    
    volatile int distanceUSFL = 0;
    volatile int distanceUSFR = 0;
    volatile int distanceUSBL = 0;
    volatile int distanceUSBR = 0;
    
    
    void ultrasonicSensorFrontLeft(){
    	while (1) {
        	int incomingByte;
    		int distanceMSB;
    		int distanceLSB;
    		int distanceCRC;
    		int distanceUSFLT;
    
    		if (Serial1.available() > 0) {
    			incomingByte = Serial1.read();
    
    			if(incomingByte==255){
                	distanceMSB=Serial1.read();
                	distanceLSB=Serial1.read();
                	distanceCRC=Serial1.read();
                	distanceUSFLT=((distanceMSB*256)+distanceLSB)/10; 
    				if(distanceUSFLT>19 && distanceUSFLT<201){ 
    					distanceUSFL=distanceUSFLT;
    				}
            	}
    		}
    		threads.yield();
    	}
    }
    
    void ultrasonicSensorFrontRight() {
    	while (1) {
        	int incomingByte;
    		int distanceMSB;
    		int distanceLSB;
    		int distanceCRC;
    		int distanceUSFRT;
    
    		if (Serial2.available() > 0) {
    			incomingByte = Serial2.read();
    
    			if(incomingByte==255){
                	distanceMSB=Serial2.read();
                	distanceLSB=Serial2.read();
                	distanceCRC=Serial2.read();
                	distanceUSFRT=((distanceMSB*256)+distanceLSB)/10; 
    				if(distanceUSFRT>19 && distanceUSFRT<201){ 
    					distanceUSFR=distanceUSFRT;
    				}
            	}
    		}
    		threads.yield();
    	}
    }
    
    void ultrasonicSensorBackLeft(){
    	while (1) {
        	int incomingByte;
    		int distanceMSB;
    		int distanceLSB;
    		int distanceCRC;
    		int distanceUSBLT;
    
    		if (Serial2.available() > 0) {
    			incomingByte = Serial3.read();
    
    			if(incomingByte==255){
                	distanceMSB=Serial3.read();
                	distanceLSB=Serial3.read();
                	distanceCRC=Serial3.read();
                	distanceUSBLT=((distanceMSB*256)+distanceLSB)/10; 
    				if(distanceUSBLT>19 && distanceUSBLT<201){ 
    					distanceUSBL=distanceUSBLT;
    				}
            	}
    		}
    		threads.yield();
    	}
    }
    
    void ultrasonicSensorBacktRight() {
    	while (1) {
        	int incomingByte;
    		int distanceMSB;
    		int distanceLSB;
    		int distanceCRC;
    		int distanceUSBRT;
    
    		if (Serial2.available() > 0) {
    			incomingByte = Serial4.read();
    
    			if(incomingByte==255){
                	distanceMSB=Serial4.read();
                	distanceLSB=Serial4.read();
                	distanceCRC=Serial4.read();
                	distanceUSBRT=((distanceMSB*256)+distanceLSB)/10; 
    				if(distanceUSBRT>19 && distanceUSBRT<201){ 
    					distanceUSBR=distanceUSBRT;
    				}
            	}
    		}
    		threads.yield();
    	}
    }
    
    void myFunc() {
      	//Serial.println("START: ");
    
    	while ( mySPI.active() ) {
        	if (mySPI.available()) {
    			mySPI.pushr(1);
    			Serial.println(mySPI.popr());
    			mySPI.pushr(2);
    			Serial.println(mySPI.popr());
    			mySPI.pushr(3);
    			Serial.println(mySPI.popr());
          	}
      	}
    	
    	//Serial.println("END");
    }
    
    
    void setup() {
      	Serial.begin(115200);
      	while (!Serial);
    
    	mySPI.begin();
    	mySPI.swapPins();
      	mySPI.onReceive(myFunc);
    
    	Serial.print("Begin...");
    
    
    	Serial1.begin(9600);
    	Serial2.begin(9600);
    	Serial3.begin(9600);
    	Serial4.begin(9600);
    
    	threads.addThread(ultrasonicSensorFrontLeft);
    	threads.addThread(ultrasonicSensorFrontRight);
    	threads.addThread(ultrasonicSensorBackLeft);
      	threads.addThread(ultrasonicSensorBacktRight);
    
    }
    
    void loop() {
    	Serial.print("millis: "); Serial.println(millis());
      	delay(1000);
    }

    Raspberry PI 4 SPI MASTER
    App.java
    Code:
            public static class Task_1 implements Runnable {
                    public void run() {
                            try
                            {
                                    SPI.Init();
                                    SPI.Refresh(true);
                                    int ans=0;
                                    SPI.SendByte(255);
                                    SPI.SendByte(255);
                                    while (true) {
                                            SPI.SendByte(101);
                                            ans=SPI.ReceiveByte();
                                            System.out.println("---> " + ans + "\n");
                                            SPI.SendByte(102);
                                            ans=SPI.ReceiveByte();
                                            System.out.println("---> " + ans + "\n");
                                            SPI.SendByte(103);
                                            ans=SPI.ReceiveByte();
                                            System.out.println("---> " + ans + "\n");
                                            System.out.println("--------------------------------------\n");
                                            Thread.sleep(1000);
                                    }
                            }
                            catch (InterruptedException e)
                            {
                            }
                    }
            }
    SPI.java
    Code:
            public static void Init() {
                    Busy=true;
                    int fd = Spi.wiringPiSPISetup(0, 4000000);
                    if (fd <= -1) {
                            System.out.println(" ==>> SPI SETUP FAILED");
                            Busy=false;
                            return;
                    }
                    Busy=false;
            }
    
            public static int ReceiveByte() throws InterruptedException {
                    Busy=true;
                    byte SPIbufer[] = new byte[1];
                    Spi.wiringPiSPIDataRW(0, SPIbufer, 1);
                    //Thread.sleep(5);
                    //System.out.println("<<<<... " + SPIbufer[0]);
                    Busy=false;
                    return (int)SPIbufer[0]&0xff;
            }
    
            public static void SendByte(int SPIByte) throws InterruptedException {
                    Busy=true;
                    byte SPIbufer[] = new byte[1];
                    SPIbufer[0] = (byte)SPIByte;
                    //System.out.println(">>>>... " + SPIbufer[0]);
                    Spi.wiringPiSPIDataRW(0, SPIbufer, 1);
                    //Thread.sleep(5);
                    Busy=false;
            }
    The above code gives the following output:
    Click image for larger version. 

Name:	screen1.jpg 
Views:	92 
Size:	62.2 KB 
ID:	26291

    After adding a code that sends/receives 4th byte I got the following output:
    Click image for larger version. 

Name:	screen2.jpg 
Views:	88 
Size:	79.2 KB 
ID:	26292


    Can you please advice on what the problem might be?

    Best Regards
    Marek

  22. #22
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,095
    you're pushing and popping 3 times per every byte transfer, it supposed to be done only once per byte

    Code:
    	while ( mySPI.active() ) {
        	if (mySPI.available()) {
    			mySPI.pushr(1);
    			Serial.println(mySPI.popr());
    			mySPI.pushr(2);
    			Serial.println(mySPI.popr());
    			mySPI.pushr(3);
    			Serial.println(mySPI.popr());
          	}

  23. #23
    Junior Member
    Join Date
    Oct 2021
    Posts
    8
    Quote Originally Posted by tonton81 View Post
    you're pushing and popping 3 times per every byte transfer, it supposed to be done only once per byte]
    I am not sure I understand, so what I did was copping this from your example:

    Code:
    void myFunc() {
      Serial.println("START: ");
      uint8_t arr[] = { 3, 2, 8, 3, 10, 11, 33, 13, 14 };
      uint8_t i = 0;
      while ( mySPI.active() ) {
        if (mySPI.available()) {
          if ( i++ > sizeof(arr) ) i = 0;
          mySPI.pushr(arr[i]);
          Serial.print("VALUE: ");
          Serial.println(mySPI.popr());
        }
      }
      Serial.println("END");
    }
    After sending/receiving 8 bytes I got this:


    ---> 2

    ---> 2

    ---> 2

    ---> 2

    ---> 2

    ---> 255

    ---> 255

    ---> 2

    ---> 2

    --------------------------------------


    Sorry for this question (I'm not a professional developer) but as I understand this should give 3, 2, 8, 3, 10, 11, 33, 13, 14 from the array. Am I right?

  24. #24
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,095
    yes, if not check connections, it uses SPI MODE 0 MSBFIRST

  25. #25
    Junior Member
    Join Date
    Oct 2021
    Posts
    8
    OK. 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
  •