Skip to content

Commit 3cc0846

Browse files
authored
Fix adafruit#105 - make setspeed more robust
- prevent out of range I2C speeds for AVR
1 parent 8fce6cd commit 3cc0846

File tree

1 file changed

+19
-9
lines changed

1 file changed

+19
-9
lines changed

Adafruit_I2CDevice.cpp

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -264,33 +264,43 @@ bool Adafruit_I2CDevice::setSpeed(uint32_t desiredclk) {
264264
#if defined(__AVR_ATmega328__) || \
265265
defined(__AVR_ATmega328P__) // fix arduino core set clock
266266
// calculate TWBR correctly
267-
uint8_t prescaler = 1;
267+
268+
if ((F_CPU / 18) < desiredclk) {
269+
#ifdef DEBUG_SERIAL
270+
Serial.println(F("I2C.setSpeed too high."));
271+
#endif
272+
return false;
273+
}
268274
uint32_t atwbr = ((F_CPU / desiredclk) - 16) / 2;
275+
if (atwbr > 16320) {
276+
#ifdef DEBUG_SERIAL
277+
Serial.println(F("I2C.setSpeed too low."));
278+
#endif
279+
return false;
280+
}
281+
269282
if (atwbr <= 255) {
270-
prescaler = 1;
283+
atwbr /= 1;
271284
TWSR = 0x0;
272285
} else if (atwbr <= 1020) {
273286
atwbr /= 4;
274-
prescaler = 4;
275287
TWSR = 0x1;
276288
} else if (atwbr <= 4080) {
277289
atwbr /= 16;
278-
prescaler = 16;
279290
TWSR = 0x2;
280-
} else if (atwbr <= 16320) {
291+
} else { // if (atwbr <= 16320)
281292
atwbr /= 64;
282-
prescaler = 64;
283293
TWSR = 0x3;
284294
}
295+
TWBR = atwb;
296+
285297
#ifdef DEBUG_SERIAL
286298
Serial.print(F("TWSR prescaler = "));
287-
Serial.println(prescaler);
299+
Serial.println(pow(4, TWSR));
288300
Serial.print(F("TWBR = "));
289301
Serial.println(atwbr);
290302
#endif
291-
TWBR = atwbr;
292303
return true;
293-
294304
#elif (ARDUINO >= 157) && !defined(ARDUINO_STM32_FEATHER) && \
295305
!defined(TinyWireM_h)
296306
_wire->setClock(desiredclk);

0 commit comments

Comments
 (0)