i2c write fail incorrect
Deous opened this issue · comments
This part of code makes some identical oleds not to work
if (!i2c->write(address)) {
i2c->stop();
ESP_LOGE("oled", "OLED I2C bus not responding.");
goto oled_init_fail;
}
It is caused by I2C::write()
// return: true - ACK; false - NACK
bool I2C::write(uint8_t data)
{
uint8_t ibit;
bool ret;
for (ibit = 0; ibit < 8; ++ibit)
{
if (data & 0x80)
_SDA1;
else
_SDA0;
_DELAY;
_SCL1;
_DELAY;
data = data << 1;
_SCL0;
}
_SDA1;
_DELAY;
_SCL1;
_DELAY;
ret = (_SDAX == 0); // it is always 0 on some oleds
_SCL0;
_DELAY;
return ret;
}
If we ignore __SDAX==0 and return true all works fine. Might related be some incorrect protocol response
According to the datasheet of SSD1306, ACK (SDAout=0) should be sent after every byte. I guess some of the panels only connects SDAin without SDAout to SDA pin. In this situation of cause ACK should be ignored. However I don't think it's a good idea to always ignore ACK no matter whether SDAout is connected. For details please refer to pp.19 of the datasheet.
The interesting thing is - those oleds somehow work fine on Arduino libraries - particularly Adafruit.
I haven't looked deeper there because it is heavy wrapped but they do some kind of oled test before switching it on. Maybe something should be done in our case