mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
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
This commit is contained in:
parent
809e5c967a
commit
3197d2ac4e
@ -63,7 +63,7 @@ class Twi
|
||||
{
|
||||
private:
|
||||
unsigned int preferred_si2c_clock = 100000;
|
||||
unsigned char twi_dcount = 18;
|
||||
uint32_t twi_dcount = 18;
|
||||
unsigned char twi_sda = 0;
|
||||
unsigned char twi_scl = 0;
|
||||
unsigned char twi_addr = 0;
|
||||
@ -112,7 +112,7 @@ private:
|
||||
bool _slaveEnabled = false;
|
||||
|
||||
// Internal use functions
|
||||
void ICACHE_RAM_ATTR busywait(unsigned char v);
|
||||
void ICACHE_RAM_ATTR busywait(unsigned int v);
|
||||
bool write_start(void);
|
||||
bool write_stop(void);
|
||||
bool write_bit(bool bit);
|
||||
@ -148,7 +148,6 @@ public:
|
||||
void attachSlaveRxEvent(void (*function)(uint8_t*, size_t));
|
||||
void attachSlaveTxEvent(void (*function)(void));
|
||||
void ICACHE_RAM_ATTR reply(uint8_t ack);
|
||||
void ICACHE_RAM_ATTR stop(void);
|
||||
void ICACHE_RAM_ATTR releaseBus(void);
|
||||
void enableSlave();
|
||||
};
|
||||
@ -161,65 +160,25 @@ static Twi twi;
|
||||
|
||||
void Twi::setClock(unsigned int freq)
|
||||
{
|
||||
if (freq < 1000) // minimum freq 1000Hz to minimize slave timeouts and WDT resets
|
||||
freq = 1000;
|
||||
|
||||
preferred_si2c_clock = freq;
|
||||
|
||||
#if F_CPU == FCPU80
|
||||
if (freq <= 50000)
|
||||
{
|
||||
twi_dcount = 38; //about 50KHz
|
||||
}
|
||||
else if (freq <= 100000)
|
||||
{
|
||||
twi_dcount = 19; //about 100KHz
|
||||
}
|
||||
else if (freq <= 200000)
|
||||
{
|
||||
twi_dcount = 8; //about 200KHz
|
||||
}
|
||||
else if (freq <= 300000)
|
||||
{
|
||||
twi_dcount = 3; //about 300KHz
|
||||
}
|
||||
else if (freq <= 400000)
|
||||
{
|
||||
twi_dcount = 1; //about 400KHz
|
||||
}
|
||||
else
|
||||
{
|
||||
twi_dcount = 1; //about 400KHz
|
||||
}
|
||||
|
||||
if (freq > 400000)
|
||||
freq = 400000;
|
||||
twi_dcount = (500000000 / freq); // half-cycle period in ns
|
||||
twi_dcount = (1000*(twi_dcount - 1120)) / 62500; // (half cycle - overhead) / busywait loop time
|
||||
|
||||
#else
|
||||
if (freq <= 50000)
|
||||
{
|
||||
twi_dcount = 64; //about 50KHz
|
||||
}
|
||||
else if (freq <= 100000)
|
||||
{
|
||||
twi_dcount = 32; //about 100KHz
|
||||
}
|
||||
else if (freq <= 200000)
|
||||
{
|
||||
twi_dcount = 14; //about 200KHz
|
||||
}
|
||||
else if (freq <= 300000)
|
||||
{
|
||||
twi_dcount = 8; //about 300KHz
|
||||
}
|
||||
else if (freq <= 400000)
|
||||
{
|
||||
twi_dcount = 5; //about 400KHz
|
||||
}
|
||||
else if (freq <= 500000)
|
||||
{
|
||||
twi_dcount = 3; //about 500KHz
|
||||
}
|
||||
else if (freq <= 600000)
|
||||
{
|
||||
twi_dcount = 2; //about 600KHz
|
||||
}
|
||||
else
|
||||
{
|
||||
twi_dcount = 1; //about 700KHz
|
||||
}
|
||||
|
||||
if (freq > 800000)
|
||||
freq = 800000;
|
||||
twi_dcount = (500000000 / freq); // half-cycle period in ns
|
||||
twi_dcount = (1000*(twi_dcount - 560)) / 31250; // (half cycle - overhead) / busywait loop time
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -262,18 +221,13 @@ void Twi::enableSlave()
|
||||
}
|
||||
}
|
||||
|
||||
void ICACHE_RAM_ATTR Twi::busywait(unsigned char v)
|
||||
void ICACHE_RAM_ATTR Twi::busywait(unsigned int v)
|
||||
{
|
||||
unsigned int i;
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||
unsigned int reg;
|
||||
for (i = 0; i < v; i++)
|
||||
for (i = 0; i < v; i++) // loop time is 5 machine cycles: 31.25ns @ 160MHz, 62.5ns @ 80MHz
|
||||
{
|
||||
reg = GPI;
|
||||
asm("nop"); // minimum element to keep GCC from optimizing this function out.
|
||||
}
|
||||
(void)reg;
|
||||
#pragma GCC diagnostic pop
|
||||
}
|
||||
|
||||
bool Twi::write_start(void)
|
||||
@ -529,17 +483,6 @@ void ICACHE_RAM_ATTR Twi::reply(uint8_t ack)
|
||||
}
|
||||
}
|
||||
|
||||
void ICACHE_RAM_ATTR Twi::stop(void)
|
||||
{
|
||||
// send stop condition
|
||||
//TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
|
||||
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
|
||||
twi_ack = 1; // _BV(TWEA)
|
||||
busywait(5); // Maybe this should be here
|
||||
SDA_HIGH(twi.twi_sda); // _BV(TWSTO)
|
||||
// update twi state
|
||||
twi_state = TWI_READY;
|
||||
}
|
||||
|
||||
void ICACHE_RAM_ATTR Twi::releaseBus(void)
|
||||
{
|
||||
@ -657,7 +600,6 @@ void ICACHE_RAM_ATTR Twi::onTwipEvent(uint8_t status)
|
||||
break;
|
||||
case TW_BUS_ERROR: // bus error, illegal stop/start
|
||||
twi_error = TW_BUS_ERROR;
|
||||
stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -949,7 +891,7 @@ void ICACHE_RAM_ATTR Twi::onSdaChange(void)
|
||||
if (sda)
|
||||
{
|
||||
// STOP
|
||||
SCL_LOW(twi.twi_scl); // clock stretching
|
||||
SCL_LOW(twi.twi_scl); // generates a low SCL pulse after STOP
|
||||
ets_timer_disarm(&twi.timer);
|
||||
twi.twip_state = TWIP_IDLE;
|
||||
twi.twip_mode = TWIPM_IDLE;
|
||||
@ -1018,11 +960,6 @@ extern "C" {
|
||||
return twi.setAddress(a);
|
||||
}
|
||||
|
||||
void twi_stop(void)
|
||||
{
|
||||
twi.stop();
|
||||
}
|
||||
|
||||
void twi_setClock(unsigned int freq)
|
||||
{
|
||||
twi.setClock(freq);
|
||||
|
Loading…
x
Reference in New Issue
Block a user