diff options
Diffstat (limited to 'src/ds3231.rs')
-rw-r--r-- | src/ds3231.rs | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/ds3231.rs b/src/ds3231.rs new file mode 100644 index 0000000..6ad75d8 --- /dev/null +++ b/src/ds3231.rs @@ -0,0 +1,77 @@ +extern crate stm32f103xx; +use ::i2c::{I2C, TransDir}; + +const DS3231_ADDR: u8 = 0b1101000; +const DS3231_REG_SEC: u8 = 0x00; + +pub struct DS3231<'a> { + i2c: I2C<'a> +} + +pub struct Date { + second: u8, + minute: u8, + hour: u8, + day: u8, + date: u8, + month: u8, + year: u8 +} + +impl<'a> DS3231<'a> { + pub fn new(i2c_reg: &'a stm32f103xx::i2c1::RegisterBlock) -> DS3231<'a> { + DS3231{i2c: I2C::new(i2c_reg)} + } + + fn bcd2dec(bcd: u8) -> u8 { + (bcd >> 4) * 10 + (bcd & 0x0f) + } + + fn dec2bcd(dec: u8) -> u8 { + ((dec / 10) << 4) | (dec % 10) + } + + pub fn read_fulldate(&self) -> Date { + let mut buf: [u8; 7] = [0; 7]; + let i2c = &self.i2c; + i2c.conf_ack(true); /* enable ack */ + i2c.start(true, true); /* start condition (for writing reg addr) */ + i2c.send_addr(DS3231_ADDR, TransDir::TRANSMITTER, true); + i2c.send(DS3231_REG_SEC, true); + /* restart condition (for reading val from the reg addr) */ + i2c.start(true, true); + i2c.send_addr(DS3231_ADDR, TransDir::RECEIVER, true); + for i in 0..6 { + buf[i] = i2c.recv(true); + } + i2c.conf_ack(false); /* disable ack (send nack) */ + buf[6] = i2c.recv(true); + i2c.stop(true); + Date{second: DS3231::bcd2dec(buf[0]), + minute: DS3231::bcd2dec(buf[1]), + hour: DS3231::bcd2dec(buf[2]), + day: DS3231::bcd2dec(buf[3]), + date: DS3231::bcd2dec(buf[4]), + month: DS3231::bcd2dec(buf[5]), + year: DS3231::bcd2dec(buf[6])} + } + + pub fn write_fulldate(&self, date: &Date) { + let i2c = &self.i2c; + let buf: [u8; 7] = [DS3231::dec2bcd(date.second), + DS3231::dec2bcd(date.minute), + DS3231::dec2bcd(date.hour), + DS3231::dec2bcd(date.day), + DS3231::dec2bcd(date.date), + DS3231::dec2bcd(date.month), + DS3231::dec2bcd(date.year)]; + i2c.conf_ack(true); + i2c.start(true, true); /* start condition for writing */ + i2c.send_addr(DS3231_ADDR, TransDir::TRANSMITTER, true); + i2c.send(DS3231_REG_SEC, true); + for i in 0..7 { + i2c.send(buf[i], true); + } + i2c.stop(true); + } +} |