#![no_std] #![feature(asm)] #[macro_use] extern crate stm32f103xx; extern crate cortex_m; use stm32f103xx::{GPIOA, GPIOB, RCC, SYST, I2C1, EXTI, NVIC, Interrupt, AFIO, Peripherals}; use stm32f103xx::{gpioa}; use cortex_m::peripheral::SystClkSource; mod mutex; mod i2c; mod ds3231; mod at24c; const SYNC_PERIOD: u8 = 10; struct ShiftRegister<'a> { gpioa: &'a gpioa::RegisterBlock, width: u8, } struct Clock { sec: u8, min: u8, hr: u8, reset: u8 } struct GlobalState { disp: Option>, i2c: Option>, i2c_inited: bool, buff: [u8; 6], time: Clock, perip: Option>, bs: bool } static mut GS: GlobalState = GlobalState{disp: None, i2c: None, i2c_inited: false, buff: [0; 6], time: Clock{sec: 0, min: 0, hr: 0, reset: 0}, perip: None, bs: false}; fn get_gs() -> &'static mut GlobalState { unsafe {&mut GS} } fn digits2bcds(digs: &[u8]) -> u32 { let mut res: u32 = 0; for d in digs.iter().rev() { res = (res << 4) | (*d as u32); } res } fn display() { let gs = get_gs(); gs.disp.as_ref().unwrap().output_bits(digits2bcds(&gs.buff[..])); } fn digits_countup() { let gs = get_gs(); let mut digits = gs.buff; gs.disp.as_ref().unwrap().output_bits(digits2bcds(&digits[..])); let mut i = 0; let mut carry = 1; while carry > 0 && i < digits.len() { digits[i] += carry; carry = if digits[i] > 9 {digits[i] = 0; 1} else {0}; i += 1; } } fn render_clock() { let gs = get_gs(); let mut digits = gs.buff; let time = &gs.time; if gs.bs { digits[1] = time.sec / 10; digits[0] = time.sec - digits[1] * 10; digits[3] = time.min / 10; digits[2] = time.min - digits[3] * 10; digits[5] = time.hr / 10; digits[4] = time.hr - digits[5] * 10; } else { for i in &mut digits { *i = 0xf; } } } fn update_clock() { let gs = get_gs(); let p = gs.perip.as_ref().unwrap(); let rtc = ds3231::DS3231(gs.i2c.as_ref().unwrap()); if !gs.i2c_inited {return} if !gs.time.tick() { let ds3231::Date{second: sec, minute: min, hour: hr, ..} = rtc.read_fulldate(); gs.time = Clock{sec, min, hr, reset: SYNC_PERIOD}; } render_clock(); display(); } fn systick_handler() { // digits_countup(); update_clock(); } fn exti3_handler() { let gs = get_gs(); let p = gs.perip.as_ref().unwrap(); p.EXTI.pr.write(|w| w.pr3().set_bit()); let x = p.GPIOA.idr.read().idr3().bit(); if !x && !gs.bs { gs.bs = true; } else if x && gs.bs { gs.bs = false; } render_clock(); display(); } exception!(SYS_TICK, systick_handler); interrupt!(EXTI3, exti3_handler); impl<'a> ShiftRegister<'a> { fn new(gpioa: &'a gpioa::RegisterBlock, width: u8) -> ShiftRegister<'a> { let this = ShiftRegister{gpioa, width}; this } 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 Clock { fn tick(&mut self) -> bool { if self.reset == 0 { return false; } 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; } self.reset -= 1; true } } fn init() { let gs = get_gs(); let p = { gs.perip = Some(unsafe {Peripherals::all()}); gs.perip.as_ref().unwrap() }; p.SYST.set_clock_source(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()); /* GPIO */ /* enable PA0-2 for manipulating shift register */ p.GPIOA.odr.modify(|_, w| w.odr3().set_bit()); p.GPIOA.crl.modify(|_, w| w.mode0().output().cnf0().push() .mode1().output().cnf1().push() .mode2().output().cnf2().push() .mode3().input().cnf3().bits(0b10)); /* 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 */ p.AFIO.exticr1.write(|w| unsafe { w.exti3().bits(0b0000) }); p.NVIC.enable(Interrupt::EXTI3); p.EXTI.imr.write(|w| w.mr3().set_bit()); p.EXTI.rtsr.write(|w| w.tr3().set_bit()); p.EXTI.ftsr.write(|w| w.tr3().set_bit()); 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); } fn set_clock() { let gs = get_gs(); let p = gs.perip.as_ref().unwrap(); let rtc = ds3231::DS3231(gs.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); */ } fn main() { init(); //set_clock(); /* let x = mutex::Mutex::new(42); { let y = x.lock(); let z = *y + 1; let w = z; } */ update_clock(); }