1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
//! UART peripheral control.
//!
//! Implements the traits required for reading from and writing to a serial port.
//!
//! The ESP8266 has two UARTs available, `UART0` and `UART1`. `UART1` is write-only.

use crate::gpio::*;

use embedded_hal::serial::{Read, Write};
use esp8266::{UART0, UART1};
use void::Void;

/// Extension trait for `UART0` for easily creating `UART0Serial` instances.
pub trait UART0Ext {
    fn serial(self, tdx: Gpio1<UART>, rxd: Gpio3<UART>) -> UART0Serial;
}

impl UART0Ext for UART0 {
    /// Create a new `UART0Serial` instance using the provided pins.
    fn serial(self, txd: Gpio1<UART>, rxd: Gpio3<UART>) -> UART0Serial {
        UART0Serial {
            uart: self,
            txd,
            rxd,
        }
    }
}

/// Extension trait for `UART1` for easily creating `UART1Serial` instances.
///
/// Note that `UART1` is write-only.
pub trait UART1Ext {
    fn serial(self, txd: Gpio2<UART>) -> UART1Serial;
}

impl UART1Ext for UART1 {
    /// Create a new write-only `UART1Serial` instance using the provided pin.
    fn serial(self, txd: Gpio2<UART>) -> UART1Serial {
        UART1Serial { uart: self, txd }
    }
}

/// Serial port using `UART0`.
pub struct UART0Serial {
    uart: UART0,
    txd: Gpio1<UART>,
    rxd: Gpio3<UART>,
}

impl UART0Serial {
    /// Free up the UART device and return the pins used.
    ///
    /// This operation blocks while there are still bytes in the transmit buffer.
    pub fn decompose(mut self) -> nb::Result<(UART0, Gpio1<UART>, Gpio3<UART>), Void> {
        self.flush()?;
        Ok((self.uart, self.txd, self.rxd))
    }
}

impl Read<u8> for UART0Serial {
    type Error = Void;

    /// Reads a single word from the serial interface.
    fn read(&mut self) -> nb::Result<u8, Self::Error> {
        if self.uart.uart_status.read().rxfifo_cnt().bits() > 0 {
            Ok(self.uart.uart_fifo.read().rxfifo_rd_byte().bits())
        } else {
            Err(nb::Error::WouldBlock)
        }
    }
}

impl Write<u8> for UART0Serial {
    type Error = Void;

    fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
        if self.uart.uart_status.read().txfifo_cnt().bits() < 128 {
            self.uart
                .uart_fifo
                .write(|w| unsafe { w.rxfifo_write_byte().bits(word) });
            Ok(())
        } else {
            Err(nb::Error::WouldBlock)
        }
    }

    fn flush(&mut self) -> nb::Result<(), Void> {
        if self.uart.uart_status.read().txfifo_cnt().bits() > 0 {
            Err(nb::Error::WouldBlock)
        } else {
            Ok(())
        }
    }
}

impl core::fmt::Write for UART0Serial {
    fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
        s.as_bytes()
            .iter()
            .try_for_each(|c| nb::block!(self.write(*c)))
            .map_err(|_| core::fmt::Error)
    }
}

/// Write-only serial port using `UART1`.
pub struct UART1Serial {
    uart: UART1,
    txd: Gpio2<UART>,
}

impl UART1Serial {
    /// Free up the UART device and return the pins used.
    ///
    /// This operation blocks while there are still bytes in the transmit buffer.
    pub fn decompose(mut self) -> nb::Result<(UART1, Gpio2<UART>), Void> {
        self.flush()?;
        Ok((self.uart, self.txd))
    }
}

impl Write<u8> for UART1Serial {
    type Error = Void;

    fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
        if self.uart.uart_status.read().txfifo_cnt().bits() < 128 {
            self.uart
                .uart_fifo
                .write(|w| unsafe { w.rxfifo_write_byte().bits(word) });
            Ok(())
        } else {
            Err(nb::Error::WouldBlock)
        }
    }

    fn flush(&mut self) -> nb::Result<(), Void> {
        if self.uart.uart_status.read().txfifo_cnt().bits() > 0 {
            Err(nb::Error::WouldBlock)
        } else {
            Ok(())
        }
    }
}

impl core::fmt::Write for UART1Serial {
    fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
        s.as_bytes()
            .iter()
            .try_for_each(|c| nb::block!(self.write(*c)))
            .map_err(|_| core::fmt::Error)
    }
}

impl embedded_hal::blocking::serial::write::Default<u8> for UART0Serial {}

impl embedded_hal::blocking::serial::write::Default<u8> for UART1Serial {}

#[cfg(all(feature = "rt", feature = "interrupt"))]
mod interrupt {
    use super::*;

    int_handler!(UART => UartInterruptHandler(UART0Serial));

    impl UART0Serial {
        #[must_use = "the interrupt handler must be kept in scope for the interrupt to be handled"]
        pub fn attach_interrupt<F: FnMut(&mut UART0Serial)>(
            self,
            mut f: F,
        ) -> Pin<UartInterruptHandler<impl FnMut(&mut UART0Serial)>> {
            UartInterruptHandler::new(self, move |serial: &mut UART0Serial| {
                f(serial);
                serial.uart.uart_int_clr.write(|w| unsafe { w.bits(0xff) });
            })
        }
    }
}