From c6477e2f667f7e9942e295b0a8302e4292213cab Mon Sep 17 00:00:00 2001 From: rkinnett Date: Thu, 11 May 2017 02:20:01 -0700 Subject: [PATCH 1/4] Update Wire.h to match esp8266 community latest Adds prototypes for setClockStretchLimit() and status() to TwoWire class. Wraps final TwoWire wire declaration in preexistance conditional --- libraries/Wire/Wire.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/Wire/Wire.h b/libraries/Wire/Wire.h index 9fc8f9c..e14b90a 100644 --- a/libraries/Wire/Wire.h +++ b/libraries/Wire/Wire.h @@ -56,11 +56,13 @@ class TwoWire : public Stream void begin(uint8_t); void begin(int); void setClock(uint32_t); + void setClockStretchLimit(uint32_t); void beginTransmission(uint8_t); void beginTransmission(int); uint8_t endTransmission(void); uint8_t endTransmission(uint8_t); size_t requestFrom(uint8_t address, size_t size, bool sendStop); + uint8_t status(); uint8_t requestFrom(uint8_t, uint8_t); uint8_t requestFrom(uint8_t, uint8_t, uint8_t); @@ -83,7 +85,9 @@ class TwoWire : public Stream using Print::write; }; +#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_TWOWIRE) extern TwoWire Wire; +#endif #endif From af4e9b70b05b2af134d17d1ccd1273ac65d03369 Mon Sep 17 00:00:00 2001 From: rkinnett Date: Thu, 11 May 2017 02:24:47 -0700 Subject: [PATCH 2/4] Merge Wire.cpp from esp8266 community core Added definitions for TwoWire::status() and TwoWire::setClockStretchLimit(), wrap TwoWire declaration in preexistance check --- libraries/Wire/Wire.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index c1f457a..8a48fcc 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -77,6 +77,10 @@ void TwoWire::begin(uint8_t address){ begin(); } +uint8_t TwoWire::status(){ + return twi_status(); +} + void TwoWire::begin(int address){ begin((uint8_t)address); } @@ -85,6 +89,10 @@ void TwoWire::setClock(uint32_t frequency){ twi_setClock(frequency); } +void TwoWire::setClockStretchLimit(uint32_t limit){ + twi_setClockStretchLimit(limit); +} + size_t TwoWire::requestFrom(uint8_t address, size_t size, bool sendStop){ if(size > BUFFER_LENGTH){ size = BUFFER_LENGTH; @@ -243,4 +251,6 @@ void TwoWire::onRequest( void (*function)(void) ){ // Preinstantiate Objects ////////////////////////////////////////////////////// -TwoWire Wire = TwoWire(); +#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_TWOWIRE) +TwoWire Wire; +#endif From 9e178b5f54326d907c05fd16ea9db1fb0da73976 Mon Sep 17 00:00:00 2001 From: rkinnett Date: Thu, 11 May 2017 02:28:53 -0700 Subject: [PATCH 3/4] Merge core_esp8266_si2c.c from esp8266 community core Defines twi_setClockStretch() and updates time stretch calculations as multiplier; defines twi_status(). --- cores/oak/core_esp8266_si2c.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/cores/oak/core_esp8266_si2c.c b/cores/oak/core_esp8266_si2c.c index 051b9f5..fc50c04 100644 --- a/cores/oak/core_esp8266_si2c.c +++ b/cores/oak/core_esp8266_si2c.c @@ -24,6 +24,7 @@ unsigned char twi_dcount = 18; static unsigned char twi_sda, twi_scl; +static uint32_t twi_clockStretchLimit; #define SDA_LOW() (GPES = (1 << twi_sda)) //Enable SDA (becomes output and since GPO is 0 for the pin, it will pull the line low) #define SDA_HIGH() (GPEC = (1 << twi_sda)) //Disable SDA (becomes input and since it has pullup it will go high) @@ -37,9 +38,9 @@ static unsigned char twi_sda, twi_scl; #endif #if F_CPU == FCPU80 -#define TWI_CLOCK_STRETCH 800 +#define TWI_CLOCK_STRETCH_MULTIPLIER 3 #else -#define TWI_CLOCK_STRETCH 1600 +#define TWI_CLOCK_STRETCH_MULTIPLIER 6 #endif void twi_setClock(unsigned int freq){ @@ -60,12 +61,17 @@ void twi_setClock(unsigned int freq){ #endif } +void twi_setClockStretchLimit(uint32_t limit){ + twi_clockStretchLimit = limit * TWI_CLOCK_STRETCH_MULTIPLIER; +} + void twi_init(unsigned char sda, unsigned char scl){ twi_sda = esp8266_pinToGpio[sda]; twi_scl = esp8266_pinToGpio[scl]; pinMode(sda, INPUT_PULLUP); pinMode(scl, INPUT_PULLUP); twi_setClock(100000); + twi_setClockStretchLimit(230); // default value is 230 uS } void twi_stop(void){ @@ -98,7 +104,7 @@ static bool twi_write_stop(void){ SDA_LOW(); twi_delay(twi_dcount); SCL_HIGH(); - while (SCL_READ() == 0 && (i++) < TWI_CLOCK_STRETCH);// Clock stretching (up to 100us) + while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit);// Clock stretching (up to 100us) twi_delay(twi_dcount); SDA_HIGH(); twi_delay(twi_dcount); @@ -113,7 +119,7 @@ static bool twi_write_bit(bool bit) { else SDA_LOW(); twi_delay(twi_dcount+1); SCL_HIGH(); - while (SCL_READ() == 0 && (i++) < TWI_CLOCK_STRETCH);// Clock stretching (up to 100us) + while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit);// Clock stretching (up to 100us) twi_delay(twi_dcount); return true; } @@ -124,7 +130,7 @@ static bool twi_read_bit(void) { SDA_HIGH(); twi_delay(twi_dcount+2); SCL_HIGH(); - while (SCL_READ() == 0 && (i++) < TWI_CLOCK_STRETCH);// Clock stretching (up to 100us) + while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit);// Clock stretching (up to 100us) bool bit = SDA_READ(); twi_delay(twi_dcount); return bit; @@ -190,3 +196,18 @@ unsigned char twi_readFrom(unsigned char address, unsigned char* buf, unsigned i } return 0; } + +uint8_t twi_status(){ + if (SCL_READ()==0) return I2C_SCL_HELD_LOW; //SCL held low by another device, no procedure available to recover + int clockCount = 20; + + while (SDA_READ()==0 && clockCount>0){ //if SDA low, read the bits slaves have to sent to a max + twi_read_bit(); + if (SCL_READ()==0) return I2C_SCL_HELD_LOW_AFTER_READ; //I2C bus error. SCL held low beyond slave clock stretch time + } + + if (SDA_READ()==0) return I2C_SDA_HELD_LOW; //I2C bus error. SDA line held low by slave/another_master after n bits. + + if(!twi_write_start()) return I2C_SDA_HELD_LOW_AFTER_INIT; //line busy. SDA again held low by another device. 2nd master? + else return I2C_OK; //all ok +} From 09e4d23789d37bb6cbd206ea08245e0024df1dec Mon Sep 17 00:00:00 2001 From: rkinnett Date: Thu, 11 May 2017 02:30:45 -0700 Subject: [PATCH 4/4] Merge twi.h from esp8266 community core Adds prototypes for twi_setClockStretchLimit() and twi_status(), adds I2C macros --- cores/oak/twi.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/cores/oak/twi.h b/cores/oak/twi.h index 9e661e8..543e82a 100644 --- a/cores/oak/twi.h +++ b/cores/oak/twi.h @@ -26,14 +26,22 @@ extern "C" { #endif +#define I2C_OK 0 +#define I2C_SCL_HELD_LOW 1 +#define I2C_SCL_HELD_LOW_AFTER_READ 2 +#define I2C_SDA_HELD_LOW 3 +#define I2C_SDA_HELD_LOW_AFTER_INIT 4 + void twi_init(unsigned char sda, unsigned char scl); void twi_stop(void); void twi_setClock(unsigned int freq); +void twi_setClockStretchLimit(uint32_t limit); // default value is 230 uS uint8_t twi_writeTo(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop); uint8_t twi_readFrom(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop); +uint8_t twi_status(); #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif