use crate::datetime::*;
use crate::rcc::{BDCR, APB1R1};
use crate::pwr;
use crate::stm32::{RTC};
pub struct Rtc {
rtc: RTC
}
impl Rtc {
pub fn rtc(rtc: RTC, apb1r1: &mut APB1R1, bdcr: &mut BDCR, pwrcr1: &mut pwr::CR1) -> Self {
apb1r1.enr().modify(|_, w| w.rtcapben().set_bit());
pwrcr1.reg().read();
pwrcr1.reg().modify(|_, w| w.dbp().set_bit());
while pwrcr1.reg().read().dbp().bit_is_clear() {}
bdcr.enr().modify(|_, w| { w.bdrst().set_bit() });
bdcr.enr().modify(|_, w| unsafe {
w.rtcsel()
.bits(0b10)
.rtcen()
.set_bit()
.bdrst() .clear_bit()
});
write_protection(&rtc, false);
{
init_mode(&rtc, true);
{
rtc.cr.modify(|_, w| unsafe {
w.fmt()
.clear_bit() .osel()
.bits(0b00)
.pol()
.clear_bit() });
rtc.prer.modify(|_, w| unsafe {
w.prediv_s()
.bits(255)
.prediv_a()
.bits(127)
});
}
init_mode(&rtc, false);
rtc.or.modify(|_, w| {
w.rtc_alarm_type()
.clear_bit()
.rtc_out_rmp()
.clear_bit()
});
}
write_protection(&rtc, true);
Self {
rtc: rtc
}
}
pub fn set_time(&self, time: &Time){
write_protection(&self.rtc, false);
{
init_mode(&self.rtc, true);
{
let (ht, hu) = byte_to_bcd2(time.hours as u8);
let (mnt, mnu) = byte_to_bcd2(time.minutes as u8);
let (st, su) = byte_to_bcd2(time.seconds as u8);
self.rtc.tr.write(|w| unsafe {
w.ht().bits(ht)
.hu().bits(hu)
.mnt().bits(mnt)
.mnu().bits(mnu)
.st().bits(st)
.su().bits(su)
.pm()
.clear_bit()
});
self.rtc.cr.modify(|_, w| {
w.fmt()
.bit(time.daylight_savings)
});
}
init_mode(&self.rtc, false);
}
write_protection(&self.rtc, true);
}
pub fn get_time(&self) -> Time {
let time;
let timer = self.rtc.tr.read();
let cr = self.rtc.cr.read();
time = Time::new(bcd2_to_byte((timer.ht().bits(), timer.hu().bits())).into(),
bcd2_to_byte((timer.mnt().bits(), timer.mnu().bits())).into(),
bcd2_to_byte((timer.st().bits(), timer.su().bits())).into(),
cr.fmt().bit());
write_protection(&self.rtc, true);
time
}
pub fn set_date(&self, date: &Date){
write_protection(&self.rtc, false);
{
init_mode(&self.rtc, true);
{
let (dt, du) = byte_to_bcd2(date.date as u8);
let (mt, mu) = byte_to_bcd2(date.month as u8);
let yr = date.year as u16;
let yr_offset = (yr - 1970_u16) as u8;
let (yt, yu) = byte_to_bcd2(yr_offset);
self.rtc.dr.write(|w| unsafe {
w.dt().bits(dt)
.du().bits(du)
.mt().bit(mt > 0)
.mu().bits(mu)
.yt().bits(yt)
.yu().bits(yu)
.wdu().bits(date.day as u8)
});
}
init_mode(&self.rtc, false);
}
write_protection(&self.rtc, true);
}
pub fn get_date(&self) -> Date {
let date;
let dater = self.rtc.dr.read();
date = Date::new(dater.wdu().bits().into(),
bcd2_to_byte((dater.dt().bits(), dater.du().bits())).into(),
bcd2_to_byte((dater.mt().bit() as u8, dater.mu().bits())).into(),
(bcd2_to_byte((dater.yt().bits(), dater.yu().bits())) as u16 + 1970_u16).into());
date
}
}
fn write_protection(rtc: &RTC, enable: bool){
if enable {
rtc.wpr.write(|w| unsafe {
w.bits(0xFF)
});
} else {
rtc.wpr.write(|w| unsafe {
w.bits(0xCA)
});
rtc.wpr.write(|w| unsafe {
w.bits(0x53)
});
}
}
fn init_mode(rtc: &RTC, enabled: bool) {
if enabled {
let isr = rtc.isr.read();
if isr.initf().bit_is_clear() { rtc.isr.write(|w| { w.init().set_bit() });
while rtc.isr.read().initf().bit_is_clear() {} }
} else {
rtc.isr.write(|w| { w.init().clear_bit() }); }
}
fn byte_to_bcd2(byte: u8) -> (u8, u8){
let mut bcd_high: u8 = 0;
let mut value = byte;
while value >= 10 {
bcd_high += 1;
value -= 10;
}
(bcd_high, ((bcd_high << 4) | value) as u8)
}
fn bcd2_to_byte(bcd: (u8, u8)) -> u8 { let value = bcd.1 | bcd.0 << 4;
let tmp = ((value & 0xF0) >> 0x4) * 10;
(tmp + (value & 0x0F))
}