From 0f323aad41866aa780b190a9e9dd57c33830e75a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= <timokroeger93@gmail.com>
Date: Sun, 26 Apr 2020 09:22:39 +0200
Subject: [PATCH 1/8] can: `Frame`, `Transmitter` and `Receiver` traits

# Conflicts:
#	src/lib.rs
---
 src/can.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lib.rs |  1 +
 2 files changed, 69 insertions(+)
 create mode 100644 src/can.rs

diff --git a/src/can.rs b/src/can.rs
new file mode 100644
index 000000000..446837430
--- /dev/null
+++ b/src/can.rs
@@ -0,0 +1,68 @@
+//! Controller Area Network
+
+/// A CAN2.0 Frame
+pub trait Frame {
+    /// Creates a new frame with a standard identifier.
+    fn new_standard(id: u32, data: &[u8]) -> Self;
+
+    /// Creates a new frame with an extended identifier.
+    fn new_extended(id: u32, data: &[u8]) -> Self;
+
+    /// Marks this frame as a remote frame (by setting the RTR bit).
+    fn with_rtr(&mut self, dlc: usize) -> &mut Self;
+
+    /// Returns true if this frame is a extended frame.
+    fn is_extended(&self) -> bool;
+
+    /// Returns true if this frame is a standard frame.
+    fn is_standard(&self) -> bool {
+        !self.is_extended()
+    }
+
+    /// Returns true if this frame is a remote frame.
+    fn is_remote_frame(&self) -> bool;
+
+    /// Returns true if this frame is a data frame.
+    fn is_data_frame(&self) -> bool {
+        !self.is_remote_frame()
+    }
+
+    /// Returns the frame identifier.
+    fn id(&self) -> u32;
+
+    /// Returns the data length code (DLC) which is in the range 0..8.
+    ///
+    /// For data frames the DLC value always matches the length of the data.
+    /// Remote frames do not carry any data, yet the DLC can be greater than 0.
+    fn dlc(&self) -> usize;
+
+    /// Returns the frame data (0..8 bytes in length).
+    fn data(&self) -> &[u8];
+}
+
+/// A CAN interface that is able to transmit frames.
+pub trait Transmitter {
+    /// Associated frame type.
+    type Frame: Frame;
+
+    /// Associated error type.
+    type Error;
+
+    /// Puts a frame in the transmit buffer.
+    ///
+    /// If the buffer is full, this function will try to replace a lower priority frame
+    /// and return it. This is to avoid the priority inversion problem.
+    fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error>;
+}
+
+/// A CAN interface that is able to receive frames.
+pub trait Receiver {
+    /// Associated frame type.
+    type Frame: Frame;
+
+    /// Associated error type.
+    type Error;
+
+    /// Returns a received frame if available.
+    fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error>;
+}
diff --git a/src/lib.rs b/src/lib.rs
index 8b89f203a..f8a7c0838 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -406,6 +406,7 @@
 
 pub mod adc;
 pub mod blocking;
+pub mod can;
 pub mod capture;
 pub mod digital;
 pub mod fmt;

From c5b4816653d5fc61adcd00ad54f4f92b72957cbb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= <timokroeger93@gmail.com>
Date: Mon, 3 Aug 2020 13:09:26 +0200
Subject: [PATCH 2/8] can: Make frame constructors return `Result`

As noted by @marcelbuesing @reneherrero invalid identfiers can be passed which
---
 src/can.rs | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/src/can.rs b/src/can.rs
index 446837430..4f8bd3184 100644
--- a/src/can.rs
+++ b/src/can.rs
@@ -1,12 +1,14 @@
 //! Controller Area Network
 
 /// A CAN2.0 Frame
-pub trait Frame {
-    /// Creates a new frame with a standard identifier.
-    fn new_standard(id: u32, data: &[u8]) -> Self;
-
-    /// Creates a new frame with an extended identifier.
-    fn new_extended(id: u32, data: &[u8]) -> Self;
+pub trait Frame: Sized {
+    /// Creates a new frame with a standard identifier (0..=0x7FF).
+    /// Returns an error when the the identifier is not valid.
+    fn new_standard(id: u32, data: &[u8]) -> Result<Self, ()>;
+
+    /// Creates a new frame with an extended identifier (0..=0x1FFF_FFFF).
+    /// Returns an error when the the identifier is not valid.
+    fn new_extended(id: u32, data: &[u8]) -> Result<Self, ()>;
 
     /// Marks this frame as a remote frame (by setting the RTR bit).
     fn with_rtr(&mut self, dlc: usize) -> &mut Self;

From 449b801f74dfe8df19713905d718045c59ff8fed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= <timokroeger93@gmail.com>
Date: Fri, 28 Aug 2020 11:43:34 +0200
Subject: [PATCH 3/8] can: Merge `Transmitter` and `Receiver` traits

---
 src/can.rs | 14 +++-----------
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/src/can.rs b/src/can.rs
index 4f8bd3184..d1bd82bf7 100644
--- a/src/can.rs
+++ b/src/can.rs
@@ -42,8 +42,8 @@ pub trait Frame: Sized {
     fn data(&self) -> &[u8];
 }
 
-/// A CAN interface that is able to transmit frames.
-pub trait Transmitter {
+/// A CAN interface that is able to transmit and receive frames.
+pub trait Can {
     /// Associated frame type.
     type Frame: Frame;
 
@@ -54,16 +54,8 @@ pub trait Transmitter {
     ///
     /// If the buffer is full, this function will try to replace a lower priority frame
     /// and return it. This is to avoid the priority inversion problem.
+    /// Transmits frames of equal identifier in FIFO fashion.
     fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error>;
-}
-
-/// A CAN interface that is able to receive frames.
-pub trait Receiver {
-    /// Associated frame type.
-    type Frame: Frame;
-
-    /// Associated error type.
-    type Error;
 
     /// Returns a received frame if available.
     fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error>;

From 285efaa0dcfcad5773c0759adc42bafd1ab2a1ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= <timokroeger93@gmail.com>
Date: Fri, 28 Aug 2020 20:34:34 +0200
Subject: [PATCH 4/8] can: Use enum for the identifier

---
 src/can.rs | 38 ++++++++++++++++++++++++++++----------
 1 file changed, 28 insertions(+), 10 deletions(-)

diff --git a/src/can.rs b/src/can.rs
index d1bd82bf7..a3609e841 100644
--- a/src/can.rs
+++ b/src/can.rs
@@ -1,17 +1,35 @@
 //! Controller Area Network
 
+/// CAN Identifier
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum Id {
+    /// Standard 11bit Identifier (0..=0x7FF)
+    Standard(u32),
+
+    /// Extended 29bit Identifier (0..=0x1FFF_FFFF)
+    Extended(u32),
+}
+
+impl Id {
+    /// Returs true when the identifier is valid, false otherwise.
+    pub fn valid(self) -> bool {
+        match self {
+            Id::Standard(id) if id <= 0x7FF => true,
+            Id::Extended(id) if id <= 0x1FFF_FFFF => true,
+            _ => false,
+        }
+    }
+}
+
 /// A CAN2.0 Frame
 pub trait Frame: Sized {
-    /// Creates a new frame with a standard identifier (0..=0x7FF).
-    /// Returns an error when the the identifier is not valid.
-    fn new_standard(id: u32, data: &[u8]) -> Result<Self, ()>;
-
-    /// Creates a new frame with an extended identifier (0..=0x1FFF_FFFF).
-    /// Returns an error when the the identifier is not valid.
-    fn new_extended(id: u32, data: &[u8]) -> Result<Self, ()>;
+    /// Creates a new frame.
+    /// Returns an error when the the identifier is not valid or the data slice is too long.
+    fn new(id: Id, data: &[u8]) -> Result<Self, ()>;
 
-    /// Marks this frame as a remote frame (by setting the RTR bit).
-    fn with_rtr(&mut self, dlc: usize) -> &mut Self;
+    /// Creates a new remote frame (RTR bit set).
+    /// Returns an error when the the identifier is  or the data length code (DLC) not valid.
+    fn new_remote(id: Id, dlc: usize) -> Result<Self, ()>;
 
     /// Returns true if this frame is a extended frame.
     fn is_extended(&self) -> bool;
@@ -30,7 +48,7 @@ pub trait Frame: Sized {
     }
 
     /// Returns the frame identifier.
-    fn id(&self) -> u32;
+    fn id(&self) -> Id;
 
     /// Returns the data length code (DLC) which is in the range 0..8.
     ///

From 439242ea01e9f9c8cc2d50316782c74bde01990a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= <timokroeger93@gmail.com>
Date: Tue, 13 Oct 2020 15:37:24 +0200
Subject: [PATCH 5/8] can: `try_` prefixes and improved documentation

---
 src/can.rs | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/src/can.rs b/src/can.rs
index a3609e841..538a993ce 100644
--- a/src/can.rs
+++ b/src/can.rs
@@ -68,13 +68,22 @@ pub trait Can {
     /// Associated error type.
     type Error;
 
-    /// Puts a frame in the transmit buffer.
+    /// Puts a frame in the transmit buffer to be sent on the bus.
     ///
-    /// If the buffer is full, this function will try to replace a lower priority frame
-    /// and return it. This is to avoid the priority inversion problem.
-    /// Transmits frames of equal identifier in FIFO fashion.
-    fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error>;
+    /// If the transmit buffer is full, this function will try to replace a pending
+    /// lower priority frame and return the frame that was replaced.
+    /// Returns `Err(WouldBlock)` if the transmit buffer is full and no frame can be
+    /// replaced.
+    ///
+    /// # Notes for implementers
+    ///
+    /// * Frames of equal identifier shall be transmited in FIFO fashion when more
+    ///   than one transmit buffer is available.
+    /// * When replacing pending frames make sure the frame is not in the process of
+    ///   being send to the bus.
+    fn try_transmit(&mut self, frame: &Self::Frame)
+        -> nb::Result<Option<Self::Frame>, Self::Error>;
 
     /// Returns a received frame if available.
-    fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error>;
+    fn try_receive(&mut self) -> nb::Result<Self::Frame, Self::Error>;
 }

From 95b17a3f84e37b6a34b0432a2d2d0bcca1cf9282 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= <timokroeger93@gmail.com>
Date: Tue, 13 Oct 2020 16:05:33 +0200
Subject: [PATCH 6/8] can: Add blocking API with default implementation

---
 src/blocking/can.rs | 42 ++++++++++++++++++++++++++++++++++++++++++
 src/blocking/mod.rs |  1 +
 2 files changed, 43 insertions(+)
 create mode 100644 src/blocking/can.rs

diff --git a/src/blocking/can.rs b/src/blocking/can.rs
new file mode 100644
index 000000000..d0155fcfa
--- /dev/null
+++ b/src/blocking/can.rs
@@ -0,0 +1,42 @@
+//! Blocking CAN API
+
+/// A blocking CAN interface that is able to transmit and receive frames.
+pub trait Can {
+    /// Associated frame type.
+    type Frame: crate::can::Frame;
+
+    /// Associated error type.
+    type Error;
+
+    /// Puts a frame in the transmit buffer. Blocks until space is available in
+    /// the transmit buffer.
+    fn try_transmit(&mut self, frame: &Self::Frame) -> Result<(), Self::Error>;
+
+    /// Blocks until a frame was received or an error occured.
+    fn try_receive(&mut self) -> Result<Self::Frame, Self::Error>;
+}
+
+/// Default implementation of `blocking::can::Can` for implementers of `can::Can`
+pub trait Default: crate::can::Can {}
+
+impl<S> crate::blocking::can::Can for S
+where
+    S: Default,
+{
+    type Frame = S::Frame;
+    type Error = S::Error;
+
+    fn try_transmit(&mut self, frame: &Self::Frame) -> Result<(), Self::Error> {
+        let mut replaced_frame;
+        let mut frame_to_transmit = frame;
+        while let Some(f) = nb::block!(self.try_transmit(&frame_to_transmit))? {
+            replaced_frame = f;
+            frame_to_transmit = &replaced_frame;
+        }
+        Ok(())
+    }
+
+    fn try_receive(&mut self) -> Result<Self::Frame, Self::Error> {
+        nb::block!(self.try_receive())
+    }
+}
diff --git a/src/blocking/mod.rs b/src/blocking/mod.rs
index 3a050f6d2..e3c132826 100644
--- a/src/blocking/mod.rs
+++ b/src/blocking/mod.rs
@@ -4,6 +4,7 @@
 //! traits. To save boilerplate when that's the case a `Default` marker trait may be provided.
 //! Implementing that marker trait will opt in your type into a blanket implementation.
 
+pub mod can;
 pub mod delay;
 pub mod i2c;
 pub mod rng;

From 103b41e0f41cb7f4bef949323e77ab3139a4703d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= <timokroeger93@gmail.com>
Date: Sat, 14 Nov 2020 10:26:21 +0100
Subject: [PATCH 7/8] Rename blocking trait methods

Use `try_read()` / `try_write()` as suggested by @marcelbuesing
---
 src/blocking/can.rs | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/blocking/can.rs b/src/blocking/can.rs
index d0155fcfa..ca01faa2a 100644
--- a/src/blocking/can.rs
+++ b/src/blocking/can.rs
@@ -10,10 +10,10 @@ pub trait Can {
 
     /// Puts a frame in the transmit buffer. Blocks until space is available in
     /// the transmit buffer.
-    fn try_transmit(&mut self, frame: &Self::Frame) -> Result<(), Self::Error>;
+    fn try_write(&mut self, frame: &Self::Frame) -> Result<(), Self::Error>;
 
     /// Blocks until a frame was received or an error occured.
-    fn try_receive(&mut self) -> Result<Self::Frame, Self::Error>;
+    fn try_read(&mut self) -> Result<Self::Frame, Self::Error>;
 }
 
 /// Default implementation of `blocking::can::Can` for implementers of `can::Can`
@@ -26,7 +26,7 @@ where
     type Frame = S::Frame;
     type Error = S::Error;
 
-    fn try_transmit(&mut self, frame: &Self::Frame) -> Result<(), Self::Error> {
+    fn try_write(&mut self, frame: &Self::Frame) -> Result<(), Self::Error> {
         let mut replaced_frame;
         let mut frame_to_transmit = frame;
         while let Some(f) = nb::block!(self.try_transmit(&frame_to_transmit))? {
@@ -36,7 +36,7 @@ where
         Ok(())
     }
 
-    fn try_receive(&mut self) -> Result<Self::Frame, Self::Error> {
+    fn try_read(&mut self) -> Result<Self::Frame, Self::Error> {
         nb::block!(self.try_receive())
     }
 }

From 7daeaba21a7380b8ce7eaec820fcd4a48159fa7b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= <timokroeger93@gmail.com>
Date: Tue, 17 Nov 2020 19:03:47 +0100
Subject: [PATCH 8/8] can: Only allow valid `Id` s to be constructed

Use newtypes for the enum variants so they cannot be constructed
anymore. Implement the `From` trait for the variants to access the id
value as integer.
https://github.com/timokroeger/embedded-can/pull/7
---
 src/can.rs | 84 +++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 73 insertions(+), 11 deletions(-)

diff --git a/src/can.rs b/src/can.rs
index 538a993ce..d41673357 100644
--- a/src/can.rs
+++ b/src/can.rs
@@ -1,34 +1,96 @@
 //! Controller Area Network
+/// Standard 11bit Identifier (0..=0x7FF)
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct StandardId(u16);
+
+impl StandardId {
+    /// Creates a new standard identifier.
+    pub fn new(id: u16) -> Result<StandardId, ()> {
+        if id <= 0x7FF {
+            Ok(StandardId(id))
+        } else {
+            Err(())
+        }
+    }
+}
+
+impl core::convert::From<StandardId> for u16 {
+    fn from(id: StandardId) -> u16 {
+        id.0
+    }
+}
+
+impl core::convert::From<StandardId> for u32 {
+    fn from(id: StandardId) -> u32 {
+        id.0 as u32
+    }
+}
+
+impl ExtendedId {
+    /// Creates a new extended identifier.
+    pub fn new(id: u32) -> Result<ExtendedId, ()> {
+        if id <= 0x1FFF_FFFF {
+            Ok(ExtendedId(id))
+        } else {
+            Err(())
+        }
+    }
+}
+
+impl core::convert::From<ExtendedId> for u32 {
+    fn from(id: ExtendedId) -> u32 {
+        id.0
+    }
+}
+
+/// Extended 29bit Identifier (0..=0x1FFF_FFFF)
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct ExtendedId(u32);
 
 /// CAN Identifier
+///
+/// The variants are wrapped in newtypes so they can only be costructed with valid values.
 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
 pub enum Id {
     /// Standard 11bit Identifier (0..=0x7FF)
-    Standard(u32),
+    Standard(StandardId),
 
     /// Extended 29bit Identifier (0..=0x1FFF_FFFF)
-    Extended(u32),
+    Extended(ExtendedId),
 }
 
 impl Id {
-    /// Returs true when the identifier is valid, false otherwise.
-    pub fn valid(self) -> bool {
-        match self {
-            Id::Standard(id) if id <= 0x7FF => true,
-            Id::Extended(id) if id <= 0x1FFF_FFFF => true,
-            _ => false,
-        }
+    /// Creates a new standard identifier.
+    pub fn new_standard(id: u16) -> Result<Id, ()> {
+        Ok(StandardId::new(id)?.into())
+    }
+
+    /// Creates a new extended identifier.
+    pub fn new_extended(id: u32) -> Result<Id, ()> {
+        Ok(ExtendedId::new(id)?.into())
+    }
+}
+
+impl core::convert::From<StandardId> for Id {
+    fn from(id: StandardId) -> Id {
+        Id::Standard(id)
+    }
+}
+
+impl core::convert::From<ExtendedId> for Id {
+    fn from(id: ExtendedId) -> Id {
+        Id::Extended(id)
     }
 }
 
 /// A CAN2.0 Frame
 pub trait Frame: Sized {
     /// Creates a new frame.
-    /// Returns an error when the the identifier is not valid or the data slice is too long.
+    /// Returns an error when the data slice is too long.
     fn new(id: Id, data: &[u8]) -> Result<Self, ()>;
 
     /// Creates a new remote frame (RTR bit set).
-    /// Returns an error when the the identifier is  or the data length code (DLC) not valid.
+    /// Returns an error when the data length code (DLC) is not valid.
     fn new_remote(id: Id, dlc: usize) -> Result<Self, ()>;
 
     /// Returns true if this frame is a extended frame.