Files
sinclair-sci-calc/src/display.rs

263 lines
6.8 KiB
Rust

use core::ops::{Index, IndexMut};
use arduino_hal::{
hal::port::{PB0, PB1, PB2, PC0, PC4, PC5, PD5, PD6},
port::{mode::Output, Pin},
};
use crate::DISPLAY_SEGMENTS;
pub struct SegmentPins {
kd_seg_a: Pin<Output, PD5>,
kd_seg_b: Pin<Output, PB0>,
kd_seg_c: Pin<Output, PB2>,
kd_seg_d: Pin<Output, PC5>,
kd_seg_e: Pin<Output, PB1>,
kd_seg_f: Pin<Output, PD6>,
kd_seg_g: Pin<Output, PC0>,
kd_seg_dp: Pin<Output, PC4>,
}
impl SegmentPins {
pub fn new(
kd_seg_a: Pin<Output, PD5>,
kd_seg_b: Pin<Output, PB0>,
kd_seg_c: Pin<Output, PB2>,
kd_seg_d: Pin<Output, PC5>,
kd_seg_e: Pin<Output, PB1>,
kd_seg_f: Pin<Output, PD6>,
kd_seg_g: Pin<Output, PC0>,
kd_seg_dp: Pin<Output, PC4>,
) -> SegmentPins {
let mut out = SegmentPins {
kd_seg_a,
kd_seg_b,
kd_seg_c,
kd_seg_d,
kd_seg_e,
kd_seg_f,
kd_seg_g,
kd_seg_dp,
};
out.set_off();
out
}
pub fn set_off(&mut self) {
self.kd_seg_a.set_high();
self.kd_seg_b.set_high();
self.kd_seg_c.set_high();
self.kd_seg_d.set_high();
self.kd_seg_e.set_high();
self.kd_seg_f.set_high();
self.kd_seg_g.set_high();
self.kd_seg_dp.set_high();
}
pub fn set_a(&mut self) {
self.kd_seg_a.set_low();
}
pub fn set_b(&mut self) {
self.kd_seg_b.set_low();
}
pub fn set_c(&mut self) {
self.kd_seg_c.set_low();
}
pub fn set_d(&mut self) {
self.kd_seg_d.set_low();
}
pub fn set_e(&mut self) {
self.kd_seg_e.set_low();
}
pub fn set_f(&mut self) {
self.kd_seg_f.set_low();
}
pub fn set_g(&mut self) {
self.kd_seg_g.set_low();
}
pub fn set_dp(&mut self) {
self.kd_seg_dp.set_low();
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum SegmentState {
Num(u8, bool),
Minus,
Prompt(bool),
Dot,
Off,
}
impl SegmentState {
pub fn apply(&self, seg: &mut SegmentPins) {
seg.set_off();
match self {
SegmentState::Num(no, dp) => {
match no {
0 => {
seg.set_a();
seg.set_b();
seg.set_c();
seg.set_d();
seg.set_e();
seg.set_f();
}
1 => {
seg.set_b();
seg.set_c();
}
2 => {
seg.set_a();
seg.set_b();
seg.set_g();
seg.set_e();
seg.set_d();
}
3 => {
seg.set_a();
seg.set_b();
seg.set_g();
seg.set_c();
seg.set_d();
}
4 => {
seg.set_f();
seg.set_g();
seg.set_b();
seg.set_c();
}
5 => {
seg.set_a();
seg.set_f();
seg.set_g();
seg.set_c();
seg.set_d();
}
6 => {
seg.set_a();
seg.set_f();
seg.set_g();
seg.set_c();
seg.set_d();
seg.set_e();
}
7 => {
seg.set_a();
seg.set_b();
seg.set_c();
}
8 => {
seg.set_a();
seg.set_b();
seg.set_c();
seg.set_d();
seg.set_e();
seg.set_f();
seg.set_g();
}
9 => {
seg.set_a();
seg.set_b();
seg.set_c();
seg.set_d();
seg.set_f();
seg.set_g();
}
_ => panic!("SegmentState::Num out of range"),
}
if *dp {
seg.set_dp()
}
}
SegmentState::Minus => seg.set_g(),
SegmentState::Dot => seg.set_dp(),
SegmentState::Prompt(dot) => {
seg.set_d();
if *dot {
seg.set_dp()
}
}
SegmentState::Off => (),
}
}
}
pub struct DispalyState([SegmentState; DISPLAY_SEGMENTS]);
impl Default for DispalyState {
fn default() -> DispalyState {
DispalyState([
SegmentState::Off,
SegmentState::Off,
SegmentState::Off,
SegmentState::Off,
SegmentState::Off,
SegmentState::Off,
SegmentState::Off,
SegmentState::Off,
SegmentState::Off,
])
}
}
impl Index<usize> for DispalyState {
type Output = SegmentState;
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
impl IndexMut<usize> for DispalyState {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.0[index]
}
}
impl DispalyState {
pub fn iter_segments(&self) -> impl Iterator<Item = &SegmentState> {
self.0.iter()
}
}
impl DispalyState {
fn set(&mut self, seg: [SegmentState; DISPLAY_SEGMENTS]) {
self.0 = seg;
}
pub fn prompt(&mut self) {
self.set([
SegmentState::Prompt(false),
SegmentState::Prompt(true),
SegmentState::Prompt(false),
SegmentState::Prompt(false),
SegmentState::Prompt(false),
SegmentState::Prompt(false),
SegmentState::Prompt(false),
SegmentState::Prompt(false),
SegmentState::Prompt(false),
])
}
pub fn error(&mut self) {
self.set([
SegmentState::Off,
SegmentState::Dot,
SegmentState::Off,
SegmentState::Off,
SegmentState::Off,
SegmentState::Off,
SegmentState::Off,
SegmentState::Off,
SegmentState::Off,
])
}
}
// Show data on segment display
pub trait Show {
fn show(&self, display: &mut DispalyState);
}