use i2c::{I2C, TransDir, DutyType}; const DS3231_ADDR: u8 = 0b1101000; const DS3231_REG_SEC: u8 = 0x00; const DS3231_REG_DATE: u8 = 0x04; const DS3231_REG_CTL: u8 = 0x0e; const DS3231_REG_TEMP: u8 = 0x11; pub struct DS3231<'a>(pub &'a I2C<'a>); pub struct Date { 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_enabled: bool } pub struct Temp { pub cels: i8, pub quarter: u8 } fn bcd2dec(bcd: u8) -> u8 { (bcd >> 4) * 10 + (bcd & 0x0f) } fn dec2bcd(dec: u8) -> u8 { ((dec / 10) << 4) | (dec % 10) } impl<'a> DS3231<'a> { fn read_register(&self, start: u8, size: usize, buf: &mut [u8]){ let &DS3231(ref i2c) = self; 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(start, 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..(size - 1) { buf[i] = i2c.recv(true); } i2c.conf_ack(false); /* disable ack (send nack) */ buf[size - 1] = i2c.recv(true); i2c.stop(true); } fn write_register(&self, start: u8, size: usize, buf: &[u8]) { let &DS3231(ref i2c) = self; i2c.conf_ack(true); i2c.start(true, true); /* start condition for writing */ i2c.send_addr(DS3231_ADDR, TransDir::TRANSMITTER, true); i2c.send(start, true); for i in 0..size { i2c.send(buf[i], true); } i2c.stop(true); } pub fn read_fulldate(&self) -> Date { let mut buf: [u8; 7] = [0; 7]; self.read_register(DS3231_REG_SEC, 7, &mut buf); let am_enabled = (buf[2] >> 6) & 1 == 1; let hour = if am_enabled { (buf[2] & 0x0f) + ((buf[2] >> 4) & 1) * 10 } else { bcd2dec(buf[2]) }; let am = if am_enabled {(buf[2] >> 5) & 1 == 0} else {hour < 12}; Date{second: bcd2dec(buf[0]), minute: bcd2dec(buf[1]), hour, day: bcd2dec(buf[3]), date: bcd2dec(buf[4]), month: bcd2dec(buf[5]), year: bcd2dec(buf[6]), am, am_enabled} } pub fn write_fulldate(&self, date: &Date) { let hour = if date.am_enabled { (1 << 6) | ((if date.am {0} else {1}) << 5) | ((date.hour / 10) << 4) | (date.hour % 10) } else { dec2bcd(date.hour) }; let buf: [u8; 7] = [dec2bcd(date.second), dec2bcd(date.minute), hour, dec2bcd(date.day), dec2bcd(date.date), dec2bcd(date.month), dec2bcd(date.year)]; self.write_register(DS3231_REG_SEC, buf.len(), &buf); } pub fn write_time(&self, date: &Date) { let hour = if date.am_enabled { (1 << 6) | ((if date.am {0} else {1}) << 5) | ((date.hour / 10) << 4) | (date.hour % 10) } else { dec2bcd(date.hour) }; let buf: [u8; 3] = [dec2bcd(date.second), dec2bcd(date.minute), hour]; self.write_register(DS3231_REG_SEC, buf.len(), &buf); } pub fn write_date(&self, date: &Date) { let buf: [u8; 3] = [dec2bcd(date.date), dec2bcd(date.month), dec2bcd(date.year)]; self.write_register(DS3231_REG_DATE, buf.len(), &buf); } pub fn write_control(&self) { let buf: [u8; 2] = [0; 2]; self.write_register(DS3231_REG_CTL, 2, &buf); } pub fn read_temperature(&self) -> Temp { let mut buf: [u8; 2] = [0; 2]; self.read_register(DS3231_REG_TEMP, 2, &mut buf); Temp{cels: buf[0] as i8, quarter: buf[1] >> 6} } }