Skip to content

i2c has incorrect timing, causing i2c communication to not function #365

Description

@phsdv

According to https://www.nxp.com/docs/en/user-guide/UM10204.pdf section 3.1.3: The data on the SDA line must be stable during the HIGH period of the clock. The HIGH or LOW state of the data line can only change when the clock signal on the SCL line is LOW

However in the code (tools/communication/src/i2c.cpp) both SDA and SCL are changing at the same time, which is a violation of the standard. Therefore i2c communication does not work, at least not with the devices I tested.

In writeBit for example, the SCL must be low, then SDA can change, and after a little time the SCL can go high, wait half a clock cycle then SCL can go low again.

In below image it can be seen that SCL in SDA change at the same time (using libiio 0.25 and libm2k 0.8.0)
afbeelding

[edit]this concerns the i2c in the tools / digital communications. My code that generated above image is based on https://github.com/analogdevicesinc/libm2k/blob/master/bindings/python/examples/i2c.py
[edit2] clarified which code and fixed a typo 'now' -> 'not'

proposal for improvement:
The code for writeBit in tools/communication/src/i2c.cpp should be something like shown below, as SDA should already be valid before SCL goes high. As there are now 4 changes per sample, samplesPerHalfBit might need to be changed and I renamed it to samplesPerQuartBit. Further it would be clearer if writebyte calls writebit 8 times and then only this change has to be made.

static void writeBit(struct i2c_desc *desc, std::vector<unsigned short> &buffer, bool bit)
{
	auto *m2KI2CDesc = (m2k_i2c_desc *) desc->extra;
	auto samplesPerQuartBit = (unsigned int) (m2KI2CDesc->sample_rate / desc->max_speed_hz) / 4;
	//scl LOW
	for (unsigned int i = 0; i < samplesPerQuartBit; ++i) {
		unsigned short sample = 0;
		if (bit) {
			setBit(sample, m2KI2CDesc->sda);
		}
		buffer.push_back(sample);
	}
	//scl HIGH for 2 quarts
	for (unsigned int i = 0; i < (samplesPerQuartBit*2); ++i) {
		unsigned short sample = 0;
		setBit(sample, m2KI2CDesc->scl);
		if (bit) {
			setBit(sample, m2KI2CDesc->sda);
		}
		buffer.push_back(sample);
	}
	//scl LOW
	for (unsigned int i = 0; i < samplesPerQuartBit; ++i) {
		unsigned short sample = 0;
		if (bit) {
			setBit(sample, m2KI2CDesc->sda);
		}
		buffer.push_back(sample);
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions