# HardwareSerial API Documentation

## Overview

`HardwareSerial` provides access to hardware UART serial ports on ESP32 and related chips. It allows configuration, reading, writing, and event handling for serial communication.

---

## Constructor & Destructor

### `HardwareSerial(uint8_t uart_nr)`
- **Purpose:** Creates a serial port object for the specified UART number (e.g., 0, 1, 2).
- **Precedence:** Must be called before using any other methods.

### `~HardwareSerial()`
- **Purpose:** Cleans up resources when the object is destroyed.

---

## Initialization & Configuration

### `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, uint8_t rxfifo_full_thrhd = 120)`
- **Purpose:** Initializes the UART port with baud rate, data format, pin assignment, polarity, timeout, and FIFO threshold.
- **Comments:**  
  - When pins are changed, it will detach the previous ones.
  - If pin is negative, it won't be set/changed and will be kept as is.
  - `timeout_ms` is used in baudrate detection (ESP32, ESP32S2 only).
  - `invert` will invert RX/TX polarity.
  - `rxfifo_full_thrhd` is the UART Flow Control Threshold in the UART FIFO (max 127).
- **Precedence:** Must be called before using read/write functions. If you need to set clock source or pins, call those methods *before* `begin()`.

### `void end(void)`
- **Purpose:** Deinitializes the UART port, freeing resources.

### `void updateBaudRate(unsigned long baud)`
- **Purpose:** Changes the baud rate after initialization.

### `bool setClockSource(SerialClkSrc clkSrc)`
- **Purpose:** Sets the UART clock source.
- **Comments:**  
  - Must be set before calling `begin()`, otherwise it won't have any effect.
  - Not all clock sources are available to every SoC. See comments for compatible options.

### `bool setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin = -1, int8_t rtsPin = -1)`
- **Purpose:** Assigns RX, TX, CTS, RTS pins.
- **Comments:**  
  - Negative Pin Number will keep it unmodified, thus this function can set individual pins.
  - Can be called after or before `begin()`.
  - When pins are changed, it will detach the previous ones.

### `bool setHwFlowCtrlMode(SerialHwFlowCtrl mode = UART_HW_FLOWCTRL_CTS_RTS, uint8_t threshold = 64)`
- **Purpose:** Enables/disables hardware flow control (RTS/CTS).
- **Comments:**  
  - Must use `setPins()` before enabling flow control.
  - `UART_HW_FLOWCTRL_DISABLE = 0x0` disables hardware flow control.
  - `UART_HW_FLOWCTRL_RTS = 0x1` enables RX hardware flow control (RTS).
  - `UART_HW_FLOWCTRL_CTS = 0x2` enables TX hardware flow control (CTS).
  - `UART_HW_FLOWCTRL_CTS_RTS = 0x3` enables both.

### `bool setMode(SerialMode mode)`
- **Purpose:** Sets UART mode (e.g., RS485, IRDA).
- **Comments:**  
  - Used to set RS485 modes such as `UART_MODE_RS485_HALF_DUPLEX` for Auto RTS function on ESP32.
  - Should be set before `begin()`.

### `void setRxInvert(bool)`
- **Purpose:** Inverts RX/TX polarity.

### `void setDebugOutput(bool)`
- **Purpose:** Enables debug output for troubleshooting.

### `size_t setRxBufferSize(size_t new_size)`
- **Purpose:** Sets the size of the RX buffer.

### `size_t setTxBufferSize(size_t new_size)`
- **Purpose:** Sets the size of the TX buffer.

---

## Data Transmission

### `size_t write(uint8_t)`
### `size_t write(const uint8_t *buffer, size_t size)`
### `size_t write(const char *buffer, size_t size)`
### `size_t write(const char *s)`
### `size_t write(unsigned long n)`
### `size_t write(long n)`
### `size_t write(unsigned int n)`
### `size_t write(int n)`
- **Purpose:** Sends data over the serial port.
- **Comments:**  
  - Overloads allow writing single bytes, buffers, strings, and numbers.

---

## Data Reception

### `int available(void)`
- **Purpose:** Returns the number of bytes available to read.
- **Comments:**  
  - Affected by `setRxFIFOFull()`, as the internal RxRingBuffer is filled only after the specified number of bytes arrive or a RX Timeout happens.

### `int availableForWrite(void)`
- **Purpose:** Returns the number of bytes available for writing (free space in TX buffer).

### `int peek(void)`
- **Purpose:** Returns the next byte in the RX buffer without removing it.

### `int read(void)`
- **Purpose:** Reads a single byte from the RX buffer.

### `size_t read(uint8_t *buffer, size_t size)`
### `size_t read(char *buffer, size_t size)`
- **Purpose:** Reads multiple bytes into a buffer.

### `size_t readBytes(uint8_t *buffer, size_t length)`
### `size_t readBytes(char *buffer, size_t length)`
- **Purpose:** Reads a specified number of bytes into a buffer, optimized for speed.
- **Comments:**  
  - Overrides `Stream::readBytes()` to be faster using IDF.

### `void flush(void)`
- **Purpose:** Waits for transmission of outgoing serial data to complete.

### `void flush(bool txOnly)`
- **Purpose:** If `txOnly` is true, only flushes TX buffer.

---

## Event Handling

### `bool setRxTimeout(uint8_t symbols_timeout)`
- **Purpose:** Sets the RX inactivity timeout for triggering the `onReceive` callback.
- **Comments:**  
  - `symbols_timeout` defines a timeout threshold in UART symbol periods.
  - Setting 0 disables the callback call by timeout.
  - Maximum timeout is calculated automatically by IDF; if set above the maximum, it is ignored and an error is printed on Serial0.
  - Example: For a baudrate of 9600, `SERIAL_8N1` (10 bit symbol) and `symbols_timeout = 3`, the timeout would be 3 / (9600 / 10) = 3.125 ms.

### `bool setRxFIFOFull(uint8_t fifoBytes)`
- **Purpose:** Sets the RX FIFO threshold for triggering interrupts and filling the RX buffer.
- **Comments:**  
  - This affects functions such as `available()` and `read()`.
  - Setting to 1 allows receiving byte by byte, but increases CPU usage.

### `void onReceive(OnReceiveCb function, bool onlyOnTimeout = false)`
- **Purpose:** Registers a callback for RX events (FIFO full or timeout).
- **Comments:**  
  - Called whenever a UART interruption occurs (`UART_INTR_RXFIFO_FULL` or `UART_INTR_RXFIFO_TOUT`).
  - `onlyOnTimeout = true`: Callback only called when RX Timeout happens; whole stream of bytes will be ready at once.
  - `onlyOnTimeout = false`: Callback called when FIFO reaches 120 bytes and also on RX Timeout; stream is split into blocks of 120 bytes.
  - This option avoids Rx Overflow but leaves packet reassembling to the application.

### `void onReceiveError(OnReceiveErrorCb function)`
- **Purpose:** Registers a callback for UART error events.
- **Comments:**  
  - Called on error events (see `hardwareSerial_error_t`).

### `void eventQueueReset()`
- **Purpose:** Clears all pending RX and error events.
- **Comments:**  
  - Useful in some use cases.

---

## Miscellaneous

### `uint32_t baudRate()`
- **Purpose:** Returns the current baud rate (may be rounded).
- **Comments:**  
  - Baudrate detection is supported; see example in file header.

### `operator bool() const`
- **Purpose:** Returns true if the serial port is initialized.

---

## Usage Order/Precedence

1. **Create** a `HardwareSerial` object.
2. **(Optional)** Set clock source, pins, mode, flow control, buffer sizes, RX invert, debug output.
3. **Call `begin()`** to initialize the port.
4. **Register event callbacks** if needed.
5. **Use read/write methods** for data transfer.
6. **Call `end()`** to deinitialize when done.

---

## Enums & Typedefs

- `SerialConfig`: Data format (bits, parity, stop bits).
- `SerialMode`: UART mode (RS485, IRDA, etc.).
- `SerialHwFlowCtrl`: Hardware flow control options.
- `hardwareSerial_error_t`: UART error types.
- `SerialClkSrc`: UART clock source options.
- `OnReceiveCb`: RX event callback type.
- `OnReceiveErrorCb`: Error event callback type.

---

## Global Instances

- `Serial0`, `Serial1`, ...: Predefined global objects for each UART port (if available).
- **Comments:**  
  - If not using CDC on Boot, Arduino Serial is the UART0 device.
  - There is always Serial0 for UART0.

---

## Example: Baudrate Detection

```cpp
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!");
  }
}
```
- **Note:** The baudrate returned by `baudRate()` may be rounded, e.g., 115200 returns 115201.

---

**For further details, see the comments in the source file above.**