-
Notifications
You must be signed in to change notification settings - Fork 232
Description
I have analized your implementation of i2c driver & lua module and found some problems/bugs.
First, the whole idea of esp-idf i2c master driver implementation (i2c_cmd_link_create -> commands -> i2c_master_cmd_begin) is to place complete master<->slave communication in one transaction which includes start condition, addres/rd|wr, data r/w, [repeated start, address/rd|wr, data r/w], stop condition.
In your current implementation, the master <->slave transaction is executed after each write or read command (i2c_flush in li2c_read & li2c_write functions) and all commands after the first read|write are executed as separate transactions. In most cases it will work (specially when single slave is present on the bus), but can potentially lead to problems (specially when multiple slaves are connected to the i2c bus).
I understand that you have to issue the i2c_flush command if you want to return the single read byte, but I don't understand why it is necessary after each write
// We need to flush because data buffers are on the stack and if we // flush on the stop condition its values will be indeterminate
I would also suggest changing:
i2c_master_read(cmd, (uint8_t *)data, len, 1);
in i2c driver function i2c_read to:
if (len > 1) {
i2c_master_read(cmd, (uint8_t *)data, len-1, 0);
}
i2c_master_read_byte(cmd, (uint8_t *)(data+len-1), 1);
so that reading multiple bytes from slave can handle ACK/NACK correctly.
With current implementation, reading multiple bytes will return wrong result (tested with BME280 sensor).
I understand your desire to have low level i2c commands (start, address, read, write, stop), it is great for educational purposes, but for all practical purposes I think you should consider implementing higher level functions (send, receive, send_receive), which would handle complete master<->slave transactions with data from/to Lua string, table or numbers.
Best regards.