mirror of https://github.com/arendst/Tasmota.git
Patch library I2Cdevlib-Core for 2.4.0-rc2
This commit is contained in:
parent
8366ee116a
commit
503a0d9f00
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue