pub use rtc_hal::control::RtcPowerControl;
use crate::{
Ds1307,
registers::{CH_BIT, Register},
};
impl<I2C, E> RtcPowerControl for Ds1307<I2C>
where
I2C: embedded_hal::i2c::I2c<Error = E>,
E: core::fmt::Debug,
{
fn start_clock(&mut self) -> Result<(), Self::Error> {
self.clear_register_bits(Register::Seconds, CH_BIT)
}
fn halt_clock(&mut self) -> Result<(), Self::Error> {
self.set_register_bits(Register::Seconds, CH_BIT)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::registers::{CH_BIT, Register};
use embedded_hal_mock::eh1::i2c::{Mock as I2cMock, Transaction as I2cTransaction};
use rtc_hal::control::RtcPowerControl;
const DS1307_ADDR: u8 = 0x68;
#[test]
fn test_start_clock_clears_ch_bit() {
let expectations = vec![
I2cTransaction::write_read(
DS1307_ADDR,
vec![Register::Seconds.addr()],
vec![CH_BIT], ),
I2cTransaction::write(DS1307_ADDR, vec![Register::Seconds.addr(), 0b0000_0000]),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds1307 = Ds1307::new(&mut i2c_mock);
let result = ds1307.start_clock();
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_start_clock_already_running() {
let expectations = vec![
I2cTransaction::write_read(
DS1307_ADDR,
vec![Register::Seconds.addr()],
vec![0b0000_0000], ),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds1307 = Ds1307::new(&mut i2c_mock);
let result = ds1307.start_clock();
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_start_clock_preserves_seconds_value() {
let expectations = vec![
I2cTransaction::write_read(
DS1307_ADDR,
vec![Register::Seconds.addr()],
vec![0b0010_1010 | CH_BIT],
),
I2cTransaction::write(
DS1307_ADDR,
vec![Register::Seconds.addr(), 0b0010_1010], ),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds1307 = Ds1307::new(&mut i2c_mock);
let result = ds1307.start_clock();
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_halt_clock_sets_ch_bit() {
let expectations = vec![
I2cTransaction::write_read(
DS1307_ADDR,
vec![Register::Seconds.addr()],
vec![0b0000_0000], ),
I2cTransaction::write(DS1307_ADDR, vec![Register::Seconds.addr(), CH_BIT]),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds1307 = Ds1307::new(&mut i2c_mock);
let result = ds1307.halt_clock();
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_halt_clock_already_halted() {
let expectations = vec![
I2cTransaction::write_read(
DS1307_ADDR,
vec![Register::Seconds.addr()],
vec![CH_BIT], ),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds1307 = Ds1307::new(&mut i2c_mock);
let result = ds1307.halt_clock();
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_halt_clock_preserves_seconds_value() {
let expectations = vec![
I2cTransaction::write_read(
DS1307_ADDR,
vec![Register::Seconds.addr()],
vec![0b0101_1001], ),
I2cTransaction::write(
DS1307_ADDR,
vec![Register::Seconds.addr(), 0b0101_1001 | CH_BIT], ),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds1307 = Ds1307::new(&mut i2c_mock);
let result = ds1307.halt_clock();
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_start_clock_i2c_read_error() {
let expectations = vec![
I2cTransaction::write_read(DS1307_ADDR, vec![Register::Seconds.addr()], vec![0x00])
.with_error(embedded_hal::i2c::ErrorKind::Other),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds1307 = Ds1307::new(&mut i2c_mock);
let result = ds1307.start_clock();
assert!(result.is_err());
i2c_mock.done();
}
#[test]
fn test_start_clock_i2c_write_error() {
let expectations = vec![
I2cTransaction::write_read(
DS1307_ADDR,
vec![Register::Seconds.addr()],
vec![CH_BIT], ),
I2cTransaction::write(DS1307_ADDR, vec![Register::Seconds.addr(), 0b0000_0000])
.with_error(embedded_hal::i2c::ErrorKind::Other),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds1307 = Ds1307::new(&mut i2c_mock);
let result = ds1307.start_clock();
assert!(result.is_err());
i2c_mock.done();
}
#[test]
fn test_halt_clock_i2c_read_error() {
let expectations = vec![
I2cTransaction::write_read(DS1307_ADDR, vec![Register::Seconds.addr()], vec![0x00])
.with_error(embedded_hal::i2c::ErrorKind::Other),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds1307 = Ds1307::new(&mut i2c_mock);
let result = ds1307.halt_clock();
assert!(result.is_err());
i2c_mock.done();
}
#[test]
fn test_halt_clock_i2c_write_error() {
let expectations = vec![
I2cTransaction::write_read(
DS1307_ADDR,
vec![Register::Seconds.addr()],
vec![0b0000_0000], ),
I2cTransaction::write(DS1307_ADDR, vec![Register::Seconds.addr(), CH_BIT])
.with_error(embedded_hal::i2c::ErrorKind::Other),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds1307 = Ds1307::new(&mut i2c_mock);
let result = ds1307.halt_clock();
assert!(result.is_err());
i2c_mock.done();
}
#[test]
fn test_power_control_sequence_start_halt_start() {
let expectations = vec![
I2cTransaction::write_read(DS1307_ADDR, vec![Register::Seconds.addr()], vec![CH_BIT]),
I2cTransaction::write(DS1307_ADDR, vec![Register::Seconds.addr(), 0b0000_0000]),
I2cTransaction::write_read(
DS1307_ADDR,
vec![Register::Seconds.addr()],
vec![0b0000_0000],
),
I2cTransaction::write(DS1307_ADDR, vec![Register::Seconds.addr(), CH_BIT]),
I2cTransaction::write_read(DS1307_ADDR, vec![Register::Seconds.addr()], vec![CH_BIT]),
I2cTransaction::write(DS1307_ADDR, vec![Register::Seconds.addr(), 0b0000_0000]),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds1307 = Ds1307::new(&mut i2c_mock);
assert!(ds1307.start_clock().is_ok());
assert!(ds1307.halt_clock().is_ok());
assert!(ds1307.start_clock().is_ok());
i2c_mock.done();
}
#[test]
fn test_start_clock_clears_only_ch_bit() {
let expectations = vec![
I2cTransaction::write_read(
DS1307_ADDR,
vec![Register::Seconds.addr()],
vec![0b1111_1111], ),
I2cTransaction::write(
DS1307_ADDR,
vec![Register::Seconds.addr(), !CH_BIT], ),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds1307 = Ds1307::new(&mut i2c_mock);
let result = ds1307.start_clock();
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_halt_clock_sets_only_ch_bit() {
let expectations = vec![
I2cTransaction::write_read(
DS1307_ADDR,
vec![Register::Seconds.addr()],
vec![0b0000_0000], ),
I2cTransaction::write(
DS1307_ADDR,
vec![Register::Seconds.addr(), CH_BIT], ),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds1307 = Ds1307::new(&mut i2c_mock);
let result = ds1307.halt_clock();
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_power_control_with_valid_bcd_seconds() {
let expectations = vec![
I2cTransaction::write_read(
DS1307_ADDR,
vec![Register::Seconds.addr()],
vec![0b0010_0101 | CH_BIT],
),
I2cTransaction::write(
DS1307_ADDR,
vec![Register::Seconds.addr(), 0b0010_0101], ),
I2cTransaction::write_read(
DS1307_ADDR,
vec![Register::Seconds.addr()],
vec![0b0010_0101], ),
I2cTransaction::write(
DS1307_ADDR,
vec![Register::Seconds.addr(), 0b0010_0101 | CH_BIT], ),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds1307 = Ds1307::new(&mut i2c_mock);
assert!(ds1307.start_clock().is_ok());
assert!(ds1307.halt_clock().is_ok());
i2c_mock.done();
}
}