Skip to content

Commit

Permalink
Add Hardware Serial Fallback to TasmotaSerial
Browse files Browse the repository at this point in the history
5.13.1a
* Update TasmotaSerial to 2.0.0 allowing Hardware Serial Fallback when
correct connection are configured
  • Loading branch information
arendst committed May 10, 2018
1 parent ff204a4 commit 054f1bd
Show file tree
Hide file tree
Showing 14 changed files with 131 additions and 128 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# TasmotaSerial

Implementation of software serial library for the ESP8266
Implementation of software serial with hardware serial fallback library for the ESP8266

Allows for several instances to be active at the same time.

Please note that due to the fact that the ESP always have other activities ongoing, there will be some inexactness in interrupt
timings. This may lead to bit errors when having heavy data traffic.
Please note that due to the fact that the ESP always have other activities ongoing, there will be some inexactness in interrupt timings. This may lead to bit errors when having heavy data traffic.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"name": "TasmotaSerial",
"version": "1.3.0",
"version": "2.0.0",
"keywords": [
"serial", "io", "TasmotaSerial"
],
"description": "Implementation of software serial for ESP8266.",
"description": "Implementation of software serial with hardware serial fallback for ESP8266.",
"repository":
{
"type": "git",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name=TasmotaSerial
version=1.3.0
version=2.0.0
author=Theo Arends
maintainer=Theo Arends <[email protected]>
sentence=Implementation of software serial for ESP8266.
sentence=Implementation of software serial with hardware serial fallback for ESP8266.
paragraph=
category=Signal Input/Output
url=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,27 +76,32 @@ static void (*ISRList[16])() = {
tms_isr_15
};

TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin)
TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fallback)
{
m_valid = false;
m_hardserial = 0;
if (!((isValidGPIOpin(receive_pin)) && (isValidGPIOpin(transmit_pin) || transmit_pin == 16))) {
return;
}
m_rx_pin = receive_pin;
m_tx_pin = transmit_pin;
m_in_pos = m_out_pos = 0;
if (m_rx_pin > -1) {
m_buffer = (uint8_t*)malloc(TM_SERIAL_BUFFER_SIZE);
if (m_buffer == NULL) return;
// Use getCycleCount() loop to get as exact timing as possible
m_bit_time = ESP.getCpuFreqMHz() *1000000 /TM_SERIAL_BAUDRATE;
pinMode(m_rx_pin, INPUT);
tms_obj_list[m_rx_pin] = this;
attachInterrupt(m_rx_pin, ISRList[m_rx_pin], FALLING);
}
if (m_tx_pin > -1) {
pinMode(m_tx_pin, OUTPUT);
digitalWrite(m_tx_pin, HIGH);
if (hardware_fallback && (((1 == m_rx_pin) && (3 == m_tx_pin)) || ((3 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (1 == m_tx_pin)))) {
m_hardserial = 1;
} else {
if (m_rx_pin > -1) {
m_buffer = (uint8_t*)malloc(TM_SERIAL_BUFFER_SIZE);
if (m_buffer == NULL) return;
// Use getCycleCount() loop to get as exact timing as possible
m_bit_time = ESP.getCpuFreqMHz() *1000000 /TM_SERIAL_BAUDRATE;
pinMode(m_rx_pin, INPUT);
tms_obj_list[m_rx_pin] = this;
attachInterrupt(m_rx_pin, ISRList[m_rx_pin], FALLING);
}
if (m_tx_pin > -1) {
pinMode(m_tx_pin, OUTPUT);
digitalWrite(m_tx_pin, HIGH);
}
}
m_valid = true;
}
Expand All @@ -107,38 +112,63 @@ bool TasmotaSerial::isValidGPIOpin(int pin)
}

bool TasmotaSerial::begin(long speed) {
// Use getCycleCount() loop to get as exact timing as possible
m_bit_time = ESP.getCpuFreqMHz() *1000000 /speed;
m_high_speed = (speed > 9600);
if (m_hardserial) {
Serial.flush();
Serial.begin(speed, SERIAL_8N1);
} else {
// Use getCycleCount() loop to get as exact timing as possible
m_bit_time = ESP.getCpuFreqMHz() *1000000 /speed;
m_high_speed = (speed > 9600);
}
return m_valid;
}

bool TasmotaSerial::begin() {
return begin(TM_SERIAL_BAUDRATE);
}

bool TasmotaSerial::hardwareSerial() {
return m_hardserial;
}

void TasmotaSerial::flush() {
m_in_pos = m_out_pos = 0;
if (m_hardserial) {
Serial.flush();
} else {
m_in_pos = m_out_pos = 0;
}
}

int TasmotaSerial::peek() {
if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) return -1;
return m_buffer[m_out_pos];
if (m_hardserial) {
return Serial.peek();
} else {
if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) return -1;
return m_buffer[m_out_pos];
}
}

int TasmotaSerial::read()
{
if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) return -1;
uint8_t ch = m_buffer[m_out_pos];
m_out_pos = (m_out_pos +1) % TM_SERIAL_BUFFER_SIZE;
return ch;
if (m_hardserial) {
return Serial.read();
} else {
if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) return -1;
uint8_t ch = m_buffer[m_out_pos];
m_out_pos = (m_out_pos +1) % TM_SERIAL_BUFFER_SIZE;
return ch;
}
}

int TasmotaSerial::available()
{
int avail = m_in_pos - m_out_pos;
if (avail < 0) avail += TM_SERIAL_BUFFER_SIZE;
return avail;
if (m_hardserial) {
return Serial.available();
} else {
int avail = m_in_pos - m_out_pos;
if (avail < 0) avail += TM_SERIAL_BUFFER_SIZE;
return avail;
}
}

#ifdef TM_SERIAL_USE_IRAM
Expand All @@ -149,24 +179,28 @@ int TasmotaSerial::available()

size_t TasmotaSerial::write(uint8_t b)
{
if (-1 == m_tx_pin) return 0;
if (m_high_speed) cli(); // Disable interrupts in order to get a clean transmit
unsigned long wait = m_bit_time;
digitalWrite(m_tx_pin, HIGH);
unsigned long start = ESP.getCycleCount();
// Start bit;
digitalWrite(m_tx_pin, LOW);
TM_SERIAL_WAIT;
for (int i = 0; i < 8; i++) {
digitalWrite(m_tx_pin, (b & 1) ? HIGH : LOW);
if (m_hardserial) {
return Serial.write(b);
} else {
if (-1 == m_tx_pin) return 0;
if (m_high_speed) cli(); // Disable interrupts in order to get a clean transmit
unsigned long wait = m_bit_time;
digitalWrite(m_tx_pin, HIGH);
unsigned long start = ESP.getCycleCount();
// Start bit;
digitalWrite(m_tx_pin, LOW);
TM_SERIAL_WAIT;
for (int i = 0; i < 8; i++) {
digitalWrite(m_tx_pin, (b & 1) ? HIGH : LOW);
TM_SERIAL_WAIT;
b >>= 1;
}
// Stop bit
digitalWrite(m_tx_pin, HIGH);
TM_SERIAL_WAIT;
b >>= 1;
if (m_high_speed) sei();
return 1;
}
// Stop bit
digitalWrite(m_tx_pin, HIGH);
TM_SERIAL_WAIT;
if (m_high_speed) sei();
return 1;
}

#ifdef TM_SERIAL_USE_IRAM
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@

class TasmotaSerial : public Stream {
public:
TasmotaSerial(int receive_pin, int transmit_pin);
TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fallback = false);
bool begin(long speed);
bool begin();
bool hardwareSerial();
int peek();

virtual size_t write(uint8_t byte);
Expand All @@ -57,6 +58,7 @@ class TasmotaSerial : public Stream {

// Member variables
bool m_valid;
bool m_hardserial;
bool m_high_speed;
int m_rx_pin;
int m_tx_pin;
Expand Down
1 change: 1 addition & 0 deletions sonoff/_releasenotes.ino
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* Add rule state test for On/Off in addition to 0/1 (#2613)
* Add hardware serial option to MHZ-19 sensor (#2659)
* Updated Italian language file (#2618)
* Update TasmotaSerial to 2.0.0 allowing Hardware Serial Fallback when correct connection are configured
* Optimize command handling
*
* 5.13.1 20180501
Expand Down
11 changes: 6 additions & 5 deletions sonoff/support.ino
Original file line number Diff line number Diff line change
Expand Up @@ -486,12 +486,13 @@ void SetSerialBaudrate(int baudrate)
}
}

void SetSerialLocal(bool slocal)
void ClaimSerial()
{
serial_local = slocal;
if (slocal) {
SetSeriallog(LOG_LEVEL_NONE);
}
serial_local = 1;
AddLog_P(LOG_LEVEL_INFO, PSTR("SNS: Hardware Serial"));
SetSeriallog(LOG_LEVEL_NONE);
baudrate = Serial.baudRate();
Settings.baudrate = baudrate / 1200;
}

uint32_t GetHash(const char *buffer, size_t size)
Expand Down
21 changes: 12 additions & 9 deletions sonoff/xdrv_03_energy.ino
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,8 @@ void CseEverySecond()
*
* Source: Victor Ferrer https://github.com/vicfergar/Sonoff-MQTT-OTA-Arduino
* Based on: PZEM004T library https://github.com/olehs/PZEM004T
*
* Hardware Serial will be selected if GPIO1 = [PZEM Rx] and [GPIO3 = PZEM Tx]
\*********************************************************************************************/

#include <TasmotaSerial.h>
Expand All @@ -434,6 +436,8 @@ TasmotaSerial *PzemSerial;

#define PZEM_DEFAULT_READ_TIMEOUT 500

/*********************************************************************************************/

struct PZEMCommand {
uint8_t command;
uint8_t addr[4];
Expand Down Expand Up @@ -564,12 +568,6 @@ void PzemEvery200ms()
}
}

bool PzemInit()
{
PzemSerial = new TasmotaSerial(pin[GPIO_PZEM_RX], pin[GPIO_PZEM_TX]);
return PzemSerial->begin();
}

/********************************************************************************************/
#endif // USE_PZEM004T

Expand Down Expand Up @@ -1033,7 +1031,7 @@ void EnergyDrvInit()
serial_config = SERIAL_8E1;
energy_flg = ENERGY_CSE7766;
#ifdef USE_PZEM004T
} else if ((pin[GPIO_PZEM_RX] < 99) && (pin[GPIO_PZEM_TX])) { // Any device with a Pzem004T
} else if ((pin[GPIO_PZEM_RX] < 99) && (pin[GPIO_PZEM_TX] < 99)) { // Any device with a Pzem004T
energy_flg = ENERGY_PZEM004T;
#endif // USE_PZEM004T
}
Expand All @@ -1044,8 +1042,13 @@ void EnergySnsInit()
if (ENERGY_HLW8012 == energy_flg) HlwInit();

#ifdef USE_PZEM004T
if ((ENERGY_PZEM004T == energy_flg) && !PzemInit()) { // PzemInit needs to be done here as earlier (serial) interrupts may lead to Exceptions
energy_flg = ENERGY_NONE;
if (ENERGY_PZEM004T == energy_flg) { // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions
PzemSerial = new TasmotaSerial(pin[GPIO_PZEM_RX], pin[GPIO_PZEM_TX], 1);
if (PzemSerial->begin(9600)) {
if (PzemSerial->hardwareSerial()) { ClaimSerial(); }
} else {
energy_flg = ENERGY_NONE;
}
}
#endif // USE_PZEM004T

Expand Down
Loading

0 comments on commit 054f1bd

Please sign in to comment.