Browse Source

Implement Rtcc trait

pull/4/head
Diego Barrios Romero 3 years ago
parent
commit
3c8d378d6f
  1. 1
      Cargo.toml
  2. 20
      README.md
  3. 23
      examples/linux.rs
  4. 233
      src/ds323x/datetime.rs
  5. 2
      src/ds323x/mod.rs
  6. 90
      src/lib.rs
  7. 842
      tests/alarms.rs
  8. 18
      tests/common/mod.rs
  9. 170
      tests/configuration.rs
  10. 227
      tests/datetime.rs
  11. 51
      tests/ds3232_4.rs

1
Cargo.toml

@ -26,6 +26,7 @@ maintenance = { status = "actively-developed" }
[dependencies]
embedded-hal = "0.2.3"
rtcc = "0.2"
[dev-dependencies]
linux-embedded-hal = "0.3"

20
README.md

@ -137,26 +137,20 @@ Please find additional examples using hardware in this repository: [driver-examp
[driver-examples]: https://github.com/eldruin/driver-examples
```rust
extern crate linux_embedded_hal as hal;
extern crate ds323x;
use ds323x::{ Ds323x, DateTime, Hours };
extern crate linux_embedded_hal as hal;
use ds323x::{Ds323x, NaiveDate, Rtcc};
fn main() {
let dev = hal::I2cdev::new("/dev/i2c-1").unwrap();
let mut rtc = Ds323x::new_ds3231(dev);
let datetime = DateTime {
year: 2018,
month: 8,
day: 20,
weekday: 4,
hour: Hours::H24(19),
minute: 59,
second: 58
};
let datetime = NaiveDate::from_ymd(2020, 5, 1).and_hms(19, 59, 58);
rtc.set_datetime(&datetime).unwrap();
// do something else...
let seconds = rtc.get_seconds().unwrap();
println!("Seconds: {}", seconds);
let time = rtc.get_time().unwrap();
println!("Time: {}", time);
let _dev = rtc.destroy_ds3231();
}
```

23
examples/linux.rs

@ -1,26 +1,15 @@
extern crate ds323x;
extern crate embedded_hal;
extern crate linux_embedded_hal;
use ds323x::{DateTime, Ds323x, Hours};
use linux_embedded_hal::I2cdev;
extern crate linux_embedded_hal as hal;
use ds323x::{Ds323x, NaiveDate, Rtcc};
fn main() {
let dev = I2cdev::new("/dev/i2c-1").unwrap();
let dev = hal::I2cdev::new("/dev/i2c-1").unwrap();
let mut rtc = Ds323x::new_ds3231(dev);
let datetime = DateTime {
year: 2018,
month: 8,
day: 20,
weekday: 4,
hour: Hours::H24(19),
minute: 59,
second: 58,
};
let datetime = NaiveDate::from_ymd(2020, 5, 1).and_hms(19, 59, 58);
rtc.set_datetime(&datetime).unwrap();
// do something else...
let seconds = rtc.get_seconds().unwrap();
println!("Seconds: {}", seconds);
let time = rtc.get_time().unwrap();
println!("Time: {}", time);
let _dev = rtc.destroy_ds3231();
}

233
src/ds323x/datetime.rs

@ -2,160 +2,156 @@
use super::super::{BitFlags, Ds323x, Error, Register};
use super::{decimal_to_packed_bcd, hours_to_register, packed_bcd_to_decimal};
use super::{Datelike, Hours, NaiveDate, NaiveDateTime, NaiveTime, Rtcc, Timelike};
use interface::{ReadData, WriteData};
/// Date and time
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct DateTime {
/// Year [2000-2099]
pub year: u16,
/// Month [1-12]
pub month: u8,
/// Day [1-31]
pub day: u8,
/// Weekday [1-7]
pub weekday: u8,
/// Hour in 24h/12h format
pub hour: Hours,
/// Minute [0-59]
pub minute: u8,
/// Second [0-59]
pub second: u8,
}
/// Hours in either 12-hour (AM/PM) or 24-hour format
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Hours {
/// AM [1-12]
AM(u8),
/// PM [1-12]
PM(u8),
/// 24H format [0-23]
H24(u8),
}
impl<DI, IC, CommE, PinE> Ds323x<DI, IC>
impl<DI, IC, CommE, PinE> Rtcc for Ds323x<DI, IC>
where
DI: ReadData<Error = Error<CommE, PinE>> + WriteData<Error = Error<CommE, PinE>>,
{
/// Read the seconds.
pub fn get_seconds(&mut self) -> Result<u8, Error<CommE, PinE>> {
type Error = Error<CommE, PinE>;
fn get_seconds(&mut self) -> Result<u8, Self::Error> {
self.read_register_decimal(Register::SECONDS)
}
/// Read the minutes.
pub fn get_minutes(&mut self) -> Result<u8, Error<CommE, PinE>> {
fn get_minutes(&mut self) -> Result<u8, Self::Error> {
self.read_register_decimal(Register::MINUTES)
}
/// Read the hours.
pub fn get_hours(&mut self) -> Result<Hours, Error<CommE, PinE>> {
fn get_hours(&mut self) -> Result<Hours, Self::Error> {
let data = self.iface.read_register(Register::HOURS)?;
Ok(hours_from_register(data))
}
/// Read the day of the week [1-7].
pub fn get_weekday(&mut self) -> Result<u8, Error<CommE, PinE>> {
fn get_time(&mut self) -> Result<NaiveTime, Self::Error> {
let mut data = [0; 4];
self.iface.read_data(&mut data)?;
let hour = hours_from_register(data[Register::HOURS as usize + 1]);
let minute = packed_bcd_to_decimal(data[Register::MINUTES as usize + 1]);
let second = packed_bcd_to_decimal(data[Register::SECONDS as usize + 1]);
let h24 = match hour {
Hours::H24(h) => h,
Hours::AM(h) => h,
Hours::PM(h) => h + 12,
};
Ok(NaiveTime::from_hms(
h24.into(),
minute.into(),
second.into(),
))
}
fn get_weekday(&mut self) -> Result<u8, Self::Error> {
self.read_register_decimal(Register::DOW)
}
/// Read the day of the month [1-31].
pub fn get_day(&mut self) -> Result<u8, Error<CommE, PinE>> {
fn get_day(&mut self) -> Result<u8, Self::Error> {
self.read_register_decimal(Register::DOM)
}
/// Read the month [1-12].
pub fn get_month(&mut self) -> Result<u8, Error<CommE, PinE>> {
fn get_month(&mut self) -> Result<u8, Self::Error> {
let data = self.iface.read_register(Register::MONTH)?;
let value = data & !BitFlags::CENTURY;
Ok(packed_bcd_to_decimal(value))
}
/// Read the year [2000-2100].
pub fn get_year(&mut self) -> Result<u16, Error<CommE, PinE>> {
fn get_year(&mut self) -> Result<u16, Self::Error> {
let mut data = [0; 3];
data[0] = Register::MONTH;
self.iface.read_data(&mut data)?;
Ok(year_from_registers(data[1], data[2]))
}
/// Read the date and time.
pub fn get_datetime(&mut self) -> Result<DateTime, Error<CommE, PinE>> {
let mut data = [0; 8];
fn get_date(&mut self) -> Result<NaiveDate, Self::Error> {
let mut data = [0; 4];
data[0] = Register::DOM;
self.iface.read_data(&mut data)?;
Ok(DateTime {
year: year_from_registers(
data[Register::MONTH as usize + 1],
data[Register::YEAR as usize + 1],
),
month: packed_bcd_to_decimal(data[Register::MONTH as usize + 1] & !BitFlags::CENTURY),
day: packed_bcd_to_decimal(data[Register::DOM as usize + 1]),
weekday: packed_bcd_to_decimal(data[Register::DOW as usize + 1]),
hour: hours_from_register(data[Register::HOURS as usize + 1]),
minute: packed_bcd_to_decimal(data[Register::MINUTES as usize + 1]),
second: packed_bcd_to_decimal(data[Register::SECONDS as usize + 1]),
})
let offset = Register::DOM as usize;
let year = year_from_registers(
data[Register::MONTH as usize + 1 - offset],
data[Register::YEAR as usize + 1 - offset],
);
let month =
packed_bcd_to_decimal(data[Register::MONTH as usize + 1 - offset] & !BitFlags::CENTURY);
let day = packed_bcd_to_decimal(data[Register::DOM as usize + 1 - offset]);
Ok(NaiveDate::from_ymd(year.into(), month.into(), day.into()))
}
fn read_register_decimal(&mut self, register: u8) -> Result<u8, Error<CommE, PinE>> {
let data = self.iface.read_register(register)?;
Ok(packed_bcd_to_decimal(data))
fn get_datetime(&mut self) -> Result<NaiveDateTime, Self::Error> {
let mut data = [0; 8];
self.iface.read_data(&mut data)?;
let year = year_from_registers(
data[Register::MONTH as usize + 1],
data[Register::YEAR as usize + 1],
);
let month = packed_bcd_to_decimal(data[Register::MONTH as usize + 1] & !BitFlags::CENTURY);
let day = packed_bcd_to_decimal(data[Register::DOM as usize + 1]);
let hour = hours_from_register(data[Register::HOURS as usize + 1]);
let minute = packed_bcd_to_decimal(data[Register::MINUTES as usize + 1]);
let second = packed_bcd_to_decimal(data[Register::SECONDS as usize + 1]);
let h24 = match hour {
Hours::H24(h) => h,
Hours::AM(h) => h,
Hours::PM(h) => h + 12,
};
Ok(
rtcc::NaiveDate::from_ymd(year.into(), month.into(), day.into()).and_hms(
h24.into(),
minute.into(),
second.into(),
),
)
}
/// Set the seconds [0-59].
///
/// Will return an `Error::InvalidInputData` if the seconds are out of range.
pub fn set_seconds(&mut self, seconds: u8) -> Result<(), Error<CommE, PinE>> {
fn set_seconds(&mut self, seconds: u8) -> Result<(), Self::Error> {
if seconds > 59 {
return Err(Error::InvalidInputData);
}
self.write_register_decimal(Register::SECONDS, seconds)
}
/// Set the minutes [0-59].
///
/// Will return an `Error::InvalidInputData` if the minutes are out of range.
pub fn set_minutes(&mut self, minutes: u8) -> Result<(), Error<CommE, PinE>> {
fn set_minutes(&mut self, minutes: u8) -> Result<(), Self::Error> {
if minutes > 59 {
return Err(Error::InvalidInputData);
}
self.write_register_decimal(Register::MINUTES, minutes)
}
/// Set the hours.
///
/// Changes the operating mode to 12h/24h depending on the parameter.
///
/// Will return an `Error::InvalidInputData` if the hours are out of range.
pub fn set_hours(&mut self, hours: Hours) -> Result<(), Error<CommE, PinE>> {
fn set_hours(&mut self, hours: Hours) -> Result<(), Self::Error> {
let value = hours_to_register(hours)?;
self.iface.write_register(Register::HOURS, value)
}
/// Set the day of week [1-7].
///
/// Will return an `Error::InvalidInputData` if the day is out of range.
pub fn set_weekday(&mut self, weekday: u8) -> Result<(), Error<CommE, PinE>> {
fn set_time(&mut self, time: &NaiveTime) -> Result<(), Self::Error> {
let mut payload = [
Register::SECONDS,
decimal_to_packed_bcd(time.second() as u8),
decimal_to_packed_bcd(time.minute() as u8),
hours_to_register(Hours::H24(time.hour() as u8))?,
];
self.iface.write_data(&mut payload)
}
fn set_weekday(&mut self, weekday: u8) -> Result<(), Self::Error> {
if weekday < 1 || weekday > 7 {
return Err(Error::InvalidInputData);
}
self.iface.write_register(Register::DOW, weekday)
}
/// Set the day of month [1-31].
///
/// Will return an `Error::InvalidInputData` if the day is out of range.
pub fn set_day(&mut self, day: u8) -> Result<(), Error<CommE, PinE>> {
fn set_day(&mut self, day: u8) -> Result<(), Self::Error> {
if day < 1 || day > 7 {
return Err(Error::InvalidInputData);
}
self.iface.write_register(Register::DOM, day)
}
/// Set the month [1-12].
///
/// Will return an `Error::InvalidInputData` if the month is out of range.
pub fn set_month(&mut self, month: u8) -> Result<(), Error<CommE, PinE>> {
fn set_month(&mut self, month: u8) -> Result<(), Self::Error> {
if month < 1 || month > 12 {
return Err(Error::InvalidInputData);
}
@ -165,10 +161,7 @@ where
self.iface.write_register(Register::MONTH, value)
}
/// Set the year [2000-2100].
///
/// Will return an `Error::InvalidInputData` if the year is out of range.
pub fn set_year(&mut self, year: u16) -> Result<(), Error<CommE, PinE>> {
fn set_year(&mut self, year: u16) -> Result<(), Self::Error> {
if year < 2000 || year > 2100 {
return Err(Error::InvalidInputData);
}
@ -191,36 +184,48 @@ where
}
}
/// Set the date and time.
///
/// Will return an `Error::InvalidInputData` if any of the parameters is out of range.
pub fn set_datetime(&mut self, datetime: &DateTime) -> Result<(), Error<CommE, PinE>> {
if datetime.year < 2000
|| datetime.year > 2100
|| datetime.month < 1
|| datetime.month > 12
|| datetime.day < 1
|| datetime.day > 31
|| datetime.weekday < 1
|| datetime.weekday > 7
|| datetime.minute > 59
|| datetime.second > 59
{
fn set_date(&mut self, date: &rtcc::NaiveDate) -> Result<(), Self::Error> {
if date.year() < 2000 || date.year() > 2100 {
return Err(Error::InvalidInputData);
}
let (month, year) = month_year_to_registers(date.month() as u8, date.year() as u16);
let mut payload = [
Register::DOW,
date.weekday().number_from_sunday() as u8,
decimal_to_packed_bcd(date.day() as u8),
month,
year,
];
self.iface.write_data(&mut payload)
}
fn set_datetime(&mut self, datetime: &NaiveDateTime) -> Result<(), Self::Error> {
if datetime.year() < 2000 || datetime.year() > 2100 {
return Err(Error::InvalidInputData);
}
let (month, year) = month_year_to_registers(datetime.month, datetime.year);
let (month, year) = month_year_to_registers(datetime.month() as u8, datetime.year() as u16);
let mut payload = [
Register::SECONDS,
decimal_to_packed_bcd(datetime.second),
decimal_to_packed_bcd(datetime.minute),
hours_to_register(datetime.hour)?,
decimal_to_packed_bcd(datetime.weekday),
decimal_to_packed_bcd(datetime.day),
decimal_to_packed_bcd(datetime.second() as u8),
decimal_to_packed_bcd(datetime.minute() as u8),
hours_to_register(Hours::H24(datetime.hour() as u8))?,
datetime.weekday().number_from_sunday() as u8,
decimal_to_packed_bcd(datetime.day() as u8),
month,
year,
];
self.iface.write_data(&mut payload)
}
}
impl<DI, IC, CommE, PinE> Ds323x<DI, IC>
where
DI: ReadData<Error = Error<CommE, PinE>> + WriteData<Error = Error<CommE, PinE>>,
{
fn read_register_decimal(&mut self, register: u8) -> Result<u8, Error<CommE, PinE>> {
let data = self.iface.read_register(register)?;
Ok(packed_bcd_to_decimal(data))
}
fn write_register_decimal(
&mut self,

2
src/ds323x/mod.rs

@ -5,8 +5,8 @@ pub use self::alarms::{
Alarm1Matching, Alarm2Matching, DayAlarm1, DayAlarm2, WeekdayAlarm1, WeekdayAlarm2,
};
mod datetime;
pub use self::datetime::{DateTime, Hours};
use super::{BitFlags, Error};
use super::{Datelike, Hours, NaiveDate, NaiveDateTime, NaiveTime, Rtcc, Timelike};
// Transforms a decimal number to packed BCD format
fn decimal_to_packed_bcd(dec: u8) -> u8 {

90
src/lib.rs

@ -153,8 +153,8 @@
//! ### Create a driver instance for the DS3231
//!
//! ```no_run
//! extern crate linux_embedded_hal as hal;
//! extern crate ds323x;
//! extern crate linux_embedded_hal as hal;
//! use ds323x::Ds323x;
//!
//! # fn main() {
@ -170,8 +170,8 @@
//! ### Create a driver instance for the DS3232
//!
//! ```no_run
//! extern crate linux_embedded_hal as hal;
//! extern crate ds323x;
//! extern crate linux_embedded_hal as hal;
//! use ds323x::Ds323x;
//!
//! # fn main() {
@ -187,8 +187,8 @@
//! ### Create a driver instance for the DS3234
//!
//! ```no_run
//! extern crate linux_embedded_hal as hal;
//! extern crate ds323x;
//! extern crate linux_embedded_hal as hal;
//! use ds323x::Ds323x;
//!
//! # fn main() {
@ -205,22 +205,14 @@
//! ### Set the current date and time at once
//!
//! ```no_run
//! extern crate linux_embedded_hal as hal;
//! extern crate ds323x;
//! use ds323x::{ Ds323x, DateTime, Hours };
//! extern crate linux_embedded_hal as hal;
//! use ds323x::{Ds323x, NaiveDate, Rtcc};
//!
//! # fn main() {
//! let dev = hal::I2cdev::new("/dev/i2c-1").unwrap();
//! let mut rtc = Ds323x::new_ds3231(dev);
//! let datetime = DateTime {
//! year: 2018,
//! month: 8,
//! day: 15,
//! weekday: 4,
//! hour: Hours::H24(19),
//! minute: 59,
//! second: 58
//! };
//! let datetime = NaiveDate::from_ymd(2020, 5, 1).and_hms(19, 59, 58);
//! rtc.set_datetime(&datetime).unwrap();
//! # }
//! ```
@ -228,38 +220,27 @@
//! ### Get the current date and time at once
//!
//! ```no_run
//! extern crate linux_embedded_hal as hal;
//! extern crate ds323x;
//! use ds323x::{ Ds323x, Hours };
//! extern crate linux_embedded_hal as hal;
//! use ds323x::{Ds323x, Rtcc};
//!
//! # fn main() {
//! let dev = hal::I2cdev::new("/dev/i2c-1").unwrap();
//! let mut rtc = Ds323x::new_ds3231(dev);
//!
//! let datetime = rtc.get_datetime().unwrap();
//!
//! // The hours depend on the RTC running mode
//! match datetime.hour {
//! Hours::H24(h) => println!("{}-{}-{}, {} {}:{}:{}", datetime.year,
//! datetime.month, datetime.day, datetime.weekday,
//! h, datetime.minute, datetime.second),
//! Hours::AM(h) => println!("{}-{}-{}, {} {}:{}:{} AM", datetime.year,
//! datetime.month, datetime.day, datetime.weekday,
//! h, datetime.minute, datetime.second),
//! Hours::PM(h) => println!("{}-{}-{}, {} {}:{}:{} PM", datetime.year,
//! datetime.month, datetime.day, datetime.weekday,
//! h, datetime.minute, datetime.second),
//! }
//! // This will print something like: 2018-08-15, 4 19:59:58
//! let dt = rtc.get_datetime().unwrap();
//! println!("{}", dt);
//! // This will print something like: 2020-05-01 19:59:58
//! # }
//! ```
//!
//! ### Get the year
//!
//! Similar methods exist for month, day, weekday, hours, minutes and seconds.
//!
//! ```no_run
//! extern crate linux_embedded_hal as hal;
//! extern crate ds323x;
//! use ds323x::{ Ds323x, Hours };
//! extern crate linux_embedded_hal as hal;
//! use ds323x::{Ds323x, Rtcc};
//!
//! # fn main() {
//! let dev = hal::I2cdev::new("/dev/i2c-1").unwrap();
@ -268,14 +249,15 @@
//! println!("Year: {}", year);
//! # }
//! ```
//! Similar methods exist for month, day, weekday, hours, minutes and seconds.
//!
//! ### Set the year
//!
//! Similar methods exist for month, day, weekday, hours, minutes and seconds.
//!
//! ```no_run
//! extern crate linux_embedded_hal as hal;
//! extern crate ds323x;
//! use ds323x::{ Ds323x, Hours };
//! extern crate linux_embedded_hal as hal;
//! use ds323x::{Ds323x, Rtcc};
//!
//! # fn main() {
//! let dev = hal::I2cdev::new("/dev/i2c-1").unwrap();
@ -283,13 +265,12 @@
//! rtc.set_year(2018).unwrap();
//! # }
//! ```
//! Similar methods exist for month, day, weekday, hours, minutes and seconds.
//!
//! ### Enable/disable the device
//!
//! ```no_run
//! extern crate linux_embedded_hal as hal;
//! extern crate ds323x;
//! extern crate linux_embedded_hal as hal;
//! use ds323x::Ds323x;
//!
//! # fn main() {
@ -306,8 +287,8 @@
//! ### Read the temperature
//!
//! ```no_run
//! extern crate linux_embedded_hal as hal;
//! extern crate ds323x;
//! extern crate linux_embedded_hal as hal;
//! use ds323x::Ds323x;
//!
//! # fn main() {
@ -320,8 +301,8 @@
//! ### Read busy status
//!
//! ```no_run
//! extern crate linux_embedded_hal as hal;
//! extern crate ds323x;
//! extern crate linux_embedded_hal as hal;
//! use ds323x::Ds323x;
//!
//! # fn main() {
@ -334,9 +315,9 @@
//! ### Enable the square-wave output with a frequency of 4.096Hz
//!
//! ```no_run
//! extern crate linux_embedded_hal as hal;
//! extern crate ds323x;
//! use ds323x::{ Ds323x, SqWFreq };
//! extern crate linux_embedded_hal as hal;
//! use ds323x::{Ds323x, SqWFreq};
//!
//! # fn main() {
//! let dev = hal::I2cdev::new("/dev/i2c-1").unwrap();
@ -354,9 +335,9 @@
//! available for the devices DS3232 and DS3234.
//!
//! ```no_run
//! extern crate linux_embedded_hal as hal;
//! extern crate ds323x;
//! use ds323x::{ Ds323x, SqWFreq };
//! extern crate linux_embedded_hal as hal;
//! use ds323x::{Ds323x, SqWFreq};
//!
//! # fn main() {
//! let dev = hal::I2cdev::new("/dev/i2c-1").unwrap();
@ -369,8 +350,8 @@
//! ### Set the aging offset
//!
//! ```no_run
//! extern crate linux_embedded_hal as hal;
//! extern crate ds323x;
//! extern crate linux_embedded_hal as hal;
//! use ds323x::Ds323x;
//!
//! # fn main() {
@ -385,9 +366,9 @@
//! This is only available for the devices DS3232 and DS3234.
//!
//! ```no_run
//! extern crate linux_embedded_hal as hal;
//! extern crate ds323x;
//! use ds323x::{ Ds323x, TempConvRate };
//! extern crate linux_embedded_hal as hal;
//! use ds323x::{Ds323x, TempConvRate};
//!
//! # fn main() {
//! let dev = hal::I2cdev::new("/dev/i2c-1").unwrap();
@ -399,9 +380,9 @@
//! ### Set the Alarm1 to each week on a week day at a specific time
//!
//! ```no_run
//! extern crate linux_embedded_hal as hal;
//! extern crate ds323x;
//! use ds323x::{ Ds323x, Hours, WeekdayAlarm1, Alarm1Matching };
//! extern crate linux_embedded_hal as hal;
//! use ds323x::{Ds323x, Hours, WeekdayAlarm1, Alarm1Matching};
//!
//! # fn main() {
//! let dev = hal::I2cdev::new("/dev/i2c-1").unwrap();
@ -421,9 +402,9 @@
//! The INT/SQW output pin will be set to 1 when it the alarm matches.
//!
//! ```no_run
//! extern crate linux_embedded_hal as hal;
//! extern crate ds323x;
//! use ds323x::{ Ds323x, Hours, DayAlarm2, Alarm2Matching };
//! extern crate linux_embedded_hal as hal;
//! use ds323x::{Ds323x, Hours, DayAlarm2, Alarm2Matching};
//!
//! # fn main() {
//! let dev = hal::I2cdev::new("/dev/i2c-1").unwrap();
@ -445,6 +426,8 @@
extern crate embedded_hal as hal;
use core::marker::PhantomData;
use hal::spi::{Mode, MODE_1, MODE_3};
extern crate rtcc;
pub use self::rtcc::{Datelike, Hours, NaiveDate, NaiveDateTime, NaiveTime, Rtcc, Timelike};
/// SPI mode 1 (CPOL = 0, CPHA = 1)
pub const SPI_MODE_1: Mode = MODE_1;
@ -561,8 +544,7 @@ pub struct Ds323x<DI, IC> {
mod ds323x;
pub mod interface;
pub use ds323x::{
Alarm1Matching, Alarm2Matching, DateTime, DayAlarm1, DayAlarm2, Hours, WeekdayAlarm1,
WeekdayAlarm2,
Alarm1Matching, Alarm2Matching, DayAlarm1, DayAlarm2, WeekdayAlarm1, WeekdayAlarm2,
};
mod ds3231;
mod ds3232;

842
tests/alarms.rs

@ -28,57 +28,401 @@ macro_rules! set_invalid_alarm_test {
($name:ident, $method:ident, $alarm:expr, $matching:expr) => {
mod $name {
use super::*;
_set_invalid_alarm_test!(cannot_set_invalid_ds3231, $method, new_ds3231, destroy_ds3231, $alarm, $matching);
_set_invalid_alarm_test!(cannot_set_invalid_ds3232, $method, new_ds3232, destroy_ds3232, $alarm, $matching);
_set_invalid_alarm_test!(cannot_set_invalid_ds3234, $method, new_ds3234, destroy_ds3234, $alarm, $matching);
_set_invalid_alarm_test!(
cannot_set_invalid_ds3231,
$method,
new_ds3231,
destroy_ds3231,
$alarm,
$matching
);
_set_invalid_alarm_test!(
cannot_set_invalid_ds3232,
$method,
new_ds3232,
destroy_ds3232,
$alarm,
$matching
);
_set_invalid_alarm_test!(
cannot_set_invalid_ds3234,
$method,
new_ds3234,
destroy_ds3234,
$alarm,
$matching
);
}
};
}
mod alarm1 {
use super::*;
set_invalid_alarm_test!(day_invalid_s, set_alarm1_day, DayAlarm1{ day: 1, hour: Hours::H24(1), minute: 1, second: 60 }, A1M::AllMatch);
set_invalid_alarm_test!(day_invalid_min, set_alarm1_day, DayAlarm1{ day: 1, hour: Hours::H24(1), minute: 60, second: 1 }, A1M::AllMatch);
set_invalid_alarm_test!(day_invalid_h, set_alarm1_day, DayAlarm1{ day: 1, hour: Hours::H24(24), minute: 1, second: 1 }, A1M::AllMatch);
set_invalid_alarm_test!(day_invalid_am1, set_alarm1_day, DayAlarm1{ day: 1, hour: Hours::AM(0), minute: 1, second: 1 }, A1M::AllMatch);
set_invalid_alarm_test!(day_invalid_am2, set_alarm1_day, DayAlarm1{ day: 1, hour: Hours::AM(13), minute: 1, second: 1 }, A1M::AllMatch);
set_invalid_alarm_test!(day_invalid_pm1, set_alarm1_day, DayAlarm1{ day: 1, hour: Hours::PM(0), minute: 1, second: 1 }, A1M::AllMatch);
set_invalid_alarm_test!(day_invalid_pm2, set_alarm1_day, DayAlarm1{ day: 1, hour: Hours::PM(13), minute: 1, second: 1 }, A1M::AllMatch);
set_invalid_alarm_test!(day_invalid_d1, set_alarm1_day, DayAlarm1{ day: 0, hour: Hours::H24(1), minute: 1, second: 1 }, A1M::AllMatch);
set_invalid_alarm_test!(day_invalid_d2, set_alarm1_day, DayAlarm1{ day: 32, hour: Hours::H24(1), minute: 1, second: 1 }, A1M::AllMatch);
set_invalid_alarm_test!(wd_invalid_s, set_alarm1_weekday, WeekdayAlarm1{ weekday: 1, hour: Hours::H24(1), minute: 1, second: 60 }, A1M::AllMatch);
set_invalid_alarm_test!(wd_invalid_min, set_alarm1_weekday, WeekdayAlarm1{ weekday: 1, hour: Hours::H24(1), minute: 60, second: 1 }, A1M::AllMatch);
set_invalid_alarm_test!(wd_invalid_h, set_alarm1_weekday, WeekdayAlarm1{ weekday: 1, hour: Hours::H24(24), minute: 1, second: 1 }, A1M::AllMatch);
set_invalid_alarm_test!(wd_invalid_am1, set_alarm1_weekday, WeekdayAlarm1{ weekday: 1, hour: Hours::AM(0), minute: 1, second: 1 }, A1M::AllMatch);
set_invalid_alarm_test!(wd_invalid_am2, set_alarm1_weekday, WeekdayAlarm1{ weekday: 1, hour: Hours::AM(13), minute: 1, second: 1 }, A1M::AllMatch);
set_invalid_alarm_test!(wd_invalid_pm1, set_alarm1_weekday, WeekdayAlarm1{ weekday: 1, hour: Hours::PM(0), minute: 1, second: 1 }, A1M::AllMatch);
set_invalid_alarm_test!(wd_invalid_pm2, set_alarm1_weekday, WeekdayAlarm1{ weekday: 1, hour: Hours::PM(13), minute: 1, second: 1 }, A1M::AllMatch);
set_invalid_alarm_test!(wd_invalid_d1, set_alarm1_weekday, WeekdayAlarm1{ weekday: 0, hour: Hours::H24(1), minute: 1, second: 1 }, A1M::AllMatch);
set_invalid_alarm_test!(wd_invalid_d2, set_alarm1_weekday, WeekdayAlarm1{ weekday: 32, hour: Hours::H24(1), minute: 1, second: 1 }, A1M::AllMatch);
set_invalid_alarm_test!(
day_invalid_s,
set_alarm1_day,
DayAlarm1 {
day: 1,
hour: Hours::H24(1),
minute: 1,
second: 60
},
A1M::AllMatch
);
set_invalid_alarm_test!(
day_invalid_min,
set_alarm1_day,
DayAlarm1 {
day: 1,
hour: Hours::H24(1),
minute: 60,
second: 1
},
A1M::AllMatch
);
set_invalid_alarm_test!(
day_invalid_h,
set_alarm1_day,
DayAlarm1 {
day: 1,
hour: Hours::H24(24),
minute: 1,
second: 1
},
A1M::AllMatch
);
set_invalid_alarm_test!(
day_invalid_am1,
set_alarm1_day,
DayAlarm1 {
day: 1,
hour: Hours::AM(0),
minute: 1,
second: 1
},
A1M::AllMatch
);
set_invalid_alarm_test!(
day_invalid_am2,
set_alarm1_day,
DayAlarm1 {
day: 1,
hour: Hours::AM(13),
minute: 1,
second: 1
},
A1M::AllMatch
);
set_invalid_alarm_test!(
day_invalid_pm1,
set_alarm1_day,
DayAlarm1 {
day: 1,
hour: Hours::PM(0),
minute: 1,
second: 1
},
A1M::AllMatch
);
set_invalid_alarm_test!(
day_invalid_pm2,
set_alarm1_day,
DayAlarm1 {
day: 1,
hour: Hours::PM(13),
minute: 1,
second: 1
},
A1M::AllMatch
);
set_invalid_alarm_test!(
day_invalid_d1,
set_alarm1_day,
DayAlarm1 {
day: 0,
hour: Hours::H24(1),
minute: 1,
second: 1
},
A1M::AllMatch
);
set_invalid_alarm_test!(
day_invalid_d2,
set_alarm1_day,
DayAlarm1 {
day: 32,
hour: Hours::H24(1),
minute: 1,
second: 1
},
A1M::AllMatch
);
set_invalid_alarm_test!(
wd_invalid_s,
set_alarm1_weekday,
WeekdayAlarm1 {
weekday: 1,
hour: Hours::H24(1),
minute: 1,
second: 60
},
A1M::AllMatch
);
set_invalid_alarm_test!(
wd_invalid_min,
set_alarm1_weekday,
WeekdayAlarm1 {
weekday: 1,
hour: Hours::H24(1),
minute: 60,
second: 1
},
A1M::AllMatch
);
set_invalid_alarm_test!(
wd_invalid_h,
set_alarm1_weekday,
WeekdayAlarm1 {
weekday: 1,
hour: Hours::H24(24),
minute: 1,
second: 1
},
A1M::AllMatch
);
set_invalid_alarm_test!(
wd_invalid_am1,
set_alarm1_weekday,
WeekdayAlarm1 {
weekday: 1,
hour: Hours::AM(0),
minute: 1,
second: 1
},
A1M::AllMatch
);
set_invalid_alarm_test!(
wd_invalid_am2,
set_alarm1_weekday,
WeekdayAlarm1 {
weekday: 1,
hour: Hours::AM(13),
minute: 1,
second: 1
},
A1M::AllMatch
);
set_invalid_alarm_test!(
wd_invalid_pm1,
set_alarm1_weekday,
WeekdayAlarm1 {
weekday: 1,
hour: Hours::PM(0),
minute: 1,
second: 1
},
A1M::AllMatch
);
set_invalid_alarm_test!(
wd_invalid_pm2,
set_alarm1_weekday,
WeekdayAlarm1 {
weekday: 1,
hour: Hours::PM(13),
minute: 1,
second: 1
},
A1M::AllMatch
);
set_invalid_alarm_test!(
wd_invalid_d1,
set_alarm1_weekday,
WeekdayAlarm1 {
weekday: 0,
hour: Hours::H24(1),
minute: 1,
second: 1
},
A1M::AllMatch
);
set_invalid_alarm_test!(
wd_invalid_d2,
set_alarm1_weekday,
WeekdayAlarm1 {
weekday: 32,
hour: Hours::H24(1),
minute: 1,
second: 1
},
A1M::AllMatch
);
}
mod alarm2 {
use super::*;
set_invalid_alarm_test!(day_invalid_min, set_alarm2_day, DayAlarm2{ day: 1, hour: Hours::H24(1), minute: 60 }, A2M::AllMatch);
set_invalid_alarm_test!(day_invalid_h, set_alarm2_day, DayAlarm2{ day: 1, hour: Hours::H24(24), minute: 1 }, A2M::AllMatch);
set_invalid_alarm_test!(day_invalid_am1, set_alarm2_day, DayAlarm2{ day: 1, hour: Hours::AM(0), minute: 1 }, A2M::AllMatch);
set_invalid_alarm_test!(day_invalid_am2, set_alarm2_day, DayAlarm2{ day: 1, hour: Hours::AM(13), minute: 1 }, A2M::AllMatch);
set_invalid_alarm_test!(day_invalid_pm1, set_alarm2_day, DayAlarm2{ day: 1, hour: Hours::PM(0), minute: 1 }, A2M::AllMatch);
set_invalid_alarm_test!(day_invalid_pm2, set_alarm2_day, DayAlarm2{ day: 1, hour: Hours::PM(13), minute: 1 }, A2M::AllMatch);
set_invalid_alarm_test!(day_invalid_d1, set_alarm2_day, DayAlarm2{ day: 0, hour: Hours::H24(1), minute: 1 }, A2M::AllMatch);
set_invalid_alarm_test!(day_invalid_d2, set_alarm2_day, DayAlarm2{ day: 32, hour: Hours::H24(1), minute: 1 }, A2M::AllMatch);
set_invalid_alarm_test!(wd_invalid_min, set_alarm2_weekday, WeekdayAlarm2{ weekday: 1, hour: Hours::H24(1), minute: 60 }, A2M::AllMatch);
set_invalid_alarm_test!(wd_invalid_h, set_alarm2_weekday, WeekdayAlarm2{ weekday: 1, hour: Hours::H24(24), minute: 1 }, A2M::AllMatch);
set_invalid_alarm_test!(wd_invalid_am1, set_alarm2_weekday, WeekdayAlarm2{ weekday: 1, hour: Hours::AM(0), minute: 1 }, A2M::AllMatch);
set_invalid_alarm_test!(wd_invalid_am2, set_alarm2_weekday, WeekdayAlarm2{ weekday: 1, hour: Hours::AM(13), minute: 1 }, A2M::AllMatch);
set_invalid_alarm_test!(wd_invalid_pm1, set_alarm2_weekday, WeekdayAlarm2{ weekday: 1, hour: Hours::PM(0), minute: 1 }, A2M::AllMatch);
set_invalid_alarm_test!(wd_invalid_pm2, set_alarm2_weekday, WeekdayAlarm2{ weekday: 1, hour: Hours::PM(13), minute: 1 }, A2M::AllMatch);
set_invalid_alarm_test!(wd_invalid_d1, set_alarm2_weekday, WeekdayAlarm2{ weekday: 0, hour: Hours::H24(1), minute: 1 }, A2M::AllMatch);
set_invalid_alarm_test!(wd_invalid_d2, set_alarm2_weekday, WeekdayAlarm2{ weekday: 32, hour: Hours::H24(1), minute: 1 }, A2M::AllMatch);
}
set_invalid_alarm_test!(
day_invalid_min,
set_alarm2_day,
DayAlarm2 {
day: 1,
hour: Hours::H24(1),
minute: 60
},
A2M::AllMatch
);
set_invalid_alarm_test!(
day_invalid_h,
set_alarm2_day,
DayAlarm2 {
day: 1,
hour: Hours::H24(24),
minute: 1
},
A2M::AllMatch
);
set_invalid_alarm_test!(
day_invalid_am1,
set_alarm2_day,
DayAlarm2 {
day: 1,
hour: Hours::AM(0),
minute: 1
},
A2M::AllMatch
);
set_invalid_alarm_test!(
day_invalid_am2,
set_alarm2_day,
DayAlarm2 {
day: 1,
hour: Hours::AM(13),
minute: 1
},
A2M::AllMatch
);
set_invalid_alarm_test!(
day_invalid_pm1,
set_alarm2_day,
DayAlarm2 {
day: 1,
hour: Hours::PM(0),
minute: 1
},
A2M::AllMatch
);
set_invalid_alarm_test!(
day_invalid_pm2,
set_alarm2_day,
DayAlarm2 {
day: 1,
hour: Hours::PM(13),
minute: 1
},
A2M::AllMatch
);
set_invalid_alarm_test!(
day_invalid_d1,
set_alarm2_day,
DayAlarm2 {
day: 0,
hour: Hours::H24(1),
minute: 1
},
A2M::AllMatch
);
set_invalid_alarm_test!(
day_invalid_d2,
set_alarm2_day,
DayAlarm2 {
day: 32,
hour: Hours::H24(1),
minute: 1
},
A2M::AllMatch
);
set_invalid_alarm_test!(
wd_invalid_min,
set_alarm2_weekday,
WeekdayAlarm2 {
weekday: 1,
hour: Hours::H24(1),
minute: 60
},
A2M::AllMatch
);
set_invalid_alarm_test!(
wd_invalid_h,
set_alarm2_weekday,
WeekdayAlarm2 {
weekday: 1,
hour: Hours::H24(24),
minute: 1
},
A2M::AllMatch
);
set_invalid_alarm_test!(
wd_invalid_am1,
set_alarm2_weekday,
WeekdayAlarm2 {
weekday: 1,
hour: Hours::AM(0),
minute: 1
},
A2M::AllMatch
);
set_invalid_alarm_test!(
wd_invalid_am2,
set_alarm2_weekday,
WeekdayAlarm2 {
weekday: 1,
hour: Hours::AM(13),
minute: 1
},
A2M::AllMatch
);
set_invalid_alarm_test!(
wd_invalid_pm1,
set_alarm2_weekday,
WeekdayAlarm2 {
weekday: 1,
hour: Hours::PM(0),
minute: 1
},
A2M::AllMatch
);
set_invalid_alarm_test!(
wd_invalid_pm2,
set_alarm2_weekday,
WeekdayAlarm2 {
weekday: 1,
hour: Hours::PM(13),
minute: 1
},
A2M::AllMatch
);
set_invalid_alarm_test!(
wd_invalid_d1,
set_alarm2_weekday,
WeekdayAlarm2 {
weekday: 0,
hour: Hours::H24(1),
minute: 1
},
A2M::AllMatch
);
set_invalid_alarm_test!(
wd_invalid_d2,
set_alarm2_weekday,
WeekdayAlarm2 {
weekday: 32,
hour: Hours::H24(1),
minute: 1
},
A2M::AllMatch
);
}
macro_rules! _set_values_test {
($name:ident, $method:ident, $create_method:ident, $destroy_method:ident, $value1:expr, $value2:expr, $transactions:expr) => {
@ -96,9 +440,33 @@ macro_rules! set_values_test {
($name:ident, $method:ident, $value1:expr, $value2:expr, $i2c_transactions:expr, $spi_transactions:expr) => {
mod $name {
use super::*;
_set_values_test!(can_set_ds3231, $method, new_ds3231, destroy_ds3231, $value1, $value2, $i2c_transactions);
_set_values_test!(can_set_ds3232, $method, new_ds3232, destroy_ds3232, $value1, $value2, $i2c_transactions);
_set_values_test!(can_set_ds3234, $method, new_ds3234, destroy_ds3234, $value1, $value2, $spi_transactions);
_set_values_test!(
can_set_ds3231,
$method,
new_ds3231,
destroy_ds3231,
$value1,
$value2,
$i2c_transactions
);
_set_values_test!(
can_set_ds3232,
$method,
new_ds3232,
destroy_ds3232,
$value1,
$value2,
$i2c_transactions
);
_set_values_test!(
can_set_ds3234,
$method,
new_ds3234,
destroy_ds3234,
$value1,
$value2,
$spi_transactions
);
}
};
}
@ -111,76 +479,350 @@ macro_rules! set_alarm_test {
};
}
const AM : u8 = BF::ALARM_MATCH;
const AM: u8 = BF::ALARM_MATCH;
mod alarm1_day {
use super::*;
set_alarm_test!(h24, set_alarm1_day, DayAlarm1{ day: 1, hour: Hours::H24(2), minute: 3, second: 4 }, A1M::AllMatch,
ALARM1_SECONDS, [4, 3, 2, 1]);
set_alarm_test!(am, set_alarm1_day, DayAlarm1{ day: 1, hour: Hours::AM(2), minute: 3, second: 4 }, A1M::AllMatch,
ALARM1_SECONDS, [4, 3, 0b0100_0010, 1]);
set_alarm_test!(pm, set_alarm1_day, DayAlarm1{ day: 1, hour: Hours::PM(2), minute: 3, second: 4 }, A1M::AllMatch,
ALARM1_SECONDS, [4, 3, 0b0110_0010, 1]);
set_alarm_test!(match_hms, set_alarm1_day, DayAlarm1{ day: 1, hour: Hours::H24(2), minute: 3, second: 4 }, A1M::HoursMinutesAndSecondsMatch,
ALARM1_SECONDS, [ 4, 3, 2, AM | 1]);
set_alarm_test!(match_ms, set_alarm1_day, DayAlarm1{ day: 1, hour: Hours::H24(2), minute: 3, second: 4 }, A1M::MinutesAndSecondsMatch,
ALARM1_SECONDS, [ 4, 3, AM | 2, AM | 1]);
set_alarm_test!(match_s, set_alarm1_day, DayAlarm1{ day: 1, hour: Hours::H24(2), minute: 3, second: 4 }, A1M::SecondsMatch,
ALARM1_SECONDS, [ 4, AM | 3, AM | 2, AM | 1]);
set_alarm_test!(match_ops, set_alarm1_day, DayAlarm1{ day: 1, hour: Hours::H24(2), minute: 3, second: 4 }, A1M::OncePerSecond,
ALARM1_SECONDS, [AM | 4, AM | 3, AM | 2, AM | 1]);
set_alarm_test!(
h24,
set_alarm1_day,
DayAlarm1 {
day: 1,
hour: Hours::H24(2),
minute: 3,
second: 4
},
A1M::AllMatch,
ALARM1_SECONDS,
[4, 3, 2, 1]
);
set_alarm_test!(
am,
set_alarm1_day,
DayAlarm1 {
day: 1,
hour: Hours::AM(2),
minute: 3,
second: 4
},
A1M::AllMatch,
ALARM1_SECONDS,
[4, 3, 0b0100_0010, 1]
);
set_alarm_test!(
pm,
set_alarm1_day,
DayAlarm1 {
day: 1,
hour: Hours::PM(2),
minute: 3,
second: 4
},
A1M::AllMatch,
ALARM1_SECONDS,
[4, 3, 0b0110_0010, 1]
);
set_alarm_test!(
match_hms,
set_alarm1_day,
DayAlarm1 {
day: 1,
hour: Hours::H24(2),
minute: 3,
second: 4
},
A1M::HoursMinutesAndSecondsMatch,
ALARM1_SECONDS,
[4, 3, 2, AM | 1]
);
set_alarm_test!(
match_ms,
set_alarm1_day,
DayAlarm1 {
day: 1,
hour: Hours::H24(2),
minute: 3,
second: 4
},
A1M::MinutesAndSecondsMatch,
ALARM1_SECONDS,
[4, 3, AM | 2, AM | 1]
);
set_alarm_test!(
match_s,
set_alarm1_day,
DayAlarm1 {
day: 1,
hour: Hours::H24(2),
minute: 3,
second: 4
},
A1M::SecondsMatch,
ALARM1_SECONDS,
[4, AM | 3, AM | 2, AM | 1]
);
set_alarm_test!(
match_ops,
set_alarm1_day,
DayAlarm1 {
day: 1,
hour: Hours::H24(2),
minute: 3,
second: 4
},
A1M::OncePerSecond,
ALARM1_SECONDS,
[AM | 4, AM | 3, AM | 2, AM | 1]
);
}
mod alarm1_weekday {
use super::*;
set_alarm_test!(h24, set_alarm1_weekday, WeekdayAlarm1{ weekday: 1, hour: Hours::H24(2), minute: 3, second: 4 }, A1M::AllMatch,
ALARM1_SECONDS, [4, 3, 2, BF::WEEKDAY | 1]);
set_alarm_test!(am, set_alarm1_weekday, WeekdayAlarm1{ weekday: 1, hour: Hours::AM(2), minute: 3, second: 4 }, A1M::AllMatch,
ALARM1_SECONDS, [4, 3, 0b0100_0010, BF::WEEKDAY | 1]);
set_alarm_test!(pm, set_alarm1_weekday, WeekdayAlarm1{ weekday: 1, hour: Hours::PM(2), minute: 3, second: 4 }, A1M::AllMatch,
ALARM1_SECONDS, [4, 3, 0b0110_0010, BF::WEEKDAY | 1]);
set_alarm_test!(match_hms, set_alarm1_weekday, WeekdayAlarm1{ weekday: 1, hour: Hours::H24(2), minute: 3, second: 4 }, A1M::HoursMinutesAndSecondsMatch,
ALARM1_SECONDS, [ 4, 3, 2, AM | BF::WEEKDAY | 1]);
set_alarm_test!(match_ms, set_alarm1_weekday, WeekdayAlarm1{ weekday: 1, hour: Hours::H24(2), minute: 3, second: 4 }, A1M::MinutesAndSecondsMatch,
ALARM1_SECONDS, [ 4, 3, AM | 2, AM | BF::WEEKDAY | 1]);
set_alarm_test!(match_s, set_alarm1_weekday, WeekdayAlarm1{ weekday: 1, hour: Hours::H24(2), minute: 3, second: 4 }, A1M::SecondsMatch,
ALARM1_SECONDS, [ 4, AM | 3, AM | 2, AM | BF::WEEKDAY | 1]);
set_alarm_test!(match_ops, set_alarm1_weekday, WeekdayAlarm1{ weekday: 1, hour: Hours::H24(2), minute: 3, second: 4 }, A1M::OncePerSecond,
ALARM1_SECONDS, [AM | 4, AM | 3, AM | 2, AM | BF::WEEKDAY | 1]);
set_alarm_test!(
h24,
set_alarm1_weekday,
WeekdayAlarm1 {