Thought I knew how SPI worked till I worked on a slave...

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have been working with SPI for a while but honestly never had to write code for a slave. The prediction bytes are confusing me, how does this work?

For example, I'm copping a well known PlayStation protocol. An example.

Command in this case is the master

Data is the slave.

 

byte # 1 2 3 4 5 6 7 8 9
Command 0x01 0x41 0x00 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A
Data 0xFF 0x41 0x5A 0xFF 0xFF 0x03 0x00 0x00 0x5A

 

and

 

byte # 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
Command (hex) 01 42 00 WW YY 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Data (hex) FF 79 5A FF FF 7F 7F 7F 7F 00 00 00 00 00 00 00 00 00 00 00 00

 

The first thing I need to do is read what the master is sending so ill just send a FF to kick things off.  Spi_read( 0xff);

 

So far so good. Now I need the next byte but I'm expected to know if I get a 42 or a 41 before I send my 79 or 41?

 

How does that work? There is no way for me to know if I'm going to get a 41 or a 42 so I can not send the 79 vs 41.

 

Correct me if I'm wrong here but SPI typically is bidirectional and you always send a byte when you read a byte. I get why the first byte is always a FF because we do not know what the master will send back. but if the master always sends a 1 as the first bute, I can not predict the next byte to send?

 

In working on the master, I never cared what the slave sent unless I needed to. So I just send my data 1,2,3,4... and read whatever I needed. With a slave it's more difficult  because I need to listed to commands. These commands will get certain data based on the command. So this second byte being the command confused me as I need to send data before I know the command.

 

 

 

 

 

 

 

 

 

 

 

 

 

Last Edited: Fri. Jul 19, 2019 - 03:16 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

well, the slave is always answering to a master request,

so master sends byte 1 slave gives FF back as it is as said not knowing what to be responded.

master byte 2 slave answers to byte 1

master byte 3 slave answers to byte 2

master byte n slave answers to byte n-1

 

note that master byte1 can be a command to read a whole load of data.

 

my guess it that the last thing that normally is does is that the master writes a "dummy" byte as last byte and the slave response is the last valid byte

Then after receiving that "dummy" byte the slave goes to a wait state and the whole thing starts again.

 

as you need to be quick to me it seems that the whole checking what command is received and at least getting the first reply byte ready is done in the receive complete interrupt to make sure that when SPI continues immediately with the next byte the chance of the slave not having the right answer ready is as small as possible.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

S_K_U_N_X wrote:
Now I need the next byte but I'm expected to know if I get a 42 or a 41 before I send my 79 or 41?
I don't see how you can know this. As you have found the slave has to have their return byte already loaded into SPDR before the master clocks in the next byte to the slave. So I don't see how you can make the 41/79 decision until the 41/42 has been seen.

 

Are you SURE you have got the details of this correct? Could it be that the protocol is actually a master that sends

 

01 FF 41 FF 00 FF 5A FF ...

 

and the slave responds:

 

?? FF ?? 41 ?? 5A ?? FF

 

That is the slave replies "lag" by one byte.

 

Are you able to connect into an existing device talking this protocol with a logic analyser? That way you could see the real byte sequence.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


S_K_U_N_X wrote:

Correct me if I'm wrong here but SPI typically is bidirectional and you always send a byte when you read a byte.

 

Not really what I'd call bidirectional. Understand this diagram from the datasheet and all will become clear...

 

 

 

Remember, the Slave never initiates a data transfer, all that happens is that when the Master sends a byte it receives back whatever happens to be in the Slaves shift register at that time. 

 

 

 

More detail on the PS protocol here...

 

https://gamesx.com/controldata/p...

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

From Brian's link:

    Standard Digital Pad

    BYTE    CMND    DATA

     01     0x01    idle
     02     0x42    0x41
     03     idle    0x5A    Bit0 Bit1 Bit2 Bit3 Bit4 Bit5 Bit6 Bit7
     04     idle    data    SLCT           STRT UP   RGHT DOWN LEFT
     05     idle    data    L2   R2    L1  R1   /\   O    X    |_|

That seems to be quite different to the description in #1 ??

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe I wrote it wrong above? Looks like the same thing to me?

 

 01     0x01    idle
 02     0x42    0x79

or

01     0x01    idle
02     0x41    0x41

 

or

 

01     0x01    idle
02     0x44    0xf3

 

as I said before.

 

The first thing I need to do is read what the master is sending so ill just send a FF (ok idle) to kick things off.  Spi_read( 0xff);

 

 Now I need the next byte and as mentioned I need to put it in the shift register. With the examples above this byte is going to be  a 41,79 or f3. Though that depends on the second byte from the master? I still do not see how I'm going to know that?

 

The issue with brains link is its all 42's, here is more details on the other commands.

http://webcache.googleuserconten...

 

 

The 44->79 I get because this is the Slave ID:79 but 45-f3 confuses me as I can not load the shift register on the second read unless I know the byte the master is sending.

 

 

Last Edited: Fri. Jul 19, 2019 - 12:01 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

On that page under "The PSX Controller Data" it seems there are several possible devices (some with more than one mode of operation) but it seems to me that if, for example you are emulating "Standard Digital Pad" then the first response to 0x42 is always going to be 41 then 5A then the data. Or if you are emulating a "Negcon" it is always 23 5A then the data (more bytes from this one). I don't know what "red mode" or "green mode" for an analogue controller actually mean but it seems to say that Analogue Red always responds 73 5A then data and Green is 53 5A, etc etc.

 

So which of those devices are you pretending to be? Clearly the first byte you send back after getting the 01 and when the 42 then arrives is the "controller ID":

 

41 = Digital

23 = NegCon

73 = Analogue Red

53 = Analogue Green

12 = PSX Mouse

 

then each sends 5A in the next cycle then some variable amount of data after that according to which controller type it is.

 

I'm going to guess you plan to be an Analogue Controller? If so it seems you only need concern yourself then about "Red" or "Green" switching.

 

Presumably the PSX itself knows these controllers and know how many data bytes to clock out of each once the controller ID byte has been passed back.

 

EDIT: this appears to explain Red/Green mode:

 

https://en.wikipedia.org/wiki/Dual_Analog_Controller#Features

 

So the default analogue is "red" and it is "green" in "flightstick" mode.

Last Edited: Fri. Jul 19, 2019 - 12:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I added this.

 

The 44->79 I get because this is the Slave ID:79 but 45-f3 confuses me as I can not load the shift register on the second read unless I know the byte the master is sending.

 Your right but what in the case of a 44, data shows the slave loads f3 in to the shift register. f3 is not a controller ID, How would the slave know to load f3 if byte 2 has not yet arrived?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

S_K_U_N_X wrote:

...so ill just send a FF (ok idle) to kick things off.  Spi_read( 0xff);

 

Who is going to send the 0xFF to 'kick things off'?

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OH wait, I think I get it now... its the order of packets..

 

"Only works after the controller is in config mode (0xF3)."

 

 

So a command 42 (main poll) sends 79 because that is the controller ID but a command 41 must not be in the same order and the slave will know what to put it based on the previous command.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who is going to send the 0xFF to 'kick things off'?

Something has to be in the shift register to read the masters command, no?  So when I first connect the slave it must wait for a 0x01 from the master. So I need to load 0xff in to the shift register (idle state).

 

while ( reply != 0x01 ) { reply  =  Spi_read( 0xff);  };

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

While googling I found this:

 

http://novemberbravo.50webs.com/projects/avr_dsc/avr_dsc.html/

 

presumably that's a working implementation of an AVr pretending to be a controller. Probably a lot to be learned there.

 

(code is a bit "all over the place" but with perseverance one might follow it!)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

After studying it now it is all clear to me. Certain commands are just sent after this config mode.  but yeah thx for that ill see what I can get out of it.