@@ -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{
6464private:
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
162161void 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
279233bool 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
544487void 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