From 503a0d9f00fb0ebec6336b37d393c02dace0ad2c Mon Sep 17 00:00:00 2001 From: arendst Date: Wed, 22 Nov 2017 10:57:39 +0100 Subject: [PATCH] Patch library I2Cdevlib-Core for 2.4.0-rc2 --- lib/I2Cdevlib-Core/I2Cdev.cpp | 129 +++++++++++++++++----------------- 1 file changed, 66 insertions(+), 63 deletions(-) diff --git a/lib/I2Cdevlib-Core/I2Cdev.cpp b/lib/I2Cdevlib-Core/I2Cdev.cpp index db173b55a..676f6cfd3 100644 --- a/lib/I2Cdevlib-Core/I2Cdev.cpp +++ b/lib/I2Cdevlib-Core/I2Cdev.cpp @@ -45,6 +45,9 @@ THE SOFTWARE. #include "I2Cdev.h" +// Tasmota fixes for esp8266-core v2.4.0-rc2 +#define i2min(a,b) ((a)<(b)?(a):(b)) + #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #ifdef I2CDEV_IMPLEMENTATION_WARNINGS @@ -225,12 +228,12 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // I2C/TWI subsystem uses internal buffer that breaks with large data requests // so if user requests more than BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length; k += i2min(length, BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.send(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); + Wire.requestFrom(devAddr, (uint8_t)i2min(length - k, BUFFER_LENGTH)); for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.receive(); @@ -249,13 +252,13 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // I2C/TWI subsystem uses internal buffer that breaks with large data requests // so if user requests more than BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length; k += i2min(length, BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); - + Wire.requestFrom(devAddr, (uint8_t)i2min(length - k, BUFFER_LENGTH)); + for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.read(); #ifdef I2CDEV_SERIAL_DEBUG @@ -263,7 +266,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 if (count + 1 < length) Serial.print(" "); #endif } - + Wire.endTransmission(); } #elif (ARDUINO > 100) @@ -273,13 +276,13 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // I2C/TWI subsystem uses internal buffer that breaks with large data requests // so if user requests more than BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length; k += i2min(length, BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); - + Wire.requestFrom(devAddr, (uint8_t)i2min(length - k, BUFFER_LENGTH)); + for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.read(); #ifdef I2CDEV_SERIAL_DEBUG @@ -345,13 +348,13 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 // I2C/TWI subsystem uses internal buffer that breaks with large data requests // so if user requests more than BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length * 2; k += i2min(length * 2, BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.send(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes - + bool msb = true; // starts with MSB, then LSB for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { if (msb) { @@ -374,17 +377,17 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 #elif (ARDUINO == 100) // Arduino v1.0.0, Wire library // Adds standardized write() and read() stream methods instead of send() and receive() - + // I2C/TWI subsystem uses internal buffer that breaks with large data requests // so if user requests more than BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length * 2; k += i2min(length * 2, BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes - + bool msb = true; // starts with MSB, then LSB for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { if (msb) { @@ -401,7 +404,7 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 } msb = !msb; } - + Wire.endTransmission(); } #elif (ARDUINO > 100) @@ -411,13 +414,13 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 // I2C/TWI subsystem uses internal buffer that breaks with large data requests // so if user requests more than BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length * 2; k += i2min(length * 2, BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes - + bool msb = true; // starts with MSB, then LSB for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { if (msb) { @@ -434,7 +437,7 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 } msb = !msb; } - + Wire.endTransmission(); } #endif @@ -463,7 +466,7 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 Serial.print(count, DEC); Serial.println(" read)."); #endif - + return count; } @@ -896,50 +899,50 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; /* call this version 1.0 - + Offhand, the only funky part that I can think of is in nbrequestFrom, where the buffer length and index are set *before* the data is actually read. The problem is that these are variables local to the TwoWire object, and by the time we actually have read the - data, and know what the length actually is, we have no simple access to the object's + data, and know what the length actually is, we have no simple access to the object's variables. The actual bytes read *is* given to the callback function, though. - + The ISR code for a slave receiver is commented out. I don't have that setup, and can't verify it at this time. Save it for 2.0! - - The handling of the read and write processes here is much like in the demo sketch code: + + The handling of the read and write processes here is much like in the demo sketch code: the process is broken down into sequential functions, where each registers the next as a callback, essentially. - - For example, for the Read process, twi_read00 just returns if TWI is not yet in a + + For example, for the Read process, twi_read00 just returns if TWI is not yet in a ready state. When there's another interrupt, and the interface *is* ready, then it sets up the read, starts it, and registers twi_read01 as the function to call after the *next* interrupt. twi_read01, then, just returns if the interface is still in a "reading" state. When the reading is done, it copies the information to the buffer, - cleans up, and calls the user-requested callback function with the actual number of + cleans up, and calls the user-requested callback function with the actual number of bytes read. - + The writing is similar. - + Questions, comments and problems can go to Gene@Telobot.com. - + Thumbs Up! Gene Knight - + */ - + uint8_t TwoWire::rxBuffer[NBWIRE_BUFFER_LENGTH]; uint8_t TwoWire::rxBufferIndex = 0; uint8_t TwoWire::rxBufferLength = 0; - + uint8_t TwoWire::txAddress = 0; uint8_t TwoWire::txBuffer[NBWIRE_BUFFER_LENGTH]; uint8_t TwoWire::txBufferIndex = 0; uint8_t TwoWire::txBufferLength = 0; - + //uint8_t TwoWire::transmitting = 0; void (*TwoWire::user_onRequest)(void); void (*TwoWire::user_onReceive)(int); - + static volatile uint8_t twi_transmitting; static volatile uint8_t twi_state; static uint8_t twi_slarw; @@ -954,7 +957,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; static volatile uint8_t twi_Done; void (*twi_cbendTransmissionDone)(int); void (*twi_cbreadFromDone)(int); - + void twi_init() { // initialize state twi_state = TWI_READY; @@ -985,7 +988,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; TWSTA - TWI Start Condition */ } - + typedef struct { uint8_t address; uint8_t* data; @@ -1006,13 +1009,13 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; twi_Return_Value = bRetVal; fNextInterruptFunction = 0; } - + uint8_t twii_WaitForDone(uint16_t timeout) { uint32_t endMillis = millis() + timeout; while (!twi_Done && (timeout == 0 || millis() < endMillis)) continue; return twi_Return_Value; } - + void twii_SetState(uint8_t ucState) { twi_state = ucState; } @@ -1062,8 +1065,8 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; if (twi_cbendTransmissionDone) return twi_cbendTransmissionDone(twi_Return_Value); return; } - - + + void twi_write00() { if (TWI_READY != twi_state) return; // blocking test if (TWI_BUFFER_LENGTH < ptwv -> length) { @@ -1080,7 +1083,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; fNextInterruptFunction = twi_write01; // next routine return twi_write01(); } - + void twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait) { uint8_t i; ptwv = (twi_Write_Vars *)malloc(sizeof(twi_Write_Vars)); @@ -1100,7 +1103,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; if (twi_cbreadFromDone) return twi_cbreadFromDone(twi_Return_Value); return; } - + void twi_read00() { if (TWI_READY != twi_state) return; // blocking test if (TWI_BUFFER_LENGTH < ptwv -> length) twi_Finish(0); // error return @@ -1133,17 +1136,17 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); } } - + void twi_stop(void) { // send stop condition TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO); - + // wait for stop condition to be exectued on bus // TWINT is not set after a stop condition! while (TWCR & _BV(TWSTO)) { continue; } - + // update twi state twi_state = TWI_READY; } @@ -1151,11 +1154,11 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; void twi_releaseBus(void) { // release bus TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT); - + // update twi state twi_state = TWI_READY; } - + SIGNAL(TWI_vect) { switch (TW_STATUS) { // All Master @@ -1165,7 +1168,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; TWDR = twi_slarw; twi_reply(1); break; - + // Master Transmitter case TW_MT_SLA_ACK: // slave receiver acked address case TW_MT_DATA_ACK: // slave receiver acked data @@ -1193,7 +1196,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; twi_error = TW_MT_ARB_LOST; twi_releaseBus(); break; - + // Master Receiver case TW_MR_DATA_ACK: // data received, ack sent // put byte into buffer @@ -1291,7 +1294,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; twi_txBufferLength = 1; twi_txBuffer[0] = 0x00; } - + // transmit first byte from buffer, fall through case TW_ST_DATA_ACK: // byte sent, ack returned @@ -1329,26 +1332,26 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; } TwoWire::TwoWire() { } - + void TwoWire::begin(void) { rxBufferIndex = 0; rxBufferLength = 0; - + txBufferIndex = 0; txBufferLength = 0; twi_init(); } - + void TwoWire::beginTransmission(uint8_t address) { //beginTransmission((uint8_t)address); // indicate that we are transmitting twi_transmitting = 1; - + // set address of targeted slave txAddress = address; - + // reset tx buffer iterator vars txBufferIndex = 0; txBufferLength = 0; @@ -1375,7 +1378,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; twi_writeTo(txAddress, txBuffer, txBufferLength, 1); return; } - + void TwoWire::send(uint8_t data) { if (twi_transmitting) { // in master transmitter mode @@ -1396,21 +1399,21 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; //twi_transmit(&data, 1); } } - + uint8_t TwoWire::receive(void) { // default to returning null char // for people using with char strings uint8_t value = 0; - + // get each successive byte on each call if (rxBufferIndex < rxBufferLength) { value = rxBuffer[rxBufferIndex]; ++rxBufferIndex; } - + return value; } - + uint8_t TwoWire::requestFrom(uint8_t address, int quantity, uint16_t timeout) { // clamp to buffer length if (quantity > NBWIRE_BUFFER_LENGTH) { @@ -1425,10 +1428,10 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; // set rx buffer iterator vars rxBufferIndex = 0; rxBufferLength = read; - + return read; } - + void TwoWire::nbrequestFrom(uint8_t address, int quantity, void (*function)(int)) { // clamp to buffer length if (quantity > NBWIRE_BUFFER_LENGTH) {