#![no_std]
use embedded_hal as hal;
use hal::digital::v2::{InputPin, OutputPin};
#[derive(Debug)]
pub enum TmError {
Dio,
Ack(u8),
Clk,
Empty,
}
#[inline]
fn tm_bus_dio_wait_ack<DIO, D>(
dio: &mut DIO,
bus_delay: &mut D,
expect_high: bool,
err: u8,
) -> Result<(), TmError>
where
DIO: InputPin + OutputPin,
D: FnMut() -> (),
{
for _ in 0..5 {
if expect_high == dio.is_high().map_err(|_| TmError::Dio)? {
return Ok(());
}
bus_delay();
}
Err(TmError::Ack(err))
}
#[inline]
fn tm_bus_start<DIO, CLK, D>(dio: &mut DIO, clk: &mut CLK, bus_delay: &mut D) -> Result<(), TmError>
where
DIO: InputPin + OutputPin,
CLK: OutputPin,
D: FnMut() -> (),
{
dio.set_low().map_err(|_| TmError::Dio)?;
bus_delay();
Ok(())
}
#[inline]
fn tm_bus_stop<DIO, CLK, D>(dio: &mut DIO, clk: &mut CLK, bus_delay: &mut D) -> Result<(), TmError>
where
DIO: InputPin + OutputPin,
CLK: OutputPin,
D: FnMut() -> (),
{
dio.set_low().map_err(|_| TmError::Dio)?;
bus_delay();
clk.set_high().map_err(|_| TmError::Clk)?;
bus_delay();
dio.set_high().map_err(|_| TmError::Dio)?;
tm_bus_dio_wait_ack(dio, bus_delay, true, 255)?;
bus_delay();
Ok(())
}
#[inline]
fn tm_bus_send<DIO, CLK, D>(
dio: &mut DIO,
clk: &mut CLK,
bus_delay: &mut D,
mut byte: u8,
) -> Result<(), TmError>
where
DIO: InputPin + OutputPin,
CLK: OutputPin,
D: FnMut() -> (),
{
for _ in 0..8 {
clk.set_low().map_err(|_| TmError::Clk)?;
bus_delay();
let high = byte & 0b1 != 0;
byte = byte >> 1;
if high {
dio.set_high().map_err(|_| TmError::Dio)?;
} else {
dio.set_low().map_err(|_| TmError::Dio)?;
}
bus_delay();
clk.set_high().map_err(|_| TmError::Clk)?;
bus_delay();
}
Ok(())
}
#[inline]
fn tm_bus_ack<DIO, CLK, D>(
dio: &mut DIO,
clk: &mut CLK,
bus_delay: &mut D,
err_code: u8,
) -> Result<(), TmError>
where
DIO: InputPin + OutputPin,
CLK: OutputPin,
D: FnMut() -> (),
{
dio.set_high().map_err(|_| TmError::Dio)?;
clk.set_low().map_err(|_| TmError::Clk)?;
bus_delay();
tm_bus_dio_wait_ack(dio, bus_delay, false, err_code + 1)?;
clk.set_high().map_err(|_| TmError::Clk)?;
bus_delay();
tm_bus_dio_wait_ack(dio, bus_delay, false, err_code + 2)?;
clk.set_low().map_err(|_| TmError::Clk)?;
bus_delay();
tm_bus_dio_wait_ack(dio, bus_delay, true, err_code + 3)?;
Ok(())
}
#[inline]
fn tm_bus_send_byte<DIO, CLK, D>(
dio: &mut DIO,
clk: &mut CLK,
bus_delay: &mut D,
byte: u8,
err_code: u8,
) -> Result<(), TmError>
where
DIO: InputPin + OutputPin,
CLK: OutputPin,
D: FnMut() -> (),
{
tm_bus_send(dio, clk, bus_delay, byte)?;
tm_bus_ack(dio, clk, bus_delay, err_code)
}
#[inline]
pub fn tm_send_bytes<DIO, CLK, D>(
dio: &mut DIO,
clk: &mut CLK,
bus_delay: &mut D,
bytes: &[u8],
) -> Result<(), TmError>
where
DIO: InputPin + OutputPin,
CLK: OutputPin,
D: FnMut() -> (),
{
tm_bus_start(dio, clk, bus_delay)?;
let mut send = Err(TmError::Empty);
let mut iter = 10;
for bt in bytes {
send = tm_bus_send_byte(dio, clk, bus_delay, bt.clone(), iter);
if send.is_err() {
break;
}
iter += 10;
}
let stop = tm_bus_stop(dio, clk, bus_delay);
if send.is_err() {
send
} else {
stop
}
}
pub const BUS_DELAY_US: u16 = 500;
pub const BUS_DELAY_US_FAST: u16 = 350;
pub const COM_DATA_ADDRESS_ADD: u8 = 0b01000000;
pub const COM_DATA_ADDRESS_FIXED: u8 = 0b01000100;
pub const COM_DATA_READ: u8 = 0b01000010;
pub const COM_ADDRESS: u8 = 0b11000000;
pub const COM_DISPLAY_ON: u8 = 0b10001000;
pub const DISPLAY_BRIGHTNESS_MASK: u8 = 0b00000111;
pub const COM_DISPLAY_OFF: u8 = 0b10000000;
pub const SEG_1: u8 = 0b1;
pub const SEG_2: u8 = 0b10;
pub const SEG_3: u8 = 0b100;
pub const SEG_4: u8 = 0b1000;
pub const SEG_5: u8 = 0b10000;
pub const SEG_6: u8 = 0b100000;
pub const SEG_7: u8 = 0b1000000;
pub const SEG_8: u8 = 0b10000000;
pub const CHAR_0: u8 = SEG_1 | SEG_2 | SEG_3 | SEG_4 | SEG_5 | SEG_6;
pub const CHAR_1: u8 = SEG_2 | SEG_3;
pub const CHAR_2: u8 = SEG_1 | SEG_2 | SEG_4 | SEG_5 | SEG_7;
pub const CHAR_3: u8 = SEG_1 | SEG_2 | SEG_3 | SEG_4 | SEG_7;
pub const CHAR_4: u8 = SEG_2 | SEG_3 | SEG_6 | SEG_7;
pub const CHAR_5: u8 = SEG_1 | SEG_3 | SEG_4 | SEG_6 | SEG_7;
pub const CHAR_6: u8 = SEG_1 | SEG_3 | SEG_4 | SEG_5 | SEG_6 | SEG_7;
pub const CHAR_7: u8 = SEG_1 | SEG_2 | SEG_3;
pub const CHAR_8: u8 = SEG_1 | SEG_2 | SEG_3 | SEG_4 | SEG_5 | SEG_6 | SEG_7;
pub const CHAR_9: u8 = SEG_1 | SEG_2 | SEG_3 | SEG_4 | SEG_6 | SEG_7;
pub const CHAR_A: u8 = SEG_1 | SEG_2 | SEG_3 | SEG_5 | SEG_6 | SEG_7;
pub const CHAR_a: u8 = SEG_1 | SEG_2 | SEG_3 | SEG_4 | SEG_5 | SEG_7;
pub const CHAR_b: u8 = SEG_3 | SEG_4 | SEG_5 | SEG_6 | SEG_7;
pub const CHAR_C: u8 = SEG_1 | SEG_4 | SEG_5 | SEG_6;
pub const CHAR_c: u8 = SEG_4 | SEG_5 | SEG_7;
pub const CHAR_d: u8 = SEG_2 | SEG_3 | SEG_4 | SEG_5 | SEG_7;
pub const CHAR_E: u8 = SEG_1 | SEG_4 | SEG_5 | SEG_6 | SEG_7;
pub const CHAR_e: u8 = SEG_1 | SEG_2 | SEG_4 | SEG_5 | SEG_6 | SEG_7;
pub const CHAR_F: u8 = SEG_1 | SEG_5 | SEG_6 | SEG_7;
pub const CHAR_G: u8 = SEG_1 | SEG_3 | SEG_4 | SEG_5 | SEG_6;
pub const CHAR_g: u8 = SEG_1 | SEG_2 | SEG_3 | SEG_4 | SEG_6 | SEG_7;
pub const CHAR_H: u8 = SEG_2 | SEG_3 | SEG_5 | SEG_6 | SEG_7;
pub const CHAR_h: u8 = SEG_3 | SEG_5 | SEG_6 | SEG_7;
pub const CHAR_I: u8 = SEG_2 | SEG_3;
pub const CHAR_i: u8 = SEG_3;
pub const CHAR_J: u8 = SEG_2 | SEG_3 | SEG_4 | SEG_5;
pub const CHAR_L: u8 = SEG_4 | SEG_5 | SEG_6;
pub const CHAR_l: u8 = SEG_4 | SEG_5;
pub const CHAR_N: u8 = SEG_1 | SEG_2 | SEG_3 | SEG_5 | SEG_6;
pub const CHAR_n: u8 = SEG_3 | SEG_5 | SEG_7;
pub const CHAR_O: u8 = SEG_1 | SEG_2 | SEG_3 | SEG_4 | SEG_5 | SEG_6;
pub const CHAR_o: u8 = SEG_3 | SEG_4 | SEG_5 | SEG_7;
pub const CHAR_P: u8 = SEG_1 | SEG_2 | SEG_5 | SEG_6 | SEG_7;
pub const CHAR_q: u8 = SEG_1 | SEG_2 | SEG_3 | SEG_6 | SEG_7;
pub const CHAR_R: u8 = SEG_1 | SEG_5 | SEG_6;
pub const CHAR_r: u8 = SEG_5 | SEG_7;
pub const CHAR_S: u8 = SEG_1 | SEG_3 | SEG_4 | SEG_6 | SEG_7;
pub const CHAR_t: u8 = SEG_4 | SEG_5 | SEG_6 | SEG_7;
pub const CHAR_U: u8 = SEG_2 | SEG_3 | SEG_4 | SEG_5 | SEG_6;
pub const CHAR_u: u8 = SEG_3 | SEG_4 | SEG_5;
pub const CHAR_y: u8 = SEG_2 | SEG_3 | SEG_4 | SEG_6 | SEG_7;
pub const CHAR_E_MIRROR: u8 = SEG_1 | SEG_2 | SEG_3 | SEG_4 | SEG_7;
pub const CHAR_DEGREE: u8 = SEG_1 | SEG_2 | SEG_6 | SEG_7;
pub const CHAR_MINUS: u8 = SEG_7;
pub const CHAR_UNDERSCORE: u8 = SEG_4;
pub const CHAR_BRACKET_LEFT: u8 = SEG_1 | SEG_4 | SEG_5 | SEG_6;
pub const CHAR_BRACKET_RIGHT: u8 = SEG_1 | SEG_2 | SEG_3 | SEG_4;
pub const CHARS: [u8; 47] = [
CHAR_0,
CHAR_1,
CHAR_2,
CHAR_3,
CHAR_4,
CHAR_5,
CHAR_6,
CHAR_7,
CHAR_8,
CHAR_9,
CHAR_A,
CHAR_a,
CHAR_b,
CHAR_C,
CHAR_c,
CHAR_d,
CHAR_E,
CHAR_e,
CHAR_F,
CHAR_G,
CHAR_g,
CHAR_H,
CHAR_h,
CHAR_I,
CHAR_i,
CHAR_J,
CHAR_L,
CHAR_l,
CHAR_N,
CHAR_n,
CHAR_O,
CHAR_o,
CHAR_P,
CHAR_q,
CHAR_R,
CHAR_r,
CHAR_S,
CHAR_t,
CHAR_U,
CHAR_u,
CHAR_y,
CHAR_E_MIRROR,
CHAR_DEGREE,
CHAR_MINUS,
CHAR_UNDERSCORE,
CHAR_BRACKET_LEFT,
CHAR_BRACKET_RIGHT,
];