From 6e477fa5bf5c748942e95d1dc60c5acd345f41ff Mon Sep 17 00:00:00 2001 From: Diego Barrios Romero Date: Sun, 28 Oct 2018 20:17:36 +0100 Subject: [PATCH] Add function to enable/disable the oscillator --- README.md | 10 +++----- src/ds323x/configuration.rs | 32 ++++++++++++++++++++++++ src/ds323x/mod.rs | 1 + src/lib.rs | 12 ++++----- tests/common/mod.rs | 21 ++++++++++++++++ tests/configuration.rs | 50 +++++++++++++++++++++++++++++++++++++ 6 files changed, 112 insertions(+), 14 deletions(-) create mode 100644 src/ds323x/configuration.rs create mode 100644 tests/configuration.rs diff --git a/README.md b/README.md index 84ff483..774d85f 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,9 @@ extremely accurate real-time clocks, based on the [`embedded-hal`] traits. [`embedded-hal`]: https://github.com/rust-embedded/embedded-hal This driver allows you to: -- Read/write the seconds. -- Read/write the minutes. -- Read/write the hours in 24h or AM/PM format. -- Read/write the weekday. -- Read/write the day. -- Read/write the month. -- Read/write the year. +- Read and set date and time in 12-hour and 24-hour format. See: `get_datetime`. +- Read and set date and time elements. For example, see: `get_year`. +- Enable and disable the real-time clock. See: `enable`. ## The devices diff --git a/src/ds323x/configuration.rs b/src/ds323x/configuration.rs new file mode 100644 index 0000000..8d53048 --- /dev/null +++ b/src/ds323x/configuration.rs @@ -0,0 +1,32 @@ +//! Device configuration + +extern crate embedded_hal as hal; +use super::super::{ Ds323x, Register, BitFlags, Error }; +use interface::{ ReadData, WriteData }; + +impl Ds323x +where + DI: ReadData + WriteData +{ + /// Enable the oscillator (set the clock running). + /// + /// (Does not alter the device register if already running). + pub fn enable(&mut self) -> Result<(), Error> { + let control = self.iface.read_register(Register::CONTROL)?; + if (control & BitFlags::EOSC) != 0 { + self.iface.write_register(Register::CONTROL, control & !BitFlags::EOSC)?; + } + Ok(()) + } + + /// Disable the oscillator (stops the clock). + /// + /// (Does not alter the device register if already stopped). + pub fn disable(&mut self) -> Result<(), Error> { + let control = self.iface.read_register(Register::CONTROL)?; + if (control & BitFlags::EOSC) == 0 { + self.iface.write_register(Register::CONTROL, control | BitFlags::EOSC)?; + } + Ok(()) + } +} diff --git a/src/ds323x/mod.rs b/src/ds323x/mod.rs index aae4efd..4a7a4bb 100644 --- a/src/ds323x/mod.rs +++ b/src/ds323x/mod.rs @@ -1,2 +1,3 @@ +mod configuration; mod datetime; pub use self::datetime::{ Hours, DateTime }; diff --git a/src/lib.rs b/src/lib.rs index 9fe6c5e..6d1d095 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,13 +4,9 @@ //! [`embedded-hal`]: https://github.com/rust-embedded/embedded-hal //! //! This driver allows you to: -//! - Read/write the seconds. -//! - Read/write the minutes. -//! - Read/write the hours in 24h or AM/PM format. -//! - Read/write the weekday. -//! - Read/write the day. -//! - Read/write the month. -//! - Read/write the year. +//! - Read and set date and time in 12-hour and 24-hour format. See: `get_datetime`. +//! - Read and set date and time elements. For example, see: `get_year`. +//! - Enable and disable the real-time clock. See: `enable`. //! //! ## The devices //! @@ -189,6 +185,7 @@ impl Register { const DOM : u8 = 0x04; const MONTH : u8 = 0x05; const YEAR : u8 = 0x06; + const CONTROL : u8 = 0x0E; } struct BitFlags; @@ -197,6 +194,7 @@ impl BitFlags { const H24_H12 : u8 = 0b0100_0000; const AM_PM : u8 = 0b0010_0000; const CENTURY : u8 = 0b1000_0000; + const EOSC : u8 = 0b1000_0000; } const DEVICE_ADDRESS: u8 = 0b110_1000; diff --git a/tests/common/mod.rs b/tests/common/mod.rs index e9d8be4..a7d1c68 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -8,6 +8,7 @@ pub const DEVICE_ADDRESS: u8 = 0b110_1000; pub struct Register; +#[allow(unused)] impl Register { pub const SECONDS : u8 = 0x00; pub const MINUTES : u8 = 0x01; @@ -15,6 +16,14 @@ impl Register { pub const DOW : u8 = 0x03; pub const DOM : u8 = 0x04; pub const MONTH : u8 = 0x05; + pub const CONTROL : u8 = 0x0E; +} + +pub struct BitFlags; + +#[allow(unused)] +impl BitFlags { + pub const EOSC : u8 = 0b1000_0000; } pub struct DummyOutputPin; @@ -75,3 +84,15 @@ macro_rules! set_invalid_test { } }; } + +#[macro_export] +macro_rules! call_test { + ($name:ident, $method:ident, $create_method:ident, $transactions:expr) => { + #[test] + fn $name() { + let trans = $transactions; + let mut dev = $create_method(&trans); + dev.$method().unwrap(); + } + }; +} diff --git a/tests/configuration.rs b/tests/configuration.rs new file mode 100644 index 0000000..1023ffd --- /dev/null +++ b/tests/configuration.rs @@ -0,0 +1,50 @@ +#[deny(warnings)] + +extern crate embedded_hal_mock as hal; +use hal::i2c::Transaction as I2cTrans; +use hal::spi::Transaction as SpiTrans; +mod common; +use common::{ DEVICE_ADDRESS as DEV_ADDR, Register as Reg, new_ds3231, + new_ds3232, new_ds3234, BitFlags as BF }; + +macro_rules! call_method_test { + ($method:ident, $i2c_transactions:expr, $spi_transactions:expr) => { + call_test!(can_call_ds3231, $method, new_ds3231, $i2c_transactions); + call_test!(can_call_ds3232, $method, new_ds3232, $i2c_transactions); + call_test!(can_call_ds3234, $method, new_ds3234, $spi_transactions); + }; +} + +mod do_nothing_if_already_enabled { + use super::*; + call_method_test!(enable, + [ I2cTrans::write_read(DEV_ADDR, vec![Reg::CONTROL], vec![0]) ], + [ SpiTrans::transfer(vec![Reg::CONTROL, 0], vec![Reg::CONTROL, 0]) ]); +} + +mod enable { + use super::*; + call_method_test!(enable, + [ I2cTrans::write_read(DEV_ADDR, vec![Reg::CONTROL], vec![BF::EOSC | 0b0101_1010]), + I2cTrans::write(DEV_ADDR, vec![Reg::CONTROL, 0b0101_1010]) ], + + [ SpiTrans::transfer(vec![Reg::CONTROL, 0], vec![Reg::CONTROL, BF::EOSC | 0b0101_1010]), + SpiTrans::write(vec![Reg::CONTROL + 0x80, 0b0101_1010]) ]); +} + +mod do_nothing_if_already_disabled { + use super::*; + call_method_test!(disable, + [ I2cTrans::write_read(DEV_ADDR, vec![Reg::CONTROL], vec![BF::EOSC]) ], + [ SpiTrans::transfer(vec![Reg::CONTROL, 0], vec![Reg::CONTROL, BF::EOSC]) ]); +} + +mod disable { + use super::*; + call_method_test!(disable, + [ I2cTrans::write_read(DEV_ADDR, vec![Reg::CONTROL], vec![0b0101_1010]), + I2cTrans::write(DEV_ADDR, vec![Reg::CONTROL, BF::EOSC | 0b0101_1010]) ], + + [ SpiTrans::transfer(vec![Reg::CONTROL, 0], vec![Reg::CONTROL, 0b0101_1010]), + SpiTrans::write(vec![Reg::CONTROL + 0x80, BF::EOSC | 0b0101_1010]) ]); +}