Skip to content

Commit

Permalink
tools/i2c: Ensure SDA stability during SCL transitions
Browse files Browse the repository at this point in the history
- Modified SDA to transition 1/4 Tbit earlier, ensuring data stability when SCL is high.
- Adjusted the early transition in the start condition to leverage the open drain configuration of I2C, which ensures both lines are high initially.

Resolves issue #365

Signed-off-by: Adrian Stanea <Adrian.Stanea@analog.com>
  • Loading branch information
Adrian-Stanea committed Aug 2, 2024
1 parent 06d96a3 commit 87db378
Showing 1 changed file with 38 additions and 39 deletions.
77 changes: 38 additions & 39 deletions tools/communication/src/i2c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,23 @@ typedef struct i2c_data {
static void writeStartCondition(struct i2c_desc *desc, std::vector<unsigned short> &buffer)
{
auto *m2KI2CDesc = (m2k_i2c_desc *) desc->extra;
auto samplesPerBit = (unsigned int) (m2KI2CDesc->sample_rate / desc->max_speed_hz);
//scl low, sda high - avoid to be interpreted as a stop condition
for (unsigned int i = 0; i < samplesPerBit; ++i) {
unsigned short sample = 0;
setBit(sample, m2KI2CDesc->sda);
buffer.push_back(sample);
}
//both high
for (unsigned int i = 0; i < samplesPerBit; ++i) {
auto samplesPerQuarterBit = (unsigned int) (m2KI2CDesc->sample_rate / desc->max_speed_hz) / 4;

//scl high, sda high
for (unsigned int i = 0; i < samplesPerQuarterBit*2; ++i) {
unsigned short sample = 0;
setBit(sample, m2KI2CDesc->scl);
setBit(sample, m2KI2CDesc->sda);
buffer.push_back(sample);
}
//scl high, sda low
for (unsigned int i = 0; i < samplesPerBit; ++i) {
for (unsigned int i = 0; i < samplesPerQuarterBit*2; ++i) {
unsigned short sample = 0;
setBit(sample, m2KI2CDesc->scl);
buffer.push_back(sample);
}
//both low
for (unsigned int i = 0; i < samplesPerBit; ++i) {
//scL low, sda low
for (unsigned int i = 0; i < samplesPerQuarterBit*4; ++i) {
unsigned short sample = 0;
buffer.push_back(sample);
}
Expand All @@ -63,15 +58,21 @@ static void writeStartCondition(struct i2c_desc *desc, std::vector<unsigned shor
static void writeStopCondition(struct i2c_desc *desc, std::vector<unsigned short> &buffer)
{
auto *m2KI2CDesc = (m2k_i2c_desc *) desc->extra;
auto samplesPerBit = (unsigned int) (m2KI2CDesc->sample_rate / desc->max_speed_hz);
auto samplesPerQuarterBit = (unsigned int) (m2KI2CDesc->sample_rate / desc->max_speed_hz) / 4;

//scl low, sda low
for (unsigned int i = 0; i < samplesPerQuarterBit*2; ++i) {
unsigned short sample = 0;
buffer.push_back(sample);
}
//scl high, sda low
for (unsigned int i = 0; i < samplesPerBit; ++i) {
for (unsigned int i = 0; i < samplesPerQuarterBit * 2; ++i) {
unsigned short sample = 0;
setBit(sample, m2KI2CDesc->scl);
buffer.push_back(sample);
}
//both high
for (unsigned int i = 0; i < samplesPerBit; ++i) {
//scl high, sda high
for (unsigned int i = 0; i < samplesPerQuarterBit * 4; ++i) {
unsigned short sample = 0;
setBit(sample, m2KI2CDesc->scl);
setBit(sample, m2KI2CDesc->sda);
Expand All @@ -81,19 +82,29 @@ static void writeStopCondition(struct i2c_desc *desc, std::vector<unsigned short

static void writeBit(struct i2c_desc *desc, std::vector<unsigned short> &buffer, bool bit)
{
//during data transmission, SDA transitions must occur only when SCL is low
auto *m2KI2CDesc = (m2k_i2c_desc *) desc->extra;
auto samplesPerHalfBit = (unsigned int) (m2KI2CDesc->sample_rate / desc->max_speed_hz) / 2;
//scl high
for (unsigned int i = 0; i < samplesPerHalfBit; ++i) {
auto samplesPerQuarterBit = (unsigned int) (m2KI2CDesc->sample_rate / desc->max_speed_hz) / 4;

//sda transition; scl low
for (unsigned int i = 0; i < samplesPerQuarterBit; ++i) {
unsigned short sample = 0;
if (bit) {
setBit(sample, m2KI2CDesc->sda);
}
buffer.push_back(sample);
}
//sda stable; scl high
for (unsigned int i = 0; i < samplesPerQuarterBit*2; ++i) {
unsigned short sample = 0;
setBit(sample, m2KI2CDesc->scl);
if (bit) {
setBit(sample, m2KI2CDesc->sda);
}
setBit(sample, m2KI2CDesc->scl);
buffer.push_back(sample);
}
//scl low
for (unsigned int i = 0; i < samplesPerHalfBit; ++i) {
//sda stable; scl low for next bit
for (unsigned int i = 0; i < samplesPerQuarterBit; ++i) {
unsigned short sample = 0;
if (bit) {
setBit(sample, m2KI2CDesc->sda);
Expand All @@ -104,23 +115,11 @@ static void writeBit(struct i2c_desc *desc, std::vector<unsigned short> &buffer,

static void writeByte(struct i2c_desc *desc, std::vector<unsigned short> &buffer, uint8_t byte)
{
auto *m2KI2CDesc = (m2k_i2c_desc *) desc->extra;
auto samplesPerHalfBit = (unsigned int) (m2KI2CDesc->sample_rate / desc->max_speed_hz) / 2;
bool clockPolarity = true;

for (int i = 0; i < 16; i++) {
//encode data
for (unsigned int j = 0; j < samplesPerHalfBit; ++j) {
unsigned short sample = 0;
if (clockPolarity) {
setBit(sample, m2KI2CDesc->scl);
}
if (getBit(byte, 7 - (i / 2))) {
setBit(sample, m2KI2CDesc->sda);
}
buffer.push_back(sample);
}
clockPolarity = !clockPolarity;
//transmit the most significant bits of the byte first
const size_t BITS_IN_BYTE = 8;
for (size_t i = 0; i < BITS_IN_BYTE; i++) {
auto bit = getBit(byte, 7 - i);
writeBit(desc, buffer, bit);
}
}

Expand Down

0 comments on commit 87db378

Please sign in to comment.