summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ds3231.rs18
-rw-r--r--src/i2c.rs48
-rw-r--r--src/main.rs28
3 files changed, 50 insertions, 44 deletions
diff --git a/src/ds3231.rs b/src/ds3231.rs
index 2ebc31d..caf4825 100644
--- a/src/ds3231.rs
+++ b/src/ds3231.rs
@@ -1,5 +1,5 @@
extern crate stm32f103xx;
-use ::i2c::{I2C, TransDir};
+use ::i2c::{I2C, TransDir, DutyType};
const DS3231_ADDR: u8 = 0b1101000;
const DS3231_REG_SEC: u8 = 0x00;
@@ -18,7 +18,7 @@ pub struct Date {
pub month: u8,
pub year: u8,
pub am: bool,
- pub am_enable: bool
+ pub am_enabled: bool
}
impl<'a> DS3231<'a> {
@@ -37,7 +37,7 @@ impl<'a> DS3231<'a> {
pub fn init(&self) {
let i2c = &self.i2c;
- i2c.init(400_000, true);
+ i2c.init(0x01, 400_000, DutyType::DUTY1);
i2c.start(true, true);
i2c.send_addr(DS3231_ADDR, TransDir::TRANSMITTER, true);
i2c.send(DS3231_REG_CTL, true);
@@ -62,13 +62,13 @@ 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 {
+ let am_enabled = (buf[2] >> 6) & 1 == 1;
+ let hour = if am_enabled {
(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};
+ let am = if am_enabled {(buf[2] >> 5) & 1 == 0} else {hour < 12};
Date{second: DS3231::bcd2dec(buf[0]),
minute: DS3231::bcd2dec(buf[1]),
hour: hour,
@@ -77,14 +77,14 @@ impl<'a> DS3231<'a> {
month: DS3231::bcd2dec(buf[5]),
year: DS3231::bcd2dec(buf[6]),
am: am,
- am_enable: am_enable}
+ am_enabled: am_enabled}
}
pub fn write_fulldate(&self, date: &Date) {
let i2c = &self.i2c;
- let hour = if date.am_enable {
+ let hour = if date.am_enabled {
(1 << 6) | ((if date.am {0} else {1}) << 5) |
- ((date.hour % 10) << 4) | (date.hour & 0x0f)
+ ((date.hour / 10) << 4) | (date.hour % 10)
} else {
DS3231::dec2bcd(date.hour)
};
diff --git a/src/i2c.rs b/src/i2c.rs
index f6ff8e3..73a8f3b 100644
--- a/src/i2c.rs
+++ b/src/i2c.rs
@@ -1,6 +1,6 @@
#![allow(dead_code)]
extern crate stm32f103xx;
-use stm32f103xx::RCC;
+use core::cmp::max;
pub const EVENT_MASTER_STARTED: u32 = 0x00030001; /* BUSY, MSL and SB flag */
@@ -13,11 +13,6 @@ pub const EVENT_MASTER_BYTE_TRANSMITTED: u32 = 0x00070084; /* TRA, BUSY, MSL, T
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 CCR_DUTY_SET: u16 = 0x4000;
-const CR1_CLEAR_MASK: u16 = 0xFBF5;
-const I2C_ACK_ENABLE: u16 = 0x0400;
pub struct I2C<'a> {
i2c: &'a stm32f103xx::i2c1::RegisterBlock,
@@ -29,6 +24,11 @@ pub enum TransDir {
RECEIVER
}
+pub enum DutyType {
+ DUTY0,
+ DUTY1
+}
+
impl<'a> I2C<'a> {
pub fn new(i2c_reg: &'a stm32f103xx::i2c1::RegisterBlock,
rcc_reg: &'a stm32f103xx::rcc::RegisterBlock) -> I2C<'a> {
@@ -66,31 +66,33 @@ impl<'a> I2C<'a> {
}
/// TODO: support for standard mode
- pub fn init(&self, freq: u32, duty: bool) {
+ pub fn init(&self,
+ addr: u8,
+ scl_freq: u32,
+ duty_type: DutyType) {
let i2c = &self.i2c;
unsafe {
- self.pe(true); /* PE = 1, enable I2C */
- /* CR2 configuration */
let pclk1 = self.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 */
+ let freq_range: u16 = (pclk1 / 1_000_000) as u16;
self.pe(false);
- let mut res = match duty {
- true => (pclk1 / (freq * (16 + 9))) as u16 | CCR_DUTY_SET,
- false => (pclk1 / (freq * (2 + 1))) as u16
- };
- if (res & CCR_CCR_SET) == 0 {
- res |= 0x0001;
- }
- /* TRISE configuration */
+ /* TRISE configuration (in Fm mode, max rise interval is 300) */
i2c.trise.write(|w| w.bits(((freq_range * 300) / 1000 + 1) as u32));
- i2c.ccr.write(|w| w.bits((res | CCR_FS_SET) as u32));
+ /* CCR configuration */
+ i2c.ccr.write(|w| match duty_type {
+ DutyType::DUTY0 => w.ccr().bits(max(pclk1 / (scl_freq * (2 + 1)), 0x1) as u16),
+ DutyType::DUTY1 => w.ccr().bits(max(pclk1 / (scl_freq * (16 + 9)), 0x1) as u16)
+ .duty().set_bit(),
+ }.f_s().set_bit());
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));
+ i2c.cr1.modify(|r, w| w.bits(r.bits())
+ .smbus().clear_bit()
+ .smbtype().clear_bit()
+ .ack().set_bit());
+ /* CR2 configuration */
+ i2c.cr2.modify(|r, w| w.bits(r.bits()).freq().bits(freq_range as u8));
/* OAR1 configuration */
- i2c.oar1.write(|w| w.addmode().clear_bit().add7().bits(0x01));
+ i2c.oar1.write(|w| w.addmode().clear_bit().add7().bits(addr));
while i2c.sr2.read().busy().bit() {} /* wait until the bus is free */
}
}
diff --git a/src/main.rs b/src/main.rs
index ce4c2b6..a79107c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -25,9 +25,16 @@ static mut RTC: Option<ds3231::DS3231> = None;
static mut DIGITS: [u8; 6] = [0; 6];
static mut TIME: Clock = Clock{sec: 0, min: 0, hr: 0, reset: 0};
-fn update_clock() {
+fn digits2bcds(digs: &[u8]) -> u32 {
+ let mut res: u32 = 0;
+ for d in digs.iter().rev() {
+ res = (res << 4) | (*d as u32);
+ }
+ res
+}
+
+fn digits_countup() {
unsafe {
- /*
SR.as_mut().unwrap().output_bits(digits2bcds(&DIGITS[..]));
let mut i = 0;
let mut carry = 1;
@@ -36,7 +43,11 @@ fn update_clock() {
carry = if DIGITS[i] > 9 {DIGITS[i] = 0; 1} else {0};
i += 1;
}
- */
+ }
+}
+
+fn update_clock() {
+ unsafe {
if !TIME.tick() {
let ds3231::Date{second: sec,
minute: min,
@@ -56,6 +67,7 @@ fn update_clock() {
}
fn systick_handler() {
+ // digits_countup();
update_clock();
}
@@ -87,14 +99,6 @@ impl<'a> ShiftRegister<'a> {
}
}
-fn digits2bcds(digs: &[u8]) -> u32 {
- let mut res: u32 = 0;
- for d in digs.iter().rev() {
- res = (res << 4) | (*d as u32);
- }
- res
-}
-
impl Clock {
fn tick(&mut self) -> bool {
if self.reset == 0 {
@@ -172,7 +176,7 @@ fn main() {
month: 9,
year: 17,
am: false,
- am_enable: false});
+ am_enabled: false});
*/
}