Skip to content

Added baudrate detection to esp32-hal-uart and HardwareSerial #1961

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Nov 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions cores/esp32/HardwareSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ HardwareSerial Serial2(2);

HardwareSerial::HardwareSerial(int uart_nr) : _uart_nr(uart_nr), _uart(NULL) {}

void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert)
void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert, unsigned long timeout_ms)
{
if(0 > _uart_nr || _uart_nr > 2) {
log_e("Serial number is invalid, please use 0, 1 or 2");
Expand All @@ -51,7 +51,26 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
rxPin = RX2;
txPin = TX2;
}
_uart = uartBegin(_uart_nr, baud, config, rxPin, txPin, 256, invert);

_uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, 256, invert);

if(!baud) {
time_t startMillis = millis();
unsigned long detectedBaudRate;
while(millis() - startMillis < timeout_ms && !(detectedBaudRate = uartDetectBaudrate(_uart))) {
yield();
}

end();

if(detectedBaudRate) {
delay(100); // Give some time...
_uart = uartBegin(_uart_nr, detectedBaudRate, config, rxPin, txPin, 256, invert);
} else {
log_e("Could not detect baudrate. Serial data at the port must be present within the timeout for detection to be possible");
_uart = NULL;
}
}
}

void HardwareSerial::end()
Expand Down
20 changes: 19 additions & 1 deletion cores/esp32/HardwareSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@
Modified 18 December 2014 by Ivan Grokhotkov (esp8266 platform support)
Modified 31 March 2015 by Markus Sattler (rewrite the code for UART0 + UART1 support in ESP8266)
Modified 25 April 2015 by Thomas Flayols (add configuration different from 8N1 in ESP8266)
Modified 13 October 2018 by Jeroen Döll (add baudrate detection)
Baudrate detection example usage (detection on Serial1):
void setup() {
Serial.begin(115200);
delay(100);
Serial.println();
Serial1.begin(0, SERIAL_8N1, -1, -1, true, 11000UL); // Passing 0 for baudrate to detect it, the last parameter is a timeout in ms
unsigned long detectedBaudRate = Serial1.baudRate();
if(detectedBaudRate) {
Serial.printf("Detected baudrate is %lu\n", detectedBaudRate);
} else {
Serial.println("No baudrate detected, Serial1 will not work!");
}
}
Pay attention: the baudrate returned by baudRate() may be rounded, eg 115200 returns 115201
*/

#ifndef HardwareSerial_h
Expand All @@ -37,7 +55,7 @@ class HardwareSerial: public Stream
public:
HardwareSerial(int uart_nr);

void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1, bool invert=false);
void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1, bool invert=false, unsigned long timeout_ms = 20000UL);
void end();
int available(void);
int availableForWrite(void);
Expand Down
64 changes: 63 additions & 1 deletion cores/esp32/esp32-hal-uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ void uartEnd(uart_t* uart)

size_t uartResizeRxBuffer(uart_t * uart, size_t new_size) {
if(uart == NULL) {
return;
return 0;
}

UART_MUTEX_LOCK();
Expand Down Expand Up @@ -455,3 +455,65 @@ int log_printf(const char *format, ...)
}
return len;
}

/*
* if enough pulses are detected return the minimum high pulse duration + minimum low pulse duration divided by two.
* This equals one bit period. If flag is true the function return inmediately, otherwise it waits for enough pulses.
*/
unsigned long uartBaudrateDetect(uart_t *uart, bool flg)
{
while(uart->dev->rxd_cnt.edge_cnt < 30) { // UART_PULSE_NUM(uart_num)
if(flg) return 0;
ets_delay_us(1000);
}

UART_MUTEX_LOCK();
unsigned long ret = ((uart->dev->lowpulse.min_cnt + uart->dev->highpulse.min_cnt) >> 1) + 12;
UART_MUTEX_UNLOCK();

return ret;
}

/*
* To start detection of baud rate with the uart the auto_baud.en bit needs to be cleared and set. The bit period is
* detected calling uartBadrateDetect(). The raw baudrate is computed using the UART_CLK_FREQ. The raw baudrate is
* rounded to the closed real baudrate.
*/
unsigned long
uartDetectBaudrate(uart_t *uart)
{
static bool uartStateDetectingBaudrate = false;

if(!uartStateDetectingBaudrate) {
uart->dev->auto_baud.glitch_filt = 0x08;
uart->dev->auto_baud.en = 0;
uart->dev->auto_baud.en = 1;
uartStateDetectingBaudrate = true;
}

unsigned long divisor = uartBaudrateDetect(uart, true);
if (!divisor) {
return 0;
}

uart->dev->auto_baud.en = 0;
uartStateDetectingBaudrate = false; // Initialize for the next round

unsigned long baudrate = UART_CLK_FREQ / divisor;

static const unsigned long default_rates[] = {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 74880, 115200, 230400, 256000, 460800, 921600, 1843200, 3686400};

size_t i;
for (i = 1; i < sizeof(default_rates) / sizeof(default_rates[0]) - 1; i++) // find the nearest real baudrate
{
if (baudrate <= default_rates[i])
{
if (baudrate - default_rates[i - 1] < default_rates[i] - baudrate) {
i--;
}
break;
}
}

return default_rates[i];
}
2 changes: 2 additions & 0 deletions cores/esp32/esp32-hal-uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ size_t uartResizeRxBuffer(uart_t* uart, size_t new_size);
void uartSetDebug(uart_t* uart);
int uartGetDebug();

unsigned long uartDetectBaudrate(uart_t *uart);

#ifdef __cplusplus
}
#endif
Expand Down