#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Mode {
Mode0,
Mode1,
Mode2,
Mode3,
}
impl Mode {
pub fn number(self) -> u8 {
match self {
Mode::Mode0 => 0,
Mode::Mode1 => 1,
Mode::Mode2 => 2,
Mode::Mode3 => 3,
}
}
pub fn from_number(number: u8) -> Option<Mode> {
match number {
0 => Some(Mode::Mode0),
1 => Some(Mode::Mode1),
2 => Some(Mode::Mode2),
3 => Some(Mode::Mode3),
_ => None,
}
}
pub fn cpol_cpha(self) -> (bool, bool) {
match self {
Mode::Mode0 => (false, false),
Mode::Mode1 => (false, true),
Mode::Mode2 => (true, false),
Mode::Mode3 => (true, true),
}
}
pub fn from_cpol_cpha(cpol: bool, cpha: bool) -> Mode {
match (cpol, cpha) {
(false, false) => Mode::Mode0,
(false, true) => Mode::Mode1,
(true, false) => Mode::Mode2,
(true, true) => Mode::Mode3,
}
}
pub fn clock_idles_high(self) -> bool {
self.cpol_cpha().0
}
pub fn samples_on_trailing_edge(self) -> bool {
self.cpol_cpha().1
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum BitOrder {
MsbFirst,
LsbFirst,
}
#[cfg(test)]
mod tests {
use super::*;
const ALL: [Mode; 4] = [Mode::Mode0, Mode::Mode1, Mode::Mode2, Mode::Mode3];
#[test]
fn number_round_trips() {
for mode in ALL {
assert_eq!(Mode::from_number(mode.number()), Some(mode));
}
assert_eq!(Mode::from_number(4), None);
}
#[test]
fn number_is_cpol_shifted_over_cpha() {
for mode in ALL {
let (cpol, cpha) = mode.cpol_cpha();
assert_eq!(mode.number(), (u8::from(cpol) << 1) | u8::from(cpha));
}
}
#[test]
fn cpol_cpha_round_trips() {
for mode in ALL {
let (cpol, cpha) = mode.cpol_cpha();
assert_eq!(Mode::from_cpol_cpha(cpol, cpha), mode);
}
}
#[test]
fn the_named_pairs_are_correct() {
assert_eq!(Mode::Mode0.cpol_cpha(), (false, false));
assert_eq!(Mode::Mode1.cpol_cpha(), (false, true));
assert_eq!(Mode::Mode2.cpol_cpha(), (true, false));
assert_eq!(Mode::Mode3.cpol_cpha(), (true, true));
assert!(!Mode::Mode0.clock_idles_high() && !Mode::Mode0.samples_on_trailing_edge());
assert!(Mode::Mode3.clock_idles_high() && Mode::Mode3.samples_on_trailing_edge());
}
}