pub use rtc_hal::square_wave::SquareWave;
pub use rtc_hal::square_wave::SquareWaveFreq;
use crate::Ds3231;
use crate::error::Error;
use crate::registers::{INTCN_BIT, RS_MASK, Register};
fn freq_to_bits<E>(freq: SquareWaveFreq) -> Result<u8, Error<E>>
where
E: core::fmt::Debug,
{
match freq {
SquareWaveFreq::Hz1 => Ok(0b0000_0000),
SquareWaveFreq::Hz1024 => Ok(0b0000_1000),
SquareWaveFreq::Hz4096 => Ok(0b0001_0000),
SquareWaveFreq::Hz8192 => Ok(0b0001_1000),
_ => Err(Error::UnsupportedSqwFrequency),
}
}
impl<I2C> SquareWave for Ds3231<I2C>
where
I2C: embedded_hal::i2c::I2c,
{
fn enable_square_wave(&mut self) -> Result<(), Self::Error> {
self.clear_register_bits(Register::Control, INTCN_BIT)
}
fn disable_square_wave(&mut self) -> Result<(), Self::Error> {
self.set_register_bits(Register::Control, INTCN_BIT)
}
fn set_square_wave_frequency(&mut self, freq: SquareWaveFreq) -> Result<(), Self::Error> {
let rs_bits = freq_to_bits(freq)?;
let current = self.read_register(Register::Control)?;
let mut new_value = current;
new_value &= !RS_MASK;
new_value |= rs_bits;
if new_value != current {
self.write_register(Register::Control, new_value)
} else {
Ok(())
}
}
fn start_square_wave(&mut self, freq: SquareWaveFreq) -> Result<(), Self::Error> {
let rs_bits = freq_to_bits(freq)?;
let current = self.read_register(Register::Control)?;
let mut new_value = current;
new_value &= !RS_MASK;
new_value |= rs_bits;
new_value &= !INTCN_BIT;
if new_value != current {
self.write_register(Register::Control, new_value)
} else {
Ok(())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use embedded_hal_mock::eh1::i2c::{Mock as I2cMock, Transaction as I2cTransaction};
use rtc_hal::square_wave::{SquareWave, SquareWaveFreq};
const DS3231_ADDR: u8 = 0x68;
#[test]
fn test_freq_to_bits_supported_frequencies() {
assert_eq!(
freq_to_bits::<()>(SquareWaveFreq::Hz1).unwrap(),
0b0000_0000
);
assert_eq!(
freq_to_bits::<()>(SquareWaveFreq::Hz1024).unwrap(),
0b0000_1000
);
assert_eq!(
freq_to_bits::<()>(SquareWaveFreq::Hz4096).unwrap(),
0b0001_0000
);
assert_eq!(
freq_to_bits::<()>(SquareWaveFreq::Hz8192).unwrap(),
0b0001_1000
);
}
#[test]
fn test_freq_to_bits_unsupported_frequency() {
let result = freq_to_bits::<()>(SquareWaveFreq::Hz32768);
assert!(matches!(result, Err(Error::UnsupportedSqwFrequency)));
}
#[test]
fn test_enable_square_wave() {
let expectations = vec![
I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b0000_0100],
),
I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0000_0000]),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.enable_square_wave();
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_enable_square_wave_already_enabled() {
let expectations = vec![I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b0000_0000],
)];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.enable_square_wave();
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_disable_square_wave() {
let expectations = vec![
I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b0000_0000],
),
I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0000_0100]),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.disable_square_wave();
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_set_square_wave_frequency_1hz() {
let expectations = vec![
I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b0001_1000],
),
I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0000_0000]),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.set_square_wave_frequency(SquareWaveFreq::Hz1);
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_set_square_wave_frequency_1024hz() {
let expectations = vec![
I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b0000_0000],
),
I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0000_1000]),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.set_square_wave_frequency(SquareWaveFreq::Hz1024);
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_set_square_wave_frequency_4096hz() {
let expectations = vec![
I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b0000_1000],
),
I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0001_0000]),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.set_square_wave_frequency(SquareWaveFreq::Hz4096);
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_set_square_wave_frequency_8192hz() {
let expectations = vec![
I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b0000_0000],
),
I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0001_1000]),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.set_square_wave_frequency(SquareWaveFreq::Hz8192);
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_set_square_wave_frequency_no_change_needed() {
let expectations = vec![I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b0001_0000], )];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.set_square_wave_frequency(SquareWaveFreq::Hz4096);
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_set_square_wave_frequency_preserves_other_bits() {
let expectations = vec![
I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b1100_0100],
),
I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b1100_1100]),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.set_square_wave_frequency(SquareWaveFreq::Hz1024);
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_set_square_wave_frequency_unsupported() {
let expectations = vec![];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.set_square_wave_frequency(SquareWaveFreq::Hz32768);
assert!(matches!(result, Err(Error::UnsupportedSqwFrequency)));
i2c_mock.done();
}
#[test]
fn test_start_square_wave_1hz() {
let expectations = vec![
I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b0001_1100],
),
I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0000_0000]),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.start_square_wave(SquareWaveFreq::Hz1);
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_start_square_wave_1024hz() {
let expectations = vec![
I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b1000_0100],
),
I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b1000_1000]),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.start_square_wave(SquareWaveFreq::Hz1024);
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_start_square_wave_4096hz() {
let expectations = vec![
I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b0100_1100],
),
I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0101_0000]),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.start_square_wave(SquareWaveFreq::Hz4096);
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_start_square_wave_8192hz() {
let expectations = vec![
I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b0000_0100],
),
I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0001_1000]),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.start_square_wave(SquareWaveFreq::Hz8192);
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_start_square_wave_already_configured() {
let expectations = vec![I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b0000_1000],
)];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.start_square_wave(SquareWaveFreq::Hz1024);
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_start_square_wave_preserves_other_bits() {
let expectations = vec![
I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b1010_0100],
),
I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b1010_0000]),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.start_square_wave(SquareWaveFreq::Hz1);
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_start_square_wave_unsupported_frequency() {
let expectations = vec![];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.start_square_wave(SquareWaveFreq::Hz32768);
assert!(matches!(result, Err(Error::UnsupportedSqwFrequency)));
i2c_mock.done();
}
#[test]
fn test_i2c_read_error_handling() {
let expectations = vec![
I2cTransaction::write_read(DS3231_ADDR, vec![Register::Control.addr()], vec![0x00])
.with_error(embedded_hal::i2c::ErrorKind::Other),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.enable_square_wave();
assert!(result.is_err());
i2c_mock.done();
}
#[test]
fn test_i2c_write_error_handling() {
let expectations = vec![
I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b0000_0100],
),
I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0000_0000])
.with_error(embedded_hal::i2c::ErrorKind::Other),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.enable_square_wave();
assert!(result.is_err());
i2c_mock.done();
}
#[test]
fn test_rs_mask_coverage() {
let expectations = vec![
I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b1111_1111],
),
I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b1110_1111]),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.set_square_wave_frequency(SquareWaveFreq::Hz1024);
assert!(result.is_ok());
i2c_mock.done();
}
#[test]
fn test_intcn_bit_manipulation() {
let expectations = vec![
I2cTransaction::write_read(
DS3231_ADDR,
vec![Register::Control.addr()],
vec![0b1111_1111],
),
I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b1111_1011]),
];
let mut i2c_mock = I2cMock::new(&expectations);
let mut ds3231 = Ds3231::new(&mut i2c_mock);
let result = ds3231.enable_square_wave();
assert!(result.is_ok());
i2c_mock.done();
}
}