#![no_std]
#![feature(asm)]
#![feature(const_fn)]
#[macro_use] extern crate stm32f103xx;
extern crate cortex_m;
use stm32f103xx::{Interrupt, Peripherals, gpioa};
use core::cell::{Cell, RefCell, UnsafeCell};
mod mutex;
mod i2c;
mod ds3231;
mod at24c;
mod tim;
#[inline]
fn digits2bcds(digs: &[u8]) -> u32 {
let mut res: u32 = 0;
for d in digs.iter().rev() {
res = (res << 4) | (*d as u32);
}
res
}
fn inc_rotate(n: &mut u8, reset: u8, limit: u8) {
*n += 1;
if *n == limit {
*n = reset;
}
}
struct ShiftRegister<'a> {
gpioa: &'a gpioa::RegisterBlock,
width: u8,
}
#[derive(Clone, Copy)]
struct Time {
sec: u8,
min: u8,
hr: u8,
}
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: [&'a Panel; 5],
}
#[derive(PartialEq, Clone, Copy)]
enum ButtonState {
Idle,
PressedLock,
PressedUnlock,
ReleaseLock
}
struct Button<'a> {
state: Cell<ButtonState>,
long: Cell<bool>,
events: &'a AlarmEventManager<'a>,
ev_id: Cell<u8>
}
enum ButtonResult {
FalseAlarm,
ShortPress,
LongPress
}
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);
}
trait Timeoutable<'a> {
fn timeout(&'a self);
}
#[derive(PartialEq, Clone, Copy)]
enum TimePanelState {
Inactive,
View,
EditHr,
EditMin,
EditSec,
}
struct TimePanel<'a> {
gs: &'a GlobalState<'a>,
state: Cell<TimePanelState>,
time: RefCell<Time>,
tmp: RefCell<Time>
}
#[derive(Clone, Copy)]
struct Date {
yr: u8,
mon: u8,
day: u8
}
#[derive(PartialEq, Clone, Copy)]
enum DatePanelState {
Inactive,
View,
EditYr,
EditMon,
EditDay
}
struct DatePanel<'a> {
gs: &'a GlobalState<'a>,
state: Cell<DatePanelState>,
date: RefCell<Date>,
tmp: RefCell<Date>
}
#[derive(PartialEq, Clone, Copy)]
enum TempPanelState {
Inactive,
View
}
struct TempPanel<'a> {
state: Cell<TempPanelState>,
temp: Cell<ds3231::Temp>,
gs: &'a GlobalState<'a>,
}
#[derive(PartialEq, Clone, Copy)]
enum CountdownPanelState {
Inactive,
View,
EditWhole,
Edit3,
Edit2,
Edit1,
Edit0,
Edit2m,
Edit1m,
OnGoing,
OnGoingPaused,
TimeUp
}
struct CountdownPanel<'a> {
state: Cell<CountdownPanelState>,
presets: RefCell<[[u8; 6]; 2]>,
counter: Cell<u32>,
didx: Cell<u8>,
gs: &'a GlobalState<'a>,
}
#[derive(PartialEq, Clone, Copy)]
enum CountupPanelState {
Inactive,
View,
OnGoing,
OnGoingPaused
}
struct CountupPanel<'a> {
state: Cell<CountupPanelState>,
counter: Cell<u32>,
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> {
fn new(gpioa: &'a gpioa::RegisterBlock,
width: u8