Open phsdv opened 2 months ago
The following code works correctly for me:
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 (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);
}
}
static void writeByte(struct i2c_desc *desc, std::vector<unsigned short> &buffer, uint8_t byte)
{
for (int i = 0; i < 8; i++) {
writeBit(desc, buffer, getBit(byte, 7 - i));
}
}
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)
[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.