markmelvin / libmpsse

Automatically exported from code.google.com/p/libmpsse
0 stars 0 forks source link

SDA line held low even after a Stop issued. #34

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
Set MPSSE to Ack following each read byte.
Perform an I2C Read followed by a Stop.  The number of bytes read doesn't 
matter.

What is the expected output? What do you see instead?
Using a logic analyzer, I can see that where the stop is issued, the SCL line 
goes high but the SDA line always stays low.  The next I2C operation fails 
because a valid start condition can't be generated.

Calling SendNacks and issuing a dummy read is incorrect if you are trying to 
read from a device that has a FIFO buffer or auto-incrementing support.

What version of the product are you using? On what operating system?
LibMPSSE v1.3 along with ftdi v1.0 on OSX 10.8.5

Please provide any additional information below.
I've tried forcing the SDA line high with a variety of set_bits or PinHigh 
calls without success.  I've tried using the FlushAfterRead call as well.  I'm 
trying to talk to an Invensense MPU9150 digital motion processor.

Original issue reported on code.google.com by northern...@gmail.com on 25 Sep 2013 at 3:47

GoogleCodeExporter commented 8 years ago
After several days of hacking, testing, and observation with a logic analyzer, 
I've come up with a fix.

Background:
The Invensense MPU-9150 supports burst reads.  From their documentation:

"To read the internal MPU-9150 registers, the master sends a start condition, 
followed by the I2C address and
a write bit, and then the register address that is going to be read. Upon 
receiving the ACK signal from the
MPU-9150, the master transmits a start signal followed by the slave address and 
read bit. As a result, the
MPU-9150 sends an ACK signal and the data. The communication ends with a not 
acknowledge (NACK)
signal and a stop bit from master. The NACK condition is defined such that the 
SDA line remains high at the
9th clock cycle."

However, the LibMPSSE Read function leaves the SDA line in the last ACK state 
seen or as specified with SendAck or SendNack.  In order to bring the SDA line 
high for a proper Stop condition to be present on the pins, what we really need 
is to have the last byte read send a NACK but all previous bytes send an ACK.

The Fix:
In support.c, we modify line 185 as follows:

// Old way
buf[i++] = mpsse->tack;

// New way
if ( j == num_blocks-1 )
   buf[i++] = 0xFF;
else 
   buf[i++] = mpsse->tack;

This causes the last byte sent to put a NACK on the line.  Now perhaps in 
future versions this should be an option.  E.g Send the inverted acknowledge 
state.  It would probably depend on the device.

Original comment by northern...@gmail.com on 27 Sep 2013 at 4:19

GoogleCodeExporter commented 8 years ago
If you are just doing a single-byte read sequence, the following should work:

i2c.SendNacks()
i2c.Start()
data = i2c.Read(1)
i2c.Stop()

For multiple bytes where you want ACKs on all but the last byte, this should 
work:

i2c.SendAcks()           # Always send ACKs
i2c.Start()
data = i2c.Read(3)     # Read the first three bytes
i2c.SendNacks()         # From here on out, send NACKs
data += i2c.Read(1)  # Read the last byte
i2c.Stop()

Is this not the case? Regardless, your solution is probably more convenient as 
sending a NACK on the last byte read is a fairly common operation.

Original comment by heffne...@gmail.com on 1 Oct 2013 at 7:11