Optimize TasmotaSerial lib to lower iram usage

Optimize TasmotaSerial lib to lower iram usage
This commit is contained in:
Theo Arends 2019-08-29 14:22:44 +02:00
parent 002a252a28
commit 82151d25a5
7 changed files with 100 additions and 101 deletions

View File

@ -79,8 +79,8 @@ static void (*ISRList[16])() = {
TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fallback, int nwmode, int buffer_size) TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fallback, int nwmode, int buffer_size)
{ {
m_valid = false; m_valid = false;
m_hardserial = 0; m_hardserial = false;
m_hardswap = 0; m_hardswap = false;
m_stop_bits = 1; m_stop_bits = 1;
m_nwmode = nwmode; m_nwmode = nwmode;
if (!((isValidGPIOpin(receive_pin)) && (isValidGPIOpin(transmit_pin) || transmit_pin == 16))) { if (!((isValidGPIOpin(receive_pin)) && (isValidGPIOpin(transmit_pin) || transmit_pin == 16))) {
@ -90,11 +90,11 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fal
m_tx_pin = transmit_pin; m_tx_pin = transmit_pin;
m_in_pos = m_out_pos = 0; m_in_pos = m_out_pos = 0;
if (hardware_fallback && (((3 == m_rx_pin) && (1 == m_tx_pin)) || ((3 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (1 == m_tx_pin)))) { if (hardware_fallback && (((3 == m_rx_pin) && (1 == m_tx_pin)) || ((3 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (1 == m_tx_pin)))) {
m_hardserial = 1; m_hardserial = true;
} }
else if ((2 == hardware_fallback) && (((13 == m_rx_pin) && (15 == m_tx_pin)) || ((13 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (15 == m_tx_pin)))) { else if ((2 == hardware_fallback) && (((13 == m_rx_pin) && (15 == m_tx_pin)) || ((13 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (15 == m_tx_pin)))) {
m_hardserial = 1; m_hardserial = true;
m_hardswap = 1; m_hardswap = true;
} }
else { else {
if (m_rx_pin > -1) { if (m_rx_pin > -1) {
@ -104,8 +104,7 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fal
m_bit_time = ESP.getCpuFreqMHz() * 1000000 / TM_SERIAL_BAUDRATE; m_bit_time = ESP.getCpuFreqMHz() * 1000000 / TM_SERIAL_BAUDRATE;
pinMode(m_rx_pin, INPUT); pinMode(m_rx_pin, INPUT);
tms_obj_list[m_rx_pin] = this; tms_obj_list[m_rx_pin] = this;
if (m_nwmode) attachInterrupt(m_rx_pin, ISRList[m_rx_pin], CHANGE); attachInterrupt(m_rx_pin, ISRList[m_rx_pin], (m_nwmode) ? CHANGE : FALLING);
else attachInterrupt(m_rx_pin, ISRList[m_rx_pin], FALLING);
} }
if (m_tx_pin > -1) { if (m_tx_pin > -1) {
pinMode(m_tx_pin, OUTPUT); pinMode(m_tx_pin, OUTPUT);
@ -184,7 +183,7 @@ int TasmotaSerial::read()
return Serial.read(); return Serial.read();
} else { } else {
if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) return -1; if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) return -1;
uint8_t ch = m_buffer[m_out_pos]; uint32_t ch = m_buffer[m_out_pos];
m_out_pos = (m_out_pos +1) % serial_buffer_size; m_out_pos = (m_out_pos +1) % serial_buffer_size;
return ch; return ch;
} }
@ -214,19 +213,19 @@ size_t TasmotaSerial::write(uint8_t b)
} else { } else {
if (-1 == m_tx_pin) return 0; if (-1 == m_tx_pin) return 0;
if (m_high_speed) cli(); // Disable interrupts in order to get a clean transmit if (m_high_speed) cli(); // Disable interrupts in order to get a clean transmit
unsigned long wait = m_bit_time; uint32_t wait = m_bit_time;
digitalWrite(m_tx_pin, HIGH); digitalWrite(m_tx_pin, HIGH);
unsigned long start = ESP.getCycleCount(); uint32_t start = ESP.getCycleCount();
// Start bit; // Start bit;
digitalWrite(m_tx_pin, LOW); digitalWrite(m_tx_pin, LOW);
TM_SERIAL_WAIT; TM_SERIAL_WAIT;
for (int i = 0; i < 8; i++) { for (uint32_t i = 0; i < 8; i++) {
digitalWrite(m_tx_pin, (b & 1) ? HIGH : LOW); digitalWrite(m_tx_pin, (b & 1) ? HIGH : LOW);
TM_SERIAL_WAIT; TM_SERIAL_WAIT;
b >>= 1; b >>= 1;
} }
// Stop bit(s) // Stop bit(s)
for (int i = 0; i < m_stop_bits; i++) { for (uint32_t i = 0; i < m_stop_bits; i++) {
digitalWrite(m_tx_pin, HIGH); digitalWrite(m_tx_pin, HIGH);
TM_SERIAL_WAIT; TM_SERIAL_WAIT;
} }
@ -242,13 +241,13 @@ void ICACHE_RAM_ATTR TasmotaSerial::rxRead()
void TasmotaSerial::rxRead() void TasmotaSerial::rxRead()
{ {
#endif #endif
if (!m_nwmode) { if (!m_nwmode) {
// Advance the starting point for the samples but compensate for the // Advance the starting point for the samples but compensate for the
// initial delay which occurs before the interrupt is delivered // initial delay which occurs before the interrupt is delivered
unsigned long wait = m_bit_time + m_bit_time/3 - 500; uint32_t wait = m_bit_time + m_bit_time/3 - 500;
unsigned long start = ESP.getCycleCount(); uint32_t start = ESP.getCycleCount();
uint8_t rec = 0; uint8_t rec = 0;
for (int i = 0; i < 8; i++) { for (uint32_t i = 0; i < 8; i++) {
TM_SERIAL_WAIT; TM_SERIAL_WAIT;
rec >>= 1; rec >>= 1;
if (digitalRead(m_rx_pin)) rec |= 0x80; if (digitalRead(m_rx_pin)) rec |= 0x80;
@ -260,7 +259,7 @@ if (!m_nwmode) {
TM_SERIAL_WAIT; TM_SERIAL_WAIT;
} }
// Store the received value in the buffer unless we have an overflow // Store the received value in the buffer unless we have an overflow
unsigned int next = (m_in_pos+1) % serial_buffer_size; uint32_t next = (m_in_pos+1) % serial_buffer_size;
if (next != (int)m_out_pos) { if (next != (int)m_out_pos) {
m_buffer[m_in_pos] = rec; m_buffer[m_in_pos] = rec;
m_in_pos = next; m_in_pos = next;
@ -268,63 +267,63 @@ if (!m_nwmode) {
// Must clear this bit in the interrupt register, // Must clear this bit in the interrupt register,
// it gets set even when interrupts are disabled // it gets set even when interrupts are disabled
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << m_rx_pin); GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << m_rx_pin);
} else { } else {
uint8_t diff; uint32_t diff;
uint8_t level; uint32_t level;
#define LASTBIT 9 #define LASTBIT 9
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << m_rx_pin); GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << m_rx_pin);
level=digitalRead(m_rx_pin); level = digitalRead(m_rx_pin);
if (!level && !ss_index) { if (!level && !ss_index) {
// start condition // start condition
ss_bstart=ESP.getCycleCount()-(m_bit_time/4); ss_bstart = ESP.getCycleCount() - (m_bit_time / 4);
ss_byte=0; ss_byte = 0;
ss_index++; ss_index++;
//digitalWrite(1, LOW); //digitalWrite(1, LOW);
} else { } else {
// now any bit changes go here // now any bit changes go here
// calc bit number // calc bit number
diff=(ESP.getCycleCount()-ss_bstart)/m_bit_time; diff = (ESP.getCycleCount() - ss_bstart) / m_bit_time;
//digitalWrite(1, level); //digitalWrite(1, level);
if (!level && diff>LASTBIT) { if (!level && diff > LASTBIT) {
// start bit of next byte, store and restart // start bit of next byte, store and restart
// leave irq at change // leave irq at change
for (uint8_t i=ss_index;i<=LASTBIT;i++) { for (uint32_t i = ss_index; i <= LASTBIT; i++) {
ss_byte|=(1<<i); ss_byte |= (1 << i);
} }
//stobyte(0,ssp->ss_byte>>1); //stobyte(0,ssp->ss_byte>>1);
unsigned int next = (m_in_pos+1) % serial_buffer_size; uint32_t next = (m_in_pos + 1) % serial_buffer_size;
if (next != (int)m_out_pos) { if (next != (uint32_t)m_out_pos) {
m_buffer[m_in_pos] = ss_byte>>1; m_buffer[m_in_pos] = ss_byte >> 1;
m_in_pos = next; m_in_pos = next;
} }
ss_bstart=ESP.getCycleCount()-(m_bit_time/4); ss_bstart = ESP.getCycleCount() - (m_bit_time / 4);
ss_byte=0; ss_byte = 0;
ss_index=1; ss_index = 1;
return; return;
} }
if (diff>=LASTBIT) { if (diff >= LASTBIT) {
// bit zero was 0, // bit zero was 0,
//stobyte(0,ssp->ss_byte>>1); //stobyte(0,ssp->ss_byte>>1);
unsigned int next = (m_in_pos+1) % serial_buffer_size; uint32_t next = (m_in_pos + 1) % serial_buffer_size;
if (next != (int)m_out_pos) { if (next != (uint32_t)m_out_pos) {
m_buffer[m_in_pos] = ss_byte>>1; m_buffer[m_in_pos] = ss_byte >> 1;
m_in_pos = next; m_in_pos = next;
} }
ss_byte=0; ss_byte = 0;
ss_index=0; ss_index = 0;
} else { } else {
// shift in // shift in
for (uint8_t i=ss_index;i<diff;i++) { for (uint32_t i = ss_index; i < diff; i++) {
if (!level) ss_byte|=(1<<i); if (!level) ss_byte |= (1 << i);
}
ss_index = diff;
} }
ss_index=diff;
} }
} }
} }
}

View File

@ -20,7 +20,7 @@
#ifndef TasmotaSerial_h #ifndef TasmotaSerial_h
#define TasmotaSerial_h #define TasmotaSerial_h
/*********************************************************************************************\ /*********************************************************************************************\
* TasmotaSerial supports up to 115200 baud with fixed buffer size of 64 bytes using optional no iram * TasmotaSerial supports up to 115200 baud with default buffer size of 64 bytes using optional no iram
* *
* Based on EspSoftwareSerial v3.4.3 by Peter Lerup (https://github.com/plerup/espsoftwareserial) * Based on EspSoftwareSerial v3.4.3 by Peter Lerup (https://github.com/plerup/espsoftwareserial)
\*********************************************************************************************/ \*********************************************************************************************/
@ -38,7 +38,7 @@
class TasmotaSerial : public Stream { class TasmotaSerial : public Stream {
public: public:
TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fallback = 0,int nwmode = 0, int buffer_size = TM_SERIAL_BUFFER_SIZE); TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fallback = 0, int nwmode = 0, int buffer_size = TM_SERIAL_BUFFER_SIZE);
virtual ~TasmotaSerial(); virtual ~TasmotaSerial();
bool begin(long speed, int stop_bits = 1); bool begin(long speed, int stop_bits = 1);
@ -60,22 +60,22 @@ class TasmotaSerial : public Stream {
size_t txWrite(uint8_t byte); size_t txWrite(uint8_t byte);
// Member variables // Member variables
int m_rx_pin;
int m_tx_pin;
uint32_t m_stop_bits;
uint32_t ss_byte;
uint32_t ss_bstart;
uint32_t ss_index;
uint32_t m_bit_time;
uint32_t m_in_pos;
uint32_t m_out_pos;
uint32_t serial_buffer_size;
bool m_valid; bool m_valid;
bool m_nwmode; bool m_nwmode;
bool m_hardserial; bool m_hardserial;
bool m_hardswap; bool m_hardswap;
bool m_high_speed; bool m_high_speed;
int m_rx_pin;
int m_tx_pin;
int m_stop_bits;
int ss_byte;
unsigned long ss_bstart;
int ss_index;
unsigned long m_bit_time;
unsigned int m_in_pos;
unsigned int m_out_pos;
uint8_t *m_buffer; uint8_t *m_buffer;
int serial_buffer_size;
}; };
#endif // TasmotaSerial_h #endif // TasmotaSerial_h