pasko-zh / brzo_i2c

Brzo I2C is a fast I2C Implementation written in Assembly for the esp8266
GNU General Public License v3.0
244 stars 47 forks source link

write/read should allow to send/read from any position in the buffer #2

Closed pasko-zh closed 8 years ago

pasko-zh commented 8 years ago

brzo_i2c_write/read(uint8_t *data, uint8_t no_of_bytes, boolean repeated_start) expects a pointer to a buffer *data. It then always sends/reads the no_of_bytes starting from the beginning of the buffer, i.e. data[0] ... data[no_of_bytes - 1].

Instead, brzo_i2c_write/read should allow that any pointer to an elemen (of array of byte) is passed to it and that this then taken as the base address from which no_of_bytes is sent/read. E.g., brzo_i2c_write(&buffer[4], 5, true) would send 5 bytes starting from buffer[4]

pasko-zh commented 8 years ago

@FWeinb I cannot reproduce your issue.

Today I had some time to look at the library again. It should be fine already in the current version: If you do brzo_i2c_write(buffer, 2, false), it will actually pass &buffer[0]. You can also do for instance brzo_i2c_write(&buffer[5], 2, false). Now, inside the function brzo_i2c_write referring to data[0] is relative to the base pointer passed to brzo_i2c_write(uint8_t *data ...: In the former case data[0] refers to buffer[0] in the latter to buffer[5]. Since I was not 100% sure, if everything is fine with the inline assembly too, I ran some tests today. But it should be fine. Can you confirm this? Or, if you still have the issue, drop me your code, so that I can check it again. Thanks

I did the tests with an ADT7420, here is the full code:

#include "brzo_i2c\brzo_i2c.h"

uint8_t SDA_PIN = 5;
uint8_t SCL_PIN = 4;
uint8_t ADT7420_ADR = 0x49;
uint8_t buffer[10];
uint8_t error = 0;
float temp = 0.0;

uint8_t ICACHE_RAM_ATTR get_temp_celsius(float *t) {
    uint32_t ADC_code = 0;
    uint8_t bcode = 0;

    brzo_i2c_start_transaction(ADT7420_ADR, 400);
        buffer[0] = 0x03;
        buffer[1] = 0xA0;

        buffer[5] = 0x03;
        buffer[6] = 0xA0;

        // sends buffer[0] and buffer[1]
        brzo_i2c_write(buffer, 2, false);

        // Works, too: I.e. sends buffer[5] and buffer[6]
        brzo_i2c_write(&buffer[5], 2, false);

        buffer[0] = 0x00;
        brzo_i2c_write(buffer, 1, true);
        brzo_i2c_read(buffer, 2, false);
    bcode = brzo_i2c_end_transaction();

    if (bcode == 0) {
        ADC_code = ((buffer[0] << 8) | buffer[1]);
        *t = ADC_code / 128.0;
        return 0;
    }
    else return bcode;
}

void setup() {
    delay(1000);
    Serial.begin(115200);
    brzo_i2c_setup(SDA_PIN, SCL_PIN, 2000);
}

void loop() {
    Serial.println("Waiting 5 seconds...");
    delay(5000);
    error = get_temp_celsius(&temp);
    if (error == 0) {
        Serial.print("Temp = ");
        Serial.println(temp, 8);
    }
    else {
        Serial.print("Brzo error : ");
        Serial.println(error);
    }

}
FWeinb commented 8 years ago

I will do my tests again. Thank you for investigating.

FWeinb commented 8 years ago

I tried the following for communicating with an OLED display using an SSD1306

       uint8_t sendBuffer[1];
       sendBuffer[0] = 0x40;
       brzo_i2c_start_transaction(this->_address, BRZO_I2C_SPEED);
       for (uint16_t i=0; i<DISPLAY_BUFFER_SIZE; i += 16) {
         brzo_i2c_write(sendBuffer,  1,  true);
         brzo_i2c_write(&buffer[i],  16,  true);
         yield();
       }
       brzo_i2c_end_transaction();

In this example I want to send the whole image (saved in buffer) to the display. The SSD1306 expects 0x40 every 16 bytes.

Is it supported to have to writes like that?

pasko-zh commented 8 years ago

Without having yet tested/checked your code, I think it should work (concerning the &buffer[.] issue) UDPATE: I can confirm that &buffer[.] works already with the current version 1.00.

However, after the loop has finished, the last write had a repeated START. According to the i2c specification, you should have a STOP sequence to free the bus. I.e., the last write before calling brzo_i2c_end_transaction should have no repeated start. So, most probably you are stalling the i2c bus after the loop has finished.