|
@@ -8,8 +8,6 @@ use tock_registers::{
|
|
|
registers::InMemoryRegister,
|
|
|
};
|
|
|
|
|
|
-const DS3231_ADDR: u8 = 0x68;
|
|
|
-
|
|
|
register_bitfields![
|
|
|
u8,
|
|
|
T_SECOND [
|
|
@@ -133,98 +131,11 @@ impl From<u8> for Weekday {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-impl Ds3231Registers {
|
|
|
- const fn default() -> Self {
|
|
|
- Self {
|
|
|
- second: InMemoryRegister::new(0x00),
|
|
|
- minute: InMemoryRegister::new(0x00),
|
|
|
- hour: InMemoryRegister::new(0x00),
|
|
|
- weekday: InMemoryRegister::new(0x00),
|
|
|
- day: InMemoryRegister::new(0x00),
|
|
|
- month: InMemoryRegister::new(0x00),
|
|
|
- year: InMemoryRegister::new(0x00),
|
|
|
- a1_second: InMemoryRegister::new(0x00),
|
|
|
- a1_minute: InMemoryRegister::new(0x00),
|
|
|
- a1_hour: InMemoryRegister::new(0x00),
|
|
|
- a1_day_date: InMemoryRegister::new(0x00),
|
|
|
- a2_minute: InMemoryRegister::new(0x00),
|
|
|
- a2_hour: InMemoryRegister::new(0x00),
|
|
|
- a2_day_date: InMemoryRegister::new(0x00),
|
|
|
- control_1: InMemoryRegister::new(0x00),
|
|
|
- control_2: InMemoryRegister::new(0x00),
|
|
|
- aging_offset: InMemoryRegister::new(0x00),
|
|
|
- temp_msb: InMemoryRegister::new(0x00),
|
|
|
- temp_lsb: InMemoryRegister::new(0x00),
|
|
|
- }
|
|
|
- }
|
|
|
- fn i2c_write_ctrl(&self, address: u8, i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
|
|
|
- let mut buffer: [u8; 3] = [0; 3];
|
|
|
- buffer[0] = offset_of!(Ds3231Registers => control_1).get_byte_offset() as u8;
|
|
|
- buffer[1] = self.control_1.get();
|
|
|
- buffer[2] = self.control_2.get();
|
|
|
-
|
|
|
- match i2c.write(address, &buffer) {
|
|
|
- Ok(_) => (),
|
|
|
- Err(_) => panic!(),
|
|
|
- }
|
|
|
- }
|
|
|
- fn i2c_write_time(&self, address: u8, i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
|
|
|
- let mut buffer: [u8; 4] = [0; 4];
|
|
|
- buffer[0] = offset_of!(Ds3231Registers => second).get_byte_offset() as u8;
|
|
|
- buffer[1] = self.second.get();
|
|
|
- buffer[2] = self.minute.get();
|
|
|
- buffer[3] = self.hour.get();
|
|
|
-
|
|
|
- match i2c.write(address, &buffer) {
|
|
|
- Ok(_) => (),
|
|
|
- Err(_) => panic!(),
|
|
|
- }
|
|
|
- }
|
|
|
- fn i2c_write_date(&self, address: u8, i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
|
|
|
- let mut buffer: [u8; 5] = [0; 5];
|
|
|
- buffer[0] = offset_of!(Ds3231Registers => weekday).get_byte_offset() as u8;
|
|
|
- buffer[1] = self.weekday.get();
|
|
|
- buffer[2] = self.day.get();
|
|
|
- buffer[3] = self.month.get();
|
|
|
- buffer[4] = self.year.get();
|
|
|
-
|
|
|
- match i2c.write(address, &buffer) {
|
|
|
- Ok(_) => (),
|
|
|
- Err(_) => panic!(),
|
|
|
- }
|
|
|
- }
|
|
|
- // Returns the second, minute, and hour from the RTC
|
|
|
- fn i2c_read_time(&mut self, address: u8, i2c: &mut impl _embedded_hal_blocking_i2c_WriteRead) {
|
|
|
- let mut buffer: [u8; 3] = [0; 3];
|
|
|
-
|
|
|
- match i2c.write_read(
|
|
|
- address,
|
|
|
- &[offset_of!(Ds3231Registers => second).get_byte_offset() as u8],
|
|
|
- &mut buffer,
|
|
|
- ) {
|
|
|
- Ok(_) => (),
|
|
|
- Err(_) => panic!(),
|
|
|
- }
|
|
|
- }
|
|
|
- // Returns the weekday, day, month, year, and century from the RTC
|
|
|
- fn i2c_read_date(&mut self, address: u8, i2c: &mut impl _embedded_hal_blocking_i2c_WriteRead) {
|
|
|
- let mut buffer: [u8; 4] = [0; 4];
|
|
|
-
|
|
|
- match i2c.write_read(
|
|
|
- address,
|
|
|
- &[offset_of!(Ds3231Registers => weekday).get_byte_offset() as u8],
|
|
|
- &mut buffer,
|
|
|
- ) {
|
|
|
- Ok(_) => (),
|
|
|
- Err(_) => panic!(),
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-pub fn init(i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
|
|
|
- let regs = Ds3231Registers::default();
|
|
|
+pub fn init(address: u8, i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
|
|
|
+ let ctrl1: InMemoryRegister<u8, CONTROL_1::Register> = InMemoryRegister::new(0);
|
|
|
+ let ctrl2: InMemoryRegister<u8, CONTROL_2::Register> = InMemoryRegister::new(0);
|
|
|
|
|
|
- regs.control_1.modify(
|
|
|
+ ctrl1.modify(
|
|
|
CONTROL_1::nEOSC::CLEAR // Enable internal oscillator on VBAT
|
|
|
+ CONTROL_1::BBSQW::CLEAR // Disable outputs on VBAT
|
|
|
+ CONTROL_1::RS1::CLEAR // Set square wave output to 1Hz
|
|
@@ -235,29 +146,50 @@ pub fn init(i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
|
|
|
);
|
|
|
|
|
|
// Disable 32kHz output
|
|
|
- regs.control_2.modify(CONTROL_2::EN32KHZ::CLEAR);
|
|
|
+ ctrl2.modify(CONTROL_2::EN32KHZ::CLEAR);
|
|
|
+
|
|
|
+ let buffer: [u8; 3] = [
|
|
|
+ offset_of!(Ds3231Registers => control_1).get_byte_offset() as u8,
|
|
|
+ ctrl1.get(),
|
|
|
+ ctrl2.get(),
|
|
|
+ ];
|
|
|
|
|
|
- regs.i2c_write_ctrl(DS3231_ADDR, i2c);
|
|
|
+ match i2c.write(address, &buffer) {
|
|
|
+ Ok(_) => (),
|
|
|
+ Err(_) => panic!(),
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
pub fn set_time(
|
|
|
+ address: u8,
|
|
|
i2c: &mut impl _embedded_hal_blocking_i2c_Write,
|
|
|
second: u32,
|
|
|
minute: u32,
|
|
|
hour: u32,
|
|
|
) {
|
|
|
- let regs = Ds3231Registers::default();
|
|
|
-
|
|
|
- regs.second
|
|
|
- .write(T_SECOND::Value.val(decimal_to_bcd(second)));
|
|
|
- regs.minute
|
|
|
- .write(T_MINUTE::Value.val(decimal_to_bcd(minute)));
|
|
|
- regs.hour.write(T_HOUR::Value.val(decimal_to_bcd(hour)));
|
|
|
-
|
|
|
- regs.i2c_write_time(DS3231_ADDR, i2c);
|
|
|
+ let second_reg: InMemoryRegister<u8, T_SECOND::Register> = InMemoryRegister::new(0);
|
|
|
+ let minute_reg: InMemoryRegister<u8, T_MINUTE::Register> = InMemoryRegister::new(0);
|
|
|
+ let hour_reg: InMemoryRegister<u8, T_HOUR::Register> = InMemoryRegister::new(0);
|
|
|
+
|
|
|
+ second_reg.write(T_SECOND::Value.val(decimal_to_bcd(second)));
|
|
|
+ minute_reg.write(T_MINUTE::Value.val(decimal_to_bcd(minute)));
|
|
|
+ hour_reg.write(T_HOUR::Value.val(decimal_to_bcd(hour)));
|
|
|
+
|
|
|
+ let buffer: [u8; 4] = [
|
|
|
+ offset_of!(Ds3231Registers => second).get_byte_offset() as u8,
|
|
|
+ second_reg.get(),
|
|
|
+ minute_reg.get(),
|
|
|
+ hour_reg.get(),
|
|
|
+ ];
|
|
|
+
|
|
|
+ match i2c.write(address, &buffer) {
|
|
|
+ Ok(_) => (),
|
|
|
+ Err(_) => panic!(),
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
pub fn set_date(
|
|
|
+ address: u8,
|
|
|
i2c: &mut impl _embedded_hal_blocking_i2c_Write,
|
|
|
weekday: Weekday,
|
|
|
day: u32,
|
|
@@ -265,45 +197,83 @@ pub fn set_date(
|
|
|
year: u32,
|
|
|
century: u32,
|
|
|
) {
|
|
|
- let regs = Ds3231Registers::default();
|
|
|
-
|
|
|
- regs.weekday
|
|
|
- .write(T_WEEKDAY::Value.val(decimal_to_bcd(weekday as u32)));
|
|
|
- regs.day.write(T_DAY::Value.val(decimal_to_bcd(day)));
|
|
|
- regs.month.modify(
|
|
|
+ let weekday_reg: InMemoryRegister<u8, T_WEEKDAY::Register> = InMemoryRegister::new(0);
|
|
|
+ let day_reg: InMemoryRegister<u8, T_DAY::Register> = InMemoryRegister::new(0);
|
|
|
+ let month_reg: InMemoryRegister<u8, T_MONTH::Register> = InMemoryRegister::new(0);
|
|
|
+ let year_reg: InMemoryRegister<u8, T_YEAR::Register> = InMemoryRegister::new(0);
|
|
|
+
|
|
|
+ weekday_reg.write(T_WEEKDAY::Value.val(decimal_to_bcd(weekday as u32)));
|
|
|
+ day_reg.write(T_DAY::Value.val(decimal_to_bcd(day)));
|
|
|
+ month_reg.modify(
|
|
|
T_MONTH::Value.val(decimal_to_bcd(month)) + T_MONTH::Century.val(decimal_to_bcd(century)),
|
|
|
);
|
|
|
- regs.year.write(T_YEAR::Value.val(decimal_to_bcd(year)));
|
|
|
-
|
|
|
- regs.i2c_write_time(DS3231_ADDR, i2c);
|
|
|
+ year_reg.write(T_YEAR::Value.val(decimal_to_bcd(year)));
|
|
|
+
|
|
|
+ let buffer: [u8; 5] = [
|
|
|
+ offset_of!(Ds3231Registers => weekday).get_byte_offset() as u8,
|
|
|
+ weekday_reg.get(),
|
|
|
+ day_reg.get(),
|
|
|
+ month_reg.get(),
|
|
|
+ year_reg.get(),
|
|
|
+ ];
|
|
|
+
|
|
|
+ match i2c.write(address, &buffer) {
|
|
|
+ Ok(_) => (),
|
|
|
+ Err(_) => panic!(),
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
pub fn get_time(
|
|
|
+ address: u8,
|
|
|
i2c: &mut impl _embedded_hal_blocking_i2c_WriteRead,
|
|
|
) -> (u32, u32, u32) {
|
|
|
- let mut regs = Ds3231Registers::default();
|
|
|
+ let mut buffer: [u8; 3] = [0; 3];
|
|
|
+
|
|
|
+ match i2c.write_read(
|
|
|
+ address,
|
|
|
+ &[offset_of!(Ds3231Registers => second).get_byte_offset() as u8],
|
|
|
+ &mut buffer,
|
|
|
+ ) {
|
|
|
+ Ok(_) => (),
|
|
|
+ Err(_) => panic!(),
|
|
|
+ }
|
|
|
|
|
|
- regs.i2c_read_time(DS3231_ADDR, i2c);
|
|
|
+ let second_reg: InMemoryRegister<u8, T_SECOND::Register> = InMemoryRegister::new(buffer[0]);
|
|
|
+ let minute_reg: InMemoryRegister<u8, T_MINUTE::Register> = InMemoryRegister::new(buffer[1]);
|
|
|
+ let hour_reg: InMemoryRegister<u8, T_HOUR::Register> = InMemoryRegister::new(buffer[2]);
|
|
|
|
|
|
- let second = bcd_to_decimal(regs.second.read(T_SECOND::Value));
|
|
|
- let minute = bcd_to_decimal(regs.minute.read(T_MINUTE::Value));
|
|
|
- let hour = bcd_to_decimal(regs.hour.read(T_HOUR::Value));
|
|
|
+ let second = bcd_to_decimal(second_reg.read(T_SECOND::Value));
|
|
|
+ let minute = bcd_to_decimal(minute_reg.read(T_MINUTE::Value));
|
|
|
+ let hour = bcd_to_decimal(hour_reg.read(T_HOUR::Value));
|
|
|
|
|
|
(second, minute, hour)
|
|
|
}
|
|
|
|
|
|
pub fn get_date(
|
|
|
+ address: u8,
|
|
|
i2c: &mut impl _embedded_hal_blocking_i2c_WriteRead,
|
|
|
) -> (Weekday, u32, u32, u32, u32) {
|
|
|
- let mut regs = Ds3231Registers::default();
|
|
|
+ let mut buffer: [u8; 4] = [0; 4];
|
|
|
+
|
|
|
+ match i2c.write_read(
|
|
|
+ address,
|
|
|
+ &[offset_of!(Ds3231Registers => weekday).get_byte_offset() as u8],
|
|
|
+ &mut buffer,
|
|
|
+ ) {
|
|
|
+ Ok(_) => (),
|
|
|
+ Err(_) => panic!(),
|
|
|
+ }
|
|
|
|
|
|
- regs.i2c_read_date(DS3231_ADDR, i2c);
|
|
|
+ let weekday_reg: InMemoryRegister<u8, T_WEEKDAY::Register> = InMemoryRegister::new(buffer[0]);
|
|
|
+ let day_reg: InMemoryRegister<u8, T_DAY::Register> = InMemoryRegister::new(buffer[1]);
|
|
|
+ let month_reg: InMemoryRegister<u8, T_MONTH::Register> = InMemoryRegister::new(buffer[2]);
|
|
|
+ let year_reg: InMemoryRegister<u8, T_YEAR::Register> = InMemoryRegister::new(buffer[3]);
|
|
|
|
|
|
- let weekday: Weekday = regs.weekday.read(T_WEEKDAY::Value).into();
|
|
|
- let day = bcd_to_decimal(regs.day.read(T_DAY::Value));
|
|
|
- let month = bcd_to_decimal(regs.month.read(T_MONTH::Value));
|
|
|
- let year = bcd_to_decimal(regs.year.read(T_YEAR::Value));
|
|
|
- let century = bcd_to_decimal(regs.month.read(T_MONTH::Century));
|
|
|
+ let weekday: Weekday = weekday_reg.read(T_WEEKDAY::Value).into();
|
|
|
+ let day = bcd_to_decimal(day_reg.read(T_DAY::Value));
|
|
|
+ let month = bcd_to_decimal(month_reg.read(T_MONTH::Value));
|
|
|
+ let year = bcd_to_decimal(year_reg.read(T_YEAR::Value));
|
|
|
+ let century = bcd_to_decimal(month_reg.read(T_MONTH::Century));
|
|
|
|
|
|
(weekday, day, month, year, century)
|
|
|
}
|