Skip to content

Commit e5f56eb

Browse files
author
Chuck Todd
committed
cleanup, fix another cmd[] corner, add example I2C sketch
Cull unused code, Remove Polling Mode, add correct 10bit Master Read, Found new corner condition where the cmd[] cannot have an END preceded by a START. If this START END exists, the SM will not respond to ctr.trans_start=1; A TimeOut is guaranteed. with SCL clocking and SDA LOW. Updated library.properties to V.2.0, added Keywords
1 parent b5d115e commit e5f56eb

File tree

8 files changed

+422
-705
lines changed

8 files changed

+422
-705
lines changed

cores/esp32/esp32-hal-i2c.c

Lines changed: 121 additions & 644 deletions
Large diffs are not rendered by default.

cores/esp32/esp32-hal-i2c.h

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,14 @@ typedef struct {
145145
struct i2c_struct_t;
146146
typedef struct i2c_struct_t i2c_t;
147147

148-
i2c_t * i2cInit(uint8_t i2c_num, uint16_t slave_addr, bool addr_10bit_en);
148+
i2c_t * i2cInit(uint8_t i2c_num);
149149

150150
//call this after you setup the bus and pins to send empty packet
151151
//required because when pins are attached, they emit pulses that lock the bus
152152
void i2cInitFix(i2c_t * i2c);
153153

154+
void i2cReset(i2c_t* i2c);
155+
154156
i2c_err_t i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed);
155157
uint32_t i2cGetFrequency(i2c_t * i2c);
156158

@@ -159,26 +161,15 @@ i2c_err_t i2cDetachSCL(i2c_t * i2c, int8_t scl);
159161
i2c_err_t i2cAttachSDA(i2c_t * i2c, int8_t sda);
160162
i2c_err_t i2cDetachSDA(i2c_t * i2c, int8_t sda);
161163

162-
i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint8_t len, bool sendStop);
163-
i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint8_t len, bool sendStop);
164-
//Stickbreakers attempt to read big blocks
165-
i2c_err_t pollI2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint16_t len, bool sendStop);
166-
i2c_err_t i2cProcQueue(i2c_t *i2c);
164+
//Stickbreakers ISR Support
165+
i2c_err_t i2cProcQueue(i2c_t *i2c, uint32_t *readCount);
167166
i2c_err_t i2cAddQueueWrite(i2c_t *i2c, uint16_t i2cDeviceAddr, uint8_t *dataPtr, uint16_t dataLen, bool SendStop, EventGroupHandle_t event);
168167
i2c_err_t i2cAddQueueRead(i2c_t *i2c, uint16_t i2cDeviceAddr, uint8_t *dataPtr, uint16_t dataLen, bool SendStop, EventGroupHandle_t event);
169168
i2c_err_t i2cFreeQueue(i2c_t *i2c);
170169
i2c_err_t i2cReleaseISR(i2c_t *i2c);
171-
uint16_t i2cQueueReadPendingCount(i2c_t *i2c);
172-
uint16_t i2cQueueReadCount(i2c_t *i2c);
173-
i2c_err_t i2cGetReadQueue(i2c_t *i2c, uint8_t** buffPtr, uint16_t* lenPtr,uint8_t *savePtr);
170+
//stickbreaker debug support
174171
void i2cDumpInts();
175172

176-
177-
static void IRAM_ATTR i2c_isr_handler_default(void* arg); //ISR
178-
179-
180-
void i2cReset(i2c_t* i2c);
181-
182173
#ifdef __cplusplus
183174
}
184175
#endif
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
#include <Wire.h>
2+
// Connect 4.7k pullups on SDA, SCL
3+
// for ESP32 SDA(pin 21), SCL(pin 22)
4+
// for AtMega328p SDA(Pin A5), SCL(pin A4)
5+
// for Mega2560 SDA(Pin 20), SCL(pin 21)
6+
7+
/* This sketch uses the address rollover of the 24LCxx EEPROMS to detect their size.
8+
The 24LC32 (4kByte) 0x0000 .. 0x0FFF, a Write to addres 0x1000 will actually
9+
be stored in 0x0000. This allows us to read the value of 0x0000, compare
10+
it to the value read from 0x1000, if they are different, then this IC is
11+
not a 24LC32.
12+
If the Value is the same, then we have to change the byte at 0x1000 and
13+
see if the change is reflected in 0x0000. If 0x0000 changes, then we know
14+
that the chip is a 24LC32. We have to restore the 'changed' value so that
15+
the data in the EEPROM is not compromized.
16+
17+
This pattern of read, compare, test, restore is used for each possible size.
18+
All that changes is the test Address, 0x1000, 0x2000, 0x4000, 0x8000.
19+
if the 0x8000 test is does not change, then the chip is a 24LC512.
20+
*/
21+
22+
/* after a write, the I2C device requires upto 5ms to actually program
23+
the memory cells. During this programming cycle, the IC does not respond
24+
to I2C requests. This feature 'NAK' polling is used to determine when
25+
the program cycle has completed.
26+
*/
27+
bool i2cReady(uint8_t ID){
28+
uint32_t timeout=millis();
29+
bool ready=false;
30+
while((millis()-timeout<100)&&(!ready)){
31+
Wire.beginTransmission(ID);
32+
int err=Wire.endTransmission();
33+
ready=(err==0);
34+
if(!ready){
35+
if(err!=2)Serial.printf("{%d}:%s",err,Wire.getErrorText(err));
36+
}
37+
}
38+
return ready;
39+
}
40+
41+
/* eepromSize() only works on 24LC32 .. 24LC512 eeprom,
42+
the smaller 24LC01 .. 24LC16 use one byte addressings.
43+
*/
44+
void eepromSize(){
45+
Serial.println("Discovering eeprom sizes 0x50..0x57");
46+
uint8_t ID=0x50,i;
47+
uint16_t size;
48+
char buf[256];
49+
while(ID<0x58){
50+
i=0;
51+
size = 0x1000; // Start at 4k, 16bit address devices,
52+
i += sprintf_P(&buf[i],PSTR("0x%02X: "),ID);
53+
if(i2cReady(ID)) { // EEPROM answered
54+
uint8_t zeroByte;
55+
Wire.beginTransmission(ID);
56+
Wire.write((uint8_t)0); // set address ptr to 0, two bytes High
57+
Wire.write((uint8_t)0); // set address ptr to 0, two bytes Low
58+
uint8_t err=Wire.endTransmission();
59+
if(err==0){// worked, device exists at this ID
60+
err=Wire.requestFrom(ID,(uint8_t)1);
61+
if(err==1){// got the value of the byte at address 0
62+
zeroByte=Wire.read();
63+
uint8_t saveByte,testByte;
64+
do{
65+
if(i2cReady(ID)){
66+
Wire.beginTransmission(ID);
67+
Wire.write(highByte(size)); // set next test address
68+
Wire.write(lowByte(size));
69+
Wire.endTransmission();
70+
err=Wire.requestFrom(ID,(uint8_t)1);
71+
if(err==1){
72+
saveByte=Wire.read();
73+
if(saveByte == zeroByte) { // have to test it
74+
Wire.beginTransmission(ID);
75+
Wire.write(highByte(size)); // set next test address
76+
Wire.write(lowByte(size));
77+
Wire.write((uint8_t)~zeroByte); // change it
78+
err=Wire.endTransmission();
79+
if(err==0){ // changed it
80+
if(!i2cReady(ID)){
81+
i+=sprintf_P(&buf[i],PSTR(" notReady2.\n"));
82+
Serial.print(buf);
83+
ID++;
84+
break;
85+
}
86+
Wire.beginTransmission(ID);
87+
Wire.write((uint8_t)0); // address 0 byte High
88+
Wire.write((uint8_t)0); // address 0 byte Low
89+
err=Wire.endTransmission();
90+
if(err==0){
91+
err=Wire.requestFrom(ID,(uint8_t)1);
92+
if(err==1){ // now compare it
93+
testByte=Wire.read();
94+
}
95+
else {
96+
testByte=~zeroByte; // error out
97+
}
98+
}
99+
else {
100+
testByte=~zeroByte;
101+
}
102+
}
103+
else {
104+
testByte = ~zeroByte;
105+
}
106+
107+
//restore byte
108+
if(!i2cReady(ID)){
109+
i+=sprintf_P(&buf[i],PSTR(" notReady4.\n"));
110+
Serial.print(buf);
111+
ID++;
112+
break;
113+
}
114+
Wire.beginTransmission(ID);
115+
Wire.write(highByte(size)); // set next test address
116+
Wire.write(lowByte(size));
117+
Wire.write((uint8_t)saveByte); // restore it
118+
Wire.endTransmission();
119+
}
120+
else testByte = zeroByte; // They were different so the eeprom Is Bigger
121+
}
122+
else testByte=~zeroByte;
123+
}
124+
else testByte=~zeroByte;
125+
if(testByte==zeroByte){
126+
size = size <<1;
127+
}
128+
}while((testByte==zeroByte)&&(size>0));
129+
if(size==0) i += sprintf_P(&buf[i],PSTR("64k Bytes"));
130+
else i+=sprintf_P(&buf[i],PSTR("%dk Bytes"),size/1024);
131+
if(!i2cReady(ID)){
132+
i+=sprintf_P(&buf[i],PSTR(" notReady3.\n"));
133+
Serial.print(buf);
134+
ID++;
135+
continue;
136+
}
137+
Wire.beginTransmission(ID);
138+
Wire.write((uint8_t)0); // set address ptr to 0, two bytes High
139+
Wire.write((uint8_t)0); // set address ptr to 0, two bytes Low
140+
err=Wire.endTransmission();
141+
if(err==0){
142+
err= Wire.requestFrom(ID,1);
143+
if (err==1) {
144+
testByte = Wire.read();
145+
if(testByte != zeroByte){ //fix it
146+
Wire.beginTransmission(ID);
147+
Wire.write((uint8_t)0); // set address ptr to 0, two bytes High
148+
Wire.write((uint8_t)0); // set address ptr to 0, two bytes Low
149+
Wire.write(zeroByte); //Restore
150+
err=Wire.endTransmission();
151+
}
152+
}
153+
}
154+
}
155+
else i+=sprintf_P(&buf[i],PSTR("Read 0 Failure"));
156+
}
157+
else i+=sprintf_P(&buf[i],PSTR("Write Adr 0 Failure"));
158+
159+
}
160+
else i+=sprintf_P(&buf[i],PSTR("Not Present"));
161+
Serial.println(buf);
162+
ID++;
163+
}
164+
}
165+
166+
void setup(){
167+
Serial.begin(115200);
168+
Wire.begin();
169+
eepromSize();
170+
}
171+
172+
void loop(){
173+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include <Wire.h>
2+
3+
void scan(){
4+
Serial.println("\n Scanning I2C Addresses");
5+
uint8_t cnt=0;
6+
for(uint8_t i=0;i<0x7F;i++){
7+
Wire.beginTransmission(i);
8+
uint8_t ec=Wire.endTransmission(true); // if device exists on bus, it will aCK
9+
if(ec==0){ // Device ACK'd
10+
if(i<16)Serial.print('0');
11+
Serial.print(i,HEX);
12+
cnt++;
13+
}
14+
else Serial.print(".."); // no one answered
15+
Serial.print(' ');
16+
if ((i&0x0f)==0x0f)Serial.println();
17+
}
18+
Serial.print("Scan Completed, ");
19+
Serial.print(cnt);
20+
Serial.println(" I2C Devices found.");
21+
}
22+
23+
void setup(){
24+
Serial.begin(115200);
25+
Wire.begin();
26+
scan();
27+
}
28+
29+
void loop(){
30+
}

libraries/Wire/keywords.txt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,23 @@
1212

1313
begin KEYWORD2
1414
setClock KEYWORD2
15-
setClockStretchLimit KEYWORD2
1615
beginTransmission KEYWORD2
1716
endTransmission KEYWORD2
1817
requestFrom KEYWORD2
19-
send KEYWORD2
20-
receive KEYWORD2
2118
onReceive KEYWORD2
2219
onRequest KEYWORD2
20+
requestFrom KEYWORD2
21+
writeTransaction KEYWORD2
22+
transact KEYWORD2
23+
lastError KEYWORD2
24+
getErrorText KEYWORD2
25+
write KEYWORD2
26+
read KEYWORD2
27+
available KEYWORD2
28+
peek KEYWORD2
29+
flush KEYWORD2
30+
reset KEYWORD2
31+
2332

2433
#######################################
2534
# Instances (KEYWORD2)

libraries/Wire/library.properties

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
name=Wire
2-
version=1.0
3-
author=Hristo Gochkov
4-
maintainer=Hristo Gochkov <hristo@espressif.com>
5-
sentence=Allows the communication between devices or sensors connected via Two Wire Interface Bus. For esp8266 boards.
6-
paragraph=
2+
version=2.0
3+
author=StickBreaker github.com
4+
maintainer=StickBreaker at GitHub.com
5+
sentence=V2.0 Rewritten to increase stability by using ISR methods. Allows the communication between devices or sensors connected via Two Wire Interface Bus. For esp32 boards.
6+
paragraph=The origional V1.0 was written by Hristo Gochkov <[email protected]>. This new version uses Interrupts and a better understanding of the hardware. As a side benifit of using interrupts, local buffers can now be used, allowing upto 64k-1 byte transfers. The ESP32's Hardware does not allow a naked ReStart (sendStop=false). All calls that end with sendStop=false; are Queued and only executed when a STOP is encountered (endTransmission(true),requestFrom(id,len,true)).
77
category=Signal Input/Output
8-
url=http://arduino.cc/en/Reference/Wire
8+
url=https://github.com/stickbreaker/arduino-esp32
99
architectures=esp32

0 commit comments

Comments
 (0)