summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2017-10-28 00:35:52 -0400
committerDeterminant <ted.sybil@gmail.com>2017-10-28 00:35:52 -0400
commitf02632b4965e095e1850bca005f9ba75d812744e (patch)
tree566794f3dca915091748ffc837414c7f8eb37bfa
parent514b4555132d7717da92e2edc028ca7b1dcb7a47 (diff)
multiplex the event timer and fix bugs
-rw-r--r--src/ds3231.rs24
-rw-r--r--src/i2c.rs3
-rw-r--r--src/main.rs280
-rw-r--r--src/tim.rs2
4 files changed, 167 insertions, 142 deletions
diff --git a/src/ds3231.rs b/src/ds3231.rs
index b07acf7..de2201b 100644
--- a/src/ds3231.rs
+++ b/src/ds3231.rs
@@ -1,4 +1,4 @@
-use i2c::{I2C, TransDir, DutyType};
+use i2c::{I2C, TransDir};
const DS3231_ADDR: u8 = 0b1101000;
const DS3231_REG_SEC: u8 = 0x00;
@@ -103,23 +103,17 @@ impl<'a> DS3231<'a> {
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];
+ pub fn write_time(&self, hr: u8, min: u8, sec: u8) {
+ let buf: [u8; 3] = [dec2bcd(sec),
+ dec2bcd(min),
+ dec2bcd(hr)];
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)];
+ pub fn write_date(&self, yy: u8, mm: u8, dd: u8) {
+ let buf: [u8; 3] = [dec2bcd(dd),
+ dec2bcd(mm),
+ dec2bcd(yy)];
self.write_register(DS3231_REG_DATE, buf.len(), &buf);
}
diff --git a/src/i2c.rs b/src/i2c.rs
index 35a618a..b5b8b10 100644
--- a/src/i2c.rs
+++ b/src/i2c.rs
@@ -1,7 +1,6 @@
#![allow(dead_code)]
-extern crate stm32f103xx;
use core::cmp::max;
-use stm32f103xx::{i2c1, rcc, RCC};
+use stm32f103xx::{i2c1, RCC};
pub const EVENT_MASTER_STARTED: u32 = 0x00030001; /* BUSY, MSL and SB flag */
pub const EVENT_MASTER_TRANSMITTER_MODE_SELECTED: u32 = 0x00070082; /* BUSY, MSL, ADDR, TXE and TRA flags */
diff --git a/src/main.rs b/src/main.rs
index 56ba36e..41bcafc 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -6,7 +6,7 @@
extern crate cortex_m;
use stm32f103xx::{Interrupt, Peripherals, gpioa};
-use core::cell::{Cell, RefCell};
+use core::cell::{Cell, RefCell, UnsafeCell};
mod mutex;
mod i2c;
@@ -42,33 +42,37 @@ struct Time {
hr: u8,
}
-struct GlobalState {
- perip: Option<Peripherals<'static>>,
- disp: Option<ShiftRegister<'static>>,
- btn1: Option<Button<'static>>,
- btn2: Option<Button<'static>>,
- i2c: Option<i2c::I2C<'static>>,
+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,
sync_cnt: Cell<u8>,
buff: RefCell<[u8; 6]>,
disp_on: bool,
blinky: RefCell<[bool; 6]>,
blink_state: Cell<bool>,
+ blinky_enabled: Cell<Option<u8>>,
pidx: usize,
- panels: [&'static Panel; 5],
+ panels: [&'a Panel; 5],
}
#[derive(PartialEq, Clone, Copy)]
enum ButtonState {
Idle,
PressedLock,
- PressedUnlock
+ PressedUnlock,
+ ReleaseLock
}
struct Button<'a> {
state: Cell<ButtonState>,
long: Cell<bool>,
- timer: tim::Timer<'a>
+ events: &'a AlarmEventManager<'a>,
+ ev_id: Cell<u8>
}
enum ButtonResult {
@@ -85,6 +89,10 @@ trait Panel {
fn update_output(&self);
}
+trait Timeoutable<'a> {
+ fn timeout(&'a self);
+}
+
#[derive(PartialEq, Clone, Copy)]
enum TimePanelState {
Inactive,
@@ -95,7 +103,7 @@ enum TimePanelState {
}
struct TimePanel<'a> {
- gs: &'a GlobalState,
+ gs: &'a GlobalState<'a>,
state: Cell<TimePanelState>,
time: RefCell<Time>,
tmp: RefCell<Time>
@@ -118,7 +126,7 @@ enum DatePanelState {
}
struct DatePanel<'a> {
- gs: &'a GlobalState,
+ gs: &'a GlobalState<'a>,
state: Cell<DatePanelState>,
date: RefCell<Date>,
tmp: RefCell<Date>
@@ -133,7 +141,7 @@ enum TempPanelState {
struct TempPanel<'a> {
state: Cell<TempPanelState>,
temp: Cell<ds3231::Temp>,
- gs: &'a GlobalState,
+ gs: &'a GlobalState<'a>,
}
#[derive(PartialEq, Clone, Copy)]
@@ -157,7 +165,7 @@ struct CountdownPanel<'a> {
presets: RefCell<[[u8; 6]; 2]>,
counter: Cell<u32>,
didx: Cell<u8>,
- gs: &'a GlobalState,
+ gs: &'a GlobalState<'a>,
}
#[derive(PartialEq, Clone, Copy)]
@@ -171,7 +179,18 @@ enum CountupPanelState {
struct CountupPanel<'a> {
state: Cell<CountupPanelState>,
counter: Cell<u32>,
- gs: &'a GlobalState,
+ gs: &'a GlobalState<'a>,
+}
+
+#[derive(Clone, Copy)]
+struct AlarmEvent<'a> {
+ cb: &'a Timeoutable<'a>,
+ cnt: u32,
+ free: bool
+}
+
+struct AlarmEventManager<'a> {
+ events: UnsafeCell<[AlarmEvent<'a>; 8]>
}
impl<'a> ShiftRegister<'a> {
@@ -218,48 +237,50 @@ impl Time {
}
}
+impl<'a> Timeoutable<'a> for Button<'a> {
+ fn timeout(&'a self) {
+ self.state.set(match self.state.get() {
+ ButtonState::PressedLock => {
+ self.ev_id.set(self.events.add(self, 500));
+ ButtonState::PressedUnlock
+ },
+ ButtonState::PressedUnlock => {
+ self.long.set(true);
+ ButtonState::PressedUnlock
+ },
+ ButtonState::ReleaseLock => {
+ ButtonState::Idle
+ },
+ s => s
+ });
+ }
+}
+
impl<'a> Button<'a> {
- fn new(timer: tim::Timer<'a>) -> Self {
+ fn new(events: &'a AlarmEventManager<'a>) -> Self {
Button {state: Cell::new(ButtonState::Idle),
long: Cell::new(false),
- timer}
+ ev_id: Cell::new(0),
+ events}
}
- fn press(&self) {
+ fn press(&'a self) {
if self.state.get() == ButtonState::Idle {
self.state.set(ButtonState::PressedLock);
self.long.set(false);
- self.timer.init(50 * (8_000_000 / 1000));
- self.timer.reset();
- self.timer.go();
+ self.ev_id.set(self.events.add(self, 50));
}
}
- fn release(&self) -> ButtonResult {
+ fn release(&'a self) -> ButtonResult {
if self.state.get() == ButtonState::PressedUnlock {
- self.timer.stop();
- self.state.set(ButtonState::Idle);
+ self.events.drop(self.ev_id.get());
+ self.state.set(ButtonState::ReleaseLock);
+ self.ev_id.set(self.events.add(self, 50));
if self.long.get() { ButtonResult::LongPress }
else { ButtonResult::ShortPress }
} else { ButtonResult::FalseAlarm }
}
-
- fn timeout(&self) {
- self.timer.stop();
- self.state.set(match self.state.get() {
- ButtonState::PressedLock => {
- self.timer.init(500 * (8_000_000 / 1000));
- self.timer.reset();
- self.timer.go();
- ButtonState::PressedUnlock
- },
- ButtonState::PressedUnlock => {
- self.long.set(true);
- ButtonState::PressedUnlock
- },
- s => s
- });
- }
}
impl<'a> Panel for TimePanel<'a> {
@@ -298,15 +319,7 @@ impl<'a> Panel for TimePanel<'a> {
EditSec => {
let tmp = self.tmp.borrow();
ds3231::DS3231(self.gs.i2c.as_ref().unwrap())
- .write_time(&ds3231::Date{second: tmp.sec,
- minute: tmp.min,
- hour: tmp.hr,
- day: 0,
- date: 0,
- month: 0,
- year: 0,
- am: false,
- am_enabled: false});
+ .write_time(tmp.hr, tmp.min, tmp.sec);
*self.time.borrow_mut() = *tmp;
View
},
@@ -387,15 +400,7 @@ impl<'a> Panel for DatePanel<'a> {
EditDay => {
let tmp = self.tmp.borrow();
ds3231::DS3231(self.gs.i2c.as_ref().unwrap())
- .write_date(&ds3231::Date{second: 0,
- minute: 0,
- hour: 0,
- day: 0,
- date: tmp.day,
- month: tmp.mon,
- year: tmp.yr,
- am: false,
- am_enabled: false});
+ .write_date(tmp.yr, tmp.mon, tmp.day);
*self.date.borrow_mut() = *tmp;
View
},
@@ -594,7 +599,6 @@ impl<'a> Panel for CountdownPanel<'a> {
impl<'a> CountdownPanel<'a> {
fn go(&self) {
- use CountdownPanelState::*;
let tim = self.gs.perip.as_ref().unwrap().TIM3;
let timer = tim::Timer(tim);
let p = &self.presets.borrow()[self.didx.get() as usize];
@@ -689,7 +693,50 @@ impl<'a> CountupPanel<'a> {
}
}
-impl GlobalState {
+impl<'a> AlarmEventManager<'a> {
+ fn new() -> Self {
+ unsafe {
+ AlarmEventManager{events: UnsafeCell::new([AlarmEvent{cb: core::mem::uninitialized(),
+ cnt: 0,
+ free: true}; 8]) }
+ }
+ }
+
+ fn add(&self, f: &'a Timeoutable<'a>, timeout: u32) -> u8 {
+ unsafe {
+ for (i, v) in (*self.events.get()).iter_mut().enumerate() {
+ if v.free {
+ v.cb = f;
+ v.cnt = timeout;
+ v.free = false;
+ return i as u8;
+ }
+ }
+ panic!("event manager full");
+ }
+ }
+
+ fn drop(&self, id: u8) {
+ unsafe {
+ (*self.events.get())[id as usize].free = true;
+ }
+ }
+
+ fn tick(&self) {
+ unsafe {
+ for v in &mut *self.events.get() {
+ if v.free {continue;}
+ v.cnt -= 1;
+ if v.cnt == 0 {
+ v.cb.timeout();
+ v.free = true;
+ }
+ }
+ }
+ }
+}
+
+impl<'a> GlobalState<'a> {
fn render(&self, nbuff: &[u8; 6]) {
self.buff.borrow_mut().copy_from_slice(nbuff);
@@ -723,21 +770,24 @@ impl GlobalState {
self.disp.as_ref().unwrap().output_bits(digits2bcds(&buff[..]));
}
- fn update_blinky(&self, nb: u8) {
- let tim4 = self.perip.as_ref().unwrap().TIM4;
- let timer = tim::Timer(tim4);
- let en = timer.is_enabled();
+ fn update_blinky(&'a 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() {
*v = ((nb >> i) & 1) == 1;
}
- if en && flag {
- self.blink_state.set(false);
- timer.stop();
- } else if !en && !flag {
- self.blink_state.set(false);
- timer.reset();
- timer.go();
+ let ev = self.events.as_ref().unwrap();
+ if flag {
+ if let Some(ev_id) = en {
+ self.blink_state.set(false);
+ self.blinky_enabled.set(None);
+ ev.drop(ev_id);
+ }
+ } else {
+ if en.is_none() {
+ self.blink_state.set(false);
+ self.blinky_enabled.set(Some(ev.add(self, BLINK_PERIOD)));
+ }
}
}
@@ -779,33 +829,7 @@ impl GlobalState {
TEMP_PANEL.update_clock(temp);
}
}
- /*
- let rtc = ds3231::DS3231(self.i2c.as_ref().unwrap());
- rtc.write_fulldate(&ds3231::Date{second: 30,
- minute: 23,
- hour: 18,
- day: 2,
- date: 10,
- month: 10,
- year: 17,
- am: false,
- am_enabled: false});
- */
- /*
- let rom = ROM.as_ref().unwrap();
- let mut buf: [u8; 64] = [23; 64];
- rom.write(23, 64, &buf);
- let mut buf2: [u8; 80] = [0; 80];
- rom.read(20, 80, &mut buf2);
- */
- /*
- let x = mutex::Mutex::new(42);
- {
- let y = x.lock();
- let z = *y + 1;
- let w = z;
- }
- */
+
#[inline(always)]
fn tim4_callback() {
let gs = get_gs();
@@ -813,8 +837,10 @@ impl GlobalState {
let p = gs.perip.as_ref().unwrap();
p.TIM4.sr.modify(|_, w| w.uif().clear());
}
- gs.blink_state.set(!gs.blink_state.get());
- gs.display();
+ match gs.events.as_ref() {
+ Some(ev) => ev.tick(),
+ None => ()
+ }
}
#[inline(always)]
@@ -831,8 +857,19 @@ impl GlobalState {
}
}
+impl<'a> Timeoutable<'a> for GlobalState<'a> {
+ fn timeout(&'a self) {
+ let ev = self.events.as_ref().unwrap();
+ self.blink_state.set(!self.blink_state.get());
+ self.display();
+ if self.blinky_enabled.get().is_some() {
+ self.blinky_enabled.set(Some(ev.add(self, BLINK_PERIOD)));
+ }
+ }
+}
+
#[inline(always)]
-fn get_gs() -> &'static mut GlobalState {
+fn get_gs() -> &'static mut GlobalState<'static> {
unsafe {&mut GS}
}
@@ -889,23 +926,11 @@ fn exti4_handler() {
}
}
-fn tim2_handler() {
- let gs = get_gs();
- let p = gs.perip.as_ref().unwrap();
- p.TIM2.sr.modify(|_, w| w.uif().clear());
- gs.btn1.as_ref().unwrap().timeout();
- gs.btn2.as_ref().unwrap().timeout();
-}
-
-fn tim4_handler() { GlobalState::tim4_callback(); }
-fn tim3_handler() { GlobalState::tim3_callback(); }
-
exception!(SYS_TICK, systick_handler);
interrupt!(EXTI4, exti4_handler);
interrupt!(EXTI3, exti3_handler);
-interrupt!(TIM2, tim2_handler);
-interrupt!(TIM4, tim4_handler);
-interrupt!(TIM3, tim3_handler);
+interrupt!(TIM4, GlobalState::tim4_callback);
+interrupt!(TIM3, GlobalState::tim3_callback);
const SYNC_PERIOD: u8 = 10;
const BLINK_PERIOD: u32 = 500;
@@ -936,6 +961,7 @@ static mut GS: GlobalState =
disp: None,
btn1: None,
btn2: None,
+ events: None,
i2c: None,
i2c_inited: false,
sync_cnt: Cell::new(0),
@@ -943,6 +969,7 @@ static mut GS: GlobalState =
disp_on: true,
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]}
};
@@ -964,8 +991,7 @@ fn init() {
.iopben().enabled()
.afioen().enabled());
- p.RCC.apb1enr.modify(|_, w| w.tim2en().enabled()
- .tim4en().enabled()
+ p.RCC.apb1enr.modify(|_, w| w.tim4en().enabled()
.tim3en().enabled());
/* GPIO */
@@ -995,9 +1021,8 @@ fn init() {
p.AFIO.exticr2.write(|w| unsafe { w.exti4().bits(0b0000) });
p.NVIC.enable(Interrupt::EXTI3);
p.NVIC.enable(Interrupt::EXTI4);
- p.NVIC.enable(Interrupt::TIM2);
- p.NVIC.enable(Interrupt::TIM4);
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()
@@ -1013,11 +1038,18 @@ fn init() {
gs.disp.as_ref().unwrap().output_bits(0);
gs.i2c_inited = true;
- gs.btn1 = Some(Button::new(tim::Timer(p.TIM2)));
- gs.btn2 = Some(Button::new(tim::Timer(p.TIM2)));
- tim::Timer(p.TIM4).init(BLINK_PERIOD * (8_000_000 / 1000));
+ /* 10ms couting clock */
tim::Timer(p.TIM3).init(10 * (8_000_000 / 1000));
- gs.update_clock();
+ /* 1ms-precision event clock */
+ let tim4 = tim::Timer(p.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();
}
fn main() {
diff --git a/src/tim.rs b/src/tim.rs
index f6b8afa..7b63685 100644
--- a/src/tim.rs
+++ b/src/tim.rs
@@ -1,4 +1,4 @@
-use stm32f103xx::{tim1, tim2, TIM2};
+use stm32f103xx::{tim1, tim2};
pub struct Timer<'a> (pub &'a tim2::RegisterBlock);