Skip to content

Commit

Permalink
chore(v0.0.8): separate config into submodule
Browse files Browse the repository at this point in the history
  • Loading branch information
zpg6 committed Jul 5, 2024
1 parent a1f60f6 commit f0fa9dd
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 137 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mcp2003a"
version = "0.0.7"
version = "0.0.8"
description = "Rust no_std LIN Bus communication using the MCP2003A LIN transceiver."
edition = "2021"
license = "MIT"
Expand Down
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,11 @@ Here is an pseudo-code example of how to use to send and receive LIN frames with

```rust
use mcp2003a::{
LinBreakDuration,
LinBusConfig,
LinBusSpeed,
LinReadDeviceResponseTimeout,
LinInterFrameSpace,
Mcp2003a,
Mcp2003aError,
config::{
LinBreakDuration, LinBusConfig, LinBusSpeed, LinInterFrameSpace,
LinReadDeviceResponseTimeout, LinWakeupDuration,
},
Mcp2003a, Mcp2003aError,
};

let uart = // Your embedded-hal-nb UART driver (usually same baudrate as LIN Bus)
Expand Down
129 changes: 129 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/// LIN Break Duration for the MCP2003A transceiver.
/// The specification requires a minimum of 13 bits for the break signal, but the actual underlying
/// implementation of the LIN devices may require more bits for stability (maybe 13 bits + 1 or 2 bits).
#[derive(Clone, Copy, Debug)]
pub enum LinBreakDuration {
Minimum13Bits,
Minimum13BitsPlus(u8),
}

impl LinBreakDuration {
/// Get the duration in nanoseconds for the LIN break duration.
pub fn get_duration_ns(&self, bit_period_ns: u32) -> u32 {
match self {
LinBreakDuration::Minimum13Bits => bit_period_ns * 13,
LinBreakDuration::Minimum13BitsPlus(bits) => bit_period_ns * ((13u8) + bits) as u32,
}
}
}

/// LIN Wakeup Signal Duration for the MCP2003A transceiver.
/// The specification requires a minimum of 250 microseconds for the wakeup signal.
#[derive(Clone, Copy, Debug)]
pub enum LinWakeupDuration {
Minimum250Microseconds,
Minimum250MicrosecondsPlus(u32),
Maximum5Milliseconds,
}

/// How long to wait after sending a read header before reading the response, allowing the slave device to respond.
/// Typically this is a 1-10 ms delay but can vary by system.
#[derive(Clone, Copy, Debug)]
pub enum LinReadDeviceResponseTimeout {
None,
DelayMicroseconds(u32),
DelayMilliseconds(u32),
}

/// How long to wait after sending a frame before sending the next frame.
/// This applies to both sending and receiving frames. Typically, this is 1-2 ms.
#[derive(Clone, Copy, Debug)]
pub enum LinInterFrameSpace {
None,
DelayMicroseconds(u32),
DelayMilliseconds(u32),
}

/// LIN Bus Speeds available for the MCP2003A transceiver in bits per second.
#[derive(Clone, Copy, Debug)]
pub enum LinBusSpeed {
Baud9600,
Baud10400,
Baud19200,
Baud20000,
}

impl LinBusSpeed {
/// Get the baud rate in bits per second for the LIN bus speed, just bridging enum to u32.
pub fn get_baud_rate(&self) -> u32 {
match self {
LinBusSpeed::Baud9600 => 9600,
LinBusSpeed::Baud10400 => 10400,
LinBusSpeed::Baud19200 => 19200,
LinBusSpeed::Baud20000 => 20000,
}
}

/// Get the bit period in nanoseconds for the LIN bus speed. This is the time it takes to send one bit.
pub fn get_bit_period_ns(&self) -> u32 {
1_000_000_000 / self.get_baud_rate()
}
}

/// Configuration for the LIN bus.
#[derive(Clone, Copy, Debug)]
pub struct LinBusConfig {
/// LIN Bus Speed / Baud Rate in bits per second.
pub speed: LinBusSpeed,
/// Duration of the break signal at the beginning of a frame.
pub break_duration: LinBreakDuration,
/// Duration of the wakeup signal at the beginning of communication.
pub wakeup_duration: LinWakeupDuration,
/// How long to wait after sending a read header before reading the response from the device.
pub read_device_response_timeout: LinReadDeviceResponseTimeout,
/// How long to wait after sending a frame before sending the next frame.
pub inter_frame_space: LinInterFrameSpace,
}

impl Default for LinBusConfig {
fn default() -> Self {
LinBusConfig {
speed: LinBusSpeed::Baud19200,
break_duration: LinBreakDuration::Minimum13Bits,
wakeup_duration: LinWakeupDuration::Minimum250Microseconds,
read_device_response_timeout: LinReadDeviceResponseTimeout::DelayMilliseconds(2),
inter_frame_space: LinInterFrameSpace::DelayMilliseconds(1),
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_break_duration() {
let mut config = LinBusConfig {
speed: LinBusSpeed::Baud19200,
break_duration: LinBreakDuration::Minimum13Bits,
wakeup_duration: LinWakeupDuration::Minimum250Microseconds,
read_device_response_timeout: LinReadDeviceResponseTimeout::DelayMilliseconds(2),
inter_frame_space: LinInterFrameSpace::DelayMilliseconds(1),
};

assert_eq!(config.break_duration.get_duration_ns(52_083), 677_079);

config.break_duration = LinBreakDuration::Minimum13BitsPlus(1);
assert_eq!(config.break_duration.get_duration_ns(52_083), 729_162);

config.break_duration = LinBreakDuration::Minimum13BitsPlus(2);
assert_eq!(config.break_duration.get_duration_ns(52_083), 781_245);
}

#[test]
fn test_speed() {
let speed = LinBusSpeed::Baud19200;
assert_eq!(speed.get_baud_rate(), 19200);
assert_eq!(speed.get_bit_period_ns(), 52_083);
}
}
131 changes: 2 additions & 129 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,104 +25,8 @@ use embedded_hal::delay::DelayNs;
use embedded_hal::digital::OutputPin;
use embedded_hal_nb::serial::{Read as UartRead, Write as UartWrite};

/// LIN Break Duration for the MCP2003A transceiver.
/// The specification requires a minimum of 13 bits for the break signal, but the actual underlying
/// implementation of the LIN devices may require more bits for stability (maybe 13 bits + 1 or 2 bits).
#[derive(Clone, Copy, Debug)]
pub enum LinBreakDuration {
Minimum13Bits,
Minimum13BitsPlus(u8),
}

impl LinBreakDuration {
/// Get the duration in nanoseconds for the LIN break duration.
pub fn get_duration_ns(&self, bit_period_ns: u32) -> u32 {
match self {
LinBreakDuration::Minimum13Bits => bit_period_ns * 13,
LinBreakDuration::Minimum13BitsPlus(bits) => bit_period_ns * ((13u8) + bits) as u32,
}
}
}

/// LIN Wakeup Signal Duration for the MCP2003A transceiver.
/// The specification requires a minimum of 250 microseconds for the wakeup signal.
#[derive(Clone, Copy, Debug)]
pub enum LinWakeupDuration {
Minimum250Microseconds,
Minimum250MicrosecondsPlus(u32),
Maximum5Milliseconds,
}

/// How long to wait after sending a read header before reading the response, allowing the slave device to respond.
/// Typically this is a 1-10 ms delay but can vary by system.
#[derive(Clone, Copy, Debug)]
pub enum LinReadDeviceResponseTimeout {
None,
DelayMicroseconds(u32),
DelayMilliseconds(u32),
}

/// How long to wait after sending a frame before sending the next frame.
/// This applies to both sending and receiving frames. Typically, this is 1-2 ms.
#[derive(Clone, Copy, Debug)]
pub enum LinInterFrameSpace {
None,
DelayMicroseconds(u32),
DelayMilliseconds(u32),
}

/// LIN Bus Speeds available for the MCP2003A transceiver in bits per second.
#[derive(Clone, Copy, Debug)]
pub enum LinBusSpeed {
Baud9600,
Baud10400,
Baud19200,
Baud20000,
}

impl LinBusSpeed {
/// Get the baud rate in bits per second for the LIN bus speed, just bridging enum to u32.
pub fn get_baud_rate(&self) -> u32 {
match self {
LinBusSpeed::Baud9600 => 9600,
LinBusSpeed::Baud10400 => 10400,
LinBusSpeed::Baud19200 => 19200,
LinBusSpeed::Baud20000 => 20000,
}
}

/// Get the bit period in nanoseconds for the LIN bus speed. This is the time it takes to send one bit.
pub fn get_bit_period_ns(&self) -> u32 {
1_000_000_000 / self.get_baud_rate()
}
}

/// Configuration for the LIN bus.
#[derive(Clone, Copy, Debug)]
pub struct LinBusConfig {
/// LIN Bus Speed / Baud Rate in bits per second.
pub speed: LinBusSpeed,
/// Duration of the break signal at the beginning of a frame.
pub break_duration: LinBreakDuration,
/// Duration of the wakeup signal at the beginning of communication.
pub wakeup_duration: LinWakeupDuration,
/// How long to wait after sending a read header before reading the response from the device.
pub read_device_response_timeout: LinReadDeviceResponseTimeout,
/// How long to wait after sending a frame before sending the next frame.
pub inter_frame_space: LinInterFrameSpace,
}

impl Default for LinBusConfig {
fn default() -> Self {
LinBusConfig {
speed: LinBusSpeed::Baud19200,
break_duration: LinBreakDuration::Minimum13Bits,
wakeup_duration: LinWakeupDuration::Minimum250Microseconds,
read_device_response_timeout: LinReadDeviceResponseTimeout::DelayMilliseconds(2),
inter_frame_space: LinInterFrameSpace::DelayMilliseconds(1),
}
}
}
pub mod config;
use config::*;

#[derive(Debug)]
pub enum Mcp2003aError<E> {
Expand Down Expand Up @@ -315,34 +219,3 @@ where
Ok(len)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_break_duration() {
let mut config = LinBusConfig {
speed: LinBusSpeed::Baud19200,
break_duration: LinBreakDuration::Minimum13Bits,
wakeup_duration: LinWakeupDuration::Minimum250Microseconds,
read_device_response_timeout: LinReadDeviceResponseTimeout::DelayMilliseconds(2),
inter_frame_space: LinInterFrameSpace::DelayMilliseconds(1),
};

assert_eq!(config.break_duration.get_duration_ns(52_083), 677_079);

config.break_duration = LinBreakDuration::Minimum13BitsPlus(1);
assert_eq!(config.break_duration.get_duration_ns(52_083), 729_162);

config.break_duration = LinBreakDuration::Minimum13BitsPlus(2);
assert_eq!(config.break_duration.get_duration_ns(52_083), 781_245);
}

#[test]
fn test_speed() {
let speed = LinBusSpeed::Baud19200;
assert_eq!(speed.get_baud_rate(), 19200);
assert_eq!(speed.get_bit_period_ns(), 52_083);
}
}

0 comments on commit f0fa9dd

Please sign in to comment.