From 36da2e4611db0b3acb0bc7e749a2e1025f2f786d Mon Sep 17 00:00:00 2001 From: lady ada Date: Sun, 31 Jul 2022 17:04:44 -0400 Subject: [PATCH 1/2] prescaler is not calculated here https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/Wire/src/utility/twi.c#L139 which means we cannot get below 30.5mhz! --- Adafruit_I2CDevice.cpp | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/Adafruit_I2CDevice.cpp b/Adafruit_I2CDevice.cpp index e95bb40..26b62f4 100644 --- a/Adafruit_I2CDevice.cpp +++ b/Adafruit_I2CDevice.cpp @@ -259,9 +259,37 @@ uint8_t Adafruit_I2CDevice::address(void) { return _addr; } * Not necessarily that the speed was achieved! */ bool Adafruit_I2CDevice::setSpeed(uint32_t desiredclk) { -#if (ARDUINO >= 157) && !defined(ARDUINO_STM32_FEATHER) && !defined(TinyWireM_h) +#if defined(__AVR__) // fix arduino core set clock + // calculate TWBR correctly + uint8_t prescaler = 1; + uint32_t atwbr = ((F_CPU / desiredclk) - 16) / 2; + if (atwbr <= 255) { + prescaler = 1; + TWSR = 0x0; + } else if (atwbr <= 1020) { + atwbr /= 4; + prescaler = 4; + TWSR = 0x1; + } else if (atwbr <= 4080) { + atwbr /= 16; + prescaler = 16; + TWSR = 0x2; + } else if (atwbr <= 16320) { + atwbr /= 64; + prescaler = 64; + TWSR = 0x3; + } +#ifdef DEBUG_SERIAL + Serial.print(F("TWSR prescaler = ")); Serial.println(prescaler); + Serial.print(F("TWBR = ")); Serial.println(atwbr); +#endif + TWBR = atwbr; + return true; + +#elif (ARDUINO >= 157) && !defined(ARDUINO_STM32_FEATHER) && !defined(TinyWireM_h) _wire->setClock(desiredclk); return true; + #else (void)desiredclk; return false; From 3e0e740d56935705f88344bacd42cc6664a4d839 Mon Sep 17 00:00:00 2001 From: lady ada Date: Sun, 31 Jul 2022 17:06:55 -0400 Subject: [PATCH 2/2] clang --- Adafruit_I2CDevice.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Adafruit_I2CDevice.cpp b/Adafruit_I2CDevice.cpp index 26b62f4..f782e23 100644 --- a/Adafruit_I2CDevice.cpp +++ b/Adafruit_I2CDevice.cpp @@ -280,13 +280,16 @@ bool Adafruit_I2CDevice::setSpeed(uint32_t desiredclk) { TWSR = 0x3; } #ifdef DEBUG_SERIAL - Serial.print(F("TWSR prescaler = ")); Serial.println(prescaler); - Serial.print(F("TWBR = ")); Serial.println(atwbr); + Serial.print(F("TWSR prescaler = ")); + Serial.println(prescaler); + Serial.print(F("TWBR = ")); + Serial.println(atwbr); #endif TWBR = atwbr; return true; -#elif (ARDUINO >= 157) && !defined(ARDUINO_STM32_FEATHER) && !defined(TinyWireM_h) +#elif (ARDUINO >= 157) && !defined(ARDUINO_STM32_FEATHER) && \ + !defined(TinyWireM_h) _wire->setClock(desiredclk); return true;