Skip to content

Commit

Permalink
Added baudrate detection to esp32-hal-uart and HardwareSerial (#1961)
Browse files Browse the repository at this point in the history
* Added baudrate detection to esp32-hal-uart and HardwareSerial

* Solved compiler warning for uartResizeRxBuffer()

* Add unit to header variable name (timeout_ms)

* Reverting accidentally changed files to master

* Add small delay after baudrate detection
  • Loading branch information
Jeroen88 authored and me-no-dev committed Nov 19, 2018
1 parent 65c861a commit 233d31b
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 4 deletions.
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

0 comments on commit 233d31b

Please sign in to comment.