#![no_std]
use embedded_hal::blocking::delay::DelayUs;
use embedded_hal::blocking::spi;
use embedded_hal::digital::OutputPin;
pub struct SegmentDisplay<SPI, PIN> {
back_buffer: [u8; 4],
spi: SPI,
latch_pin: PIN,
current_digit: usize,
}
impl<SPI, PIN> SegmentDisplay<SPI, PIN>
where
SPI: spi::Write<u8>,
PIN: OutputPin,
{
pub fn new(spi: SPI, latch_pin: PIN) -> Self {
Self {
back_buffer: [0xff; 4],
spi,
latch_pin,
current_digit: 0,
}
}
pub fn release(self) -> (SPI, PIN) {
(self.spi, self.latch_pin)
}
pub fn refresh(&mut self) -> Result<(), SPI::Error> {
let segments_and_select: [u8; 2] = [
self.back_buffer[self.current_digit],
1 << (4 - 1 - self.current_digit),
];
self.current_digit = (self.current_digit + 1) & 0b11;
self.latch_pin.set_low();
let res = self.spi.write(&segments_and_select)?;
self.latch_pin.set_high();
Ok(res)
}
pub fn refresh_with_delay<DELAY>(&mut self, delay: &mut DELAY) -> Result<(), SPI::Error>
where
DELAY: DelayUs<u16>,
{
let segments_and_select: [u8; 2] = [
self.back_buffer[self.current_digit],
1 << (4 - 1 - self.current_digit),
];
self.current_digit = (self.current_digit + 1) & 0b11;
self.latch_pin.set_low();
let res = self.spi.write(&segments_and_select)?;
delay.delay_us(100);
self.latch_pin.set_high();
Ok(res)
}
pub fn write_chars(&mut self, buf: [char; 4]) {
for (i, c) in buf.iter().enumerate() {
self.back_buffer[i] = Self::char_to_segment_code(*c);
}
}
pub fn write_str(&mut self, s: &str) {
self.back_buffer.iter_mut().for_each(|b| *b = !0);
for (i, c) in s.chars().take(4).enumerate() {
self.back_buffer[i] = Self::char_to_segment_code(c);
}
}
pub fn write_number(&mut self, num: usize) {
let mut num = num;
if num > 9999 {
num = 9999;
}
for (i, div) in [1000, 100, 10].iter().enumerate() {
let digit;
if num >= i {
digit = num / div;
num -= div * digit;
} else {
digit = 0;
}
self.back_buffer[i] = NUMERALS[digit];
}
self.back_buffer[3] = NUMERALS[num];
}
fn char_to_segment_code(c: char) -> u8 {
if c.is_ascii_digit() {
let cb = c as u8;
let idx = cb - ('0' as u8);
NUMERALS[idx as usize]
} else if c.is_ascii_alphabetic() {
let cb = (c as u8) & !0x20; let idx = cb - ('A' as u8);
LETTERS[idx as usize]
} else {
match c {
' ' => 0b1111_1111,
'-' => 0b1011_1111,
'_' => 0b1111_0111,
_ => 0b1111_1111,
}
}
}
}
static NUMERALS: [u8; 10] = [
0b1100_0000, 0b1111_1001, 0b1010_0100, 0b1011_0000, 0b1001_1001, 0b1001_0010, 0b1000_0010, 0b1111_1000, 0b1000_0000, 0b1001_1000, ];
static LETTERS: [u8; 26] = [
0b1000_1000, 0b1000_0011, 0b1100_0110, 0b1010_0001, 0b1000_0110, 0b1000_1110, 0b1100_0010, 0b1000_1001, 0b1100_1111, 0b1110_0001, 0b1000_1010, 0b1100_0111, 0b1110_1010, 0b1100_1000, 0b1100_0000, 0b1000_1100, 0b1001_0100, 0b1100_1100, 0b1001_0010, 0b1000_0111, 0b1100_0001, 0b1100_0001, 0b1101_0101, 0b1000_1001, 0b1001_0001, 0b1010_0100, ];