From c804d5a10e3a7fe1457c3bcc63c51e30e9cf89e9 Mon Sep 17 00:00:00 2001 From: Determinant Date: Sun, 22 Oct 2017 22:55:01 -0400 Subject: add panels and time editing --- src/ds3231.rs | 66 ++++--- src/main.rs | 544 +++++++++++++++++++++++++++++++++++++++++++++++----------- src/tim.rs | 16 +- 3 files changed, 498 insertions(+), 128 deletions(-) diff --git a/src/ds3231.rs b/src/ds3231.rs index bd23fdd..fd96fed 100644 --- a/src/ds3231.rs +++ b/src/ds3231.rs @@ -2,6 +2,7 @@ use i2c::{I2C, TransDir, DutyType}; const DS3231_ADDR: u8 = 0b1101000; const DS3231_REG_SEC: u8 = 0x00; +const DS3231_REG_DATE: u8 = 0x04; const DS3231_REG_CTL: u8 = 0x0e; const DS3231_REG_TEMP: u8 = 0x11; @@ -24,15 +25,16 @@ pub struct Temp { pub quarter: u8 } -impl<'a> DS3231<'a> { - fn bcd2dec(bcd: u8) -> u8 { - (bcd >> 4) * 10 + (bcd & 0x0f) - } +fn bcd2dec(bcd: u8) -> u8 { + (bcd >> 4) * 10 + (bcd & 0x0f) +} + +fn dec2bcd(dec: u8) -> u8 { + ((dec / 10) << 4) | (dec % 10) +} - fn dec2bcd(dec: u8) -> u8 { - ((dec / 10) << 4) | (dec % 10) - } +impl<'a> DS3231<'a> { fn read_register(&self, start: u8, size: usize, buf: &mut [u8]){ let &DS3231(ref i2c) = self; i2c.conf_ack(true); /* enable ack */ @@ -69,16 +71,16 @@ impl<'a> DS3231<'a> { let hour = if am_enabled { (buf[2] & 0x0f) + ((buf[2] >> 4) & 1) * 10 } else { - DS3231::bcd2dec(buf[2]) + bcd2dec(buf[2]) }; let am = if am_enabled {(buf[2] >> 5) & 1 == 0} else {hour < 12}; - Date{second: DS3231::bcd2dec(buf[0]), - minute: DS3231::bcd2dec(buf[1]), + Date{second: bcd2dec(buf[0]), + minute: bcd2dec(buf[1]), hour, - day: DS3231::bcd2dec(buf[3]), - date: DS3231::bcd2dec(buf[4]), - month: DS3231::bcd2dec(buf[5]), - year: DS3231::bcd2dec(buf[6]), + day: bcd2dec(buf[3]), + date: bcd2dec(buf[4]), + month: bcd2dec(buf[5]), + year: bcd2dec(buf[6]), am, am_enabled} } @@ -88,16 +90,36 @@ impl<'a> DS3231<'a> { (1 << 6) | ((if date.am {0} else {1}) << 5) | ((date.hour / 10) << 4) | (date.hour % 10) } else { - DS3231::dec2bcd(date.hour) + dec2bcd(date.hour) }; - let buf: [u8; 7] = [DS3231::dec2bcd(date.second), - DS3231::dec2bcd(date.minute), + let buf: [u8; 7] = [dec2bcd(date.second), + dec2bcd(date.minute), hour, - DS3231::dec2bcd(date.day), - DS3231::dec2bcd(date.date), - DS3231::dec2bcd(date.month), - DS3231::dec2bcd(date.year)]; - self.write_register(DS3231_REG_SEC, 7, &buf); + dec2bcd(date.day), + dec2bcd(date.date), + dec2bcd(date.month), + dec2bcd(date.year)]; + self.write_register(DS3231_REG_SEC, buf.len(), &buf); + } + + pub fn write_time(&self, date: &Date) { + let hour = if date.am_enabled { + (1 << 6) | ((if date.am {0} else {1}) << 5) | + ((date.hour / 10) << 4) | (date.hour % 10) + } else { + dec2bcd(date.hour) + }; + let buf: [u8; 3] = [dec2bcd(date.second), + dec2bcd(date.minute), + hour]; + self.write_register(DS3231_REG_SEC, buf.len(), &buf); + } + + pub fn write_date(&self, date: &Date) { + let buf: [u8; 3] = [dec2bcd(date.date), + dec2bcd(date.month), + dec2bcd(date.year)]; + self.write_register(DS3231_REG_DATE, buf.len(), &buf); } pub fn write_control(&self) { diff --git a/src/main.rs b/src/main.rs index 9df73cf..673dd01 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ #![no_std] #![feature(asm)] +#![feature(const_fn)] #[macro_use] extern crate stm32f103xx; extern crate cortex_m; @@ -7,6 +8,7 @@ extern crate cortex_m; use stm32f103xx::{GPIOA, GPIOB, RCC, SYST, I2C1, EXTI, NVIC, Interrupt, AFIO, Peripherals}; use stm32f103xx::{gpioa}; use cortex_m::peripheral::SystClkSource; +use core::cell::{Cell, RefCell}; mod mutex; mod i2c; @@ -15,136 +17,502 @@ mod at24c; mod tim; const SYNC_PERIOD: u8 = 10; +const BLINK_PERIOD: u32 = 500; + +fn digits2bcds(digs: &[u8]) -> u32 { + let mut res: u32 = 0; + for d in digs.iter().rev() { + res = (res << 4) | (*d as u32); + } + res +} struct ShiftRegister<'a> { gpioa: &'a gpioa::RegisterBlock, width: u8, } -struct Clock { +#[derive(Copy, Clone)] +struct Time { sec: u8, min: u8, hr: u8, - reset: u8 } struct GlobalState { disp: Option>, i2c: Option>, - tim: Option>, + btn1: Option>, + //tim: Option>, i2c_inited: bool, - buff: [u8; 6], - time: Clock, + sync_cnt: u8, + buff: RefCell<[u8; 6]>, + blinky: RefCell<[bool; 6]>, + blink_state: Cell, perip: Option>, - bs: bool + disp_on: bool, + pidx: usize, + panels: [&'static Panel; 2], +} + +struct Button<'a> { + state: Cell, + long: Cell, + timer: tim::Timer<'a> +} + +enum ButtonResult { + FALSE_ALARM, + SHORT_PRESS, + LONG_PRSSS +} + +impl<'a> Button<'a> { + fn new(timer: tim::Timer<'a>, thres: u32) -> Self { + /* in milliseconds */ + timer.init(thres * (8_000_000 / 1000)); + Button {state: Cell::new(false), + long: Cell::new(false), + timer} + } + + fn press(&self) { + if !self.state.get() { + self.state.set(true); + self.long.set(false); + self.timer.reset(); + self.timer.go(); + } + } + + fn release(&self) -> ButtonResult { + if self.state.get() { + self.timer.stop(); + self.state.set(false); + if self.long.get() { ButtonResult::LONG_PRSSS } + else { ButtonResult::SHORT_PRESS } + } else { ButtonResult::FALSE_ALARM } + } + + fn timeout(&self) { + self.timer.stop(); + self.long.set(true); + } +} + +trait Panel { + fn btn1_short(&self) -> bool {false} + fn btn1_long(&self) -> bool {false} + fn btn2_short(&self) -> bool {false} + fn btn2_long(&self) -> bool {false} + fn update_output(&self); +} + +#[derive(PartialEq, Clone, Copy)] +enum TimePanelState { + VIEW, + EDIT_HR, + EDIT_MIN, + EDIT_SEC +} + +struct TimePanel<'a> { + gs: &'a GlobalState, + state: Cell, + time: RefCell