From b9fc2a6b33d8af88d95d750965f3fb8b1e9032d4 Mon Sep 17 00:00:00 2001
From: Jacob Davis-Hansson <jake@davis-hansson.com>
Date: Fri, 14 Apr 2023 21:05:03 +0200
Subject: [PATCH 1/3] Add ability to invert UART pins

This is useful in some cases where the surrounding circuit
for some reason inverts the UART signal, for instance if you're talking
to a device via an optocoupler.
---
 embassy-rp/src/uart/mod.rs | 33 +++++++++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs
index a945f2295..dfa56a842 100644
--- a/embassy-rp/src/uart/mod.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -6,6 +6,7 @@ use crate::dma::{AnyChannel, Channel};
 use crate::gpio::sealed::Pin;
 use crate::gpio::AnyPin;
 use crate::{pac, peripherals, Peripheral};
+use crate::pac::io::vals::Inover;
 
 #[cfg(feature = "nightly")]
 mod buffered;
@@ -53,6 +54,14 @@ pub struct Config {
     pub data_bits: DataBits,
     pub stop_bits: StopBits,
     pub parity: Parity,
+    /// Invert the tx pin output
+    pub invert_tx: bool,
+    /// Invert the rx pin input
+    pub invert_rx: bool,
+    // Invert the rts pin
+    pub invert_rts: bool,
+    // Invert the cts pin
+    pub invert_cts: bool,
 }
 
 impl Default for Config {
@@ -62,6 +71,10 @@ impl Default for Config {
             data_bits: DataBits::DataBits8,
             stop_bits: StopBits::STOP1,
             parity: Parity::ParityNone,
+            invert_rx: false,
+            invert_tx: false,
+            invert_rts: false,
+            invert_cts: false,
         }
     }
 }
@@ -381,19 +394,31 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
         let r = T::regs();
         unsafe {
             if let Some(pin) = &tx {
-                pin.io().ctrl().write(|w| w.set_funcsel(2));
+                pin.io().ctrl().write(|w| {
+                    w.set_funcsel(2);
+                    w.set_inover(if config.invert_tx { Inover::INVERT } else { Inover::NORMAL });
+                });
                 pin.pad_ctrl().write(|w| w.set_ie(true));
             }
             if let Some(pin) = &rx {
-                pin.io().ctrl().write(|w| w.set_funcsel(2));
+                pin.io().ctrl().write(|w| {
+                    w.set_funcsel(2);
+                    w.set_inover(if config.invert_rx { Inover::INVERT } else { Inover::NORMAL });
+                });
                 pin.pad_ctrl().write(|w| w.set_ie(true));
             }
             if let Some(pin) = &cts {
-                pin.io().ctrl().write(|w| w.set_funcsel(2));
+                pin.io().ctrl().write(|w| {
+                    w.set_funcsel(2);
+                    w.set_inover(if config.invert_cts { Inover::INVERT } else { Inover::NORMAL });
+                });
                 pin.pad_ctrl().write(|w| w.set_ie(true));
             }
             if let Some(pin) = &rts {
-                pin.io().ctrl().write(|w| w.set_funcsel(2));
+                pin.io().ctrl().write(|w| {
+                    w.set_funcsel(2);
+                    w.set_inover(if config.invert_rts { Inover::INVERT } else { Inover::NORMAL });
+                });
                 pin.pad_ctrl().write(|w| w.set_ie(true));
             }
 

From 81f10e136a95c33f98f5fa06ac3996bee97e66d3 Mon Sep 17 00:00:00 2001
From: Jacob Davis-Hansson <jake@davis-hansson.com>
Date: Sat, 15 Apr 2023 15:13:44 +0200
Subject: [PATCH 2/3] outover instead of inover

---
 embassy-rp/src/uart/mod.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs
index dfa56a842..f7a4c5a60 100644
--- a/embassy-rp/src/uart/mod.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -6,7 +6,7 @@ use crate::dma::{AnyChannel, Channel};
 use crate::gpio::sealed::Pin;
 use crate::gpio::AnyPin;
 use crate::{pac, peripherals, Peripheral};
-use crate::pac::io::vals::Inover;
+use crate::pac::io::vals::{Inover, Outover};
 
 #[cfg(feature = "nightly")]
 mod buffered;
@@ -396,7 +396,7 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
             if let Some(pin) = &tx {
                 pin.io().ctrl().write(|w| {
                     w.set_funcsel(2);
-                    w.set_inover(if config.invert_tx { Inover::INVERT } else { Inover::NORMAL });
+                    w.set_outover(if config.invert_tx { Outover::INVERT } else { Outover::NORMAL });
                 });
                 pin.pad_ctrl().write(|w| w.set_ie(true));
             }
@@ -417,7 +417,7 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
             if let Some(pin) = &rts {
                 pin.io().ctrl().write(|w| {
                     w.set_funcsel(2);
-                    w.set_inover(if config.invert_rts { Inover::INVERT } else { Inover::NORMAL });
+                    w.set_outover(if config.invert_rts { Outover::INVERT } else { Outover::NORMAL });
                 });
                 pin.pad_ctrl().write(|w| w.set_ie(true));
             }

From 21ea98810aed1a4a820ac8cc357d66821f80c3fc Mon Sep 17 00:00:00 2001
From: Jacob Davis-Hansson <jake@davis-hansson.com>
Date: Tue, 18 Apr 2023 17:44:19 +0200
Subject: [PATCH 3/3] Pass rx pin to right init arg

---
 embassy-rp/src/uart/mod.rs | 30 +++++++++++++++++++++++-------
 1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs
index f7a4c5a60..f9e30a78b 100644
--- a/embassy-rp/src/uart/mod.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -5,8 +5,8 @@ use embassy_hal_common::{into_ref, PeripheralRef};
 use crate::dma::{AnyChannel, Channel};
 use crate::gpio::sealed::Pin;
 use crate::gpio::AnyPin;
-use crate::{pac, peripherals, Peripheral};
 use crate::pac::io::vals::{Inover, Outover};
+use crate::{pac, peripherals, Peripheral};
 
 #[cfg(feature = "nightly")]
 mod buffered;
@@ -180,7 +180,7 @@ impl<'d, T: Instance> UartTx<'d, T, Async> {
 }
 
 impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
-    /// Create a new DMA-enabled UART which can only send data
+    /// Create a new DMA-enabled UART which can only recieve data
     pub fn new(
         _uart: impl Peripheral<P = T> + 'd,
         rx: impl Peripheral<P = impl RxPin<T>> + 'd,
@@ -188,7 +188,7 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
         config: Config,
     ) -> Self {
         into_ref!(rx, rx_dma);
-        Uart::<T, M>::init(Some(rx.map_into()), None, None, None, config);
+        Uart::<T, M>::init(None, Some(rx.map_into()), None, None, config);
         Self::new_inner(Some(rx_dma.map_into()))
     }
 
@@ -396,28 +396,44 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
             if let Some(pin) = &tx {
                 pin.io().ctrl().write(|w| {
                     w.set_funcsel(2);
-                    w.set_outover(if config.invert_tx { Outover::INVERT } else { Outover::NORMAL });
+                    w.set_outover(if config.invert_tx {
+                        Outover::INVERT
+                    } else {
+                        Outover::NORMAL
+                    });
                 });
                 pin.pad_ctrl().write(|w| w.set_ie(true));
             }
             if let Some(pin) = &rx {
                 pin.io().ctrl().write(|w| {
                     w.set_funcsel(2);
-                    w.set_inover(if config.invert_rx { Inover::INVERT } else { Inover::NORMAL });
+                    w.set_inover(if config.invert_rx {
+                        Inover::INVERT
+                    } else {
+                        Inover::NORMAL
+                    });
                 });
                 pin.pad_ctrl().write(|w| w.set_ie(true));
             }
             if let Some(pin) = &cts {
                 pin.io().ctrl().write(|w| {
                     w.set_funcsel(2);
-                    w.set_inover(if config.invert_cts { Inover::INVERT } else { Inover::NORMAL });
+                    w.set_inover(if config.invert_cts {
+                        Inover::INVERT
+                    } else {
+                        Inover::NORMAL
+                    });
                 });
                 pin.pad_ctrl().write(|w| w.set_ie(true));
             }
             if let Some(pin) = &rts {
                 pin.io().ctrl().write(|w| {
                     w.set_funcsel(2);
-                    w.set_outover(if config.invert_rts { Outover::INVERT } else { Outover::NORMAL });
+                    w.set_outover(if config.invert_rts {
+                        Outover::INVERT
+                    } else {
+                        Outover::NORMAL
+                    });
                 });
                 pin.pad_ctrl().write(|w| w.set_ie(true));
             }