diff --git a/esp8266/uart.c b/esp8266/uart.c
index f371935399e1887b097a0eca2f59d36ab860bba8..3207029fd23b99f9db7c14cae9e6b1a12e9df82f 100644
--- a/esp8266/uart.c
+++ b/esp8266/uart.c
@@ -222,6 +222,26 @@ int uart0_rx(void) {
 }
 */
 
+// Waits at most timeout microseconds for at least 1 char to become ready for reading.
+// Returns true if something available, false if not.
+bool uart_rx_wait(uint32_t timeout_us) {
+    uint32_t start = system_get_time();
+    for (;;) {
+        if (input_buf.iget != input_buf.iput) {
+            return true; // have at least 1 char ready for reading
+        }
+        if (system_get_time() - start >= timeout_us) {
+            return false; // timeout
+        }
+        ets_event_poll();
+    }
+}
+
+// Returns char from the input buffer, else -1 if buffer is empty.
+int uart_rx_char(void) {
+    return ringbuf_get(&input_buf);
+}
+
 int uart_rx_one_char(uint8 uart_no) {
     if (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
         return READ_PERI_REG(UART_FIFO(uart_no)) & 0xff;
diff --git a/esp8266/uart.h b/esp8266/uart.h
index 2f762db5a2b368c2550acd06f8f6e92023e563e7..8e09beea5804399397ee8061ad88b244974a2b23 100644
--- a/esp8266/uart.h
+++ b/esp8266/uart.h
@@ -91,6 +91,8 @@ typedef struct {
 
 void uart_init(UartBautRate uart0_br, UartBautRate uart1_br);
 int uart0_rx(void);
+bool uart_rx_wait(uint32_t timeout_us);
+int uart_rx_char(void);
 void uart_tx_one_char(uint8 uart, uint8 TxChar);
 void uart_flush(uint8 uart);
 void uart_os_config(int uart);