Skip to content

Commit 3197d2a

Browse files
Tech-TXdevyte
authored andcommitted
Issue2524 allow clocks below 100KHz (#6934)
* change bus clock (busywait) to be programmable [issue 2524], remove unused slave STOP function * change bus clock (busywait) to be programmable [issue 2524], remove unused slave STOP function * change bus clock (busywait) to be programmable [issue 2524], remove unused slave STOP function * correct for underflow < 233Hz * change bus clock (busywait) to be programmable [issue 2524], convert tabs to spaces * updated minimum I2C speed for calculated bus clock
1 parent 809e5c9 commit 3197d2a

File tree

1 file changed

+39
-102
lines changed

1 file changed

+39
-102
lines changed

cores/esp8266/core_esp8266_si2c.cpp

+39-102
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ extern "C" {
4040
{
4141
GPEC = (1 << twi_sda);
4242
}
43-
static inline __attribute__((always_inline)) bool SDA_READ(const int twi_sda)
44-
{
43+
static inline __attribute__((always_inline)) bool SDA_READ(const int twi_sda)
44+
{
4545
return (GPI & (1 << twi_sda)) != 0;
4646
}
4747
static inline __attribute__((always_inline)) void SCL_LOW(const int twi_scl)
@@ -52,8 +52,8 @@ extern "C" {
5252
{
5353
GPEC = (1 << twi_scl);
5454
}
55-
static inline __attribute__((always_inline)) bool SCL_READ(const int twi_scl)
56-
{
55+
static inline __attribute__((always_inline)) bool SCL_READ(const int twi_scl)
56+
{
5757
return (GPI & (1 << twi_scl)) != 0;
5858
}
5959

@@ -63,7 +63,7 @@ class Twi
6363
{
6464
private:
6565
unsigned int preferred_si2c_clock = 100000;
66-
unsigned char twi_dcount = 18;
66+
uint32_t twi_dcount = 18;
6767
unsigned char twi_sda = 0;
6868
unsigned char twi_scl = 0;
6969
unsigned char twi_addr = 0;
@@ -112,7 +112,7 @@ class Twi
112112
bool _slaveEnabled = false;
113113

114114
// Internal use functions
115-
void ICACHE_RAM_ATTR busywait(unsigned char v);
115+
void ICACHE_RAM_ATTR busywait(unsigned int v);
116116
bool write_start(void);
117117
bool write_stop(void);
118118
bool write_bit(bool bit);
@@ -148,7 +148,6 @@ class Twi
148148
void attachSlaveRxEvent(void (*function)(uint8_t*, size_t));
149149
void attachSlaveTxEvent(void (*function)(void));
150150
void ICACHE_RAM_ATTR reply(uint8_t ack);
151-
void ICACHE_RAM_ATTR stop(void);
152151
void ICACHE_RAM_ATTR releaseBus(void);
153152
void enableSlave();
154153
};
@@ -161,65 +160,25 @@ static Twi twi;
161160

162161
void Twi::setClock(unsigned int freq)
163162
{
163+
if (freq < 1000) // minimum freq 1000Hz to minimize slave timeouts and WDT resets
164+
freq = 1000;
165+
164166
preferred_si2c_clock = freq;
167+
165168
#if F_CPU == FCPU80
166-
if (freq <= 50000)
167-
{
168-
twi_dcount = 38; //about 50KHz
169-
}
170-
else if (freq <= 100000)
171-
{
172-
twi_dcount = 19; //about 100KHz
173-
}
174-
else if (freq <= 200000)
175-
{
176-
twi_dcount = 8; //about 200KHz
177-
}
178-
else if (freq <= 300000)
179-
{
180-
twi_dcount = 3; //about 300KHz
181-
}
182-
else if (freq <= 400000)
183-
{
184-
twi_dcount = 1; //about 400KHz
185-
}
186-
else
187-
{
188-
twi_dcount = 1; //about 400KHz
189-
}
169+
170+
if (freq > 400000)
171+
freq = 400000;
172+
twi_dcount = (500000000 / freq); // half-cycle period in ns
173+
twi_dcount = (1000*(twi_dcount - 1120)) / 62500; // (half cycle - overhead) / busywait loop time
174+
190175
#else
191-
if (freq <= 50000)
192-
{
193-
twi_dcount = 64; //about 50KHz
194-
}
195-
else if (freq <= 100000)
196-
{
197-
twi_dcount = 32; //about 100KHz
198-
}
199-
else if (freq <= 200000)
200-
{
201-
twi_dcount = 14; //about 200KHz
202-
}
203-
else if (freq <= 300000)
204-
{
205-
twi_dcount = 8; //about 300KHz
206-
}
207-
else if (freq <= 400000)
208-
{
209-
twi_dcount = 5; //about 400KHz
210-
}
211-
else if (freq <= 500000)
212-
{
213-
twi_dcount = 3; //about 500KHz
214-
}
215-
else if (freq <= 600000)
216-
{
217-
twi_dcount = 2; //about 600KHz
218-
}
219-
else
220-
{
221-
twi_dcount = 1; //about 700KHz
222-
}
176+
177+
if (freq > 800000)
178+
freq = 800000;
179+
twi_dcount = (500000000 / freq); // half-cycle period in ns
180+
twi_dcount = (1000*(twi_dcount - 560)) / 31250; // (half cycle - overhead) / busywait loop time
181+
223182
#endif
224183
}
225184

@@ -262,18 +221,13 @@ void Twi::enableSlave()
262221
}
263222
}
264223

265-
void ICACHE_RAM_ATTR Twi::busywait(unsigned char v)
224+
void ICACHE_RAM_ATTR Twi::busywait(unsigned int v)
266225
{
267226
unsigned int i;
268-
#pragma GCC diagnostic push
269-
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
270-
unsigned int reg;
271-
for (i = 0; i < v; i++)
227+
for (i = 0; i < v; i++) // loop time is 5 machine cycles: 31.25ns @ 160MHz, 62.5ns @ 80MHz
272228
{
273-
reg = GPI;
229+
asm("nop"); // minimum element to keep GCC from optimizing this function out.
274230
}
275-
(void)reg;
276-
#pragma GCC diagnostic pop
277231
}
278232

279233
bool Twi::write_start(void)
@@ -518,35 +472,24 @@ void ICACHE_RAM_ATTR Twi::reply(uint8_t ack)
518472
if (ack)
519473
{
520474
//TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
521-
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
522-
twi_ack = 1; // _BV(TWEA)
475+
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
476+
twi_ack = 1; // _BV(TWEA)
523477
}
524478
else
525479
{
526480
//TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT);
527-
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
528-
twi_ack = 0; // ~_BV(TWEA)
481+
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
482+
twi_ack = 0; // ~_BV(TWEA)
529483
}
530484
}
531485

532-
void ICACHE_RAM_ATTR Twi::stop(void)
533-
{
534-
// send stop condition
535-
//TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
536-
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
537-
twi_ack = 1; // _BV(TWEA)
538-
busywait(5); // Maybe this should be here
539-
SDA_HIGH(twi.twi_sda); // _BV(TWSTO)
540-
// update twi state
541-
twi_state = TWI_READY;
542-
}
543486

544487
void ICACHE_RAM_ATTR Twi::releaseBus(void)
545488
{
546489
// release bus
547490
//TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
548-
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
549-
twi_ack = 1; // _BV(TWEA)
491+
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
492+
twi_ack = 1; // _BV(TWEA)
550493
SDA_HIGH(twi.twi_sda);
551494

552495
// update twi state
@@ -657,7 +600,6 @@ void ICACHE_RAM_ATTR Twi::onTwipEvent(uint8_t status)
657600
break;
658601
case TW_BUS_ERROR: // bus error, illegal stop/start
659602
twi_error = TW_BUS_ERROR;
660-
stop();
661603
break;
662604
}
663605
}
@@ -718,11 +660,11 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
718660
unsigned int scl;
719661

720662
// Store bool return in int to reduce final code size.
721-
663+
722664
sda = SDA_READ(twi.twi_sda);
723665
scl = SCL_READ(twi.twi_scl);
724666

725-
twi.twip_status = 0xF8; // reset TWI status
667+
twi.twip_status = 0xF8; // reset TWI status
726668

727669
int twip_state_mask = S2M(twi.twip_state);
728670
IFSTATE(S2M(TWIP_START) | S2M(TWIP_REP_START) | S2M(TWIP_SLA_W) | S2M(TWIP_READ))
@@ -797,7 +739,7 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
797739
}
798740
else
799741
{
800-
SCL_LOW(twi.twi_scl); // clock stretching
742+
SCL_LOW(twi.twi_scl); // clock stretching
801743
SDA_HIGH(twi.twi_sda);
802744
twi.twip_mode = TWIPM_ADDRESSED;
803745
if (!(twi.twi_data & 0x01))
@@ -815,7 +757,7 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
815757
}
816758
else
817759
{
818-
SCL_LOW(twi.twi_scl); // clock stretching
760+
SCL_LOW(twi.twi_scl); // clock stretching
819761
SDA_HIGH(twi.twi_sda);
820762
if (!twi.twi_ack)
821763
{
@@ -893,7 +835,7 @@ void ICACHE_RAM_ATTR Twi::onSclChange(void)
893835
}
894836
else
895837
{
896-
SCL_LOW(twi.twi_scl); // clock stretching
838+
SCL_LOW(twi.twi_scl); // clock stretching
897839
if (twi.twi_ack && twi.twi_ack_rec)
898840
{
899841
twi.onTwipEvent(TW_ST_DATA_ACK);
@@ -939,7 +881,7 @@ void ICACHE_RAM_ATTR Twi::onSdaChange(void)
939881
else IFSTATE(S2M(TWIP_START) | S2M(TWIP_REP_START) | S2M(TWIP_SEND_ACK) | S2M(TWIP_WAIT_ACK) | S2M(TWIP_SLA_R) | S2M(TWIP_REC_ACK) | S2M(TWIP_READ_ACK) | S2M(TWIP_RWAIT_ACK) | S2M(TWIP_WRITE))
940882
{
941883
// START or STOP
942-
SDA_HIGH(twi.twi_sda); // Should not be necessary
884+
SDA_HIGH(twi.twi_sda); // Should not be necessary
943885
twi.onTwipEvent(TW_BUS_ERROR);
944886
twi.twip_mode = TWIPM_WAIT;
945887
twi.twip_state = TWIP_BUS_ERR;
@@ -949,7 +891,7 @@ void ICACHE_RAM_ATTR Twi::onSdaChange(void)
949891
if (sda)
950892
{
951893
// STOP
952-
SCL_LOW(twi.twi_scl); // clock stretching
894+
SCL_LOW(twi.twi_scl); // generates a low SCL pulse after STOP
953895
ets_timer_disarm(&twi.timer);
954896
twi.twip_state = TWIP_IDLE;
955897
twi.twip_mode = TWIPM_IDLE;
@@ -983,7 +925,7 @@ void ICACHE_RAM_ATTR Twi::onSdaChange(void)
983925
else
984926
{
985927
// during first bit in byte transfer - ok
986-
SCL_LOW(twi.twi_scl); // clock stretching
928+
SCL_LOW(twi.twi_scl); // clock stretching
987929
twi.onTwipEvent(TW_SR_STOP);
988930
if (sda)
989931
{
@@ -1018,11 +960,6 @@ extern "C" {
1018960
return twi.setAddress(a);
1019961
}
1020962

1021-
void twi_stop(void)
1022-
{
1023-
twi.stop();
1024-
}
1025-
1026963
void twi_setClock(unsigned int freq)
1027964
{
1028965
twi.setClock(freq);

0 commit comments

Comments
 (0)