From 561887acffccb8d4757d931eedfa2e494946efd1 Mon Sep 17 00:00:00 2001 From: Determinant Date: Thu, 21 Sep 2017 21:58:08 -0400 Subject: basic functionality now works --- src/ds3231.rs | 49 +++++++++++++++++++++++++++-------- src/i2c.rs | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/main.rs | 37 ++++++++++++++++++++++++--- 3 files changed, 152 insertions(+), 16 deletions(-) diff --git a/src/ds3231.rs b/src/ds3231.rs index 6ad75d8..6b20958 100644 --- a/src/ds3231.rs +++ b/src/ds3231.rs @@ -3,19 +3,22 @@ use ::i2c::{I2C, TransDir}; const DS3231_ADDR: u8 = 0b1101000; const DS3231_REG_SEC: u8 = 0x00; +const DS3231_REG_CTL: u8 = 0x0e; pub struct DS3231<'a> { i2c: I2C<'a> } pub struct Date { - second: u8, - minute: u8, - hour: u8, - day: u8, - date: u8, - month: u8, - year: u8 + pub second: u8, + pub minute: u8, + pub hour: u8, + pub day: u8, + pub date: u8, + pub month: u8, + pub year: u8, + pub am: bool, + pub am_enable: bool } impl<'a> DS3231<'a> { @@ -31,6 +34,17 @@ impl<'a> DS3231<'a> { ((dec / 10) << 4) | (dec % 10) } + pub fn init(&self) { + let i2c = &self.i2c; + i2c.init(); + i2c.start(true, true); + i2c.send_addr(DS3231_ADDR, TransDir::TRANSMITTER, true); + i2c.send(DS3231_REG_CTL, true); + i2c.send(0x00, true); + i2c.send(0x00, true); + i2c.stop(true); + } + pub fn read_fulldate(&self) -> Date { let mut buf: [u8; 7] = [0; 7]; let i2c = &self.i2c; @@ -47,20 +61,35 @@ impl<'a> DS3231<'a> { i2c.conf_ack(false); /* disable ack (send nack) */ buf[6] = i2c.recv(true); i2c.stop(true); + let am_enable = (buf[2] >> 6) & 1 == 1; + let hour = if am_enable { + (buf[2] & 0x0f) + ((buf[2] >> 4) & 1) * 10 + } else { + DS3231::bcd2dec(buf[2]) + }; + let am = if am_enable {(buf[2] >> 5) & 1 == 0} else {hour < 12}; Date{second: DS3231::bcd2dec(buf[0]), minute: DS3231::bcd2dec(buf[1]), - hour: DS3231::bcd2dec(buf[2]), + hour: hour, day: DS3231::bcd2dec(buf[3]), date: DS3231::bcd2dec(buf[4]), month: DS3231::bcd2dec(buf[5]), - year: DS3231::bcd2dec(buf[6])} + year: DS3231::bcd2dec(buf[6]), + am: am, + am_enable: am_enable} } pub fn write_fulldate(&self, date: &Date) { let i2c = &self.i2c; + let hour = if date.am_enable { + (1 << 6) | ((if date.am {0} else {1}) << 5) | + ((date.hour % 10) << 4) | (date.hour & 0x0f) + } else { + DS3231::dec2bcd(date.hour) + }; let buf: [u8; 7] = [DS3231::dec2bcd(date.second), DS3231::dec2bcd(date.minute), - DS3231::dec2bcd(date.hour), + hour, DS3231::dec2bcd(date.day), DS3231::dec2bcd(date.date), DS3231::dec2bcd(date.month), diff --git a/src/i2c.rs b/src/i2c.rs index 8b6d4da..6a8d7a4 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -1,5 +1,7 @@ #![allow(dead_code)] extern crate stm32f103xx; +use stm32f103xx::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 */ @@ -8,9 +10,13 @@ pub const EVENT_MASTER_BYTE_RECEIVED: u32 = 0x00030040; /* BUSY, MSL and RXNE f pub const EVENT_MASTER_BYTE_TRANSMITTING: u32 = 0x00070080; /* TRA, BUSY, MSL, TXE flags */ pub const EVENT_MASTER_BYTE_TRANSMITTED: u32 = 0x00070084; /* TRA, BUSY, MSL, TXE and BTF flags */ -const CR1_START_MASK: u16 = 0x0100; -const CR1_STOP_MASK: u16 = 0x0200; const FLAGS_MASK: u32 = 0x00ffffff; +const HSI_VALUE: u32 = 8000000; +const HSE_VALUE: u32 = 8000000; +const CCR_CCR_SET: u16 = 0x0FFF; +const CCR_FS_SET: u16 = 0x8000; +const CR1_CLEAR_MASK: u16 = 0xFBF5; +const I2C_ACK_ENABLE: u16 = 0x0400; pub struct I2C<'a> { i2c: &'a stm32f103xx::i2c1::RegisterBlock, @@ -26,6 +32,78 @@ impl<'a> I2C<'a> { I2C{i2c: reg} } + fn get_pclk1() -> u32 { + unsafe { + use stm32f103xx::rcc::cfgr::{SWSR, PLLSRCR, PLLXTPRER}; + let rcc: &stm32f103xx::rcc::RegisterBlock = &*RCC.get(); + let cfgr = rcc.cfgr.read(); + let sysclk_freq = match cfgr.sws() { + SWSR::HSI => HSI_VALUE, + SWSR::HSE => HSE_VALUE, + SWSR::PLL => { + let pllmull = cfgr.pllmul().bits(); + let pllsource = cfgr.pllsrc(); + let pllmull = (pllmull as u32 >> 18) + 2; + match pllsource { + PLLSRCR::INTERNAL => { + (HSI_VALUE >> 1) * pllmull + }, + PLLSRCR::EXTERNAL => { + match cfgr.pllxtpre() { + PLLXTPRER::DIV2 => (HSE_VALUE >> 1) * pllmull, + PLLXTPRER::DIV1 => HSE_VALUE * pllmull + } + } + } + } + _ => HSI_VALUE + }; + let div_table: [u8; 16] = [0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9]; + let hclk_freq = sysclk_freq >> div_table[cfgr.hpre().bits() as usize]; + let pclk1_freq = hclk_freq >> div_table[cfgr.ppre1().bits() as usize]; + pclk1_freq + } + } + + pub fn init(&self) { + let i2c = &self.i2c; + unsafe { + let rcc: &stm32f103xx::rcc::RegisterBlock = &*RCC.get(); + rcc.apb1rstr.modify(|_, w| w.i2c1rst().set_bit()); + rcc.apb1rstr.modify(|_, w| w.i2c1rst().clear_bit()); + self.pe(true); /* PE = 1, enable I2C */ + /* CR2 configuration */ + let pclk1 = I2C::get_pclk1(); + let freq_range: u16 = (pclk1 / 1000000) as u16; + i2c.cr2.modify(|r, w| w.bits(r.bits()).freq().bits(freq_range as u8)); + /* CCR configuration */ + self.pe(false); + let mut res = (pclk1 / (400000 * 3)) as u16; + if (res & CCR_CCR_SET) == 0 { + res |= 0x0001; + } + /* TRISE configuration */ + i2c.trise.write(|w| w.bits(((freq_range * 300) / 1000 + 1) as u32)); + i2c.ccr.modify(|r, w| w.bits((res | CCR_FS_SET) as u32)); + self.pe(true); /* PE = 1, enable I2C */ + /* CR1 configuration */ + i2c.cr1.modify(|r, w| w.bits(((r.bits() as u16 & CR1_CLEAR_MASK) | I2C_ACK_ENABLE) as u32)); + /* OAR1 configuration */ + i2c.oar1.write(|w| w.addmode().clear_bit().add7().bits(0x01)); + while i2c.sr2.read().busy().bit() {} /* wait until the bus is free */ + } + } + + pub fn pe(&self, enable: bool) { + let i2c = &self.i2c; + unsafe { + match enable { + true => i2c.cr1.modify(|r, w| w.bits(r.bits()).pe().set_bit()), + false => i2c.cr1.modify(|r, w| w.bits(r.bits()).pe().clear_bit()) + } + } + } + pub fn start(&self, enable: bool, synced: bool) { let i2c = &self.i2c; unsafe { diff --git a/src/main.rs b/src/main.rs index 168e55a..6690828 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ #[macro_use] extern crate stm32f103xx; extern crate cortex_m; -use stm32f103xx::{GPIOA, RCC, SYST, I2C1}; +use stm32f103xx::{GPIOA, GPIOB, RCC, SYST, I2C1}; use cortex_m::peripheral::SystClkSource; mod i2c; mod ds3231; @@ -23,6 +23,7 @@ fn systick_handler() { SR.as_mut().unwrap().output_bits(N as u32); N += 1; */ + /* SR.as_mut().unwrap().output_bits(digits2bcds(&DIGITS[..])); let mut i = 0; let mut carry = 1; @@ -31,10 +32,16 @@ fn systick_handler() { carry = if DIGITS[i] > 9 {DIGITS[i] = 0; 1} else {0}; i += 1; } + */ + let ds3231::Date{second: sec, minute: min, hour: hr, ..} = RTC.as_mut().unwrap().read_fulldate(); + DIGITS[4] = sec / 10; DIGITS[5] = sec % 10; + DIGITS[2] = min / 10; DIGITS[3] = min % 10; + DIGITS[0] = hr / 10; DIGITS[1] = hr % 10; + SR.as_mut().unwrap().output_bits(digits2bcds(&DIGITS[..])); } } -//exception!(SYS_TICK, systick_handler); +exception!(SYS_TICK, systick_handler); impl<'a> ShiftRegister<'a> { fn new(g: &'a stm32f103xx::gpioa::RegisterBlock, @@ -73,6 +80,7 @@ fn digits2bcds(digs: &[u8]) -> u32 { fn main() { let gpioa: &stm32f103xx::gpioa::RegisterBlock = unsafe { &*GPIOA.get() }; + let gpiob: &stm32f103xx::gpioa::RegisterBlock = unsafe { &*GPIOB.get() }; let rcc: &stm32f103xx::rcc::RegisterBlock = unsafe { &*RCC.get() }; let i2c: &stm32f103xx::i2c1::RegisterBlock = unsafe { &*I2C1.get() }; let syst: &cortex_m::peripheral::SYST = unsafe { &*SYST.get() }; @@ -81,16 +89,37 @@ fn main() { syst.set_reload(100_000); syst.enable_interrupt(); syst.enable_counter(); - rcc.apb2enr.modify(|_, w| w.iopaen().enabled()); + rcc.apb2enr.modify(|_, w| w.iopaen().enabled() + .iopben().enabled() + .afioen().enabled()); gpioa.crl.modify(|_, w| w.mode0().output().cnf0().push() .mode1().output().cnf1().push() .mode2().output().cnf2().push()); + gpiob.crl.modify(|_, w| + w.mode6().output50().cnf6().alt_open() + .mode7().output50().cnf7().alt_open()); + + rcc.apb1enr.modify(|_, w| w.i2c1en().enabled()); + unsafe { RTC = Some(ds3231::DS3231::new(i2c)); SR = Some(ShiftRegister::new(gpioa, 24)); SR.as_mut().unwrap().output_bits(0); - let t = RTC.as_mut().unwrap().read_fulldate(); + let rtc = RTC.as_mut().unwrap(); + rtc.init(); + let x = rtc.read_fulldate(); + /* + rtc.write_fulldate(&ds3231::Date{second: 30, + minute: 48, + hour: 21, + day: 4, + date: 21, + month: 9, + year: 17, + am: false, + am_enable: false}); + */ } } -- cgit v1.2.3