Patch library I2Cdevlib-Core for 2.4.0-rc2

This commit is contained in:
arendst 2017-11-22 10:57:39 +01:00
parent 8366ee116a
commit 503a0d9f00
1 changed files with 66 additions and 63 deletions

View File

@ -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) {