#![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};
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 {
perip: Option<Peripherals<'static>>,
disp: Option<ShiftRegister<'static>>,
btn1: Option<Button<'static>>,
i2c: Option<i2c::I2C<'static>>,
i2c_inited: bool,
sync_cnt: Cell<u8>,
buff: RefCell<[u8; 6]>,
disp_on: bool,
blinky: RefCell<[bool; 6]>,
blink_state: Cell<bool>,
pidx: usize,
panels: [&'static Panel; 4],
}
struct Button<'a> {
state: Cell<bool>,
long: Cell<bool>,
timer: tim::Timer<'a>
}
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);
}
#[derive(PartialEq, Clone, Copy)]
enum TimePanelState {
Inactive,
View,
EditHr,
EditMin,
EditSec,
}
struct TimePanel<'a> {
gs: &'a GlobalState,
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,
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,
}
#[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,
}
impl<'a> ShiftRegister<'a> {
fn new(gpioa: &'a gpioa::RegisterBlock,
width: u8) -> Self {
ShiftRegister{gpioa, width}
}
fn output_bits(&self, bits: u32) {
let bsrr = &self.gpioa.bsrr;
for i in (0..self.width).rev() {
bsrr.write(|w| w.br1().reset());
/* feed the ser */
match (bits >> i) & 1 {
0 => bsrr.write(|w| w.br0().reset()),
1 => bsrr.write(|w| w.bs0().set()),
_ => panic!()
}
/* shift (trigger the sclk) */
bsrr.write(|w| w.bs1().set());
}
/* latch on (trigger the clk) */
bsrr.write(|w| w.br2().reset());
bsrr.write(|w| w.bs2().set());
}
}
impl Time {
fn tick(&mut self) {
self.sec += 1;
if self.sec == 60 {
self.min += 1;
self.sec = 0;
}
if self.min == 60 {
self.hr += 1;
self.min = 0;
}
if self.hr == 24 {
self.hr = 0;
}
}
}
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)