Shop OBEX P1 Docs P2 Docs Learn Events
Four wire SPI functions? — Parallax Forums

Four wire SPI functions?

MauvaiMauvai Posts: 45
edited 2015-03-02 11:16 in Propeller 1
Is there any support for 4 wire SPI? The shift_in() and shift_out() functions seem to only do 3 wires, no option for a second data pin... I am aware that there is a spi object in propware, but I don't even know how to begin finding if it does 4 wire....

Comments

  • tonyp12tonyp12 Posts: 1,951
    edited 2015-02-16 12:03
    What 4th wire?

    Quote: Jens-Michael Gross

    Shouldn't use 4-wire SPI mode when you're the only master in the system.
    4-wire mode uses STE as input only. It does not control the slave (chip select) as every slave needs its own chip select. This is done by GPIO by your software.
    STE in master mode switches the USCI into slave mode when another master wants the mcu to listen or shut up.

    Personally, I think the name '4-wire' was an unlucky choice because many people thing '3 wire' means one bi-directional data line, one clock line and a chip select line,
    while '4 wire' means one input, one output, one clock and one chip select.
  • MauvaiMauvai Posts: 45
    edited 2015-02-16 12:14
    Forgive me if i am wrong but I thought 3 wire spi used a bidirectional line, and 4 wire used 2 lines.. either way, I am trying to use the version with 2 separate lines. the prop learn page http://learn.parallax.com/propeller-c-simple-protocols/spi-example, uses a bi directional line, and it seems the functions don't support the other version (what should this be called???)

    What is 4 wire spi, if not spi with 4 wires? Clk, mosi, miso, Cs? And why should I not use CS if I have only one master, particularly if the slave device actively requires CS to change? I am aware that the CS should be controlled by GPIO...

    Also finally, what do STE and USCI stand for? google turned up nothing....

    Thanks :)
  • twm47099twm47099 Posts: 867
    edited 2015-02-16 12:27
    Mauvai wrote: »
    Is there any support for 4 wire SPI? The shift_in() and shift_out() functions seem to only do 3 wires, no option for a second data pin... I am aware that there is a spi object in propware, but I don't even know how to begin finding if it does 4 wire....

    The last post (post 70) in the thread below has a SimpleIDE SPI C-library I wrote along with a number of demo programs. It can do both bidirectional I/O and separate MISO/MOSI pins. Earlier posts show the full learning experience.

    Tom

    http://forums.parallax.com/showthread.php/157441-Can-SPI-in-Simple-Libraries-be-speeded-up?p=1315065#post1315065
  • MauvaiMauvai Posts: 45
    edited 2015-02-16 12:43
    Ah! Thank you. that should be exaclty what i was looking for. I also discovered that the propware library can do 4 wire (or whatever its really called), so i have 2 options now. Thanks!
  • DavidZemonDavidZemon Posts: 2,973
    edited 2015-02-16 12:49
    PropWare also has an SPI library. A made-up example can be found here and a real example (driver for the L3GD20 chip) can be found here.

    If you prefer to deal with the Simple Library:
    The shift_out/shift_in functions take the data pin as the first parameter. You could use 1000 wire SPI communication if the Propeller had 1000 different pins. If you want to use dedicated pins for input and output, just call shift_out(x, ...) and shift_in(y, ....) where x and y are different pin numbers.
  • tonyp12tonyp12 Posts: 1,951
    edited 2015-02-16 12:50
    >What is 4 wire spi, if not spi with 4 wires? Clk, mosi, miso, Cs

    nCS does not belong to a "4th wire" spi standard, nCS is any GPIO that you use to set low before you start a 3wire SPI transfer.
  • MauvaiMauvai Posts: 45
    edited 2015-02-16 13:00
    PropWare also has an SPI library. A made-up example can be found here and a real example (driver for the L3GD20 chip) can be found here.

    The shift_out/shift_in functions take the data pin as the first parameter. You could use 1000 wire SPI communication if the Propeller had 1000 different pins. If you want to use dedicated pins for input and output, just call shift_out(x, ...) and shift_in(y, ....) where x and y are different pin numbers.

    Maybe I should be clearer... I don't have any experience with SPI. The part I am using requires that the read from it, I must shift out the address i am reading from, and then a 0xFF byte for each byte I wish to read (more or less) - each time i shift out a 0xFF on the Mosi, the Miso simultaneously returns the byte to be read. (this is for block read). Can i achieve this using shift in? Or the other spi library for that matter? It seems that shift in has no option to take a Miso pin to shift out the 0xFF byte.

    I also have no idea if what the device is doing is the standard, or is really weird....
  • DavidZemonDavidZemon Posts: 2,973
    edited 2015-02-16 13:08
    Mauvai wrote: »
    Maybe I should be clearer... I don't have any experience with SPI. The part I am using requires that the read from it, I must shift out the address i am reading from, and then a 0xFF byte for each byte I wish to read (more or less) - each time i shift out a 0xFF on the Mosi, the Miso simultaneously returns the byte to be read. (this is for block read). Can i achieve this using shift in? Or the other spi library for that matter? It seems that shift in has no option to take a Miso pin to shift out the 0xFF byte.

    I also have no idea if what the device is doing is the standard, or is really weird....

    You are understandably confused, don't worry.

    The methods "shift_*" are written with those names for a reason. Many CPUs that have hardware SPI communication don't have separate in/out functions - only one function. For every bit that is shifted out, another bit is shifted in. This shifting is so common, in fact, that many datasheets will tell you to send 0xFF because they're assuming you have to send something. What they really mean is "we don't care what you send, just give the device 8 clock ticks and we'll send you 8 bits of data on the MISO line and any data you might or might not send via MOSI is ignored."

    Because of this shifting, most SPI masters theoretically support simultaneous input/output - but I haven't seen any slaves that actually utilize it.
  • MauvaiMauvai Posts: 45
    edited 2015-02-16 13:11
    Ah.... I shall away and test it.. thank you
  • tonyp12tonyp12 Posts: 1,951
    edited 2015-02-16 13:17
    Prop don't have a hardware SPI.
    You can do customs make one that shift out $00 of $ff after the initial header etc.
    Or simple just toggle clk line and don't read and toggle data at all.

    But I guess you are asking if shift-in in C can do it.
    If you use spi library, it probably only have an option to toggle clk line if you tell it to send a 8bit byte
    These bytes should be don't_care for the slave device, but users mostly send 0 or $ff
  • MauvaiMauvai Posts: 45
    edited 2015-02-16 15:46
    I went back and looked at the data sheet (and tested) - i need to send specifically 0xFF on the MOSI when I read, 0x00 wont do. Apparently this part does use simultaneous read/write. How would I go about this? do i need to use the prop ware library, or is even that going to work?
  • jmgjmg Posts: 15,173
    edited 2015-02-16 15:59
    SPI HW will always shift data OUT on MISO as data comes in on MOSI, sometimes the host end can discard that reply

    My guess for prop ware would be you need the slightly cryptic
    read_par (T * par ) const : Read the value that the SPI cog just shifted in.
  • MauvaiMauvai Posts: 45
    edited 2015-02-16 16:18
    UPDATE: I'M A MORON

    So I was printing with print("\nStatus word: %X", reg);

    Knowing damn well %X doesn't do what I expect it to in prop code... switched it to %x and it works fine with shift_in(). Correct return values.


    Thank you all, and apologies for being stupid.
  • DavidZemonDavidZemon Posts: 2,973
    edited 2015-02-17 06:22
    Glad you got it working Mauvai!

    To answer the lingering question on how PropWare deals with reads, 0xFF is always sent out on MOSI during a read. If a slave device requires anything other than 0xFF during a read routine, the source code would have to be modified. If that ever comes up, I hope someone will let me know and I could add an option to make this configurable.

    The last line of code in the send function leaves MOSI in the high state.
  • jmgjmg Posts: 15,173
    edited 2015-02-17 13:50
    To answer the lingering question on how PropWare deals with reads, 0xFF is always sent out on MOSI during a read. If a slave device requires anything other than 0xFF during a read routine, the source code would have to be modified. If that ever comes up, I hope someone will let me know and I could add an option to make this configurable.

    The last line of code in the send function leaves MOSI in the high state.

    I thought Send always also received a byte, which was what this meant, in your LIBs ?

    read_par (T * par ) const : Read the value that the SPI cog just shifted in.

    If send also clocks in data, then users have the choice of ignore, and they can send anything for Rx.

    There are many Slave IO expanders that do full duplex, it is mainly memories that are essentially half-duplex.
  • DavidZemonDavidZemon Posts: 2,973
    edited 2015-02-17 14:05
    I'm afraid not. Shift_out only sends and shift_in only receives. I could write a full-duplex version if anyone needs it, but I don't own any devices that use it and no has asked for it.

    If you have a specific device in mind that uses it, you could create an issue for it and I can make it happen. The issue doesn't need to be anything fancy - just a brief title and make sure the part number is in the description somewhere.

    --Edit--
    Sorry - didn't realize you have to be signed into github to create an issue. If you don't have a GitHub account, just reply or PM me with the details and I'll create the issue.
  • tonyp12tonyp12 Posts: 1,951
    edited 2015-02-17 14:20
    The original Motorola SPI innovation was a using single byte for storage, to both send an receive.
    When the msbit goes out and new bit get shifted in
    if you clock it 8 times, the buffer byte have gotten sent out and it now holds a completely new value, that is the 8bit input data

    Most hardware SPI now-a-day use two bytes (example MSP430 USCI) and the forced-writes to be able to read is kind of just still there.
  • jmgjmg Posts: 15,173
    edited 2015-02-17 15:01
    I'm afraid not. Shift_out only sends and shift_in only receives. I could write a full-duplex version if anyone needs it, but I don't own any devices that use it and no has asked for it.

    One example device is OnSemi NCV7240, but even the lowly HEF4021 used as a SPI Keypad Scanner, needs Duplex. All MCU's with HW SPI operate that in Duplex.

    Duplex should be a safe-superset of SPI, if you do not care what just came in when you wrote, just ignore it.
  • Daniel NagyDaniel Nagy Posts: 26
    edited 2015-03-02 05:42
    Hello guys,

    I just wanted to say, I also own a device that uses simultaneous read-write.
    It's an automotive g sensor for airbags, called SMB460.

    I've already implemented a bare minimum driver for it in SPIN that time, and now I'm trying out propeller C, and was very surprised the standard library only have separate shift_in and shift_out functions.


    Daniel
  • DavidZemonDavidZemon Posts: 2,973
    edited 2015-03-02 06:20
    Thought I'd already created an issue for this - didn't mean to ignore you @jmg.

    But I didn't. An issue has been created now - if you want to follow the progress in PropWare, see issue #28. It will be a while before I get to it - I have some other items that I think are higher priority (proper SD card support)
  • Daniel NagyDaniel Nagy Posts: 26
    edited 2015-03-02 11:16
    Hello,

    If someone would need a quick solution, here's how I implemented it quickly.
    Please note, it doesn't contain delays. I can do that so, because my device is very fast, serial clock can be driven at 8MHz. If your device is not capable for such high speeds, delays have to inserted.
    As you can see in the code it will simply send 16 bits that is given as tx, and will return with the answer. It won't release the bus, you have to add that several lines if your application needs it.
    int spiTransfer(int tx){
     int rx=0;
     int txpuff;
     
     high(SMB460_PIN_SCK);
     high(SMB460_PIN_CS);
     set_direction(SMB460_PIN_SI,1);  
     low(SMB460_PIN_SCK);
     low(SMB460_PIN_CS);
    
     for(int i=0;i<16;i++){
          high(SMB460_PIN_SCK);
          rx = (rx << 1) | input(SMB460_PIN_SO);
          txpuff = tx;
          txpuff = (txpuff >> (15-i)) & 1;
          set_output(SMB460_PIN_SI, txpuff);
          low(SMB460_PIN_SCK);
     }
    
     high(SMB460_PIN_CS);
     high(SMB460_PIN_SCK);
    
    return rx;    
    }
    
Sign In or Register to comment.