libftdi Archives

Subject: RE: I'm still struggling with SPI.

From: "Michael Plante" <michael.plante@xxxxxxxxx>
To: <libftdi@xxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 27 Aug 2010 14:58:00 -0500
John Oyler wrote:
>> The problem is repeatable, and predictable. With the code I linked to
>> last night, it will always be exactly 2 reads behind.

Try successive reads after only one write.  If it "catches up" by reading
more data than you expected, then you need to figure the synchronization
out.  If it returns no bytes, though, there's some other problem.  My
suspicion is you just haven't fully emptied the FIFO inside the FTDI chip,
so it still has more bytes for you to read.

>> If I change pindir to 0x1b (or even 0x13) globally, it all stops working.
>> If I change it to those values from within send_command() conditionally
>> (on config_or_data), my initial write/read works, but when trying to
>> read from the data fifo, things go hinky. If I change it at the top
>> of send_command, period, then I see about 2/3rds of the register
>> reads as 0x00, but the remaining third are identical in value and
>> placement as they normally are (off by two).

I would have to look at the radio chip's data sheet in a lot more detail to
figure out what's going on here.  Consider that once you set the direction
to output, you'll always have to pay attention to what values are being
driven out.  I would not expect setting it globally to an output and then
forgetting about it would work, or else they'd have just tied it to one rail
in hardware.

>> I'm under the impression that that's supposed to be the bitmask that
tells you which pins are output.

It is.

>> Setting the 5th pin to output shouldn't make it work like this, I would
not think.

Not sure what you mean.

>> SET_BITS_LOW is just 0x80. It takes two arguments, the first byte
>> is supposed to be the value you're putting on ADBUS. The second
>> byte is pindir, which should tell you which are output.


>> 0x11 and 0x20 are the write and read commands respectively (that
>> read one byte at a time, and msb first).

Except that I would not say "the comands", but, rather "particular examples
of commands".  See below.

>> There are other similar
>> ones there that would allow for the concurrent writing and reading,
>> for one bit at a time, in different directions.

Yes, but unless you're having trouble with /CS not doing the right thing, it
sounds like you may not need those.

>> Idle low, it seems.

If that's what the radio chip's datasheet says, then using 0 on line 117
should be ok.  I just looked, and that sounds right.

>> I've only copied so far, I don't understand it well enough.
>> Hell, I can't even figure out what +VE and -VE mean in the app note.

This is fundamental to SPI, in general, regardless of whether you use FTDI
or not.  If you know what setup and hold times are, as well as clock skew,
then you know that data has to be stable a certain amount of time before and
after a clock edge into a flip flop.  Each SPI device needs to know whether
it should expect to have the setup/hold around the rising edge of the clock
or falling edge, and also needs to know what it should do to interface with
its partner device.  Usually the slave devices (radio chip, in this case)
only accept one mode of operation, and it's up to the master (FTDI, in this
case) to reconfigure itself to match.  This means you have to pick the right
command so that they talk to each other reliably.

If you look at, e.g., figure 27 on the chip's data sheet, you'll see that
SCK goes high while MOSI is stable, and SCK also goes high while MISO is
stable.  This means that each chip has to change its outputs when SCK falls,
and sample when SCK rises.  That narrows the possibilities down by 4x.  I
*believe* this means your commands should be 0x11, 0x20, and 0x31, so it
seems you're *probably* doing it right.  But I really wish AN108 had a
diagram, rather than text.  Here are the sentences I'm looking at:

0x11:  "The data will change to the next bit on the falling edge of the CLK
0x20:  "The data will be sampled on the rising edge of the CLK pin."

>> Well, if I'm setting it to 0x00 effectively, that also explains why
>> the second chip select (ADBUS4) goes low as well. But if I change
>> that "0 & ~cs_bits" to a conditional to 0x10, it doesn't keep ADBUS4
>> high as I would expect.

Hrm.  Assuming you send 0x80 0x10 0x1b , ADBUS4 should go high, and /CS
should go low.  Are you saying that isn't happening?

>> It happens to be low, both ADBUS3 and 4 are, for the duration of
>> my successful spi commands, only going high again once the SPI
>> command is over. But the radio chip defaults to config. Ugh.

What does "defaults to config" mean?

>> Ok, here's something bizarre, towards the top of ft2232_spi_command() I
put in this block of code:
>> uint_t chipselect;
>> if (config_or_data) {
>> chipselect = 0x01;
>> pindir = 0x1b;
>> } else {
>> chipselect = 0x00;
>> pindir = 0x0b
>> }
>> And I change line 117 to buf[++i] = chipselect; ... The clock goes high
>> the clock signal isn't forcing it low. This is as you'd expect (pindir
makes that
>>  pin an output, and I'm putting a 1 on it). But it doesn't seem to work
>> chipselect = 0x02 with MOSI... that still behaves normally. Nor does it
>> with it set to 0x08 for CS, or 0x10 for ADBUS4.

I'm not completely clear on what you're saying is happening.  I'm also not
sure what "config_or_data" is.  Note that you've switched from postfix i++
to prefix ++i; I don't know if that's right.  Additionally, I still think
always setting 0x1b, rather than 0x0b, makes more sense.  Anyway, it sounds
like you really just need to see what the pins are doing on the scope before
we can proceed much further on the problems with ADBUS3/4.


libftdi - see for details.
To unsubscribe send a mail to libftdi+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx   

Current Thread