+#if USE_SERIAL_0_STDIN
+int
+_ao_serial0_pollchar(void)
+{
+ uint8_t c;
+ if (ao_fifo_empty(ao_serial0_rx_fifo))
+ return AO_READ_AGAIN;
+ ao_fifo_remove(ao_serial0_rx_fifo,c);
+ return c;
+}
+#endif
+
+void
+ao_serial0_putchar(char c) __critical
+{
+ while (ao_fifo_full(ao_serial0_tx_fifo))
+ ao_sleep(&ao_serial0_tx_fifo);
+ ao_fifo_insert(ao_serial0_tx_fifo, c);
+ ao_serial0_tx_start();
+}
+
+void
+ao_serial0_drain(void) __critical
+{
+ while (!ao_fifo_empty(ao_serial0_tx_fifo))
+ ao_sleep(&ao_serial0_tx_fifo);
+}
+
+void
+ao_serial0_set_speed(uint8_t speed)
+{
+ ao_serial0_drain();
+ if (speed > AO_SERIAL_SPEED_MAX)
+ return;
+ U0UCR |= UxUCR_FLUSH;
+ U0BAUD = ao_serial_speeds[speed].baud;
+ U0GCR = ao_serial_speeds[speed].gcr;
+}
+#endif /* HAS_SERIAL_0 */
+
+#if HAS_SERIAL_1
+
+volatile __xdata struct ao_fifo ao_serial1_rx_fifo;
+volatile __xdata struct ao_fifo ao_serial1_tx_fifo;
+
+void
+ao_serial1_rx_isr(void) __interrupt 3
+{
+ if (!ao_fifo_full(ao_serial1_rx_fifo))
+ ao_fifo_insert(ao_serial1_rx_fifo, U1DBUF);
+ ao_wakeup(&ao_serial1_rx_fifo);
+#if USE_SERIAL_1_STDIN
+ ao_wakeup(&ao_stdin_ready);
+#endif
+}
+
+static __xdata uint8_t ao_serial1_tx_started;
+
+static void
+ao_serial1_tx_start(void)
+{
+ if (!ao_fifo_empty(ao_serial1_tx_fifo) &&
+ !ao_serial1_tx_started)
+ {
+ ao_serial1_tx_started = 1;
+ ao_fifo_remove(ao_serial1_tx_fifo, U1DBUF);
+ }
+}
+
+void
+ao_serial1_tx_isr(void) __interrupt 14
+{
+ UTX1IF = 0;
+ ao_serial1_tx_started = 0;
+ ao_serial1_tx_start();
+ ao_wakeup(&ao_serial1_tx_fifo);
+}
+