diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 660 |
1 files changed, 320 insertions, 340 deletions
diff --git a/src/main.rs b/src/main.rs index 1d26662..f8e0a7f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,8 @@ extern crate cortex_m; use stm32f103xx::{Interrupt, Peripherals, gpioa}; -use core::cell::{Cell, RefCell, UnsafeCell, RefMut}; +use core::cell::{Cell, UnsafeCell}; +use core::mem::uninitialized; mod mutex; mod i2c; @@ -15,6 +16,11 @@ mod ds3231; mod at24c; mod tim; +#[inline(always)] +fn get_gs() -> &'static mut GlobalState<'static> { + unsafe {GS.as_mut().unwrap()} +} + #[inline] fn digits2bcds(digs: &[u8]) -> u32 { let mut res: u32 = 0; @@ -36,14 +42,14 @@ fn countdown(n: u32) -> u32 { if n > 0 { n - 1 } else { n } } -fn render1(mut buff: RefMut<[u8; 6]>, mut n: u32) { +fn render1(buff: &mut [u8; 6], mut n: u32) { for i in 0..buff.len() { buff[i] = (n % 10) as u8; n /= 10; } } -fn render3(mut buff: RefMut<[u8; 6]>, n1: u8, n2: u8, n3: u8) { +fn render3(buff: &mut [u8; 6], n1: u8, n2: u8, n3: u8) { buff[1] = n3 / 10; buff[0] = n3 - buff[1] * 10; buff[3] = n2 / 10; buff[2] = n2 - buff[3] * 10; buff[5] = n1 / 10; buff[4] = n1 - buff[5] * 10; @@ -69,24 +75,29 @@ enum DispState { } struct GlobalState<'a> { - perip: Option<Peripherals<'a>>, - disp: Option<ShiftRegister<'a>>, - btn1: Option<Button<'a>>, - btn2: Option<Button<'a>>, - events: Option<AlarmEventManager<'a>>, - i2c: Option<i2c::I2C<'a>>, - i2c_inited: bool, + perip: Peripherals<'a>, + disp: ShiftRegister<'a>, + btn1: Button<'a>, + btn2: Button<'a>, + events: EventTimer<'a>, + i2c: i2c::I2C<'a>, sync_cnt: Cell<u8>, - buff: RefCell<[u8; 6]>, + buff: [u8; 6], disp_state: Cell<DispState>, tempon_cycle: Cell<u16>, tempon_peroid: Cell<u16>, tempon_cnt: Cell<u16>, - blinky: RefCell<[bool; 6]>, + blinky: [bool; 6], blink_state: Cell<bool>, blinky_enabled: Cell<Option<u8>>, pidx: usize, - panels: [&'a Panel<'a>; 6], + time_panel: TimePanel, + date_panel: DatePanel, + temp_panel: TempPanel, + cd_panel: CountdownPanel, + cu_panel: CountupPanel, + set_panel: SettingPanel, + panels: [&'a mut Panel<'a>; 6], } #[derive(Clone, Copy)] @@ -108,7 +119,7 @@ enum ButtonMode { struct Button<'a> { state: Cell<ButtonState>, long: Cell<bool>, - events: &'a AlarmEventManager<'a>, + events: &'a EventTimer<'a>, ev_id: Cell<u8>, mode: Cell<ButtonMode> } @@ -120,17 +131,17 @@ enum ButtonResult { } trait Panel<'a> { - fn btn1_press(&'a self) -> bool { - self.get_gs().btn1.as_ref().unwrap().press(ButtonMode::Release); + fn btn1_press(&'a mut self) -> bool { + get_gs().btn1.press(ButtonMode::Release); true } - fn btn1_release_extra(&self) {} + fn btn1_release_extra(&mut self) {} - fn btn1_release(&'a self) -> bool { + fn btn1_release(&'a mut self) -> bool { self.btn1_release_extra(); - let gs = self.get_gs(); - let btn1 = gs.btn1.as_ref().unwrap(); + let gs = get_gs(); + let btn1 = &gs.btn1; match btn1.release() { ButtonResult::FalseAlarm => true, ButtonResult::ShortPress => self.btn1_short(), @@ -142,11 +153,10 @@ trait Panel<'a> { } } - 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 get_gs(&'a self) -> &GlobalState<'a>; + fn btn1_short(&mut self) -> bool {false} + fn btn1_long(&mut self) -> bool {false} + fn btn2_short(&mut self) -> bool {false} + fn btn2_long(&mut self) -> bool {false} fn update_output(&self); } @@ -163,11 +173,10 @@ enum TimePanelState { EditSec, } -struct TimePanel<'a> { - gs: &'a GlobalState<'a>, +struct TimePanel { state: Cell<TimePanelState>, - time: RefCell<Time>, - tmp: RefCell<Time>, + time: Time, + tmp: Time, blink_enabled: Cell<bool> } @@ -187,11 +196,10 @@ enum DatePanelState { EditDay } -struct DatePanel<'a> { - gs: &'a GlobalState<'a>, +struct DatePanel { state: Cell<DatePanelState>, - date: RefCell<Date>, - tmp: RefCell<Date>, + date: Date, + tmp: Date, blink_enabled: Cell<bool> } @@ -201,10 +209,9 @@ enum TempPanelState { View } -struct TempPanel<'a> { +struct TempPanel { state: Cell<TempPanelState>, - temp: Cell<ds3231::Temp>, - gs: &'a GlobalState<'a>, + temp: Cell<ds3231::Temp> } #[derive(Clone, Copy)] @@ -220,13 +227,12 @@ enum CountdownPanelState { TimeUp } -struct CountdownPanel<'a> { +struct CountdownPanel { state: Cell<CountdownPanelState>, - presets: RefCell<[(u8, u8, u8); 4]>, + presets: [(u8, u8, u8); 4], counter: Cell<u32>, didx: Cell<u8>, - blink_enabled: Cell<bool>, - gs: &'a GlobalState<'a>, + blink_enabled: Cell<bool> } #[derive(Clone, Copy)] @@ -237,10 +243,9 @@ enum CountupPanelState { OnGoingPaused } -struct CountupPanel<'a> { +struct CountupPanel { state: Cell<CountupPanelState>, - counter: Cell<u32>, - gs: &'a GlobalState<'a>, + counter: Cell<u32> } #[derive(Clone, Copy)] @@ -260,11 +265,10 @@ enum SettingIdx { TempOnPeroid } -struct SettingPanel<'a> { +struct SettingPanel { state: Cell<SettingPanelState>, - tmp: RefCell<[u8; 6]>, - idx: Cell<SettingIdx>, - gs: &'a GlobalState<'a>, + tmp: [u8; 6], + idx: Cell<SettingIdx> } #[derive(Clone, Copy)] @@ -274,7 +278,7 @@ struct AlarmEvent<'a> { free: bool } -struct AlarmEventManager<'a> { +struct EventTimer<'a> { events: UnsafeCell<[AlarmEvent<'a>; 8]> } @@ -359,7 +363,7 @@ impl<'a> Timeoutable<'a> for Button<'a> { } impl<'a> Button<'a> { - fn new(events: &'a AlarmEventManager<'a>) -> Self { + fn new(events: &'a EventTimer<'a>) -> Self { Button {state: Cell::new(ButtonState::Idle), long: Cell::new(false), ev_id: Cell::new(0), @@ -404,10 +408,10 @@ impl<'a> Button<'a> { } } -impl<'a> Panel<'a> for TimePanel<'a> { - fn btn1_press(&'a self) -> bool { +impl<'a> Panel<'a> for TimePanel { + fn btn1_press(&'a mut self) -> bool { use TimePanelState::*; - self.gs.btn1.as_ref().unwrap().press(match self.state.get() { + get_gs().btn1.press(match self.state.get() { EditHr | EditMin | EditSec => { self.blink_enabled.set(false); self.update_output(); @@ -418,7 +422,7 @@ impl<'a> Panel<'a> for TimePanel<'a> { true } - fn btn1_release_extra(&self) { + fn btn1_release_extra(&mut self) { use TimePanelState::*; match self.state.get() { EditHr | EditMin | EditSec => { @@ -429,10 +433,10 @@ impl<'a> Panel<'a> for TimePanel<'a> { } } - fn btn1_short(&self) -> bool { + fn btn1_short(&mut self) -> bool { use TimePanelState::*; { - let mut tmp = self.tmp.borrow_mut(); + let tmp = &mut self.tmp; match self.state.get() { View => { self.state.set(Inactive); @@ -448,12 +452,12 @@ impl<'a> Panel<'a> for TimePanel<'a> { true } - fn btn2_short(&self) -> bool { + fn btn2_short(&mut self) -> bool { use TimePanelState::*; let s = match self.state.get() { View => { - let mut tmp = self.tmp.borrow_mut(); - let time = self.time.borrow(); + let tmp = &mut self.tmp; + let time = &mut self.time; tmp.hr = time.hr; tmp.min = time.min; tmp.sec = time.sec; @@ -462,10 +466,10 @@ impl<'a> Panel<'a> for TimePanel<'a> { EditHr => EditMin, EditMin => EditSec, EditSec => { - let tmp = self.tmp.borrow(); - ds3231::DS3231(self.gs.i2c.as_ref().unwrap()) + let tmp = &self.tmp; + ds3231::DS3231(&get_gs().i2c) .write_time(tmp.hr, tmp.min, tmp.sec); - *self.time.borrow_mut() = *tmp; + self.time = *tmp; View }, s => s @@ -478,7 +482,7 @@ impl<'a> Panel<'a> for TimePanel<'a> { fn update_output(&self) { use TimePanelState::*; let s = self.state.get(); - self.gs.update_blinky( + get_gs().update_blinky( if self.blink_enabled.get() { match s { EditHr => 0b110000, @@ -489,22 +493,21 @@ impl<'a> Panel<'a> for TimePanel<'a> { } else { 0x0 }); - let time = self.time.borrow(); - let tmp = self.tmp.borrow(); + let gs = get_gs(); + let time = &self.time; + let tmp = &self.tmp; match s { - View => self.gs.render3(time.hr, time.min, time.sec), - _ => self.gs.render3(tmp.hr, tmp.min, tmp.sec) - }; - self.gs.display(); + View => gs.render3(time.hr, time.min, time.sec), + _ => gs.render3(tmp.hr, tmp.min, tmp.sec) + } + gs.display(); } - - fn get_gs(&'a self) -> &GlobalState<'a> { self.gs } } -impl<'a> TimePanel<'a> { - fn update_clock(&self, clk: Option<Time>) { - let mut time = self.time.borrow_mut(); - let gs = self.gs; +impl TimePanel { + fn update_clock(&mut self, clk: Option<Time>) { + let time = &mut self.time; + let gs = get_gs(); match clk { Some(clk) => *time = clk, None => time.tick() @@ -516,10 +519,10 @@ impl<'a> TimePanel<'a> { } } -impl<'a> Panel<'a> for DatePanel<'a> { - fn btn1_press(&'a self) -> bool { +impl<'a> Panel<'a> for DatePanel { + fn btn1_press(&'a mut self) -> bool { use DatePanelState::*; - self.gs.btn1.as_ref().unwrap().press(match self.state.get() { + get_gs().btn1.press(match self.state.get() { EditYr | EditMon | EditDay => { self.blink_enabled.set(false); self.update_output(); @@ -530,7 +533,7 @@ impl<'a> Panel<'a> for DatePanel<'a> { true } - fn btn1_release_extra(&self) { + fn btn1_release_extra(&mut self) { use DatePanelState::*; match self.state.get() { EditYr | EditMon | EditDay => { @@ -541,10 +544,10 @@ impl<'a> Panel<'a> for DatePanel<'a> { } } - fn btn1_short(&self) -> bool { + fn btn1_short(&mut self) -> bool { use DatePanelState::*; { - let mut tmp = self.tmp.borrow_mut(); + let tmp = &mut self.tmp; match self.state.get() { View => { self.state.set(Inactive); @@ -560,12 +563,12 @@ impl<'a> Panel<'a> for DatePanel<'a> { true } - fn btn2_short(&self) -> bool { + fn btn2_short(&mut self) -> bool { use DatePanelState::*; let s = match self.state.get() { View => { - let date = self.date.borrow(); - let mut tmp = self.tmp.borrow_mut(); + let date = &self.date; + let tmp = &mut self.tmp; tmp.yr = date.yr; tmp.mon = date.mon; tmp.day = date.day; @@ -574,10 +577,10 @@ impl<'a> Panel<'a> for DatePanel<'a> { EditYr => EditMon, EditMon => EditDay, EditDay => { - let tmp = self.tmp.borrow(); - ds3231::DS3231(self.gs.i2c.as_ref().unwrap()) + let tmp = &self.tmp; + ds3231::DS3231(&get_gs().i2c) .write_date(tmp.yr, tmp.mon, tmp.day); - *self.date.borrow_mut() = *tmp; + self.date = *tmp; View }, s => s @@ -590,7 +593,7 @@ impl<'a> Panel<'a> for DatePanel<'a> { fn update_output(&self) { use DatePanelState::*; let s = self.state.get(); - self.gs.update_blinky( + get_gs().update_blinky( if self.blink_enabled.get() { match s { EditYr => 0b110000, @@ -601,34 +604,34 @@ impl<'a> Panel<'a> for DatePanel<'a> { } else { 0x0 }); - let date = self.date.borrow(); - let tmp = self.tmp.borrow(); + let gs = get_gs(); + let date = &self.date; + let tmp = &self.tmp; match s { - View => self.gs.render3(date.yr, date.mon, date.day), - _ => self.gs.render3(tmp.yr, tmp.mon, tmp.day) + View => gs.render3(date.yr, date.mon, date.day), + _ => gs.render3(tmp.yr, tmp.mon, tmp.day) }; - self.gs.display(); + gs.display(); } - - fn get_gs(&'a self) -> &GlobalState<'a> { self.gs } } -impl<'a> DatePanel<'a> { - fn update_clock(&self, d: Option<Date>) { - let mut date = self.date.borrow_mut(); +impl DatePanel { + fn update_clock(&mut self, d: Option<Date>) { + let date = &mut self.date; match d { Some(d) => *date = d, None => () } if let DatePanelState::View = self.state.get() { - self.gs.render3(date.yr, date.mon, date.day); - self.gs.display(); + let gs = get_gs(); + gs.render3(date.yr, date.mon, date.day); + gs.display(); } } } -impl<'a> Panel<'a> for TempPanel<'a> { - fn btn1_short(&self) -> bool { +impl<'a> Panel<'a> for TempPanel { + fn btn1_short(&mut self) -> bool { use TempPanelState::*; match self.state.get() { View => { @@ -660,15 +663,14 @@ impl<'a> Panel<'a> for TempPanel<'a> { } buff[1] = q / 10; buff[0] = q - 10 * buff[1]; - *self.gs.buff.borrow_mut() = buff; - self.gs.display(); + let gs = get_gs(); + gs.buff = buff; + gs.display(); } - - fn get_gs(&'a self) -> &GlobalState<'a> { self.gs } } -impl<'a> TempPanel<'a> { - fn update_clock(&self, temp: Option<ds3231::Temp>) { +impl TempPanel { + fn update_clock(&mut self, temp: Option<ds3231::Temp>) { match temp { Some(temp) => self.temp.set(temp), None => () @@ -679,10 +681,10 @@ impl<'a> TempPanel<'a> { } } -impl<'a> Panel<'a> for CountdownPanel<'a> { - fn btn1_press(&'a self) -> bool { +impl<'a> Panel<'a> for CountdownPanel { + fn btn1_press(&'a mut self) -> bool { use CountdownPanelState::*; - self.gs.btn1.as_ref().unwrap().press(match self.state.get() { + get_gs().btn1.press(match self.state.get() { Edit3 | Edit2 | Edit1 => { self.blink_enabled.set(false); self.update_output(); @@ -697,7 +699,7 @@ impl<'a> Panel<'a> for CountdownPanel<'a> { true } - fn btn1_release_extra(&self) { + fn btn1_release_extra(&mut self) { use CountdownPanelState::*; match self.state.get() { Edit3 | Edit2 | Edit1 => { @@ -708,13 +710,13 @@ impl<'a> Panel<'a> for CountdownPanel<'a> { } } - fn btn1_short(&self) -> bool { + fn btn1_short(&mut self) -> bool { use CountdownPanelState::*; - let tim = self.gs.perip.as_ref().unwrap().TIM3; + let tim = get_gs().perip.TIM3; let timer = tim::Timer(tim); { let didx = self.didx.get(); - let mut presets = self.presets.borrow_mut(); + let presets = &mut self.presets; let len = presets.len() as u8; let p = &mut presets[didx as usize]; match self.state.get() { @@ -746,7 +748,7 @@ impl<'a> Panel<'a> for CountdownPanel<'a> { true } - fn btn2_long(&self) -> bool { + fn btn2_long(&mut self) -> bool { use CountdownPanelState::*; self.state.set(match self.state.get() { OnGoing => OnGoing, @@ -761,7 +763,7 @@ impl<'a> Panel<'a> for CountdownPanel<'a> { true } - fn btn2_short(&self) -> bool { + fn btn2_short(&mut self) -> bool { use CountdownPanelState::*; self.state.set(match self.state.get() { View => EditWhole, @@ -782,7 +784,7 @@ impl<'a> Panel<'a> for CountdownPanel<'a> { fn update_output(&self) { use CountdownPanelState::*; let s = self.state.get(); - self.gs.update_blinky( + get_gs().update_blinky( if self.blink_enabled.get() { match s { EditWhole | TimeUp => 0b111111, @@ -794,37 +796,36 @@ impl<'a> Panel<'a> for CountdownPanel<'a> { } else { 0x0 }); + let gs = get_gs(); match s { - OnGoing | OnGoingPaused => self.gs.render1(self.counter.get()), + OnGoing | OnGoingPaused => gs.render1(self.counter.get()), _ => { - let preset = &self.presets.borrow()[self.didx.get() as usize]; - self.gs.render3(preset.0, preset.1, preset.2); + let preset = &self.presets[self.didx.get() as usize]; + gs.render3(preset.0, preset.1, preset.2); } } - self.gs.display(); + gs.display(); } - - fn get_gs(&'a self) -> &GlobalState<'a> { self.gs } } -impl<'a> CountdownPanel<'a> { +impl CountdownPanel { fn go(&self) { - let tim = self.gs.perip.as_ref().unwrap().TIM3; + let tim = get_gs().perip.TIM3; let timer = tim::Timer(tim); - let (p0, p1, p2) = self.presets.borrow()[self.didx.get() as usize]; + let (p0, p1, p2) = self.presets[self.didx.get() as usize]; let x = (p0 as u32) * 10000 + (p1 as u32) * 100 + (p2 as u32); self.counter.set(x); timer.reset(); timer.go(); } - fn update_clock(&self) { + fn update_clock(&mut self) { if let CountdownPanelState::Inactive = self.state.get() { return } let x = countdown(self.counter.get()); if x == 0 { - let tim = self.gs.perip.as_ref().unwrap().TIM3; + let tim = get_gs().perip.TIM3; let timer = tim::Timer(tim); timer.stop(); self.state.set(CountdownPanelState::TimeUp); @@ -835,10 +836,10 @@ impl<'a> CountdownPanel<'a> { } } -impl<'a> Panel<'a> for CountupPanel<'a> { - fn btn1_short(&self) -> bool { +impl<'a> Panel<'a> for CountupPanel { + fn btn1_short(&mut self) -> bool { use CountupPanelState::*; - let tim = self.gs.perip.as_ref().unwrap().TIM3; + let tim = get_gs().perip.TIM3; let timer = tim::Timer(tim); match self.state.get() { View => { @@ -859,9 +860,9 @@ impl<'a> Panel<'a> for CountupPanel<'a> { true } - fn btn2_short(&self) -> bool { + fn btn2_short(&mut self) -> bool { use CountupPanelState::*; - let tim = self.gs.perip.as_ref().unwrap().TIM3; + let tim = get_gs().perip.TIM3; let timer = tim::Timer(tim); self.state.set(match self.state.get() { View => { @@ -879,19 +880,18 @@ impl<'a> Panel<'a> for CountupPanel<'a> { fn update_output(&self) { use CountupPanelState::*; - self.gs.update_blinky(match self.state.get() { + get_gs().update_blinky(match self.state.get() { View => 0b111111, _ => 0x0 }); - self.gs.render1(self.counter.get()); - self.gs.display(); + let gs = get_gs(); + gs.render1(self.counter.get()); + gs.display(); } - - fn get_gs(&'a self) -> &GlobalState<'a> { self.gs } } -impl<'a> CountupPanel<'a> { - fn update_clock(&self) { +impl CountupPanel { + fn update_clock(&mut self) { if let CountupPanelState::Inactive = self.state.get(){ return } @@ -901,32 +901,33 @@ impl<'a> CountupPanel<'a> { } } -impl<'a> SettingPanel<'a> { - fn render_idx(&self, d: RefMut<[u8; 6]>) { - render1(d, match self.idx.get() { - SettingIdx::TempOnCycle => self.gs.tempon_cycle.get(), - SettingIdx::TempOnPeroid => self.gs.tempon_peroid.get() +impl SettingPanel { + fn render_idx(&mut self) { + let gs = get_gs(); + render1(&mut self.tmp, match self.idx.get() { + SettingIdx::TempOnCycle => gs.tempon_cycle.get(), + SettingIdx::TempOnPeroid => gs.tempon_peroid.get() } as u32); } fn set_idx(&self) { let mut x: u32 = 0; - for v in self.tmp.borrow().iter().rev() { + let gs = get_gs(); + for v in self.tmp.iter().rev() { x *= 10; x += *v as u32; } match self.idx.get() { - SettingIdx::TempOnCycle => self.gs.tempon_cycle.set(x as u16), - SettingIdx::TempOnPeroid => self.gs.tempon_peroid.set(x as u16) + SettingIdx::TempOnCycle => gs.tempon_cycle.set(x as u16), + SettingIdx::TempOnPeroid => gs.tempon_peroid.set(x as u16) } } } -impl<'a> Panel<'a> for SettingPanel<'a> { - fn btn1_short(&self) -> bool { +impl<'a> Panel<'a> for SettingPanel { + fn btn1_short(&mut self) -> bool { use SettingPanelState::*; { - let mut d = self.tmp.borrow_mut(); match self.state.get() { View => { self.state.set(Inactive); @@ -937,14 +938,14 @@ impl<'a> Panel<'a> for SettingPanel<'a> { SettingIdx::TempOnCycle => SettingIdx::TempOnPeroid, SettingIdx::TempOnPeroid => SettingIdx::TempOnCycle }); - self.render_idx(d); + self.render_idx(); }, - Edit3 => inc_rotate(&mut d[3], 0, 10), - Edit2 => inc_rotate(&mut d[2], 0, 10), - Edit1 => inc_rotate(&mut d[1], 0, 10), - Edit0 => inc_rotate(&mut d[0], 0, 10), + Edit3 => inc_rotate(&mut self.tmp[3], 0, 10), + Edit2 => inc_rotate(&mut self.tmp[2], 0, 10), + Edit1 => inc_rotate(&mut self.tmp[1], 0, 10), + Edit0 => inc_rotate(&mut self.tmp[0], 0, 10), Inactive => { - self.render_idx(d); + self.render_idx(); self.state.set(View); } } @@ -953,7 +954,7 @@ impl<'a> Panel<'a> for SettingPanel<'a> { true } - fn btn2_short(&self) -> bool { + fn btn2_short(&mut self) -> bool { use SettingPanelState::*; self.state.set(match self.state.get() { View => { @@ -970,7 +971,7 @@ impl<'a> Panel<'a> for SettingPanel<'a> { true } - fn btn2_long(&self) -> bool { + fn btn2_long(&mut self) -> bool { use SettingPanelState::*; self.state.set(match self.state.get() { View => View, @@ -984,7 +985,7 @@ impl<'a> Panel<'a> for SettingPanel<'a> { fn update_output(&self) { use SettingPanelState::*; let s = self.state.get(); - self.gs.update_blinky(match s { + get_gs().update_blinky(match s { SettingChoice => 0b111111, Edit3 => 0b001000, Edit2 => 0b000100, @@ -992,19 +993,19 @@ impl<'a> Panel<'a> for SettingPanel<'a> { Edit0 => 0b000001, _ => 0x0 }); - self.gs.render(&*self.tmp.borrow()); - self.gs.display(); + let gs = get_gs(); + gs.render(&self.tmp); + gs.display(); } - - fn get_gs(&'a self) -> &GlobalState<'a> { self.gs } } -impl<'a> AlarmEventManager<'a> { +impl<'a> EventTimer<'a> { fn new() -> Self { unsafe { - AlarmEventManager{events: UnsafeCell::new([AlarmEvent{cb: core::mem::uninitialized(), - cnt: 0, - free: true}; 8]) } + EventTimer{events: UnsafeCell::new([ + AlarmEvent{cb: uninitialized(), + cnt: 0, + free: true}; 8])} } } @@ -1044,21 +1045,21 @@ impl<'a> AlarmEventManager<'a> { impl<'a> GlobalState<'a> { - fn render(&self, nbuff: &[u8; 6]) { - self.buff.borrow_mut().copy_from_slice(nbuff); + fn render(&mut self, nbuff: &[u8; 6]) { + self.buff.copy_from_slice(nbuff); } - fn render1(&self, n: u32) { - render1(self.buff.borrow_mut(), n); + fn render1(&mut self, n: u32) { + render1(&mut self.buff, n); } - fn render3(&self, n1: u8, n2: u8, n3: u8) { - render3(self.buff.borrow_mut(), n1, n2, n3); + fn render3(&mut self, n1: u8, n2: u8, n3: u8) { + render3(&mut self.buff, n1, n2, n3); } fn display(&self) { - let mut buff = *self.buff.borrow(); + let mut buff = self.buff; let b = self.blink_state.get(); - let bs = self.blinky.borrow(); + let bs = self.blinky; match self.disp_state.get() { DispState::On | DispState::TempOn => for (i, v) in buff.iter_mut().enumerate() { @@ -1066,16 +1067,16 @@ impl<'a> GlobalState<'a> { }, DispState::Off => for i in buff.iter_mut() { *i = 0xf; } } - self.disp.as_ref().unwrap().output_bits(digits2bcds(&buff[..])); + self.disp.output_bits(digits2bcds(&buff[..])); } - fn update_blinky(&'a self, nb: u8) { + fn update_blinky(&'a mut self, nb: u8) { let flag = nb == 0; /* if nothing is blinking */ let en = self.blinky_enabled.get(); - for (i, v) in self.blinky.borrow_mut().iter_mut().enumerate() { + for (i, v) in self.blinky.iter_mut().enumerate() { *v = ((nb >> i) & 1) == 1; } - let ev = self.events.as_ref().unwrap(); + let ev = &self.events; if flag { if let Some(ev_id) = en { self.blink_state.set(false); @@ -1092,7 +1093,7 @@ impl<'a> GlobalState<'a> { fn digits_countup(&self) { self.display(); - let mut buff = *self.buff.borrow(); + let mut buff = self.buff; let mut i = 0; let mut carry = 1; while carry > 0 && i < buff.len() { @@ -1103,83 +1104,77 @@ impl<'a> GlobalState<'a> { } - fn update_clock(&self) { + fn systick_handler() { + let gs = get_gs(); let mut clk = None; let mut d = None; let mut temp = None; - if self.sync_cnt.get() == 0 { - let rtc = ds3231::DS3231(self.i2c.as_ref().unwrap()); + if gs.sync_cnt.get() == 0 { + let rtc = ds3231::DS3231(&gs.i2c); let ds3231::Date{second: sec, minute: min, hour: hr, date: day, month: mon, year: yr, ..} = rtc.read_fulldate(); - self.sync_cnt.set(SYNC_PERIOD); + gs.sync_cnt.set(SYNC_PERIOD); clk = Some(Time{sec, min, hr}); d = Some(Date{yr, mon, day}); temp = Some(rtc.read_temperature()); } else { - self.sync_cnt.set(self.sync_cnt.get() - 1); + gs.sync_cnt.set(gs.sync_cnt.get() - 1); } - let tcnt = countdown(self.tempon_cnt.get() as u32) as u16; - match self.disp_state.get() { + let tcnt = countdown(gs.tempon_cnt.get() as u32) as u16; + match gs.disp_state.get() { DispState::Off => { if tcnt == 0 { - self.disp_state.set(DispState::TempOn); - self.tempon_cnt.set(self.tempon_peroid.get()); + gs.disp_state.set(DispState::TempOn); + gs.tempon_cnt.set(gs.tempon_peroid.get()); } else { - self.tempon_cnt.set(tcnt); + gs.tempon_cnt.set(tcnt); } }, DispState::TempOn => { if tcnt == 0 { - self.disp_state.set(DispState::Off); - self.tempon_cnt.set(self.tempon_cycle.get()); + gs.disp_state.set(DispState::Off); + gs.tempon_cnt.set(gs.tempon_cycle.get()); } else { - self.tempon_cnt.set(tcnt); + gs.tempon_cnt.set(tcnt); } }, _ => () } - unsafe { - TIME_PANEL.update_clock(clk); - DATE_PANEL.update_clock(d); - TEMP_PANEL.update_clock(temp); - } + gs.time_panel.update_clock(clk); + gs.date_panel.update_clock(d); + gs.temp_panel.update_clock(temp); } #[inline(always)] fn tim4_callback() { let gs = get_gs(); { - let p = gs.perip.as_ref().unwrap(); + let p = &gs.perip; p.TIM4.sr.modify(|_, w| w.uif().clear()); } - match gs.events.as_ref() { - Some(ev) => ev.tick(), - None => () - } + gs.events.tick(); } #[inline(always)] fn tim3_callback() { let gs = get_gs(); { - let p = gs.perip.as_ref().unwrap(); + let p = &gs.perip; p.TIM3.sr.modify(|_, w| w.uif().clear()); } - unsafe { - CD_PANEL.update_clock(); - CU_PANEL.update_clock(); - } + gs.cd_panel.update_clock(); + gs.cu_panel.update_clock(); } #[inline(always)] fn exti3_handler() { let gs = get_gs(); - let p = gs.perip.as_ref().unwrap(); + let p = &gs.perip; p.EXTI.pr.write(|w| w.pr3().set_bit()); let x = p.GPIOA.idr.read().idr3().bit(); match gs.disp_state.get() { @@ -1191,6 +1186,7 @@ impl<'a> GlobalState<'a> { false => gs.panels[gs.pidx].btn1_press(), true => gs.panels[gs.pidx].btn1_release()}) { + let gs = get_gs(); /* swtich the sub state machine */ gs.pidx += 1; if gs.pidx == gs.panels.len() { @@ -1204,8 +1200,8 @@ impl<'a> GlobalState<'a> { #[inline(always)] fn exti4_handler() { let gs = get_gs(); - let btn2 = gs.btn2.as_ref().unwrap(); - let p = gs.perip.as_ref().unwrap(); + let btn2 = &gs.btn2; + let p = &gs.perip; p.EXTI.pr.write(|w| w.pr4().set_bit()); let x = p.GPIOA.idr.read().idr4().bit(); if !x { @@ -1224,7 +1220,7 @@ impl<'a> GlobalState<'a> { impl<'a> Timeoutable<'a> for GlobalState<'a> { fn timeout(&'a self) { - let ev = self.events.as_ref().unwrap(); + let ev = &self.events; self.blink_state.set(!self.blink_state.get()); self.display(); if self.blinky_enabled.get().is_some() { @@ -1233,19 +1229,7 @@ impl<'a> Timeoutable<'a> for GlobalState<'a> { } } -#[inline(always)] -fn get_gs() -> &'static mut GlobalState<'static> { - unsafe {&mut GS} -} - -fn systick_handler() { - // digits_countup(); - let gs = get_gs(); - if !gs.i2c_inited {return} - gs.update_clock(); -} - -exception!(SYS_TICK, systick_handler); +exception!(SYS_TICK, GlobalState::systick_handler); interrupt!(EXTI4, GlobalState::exti4_handler); interrupt!(EXTI3, GlobalState::exti3_handler); interrupt!(TIM4, GlobalState::tim4_callback); @@ -1256,122 +1240,47 @@ const BLINK_PERIOD: u32 = 500; const BUTTON_PRESSLOCK_PEROID: u32 = 50; const BUTTON_LONGPRESS_THRES: u32 = 500; const BUTTON_CONT_CYCLE: u32 = 100; +const SYSTICK_CYCLE: u32 = 8_000_000; -static mut TIME_PANEL: TimePanel = TimePanel{ - state: Cell::new(TimePanelState::View), - tmp: RefCell::new(Time{sec: 0, min: 0, hr: 0}), - time: RefCell::new(Time{sec: 0, min: 0, hr: 0}), - blink_enabled: Cell::new(true), - gs: unsafe{&GS} -}; - -static mut DATE_PANEL: DatePanel = DatePanel{ - state: Cell::new(DatePanelState::Inactive), - tmp: RefCell::new(Date{yr: 0, mon: 1, day: 1}), - date: RefCell::new(Date{yr: 0, mon: 1, day: 1}), - blink_enabled: Cell::new(true), - gs: unsafe{&GS} -}; - -static mut TEMP_PANEL: TempPanel = TempPanel{ - state: Cell::new(TempPanelState::Inactive), - temp: Cell::new(ds3231::Temp{cels: 0, quarter: 0}), - gs: unsafe{&GS} -}; - -static mut CD_PANEL: CountdownPanel = CountdownPanel{ - state: Cell::new(CountdownPanelState::Inactive), - presets: RefCell::new([(0, 0, 0); 4]), - counter: Cell::new(0), - didx: Cell::new(0), - blink_enabled: Cell::new(true), - gs: unsafe{&GS} -}; - -static mut CU_PANEL: CountupPanel = CountupPanel{ - state: Cell::new(CountupPanelState::Inactive), - counter: Cell::new(0), - gs: unsafe{&GS} -}; - -static mut SET_PANEL: SettingPanel = SettingPanel{ - state: Cell::new(SettingPanelState::Inactive), - tmp: RefCell::new([9; 6]), - idx: Cell::new(SettingIdx::TempOnCycle), - gs: unsafe{&GS} -}; - -static mut GS: GlobalState = - GlobalState{perip: None, - disp: None, - btn1: None, - btn2: None, - events: None, - i2c: None, - i2c_inited: false, - sync_cnt: Cell::new(0), - buff: RefCell::new([0; 6]), - disp_state: Cell::new(DispState::On), - tempon_cycle: Cell::new(20), - tempon_peroid: Cell::new(5), - tempon_cnt: Cell::new(0), - blinky: RefCell::new([false; 6]), - blink_state: Cell::new(false), - blinky_enabled: Cell::new(None), - pidx: 0, - panels: unsafe {[&TIME_PANEL, &DATE_PANEL, &TEMP_PANEL, - &CD_PANEL, &CU_PANEL, &SET_PANEL]} - }; - -fn init() { - let gs = get_gs(); - let p = { - gs.perip = Some(unsafe {Peripherals::all()}); - gs.perip.as_ref().unwrap() - }; +static mut GS: Option<GlobalState> = None; +fn init_hardware() { + let p = unsafe {Peripherals::all()}; p.SYST.set_clock_source(cortex_m::peripheral::SystClkSource::Core); - p.SYST.set_reload(8_000_000); - p.SYST.enable_interrupt(); - p.SYST.enable_counter(); - - /* enable GPIOA, GPIOB and AFIO */ - p.RCC.apb2enr.modify(|_, w| w.iopaen().enabled() - .iopben().enabled() - .afioen().enabled()); - + p.SYST.set_reload(SYSTICK_CYCLE); + + /* RCC */ + /* enable clock for GPIOA, GPIOB and AFIO */ + p.RCC.apb2enr.modify(|_, w| w.iopaen().enabled() /* GPIOA */ + .iopben().enabled() /* GPIOB */ + .afioen().enabled()); /* I2C AFIO */ + /* enable timers */ p.RCC.apb1enr.modify(|_, w| w.tim4en().enabled() .tim3en().enabled()); + /* enable and reset I2C1 */ + p.RCC.apb1enr.modify(|_, w| w.i2c1en().enabled()); + p.RCC.apb1rstr.modify(|_, w| w.i2c1rst().set_bit()); + p.RCC.apb1rstr.modify(|_, w| w.i2c1rst().clear_bit()); /* GPIO */ - /* enable PA0-2 for manipulating shift register */ + /* set button operating mode to pull down */ p.GPIOA.odr.modify(|_, w| w.odr3().set_bit() .odr4().set_bit()); + /* enable PA0-2 for manipulating shift register */ p.GPIOA.crl.modify(|_, w| - w.mode0().output().cnf0().push() - .mode1().output().cnf1().push() - .mode2().output().cnf2().push() - .mode3().input().cnf3().bits(0b10) - .mode4().input().cnf4().bits(0b10)); - + w.mode0().output().cnf0().push() /* disp bit */ + .mode1().output().cnf1().push() /* disp shift */ + .mode2().output().cnf2().push() /* disp latch */ + .mode3().input().cnf3().bits(0b10) /* button 1 */ + .mode4().input().cnf4().bits(0b10)); /* button 2 */ /* enable PB6 and PB7 for I2C1 */ p.GPIOB.crl.modify(|_, w| w.mode6().output50().cnf6().alt_open() .mode7().output50().cnf7().alt_open()); - /* I2C */ - /* enable and reset I2C1 */ - p.RCC.apb1enr.modify(|_, w| w.i2c1en().enabled()); - p.RCC.apb1rstr.modify(|_, w| w.i2c1rst().set_bit()); - p.RCC.apb1rstr.modify(|_, w| w.i2c1rst().clear_bit()); - - /* NVIC & EXTI */ + /* EXTI */ p.AFIO.exticr1.write(|w| unsafe { w.exti3().bits(0b0000) }); p.AFIO.exticr2.write(|w| unsafe { w.exti4().bits(0b0000) }); - p.NVIC.enable(Interrupt::EXTI3); - p.NVIC.enable(Interrupt::EXTI4); - p.NVIC.enable(Interrupt::TIM3); - p.NVIC.enable(Interrupt::TIM4); p.EXTI.imr.write(|w| w.mr3().set_bit() .mr4().set_bit()); p.EXTI.rtsr.write(|w| w.tr3().set_bit() @@ -1379,28 +1288,99 @@ fn init() { p.EXTI.ftsr.write(|w| w.tr3().set_bit() .tr4().set_bit()); + /* NVIC */ + p.NVIC.enable(Interrupt::EXTI3); + p.NVIC.enable(Interrupt::EXTI4); + p.NVIC.enable(Interrupt::TIM3); + p.NVIC.enable(Interrupt::TIM4); +} - gs.i2c = Some(i2c::I2C(p.I2C1)); - gs.disp = Some(ShiftRegister::new(p.GPIOA, 24)); - gs.i2c.as_ref().unwrap().init(p.RCC, 0x01, 400_000, i2c::DutyType::DUTY1, true); - //i2c.init(0x01, 100_000, i2c::DutyType::DUTY1, false); - gs.disp.as_ref().unwrap().output_bits(0); - gs.i2c_inited = true; +fn init() { + unsafe { + GS = Some(GlobalState{ + perip: Peripherals::all(), + btn1: uninitialized(), + btn2: uninitialized(), + events: EventTimer::new(), + i2c: uninitialized(), + disp: uninitialized(), + sync_cnt: Cell::new(0), + buff: [0; 6], + disp_state: Cell::new(DispState::On), + tempon_cycle: Cell::new(20), + tempon_peroid: Cell::new(5), + tempon_cnt: Cell::new(0), + blinky: [false; 6], + blink_state: Cell::new(false), + blinky_enabled: Cell::new(None), + pidx: 0, + time_panel: TimePanel { + state: Cell::new(TimePanelState::View), + tmp: Time{sec: 0, min: 0, hr: 0}, + time: Time{sec: 0, min: 0, hr: 0}, + blink_enabled: Cell::new(true) + }, + date_panel: DatePanel { + state: Cell::new(DatePanelState::Inactive), + tmp: Date{yr: 0, mon: 1, day: 1}, + date: Date{yr: 0, mon: 1, day: 1}, + blink_enabled: Cell::new(true) + }, + temp_panel: TempPanel{ + state: Cell::new(TempPanelState::Inactive), + temp: Cell::new(ds3231::Temp{cels: 0, quarter: 0}) + }, + cd_panel: CountdownPanel { + state: Cell::new(CountdownPanelState::Inactive), + presets: [(0, 0, 0); 4], + counter: Cell::new(0), + didx: Cell::new(0), + blink_enabled: Cell::new(true), + }, + cu_panel: CountupPanel{ + state: Cell::new(CountupPanelState::Inactive), + counter: Cell::new(0) + }, + set_panel: SettingPanel{ + state: Cell::new(SettingPanelState::Inactive), + tmp: [9; 6], + idx: Cell::new(SettingIdx::TempOnCycle), + }, + panels: uninitialized()}); + } + + let gs = get_gs(); - /* 10ms couting clock */ - tim::Timer(p.TIM3).init(10 * (8_000_000 / 1000)); - /* 1ms-precision event clock */ - let tim4 = tim::Timer(p.TIM4); + gs.i2c = i2c::I2C(gs.perip.I2C1); + gs.disp = ShiftRegister::new(gs.perip.GPIOA, 24); + gs.btn1 = Button::new(&gs.events); + gs.btn2 = Button::new(&gs.events); + gs.panels = [&mut gs.time_panel, + &mut gs.date_panel, + &mut gs.temp_panel, + &mut gs.cd_panel, + &mut gs.cu_panel, + &mut gs.set_panel]; + + /* configure I2C */ + gs.i2c.init(gs.perip.RCC, 0x01, 400_000, i2c::DutyType::DUTY1, true); + //gs.i2c.init(0x01, 100_000, i2c::DutyType::DUTY1, false); + /* display zeros */ + gs.disp.output_bits(0); + /* initialize 10ms couting clock */ + tim::Timer(gs.perip.TIM3).init(10 * (8_000_000 / 1000)); + /* initialize and start 1ms-precision event clock */ + let tim4 = tim::Timer(gs.perip.TIM4); tim4.init(1 * (8_000_000 / 1000)); - gs.update_clock(); /* initialize internal time */ - gs.events = Some(AlarmEventManager::new()); - let ev = gs.events.as_ref().unwrap(); - gs.btn1 = Some(Button::new(ev)); - gs.btn2 = Some(Button::new(ev)); tim4.reset(); tim4.go(); + /* start systick */ + gs.perip.SYST.enable_interrupt(); + gs.perip.SYST.enable_counter(); + GlobalState::systick_handler(); /* initialize internal time */ } fn main() { + init_hardware(); init(); } |