Skip to content

Commit fb05a59

Browse files
authored
improved glitch prevention, hardware reset
These changes should remove the possibility of a signal glitch when starting or restarting the Wire() object. Also, I think I have found a way to reset the i2c hardware to a Power On or Hardware Reset state.
1 parent 7c35002 commit fb05a59

File tree

1 file changed

+30
-14
lines changed

1 file changed

+30
-14
lines changed

libraries/Wire/src/Wire.cpp

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -68,32 +68,48 @@ void TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
6868
}
6969
}
7070

71+
i2cDetatchSCL(i2c,scl); // detach pins before resetting I2C perpherial
72+
i2cDetatchSDA(i2c,sda); // else a glitch will appear on the i2c bus
73+
i2c = i2cInit(num);// i2cInit() now performs a hardware reset
7174
if(i2c == NULL) {
72-
i2c = i2cInit(num);
73-
if(i2c == NULL) {
74-
return;
75-
}
76-
}
75+
return;
76+
}
7777

7878
i2cSetFrequency(i2c, frequency);
7979

80-
if(sda >= 0 && sda != sdaPin ) {
81-
i2cDetachSDA(i2c, sda);
82-
}
83-
84-
if(scl >= 0 && scl != sclPin ) {
85-
i2cDetachSCL(i2c, scl);
86-
}
87-
8880
sda = sdaPin;
8981
scl = sclPin;
82+
// 03/10/2018 test I2C bus before attach.
83+
// if the bus is not 'clear' try the recommended recovery sequence, START, 9 Clocks, STOP
84+
digitalWrite(sda,HIGH);
85+
digitalWrite(scl,HIGH);
86+
pinMode(sda,PULLUP|OPEN_DRAIN|OUTPUT|INPUT);
87+
pinMode(scl,PULLUP|OPEN_DRAIN|OUTPUT|INPUT);
88+
89+
if(!digitalRead(sda)||~digitalRead(scl)){ // bus in busy state
90+
log_d("invalid state sda=%d, scl=%d",digitalRead(sda),digitalRead(scl));
91+
digitalWrite(sda,HIGH);
92+
digitalWrite(scl,HIGH);
93+
delayMicroseconds(50);
94+
digitalWrite(sda,LOW);
95+
for(uint8_t a=0; a<9;a++){
96+
delayMicroseconds(50);
97+
digitalWrite(scl,LOW);
98+
delayMicroseconds(50);
99+
digitalWrite(scl,HIGH);
100+
}
101+
delayMicroseconds(50);
102+
digitalWrite(sda,HIGH);
103+
}
90104

91105
i2cAttachSDA(i2c, sda);
92106
i2cAttachSCL(i2c, scl);
93107

94108
flush();
95109

96-
i2cInitFix(i2c);
110+
/* This function should no longer be necessary, the
111+
i2cInitFix(i2c);
112+
*/
97113
}
98114

99115
void TwoWire::setTimeOut(uint16_t timeOutMillis){

0 commit comments

Comments
 (0)