#![no_std]
pub use embedded_hal::digital::OutputPin;
pub mod erased {
pub type SevenSegment<T, Common> = super::SevenSegment<T, T, T, T, T, T, T, Common>;
}
mod sealed {
pub trait Polarity {
fn is_cathode() -> bool;
}
impl Polarity for super::Anode {
fn is_cathode() -> bool {
false
}
}
impl Polarity for super::Cathode {
fn is_cathode() -> bool {
true
}
}
}
pub trait Polarity: sealed::Polarity {}
pub enum Anode {}
pub enum Cathode {}
impl Polarity for Anode {}
impl Polarity for Cathode {}
pub struct SevenSegmentPins<A, B, C, D, E, F, G> {
pub a: A,
pub b: B,
pub c: C,
pub d: D,
pub e: E,
pub f: F,
pub g: G,
}
impl<A, B, C, D, E, F, G> SevenSegmentPins<A, B, C, D, E, F, G> {
pub fn with_common<Common: Polarity>(self) -> SevenSegment<A, B, C, D, E, F, G, Common> {
SevenSegment {
common: Default::default(),
a: self.a,
b: self.b,
c: self.c,
d: self.d,
e: self.e,
f: self.f,
g: self.g,
}
}
pub fn with_common_cathode(self) -> SevenSegment<A, B, C, D, E, F, G, Cathode> {
self.with_common::<Cathode>()
}
pub fn with_common_anode(self) -> SevenSegment<A, B, C, D, E, F, G, Anode> {
self.with_common::<Anode>()
}
}
pub struct SevenSegment<A, B, C, D, E, F, G, Common> {
common: core::marker::PhantomData<Common>,
a: A,
b: B,
c: C,
d: D,
e: E,
f: F,
g: G,
}
impl<A, B, C, D, E, F, G, Common> SevenSegment<A, B, C, D, E, F, G, Common> where
A: OutputPin,
B: OutputPin,
C: OutputPin,
D: OutputPin,
E: OutputPin,
F: OutputPin,
G: OutputPin,
Common: Polarity
{
pub fn set(&mut self, value: u8) {
let mask = match value {
0 => (1, 1, 1, 1, 1, 1, 0),
1 => (0, 1, 1, 0, 0, 0, 0),
2 => (1, 1, 0, 1, 1, 0, 1),
3 => (1, 1, 1, 1, 0, 0, 1),
4 => (0, 1, 1, 0, 0, 1, 1),
5 => (1, 0, 1, 1, 0, 1, 1),
6 => (1, 0, 1, 1, 1, 1, 1),
7 => (1, 1, 1, 0, 0, 0, 0),
8 => (1, 1, 1, 1, 1, 1, 1),
9 => (1, 1, 1, 1, 0, 1, 1),
_ => (0, 0, 0, 0, 0, 0, 0),
};
if mask.0 == Common::is_cathode() as u8 {
self.a.set_high();
} else {
self.a.set_low();
}
if mask.1 == Common::is_cathode() as u8 {
self.b.set_high();
} else {
self.b.set_low();
}
if mask.2 == Common::is_cathode() as u8 {
self.c.set_high();
} else {
self.c.set_low();
}
if mask.3 == Common::is_cathode() as u8 {
self.d.set_high();
} else {
self.d.set_low();
}
if mask.4 == Common::is_cathode() as u8 {
self.e.set_high();
} else {
self.e.set_low();
}
if mask.5 == Common::is_cathode() as u8 {
self.f.set_high();
} else {
self.f.set_low();
}
if mask.6 == Common::is_cathode() as u8 {
self.g.set_high();
} else {
self.g.set_low();
}
}
}
#[cfg(test)]
mod tests {
fn test_digit(digit: u8, expected: (u8, u8, u8, u8, u8, u8, u8)) {
struct TestPin(u8);
impl TestPin {
fn inv(&self) -> u8 {
if self.0 == 0 {
1
} else if self.0 == 1 {
0
} else {
self.0
}
}
}
impl super::OutputPin for &'_ mut TestPin {
fn set_high(&mut self) {
(*self).0 = 1;
}
fn set_low(&mut self) {
(*self).0 = 0;
}
}
let mut a = TestPin(2);
let mut b = TestPin(2);
let mut c = TestPin(2);
let mut d = TestPin(2);
let mut e = TestPin(2);
let mut f = TestPin(2);
let mut g = TestPin(2);
{
let mut seven_segment = super::SevenSegmentPins {
a: &mut a,
b: &mut b,
c: &mut c,
d: &mut d,
e: &mut e,
f: &mut f,
g: &mut g,
}.with_common_anode();
seven_segment.set(digit);
}
assert_eq!((a.inv(), b.inv(), c.inv(), d.inv(), e.inv(), f.inv(), g.inv()), expected);
let mut a = TestPin(2);
let mut b = TestPin(2);
let mut c = TestPin(2);
let mut d = TestPin(2);
let mut e = TestPin(2);
let mut f = TestPin(2);
let mut g = TestPin(2);
{
let mut seven_segment = super::SevenSegmentPins {
a: &mut a,
b: &mut b,
c: &mut c,
d: &mut d,
e: &mut e,
f: &mut f,
g: &mut g,
}.with_common_cathode();
seven_segment.set(digit);
}
assert_eq!((a.0, b.0, c.0, d.0, e.0, f.0, g.0), expected);
}
#[test]
fn digit_0() {
test_digit(0, (1, 1, 1, 1, 1, 1, 0));
}
#[test]
fn digit_1() {
test_digit(1, (0, 1, 1, 0, 0, 0, 0));
}
#[test]
fn digit_2() {
test_digit(2, (1, 1, 0, 1, 1, 0, 1));
}
#[test]
fn digit_3() {
test_digit(3, (1, 1, 1, 1, 0, 0, 1));
}
#[test]
fn digit_4() {
test_digit(4, (0, 1, 1, 0, 0, 1, 1));
}
#[test]
fn digit_5() {
test_digit(5, (1, 0, 1, 1, 0, 1, 1));
}
#[test]
fn digit_6() {
test_digit(6, (1, 0, 1, 1, 1, 1, 1));
}
#[test]
fn digit_7() {
test_digit(7, (1, 1, 1, 0, 0, 0, 0));
}
#[test]
fn digit_8() {
test_digit(8, (1, 1, 1, 1, 1, 1, 1));
}
#[test]
fn digit_9() {
test_digit(9, (1, 1, 1, 1, 0, 1, 1));
}
#[test]
fn digit_invalid() {
test_digit(10, (0, 0, 0, 0, 0, 0, 0));
}
}