mirror of https://github.com/eldruin/ds323x-rs
Code formatting
parent
c74f6a86f4
commit
af20f0321c
|
@ -1,22 +1,22 @@
|
|||
extern crate ds323x;
|
||||
extern crate embedded_hal;
|
||||
extern crate linux_embedded_hal;
|
||||
extern crate ds323x;
|
||||
|
||||
use ds323x::{DateTime, Ds323x, Hours};
|
||||
use linux_embedded_hal::I2cdev;
|
||||
use ds323x::{ Ds323x, DateTime, Hours };
|
||||
|
||||
fn main() {
|
||||
let dev = 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
|
||||
};
|
||||
year: 2018,
|
||||
month: 8,
|
||||
day: 20,
|
||||
weekday: 4,
|
||||
hour: Hours::H24(19),
|
||||
minute: 59,
|
||||
second: 58,
|
||||
};
|
||||
rtc.set_datetime(&datetime).unwrap();
|
||||
// do something else...
|
||||
let seconds = rtc.get_seconds().unwrap();
|
||||
|
|
|
@ -1,25 +1,23 @@
|
|||
//! Functions exclusive of DS3231
|
||||
|
||||
extern crate embedded_hal as hal;
|
||||
use hal::blocking;
|
||||
use super::{ic, BitFlags, Ds323x, CONTROL_POR_VALUE};
|
||||
use core::marker::PhantomData;
|
||||
use super::{ Ds323x, BitFlags, ic, CONTROL_POR_VALUE };
|
||||
use hal::blocking;
|
||||
use interface::I2cInterface;
|
||||
|
||||
impl<I2C, E> Ds323x<I2cInterface<I2C>, ic::DS3231>
|
||||
where
|
||||
I2C: blocking::i2c::Write<Error = E> + blocking::i2c::WriteRead<Error = E>
|
||||
I2C: blocking::i2c::Write<Error = E> + blocking::i2c::WriteRead<Error = E>,
|
||||
{
|
||||
/// Create a new instance of the DS3231 device.
|
||||
pub fn new_ds3231(i2c: I2C) -> Self {
|
||||
const STATUS_POR_VALUE : u8 = BitFlags::OSC_STOP | BitFlags::EN32KHZ;
|
||||
const STATUS_POR_VALUE: u8 = BitFlags::OSC_STOP | BitFlags::EN32KHZ;
|
||||
Ds323x {
|
||||
iface: I2cInterface {
|
||||
i2c,
|
||||
},
|
||||
iface: I2cInterface { i2c },
|
||||
control: CONTROL_POR_VALUE,
|
||||
status: STATUS_POR_VALUE,
|
||||
_ic: PhantomData
|
||||
_ic: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,26 +1,23 @@
|
|||
//! Functions exclusive of DS3232
|
||||
|
||||
extern crate embedded_hal as hal;
|
||||
use hal::blocking;
|
||||
use super::{ic, BitFlags, Ds323x, Error, TempConvRate, CONTROL_POR_VALUE};
|
||||
use core::marker::PhantomData;
|
||||
use super::{ Ds323x, TempConvRate, BitFlags, Error, ic, CONTROL_POR_VALUE };
|
||||
use hal::blocking;
|
||||
use interface::I2cInterface;
|
||||
|
||||
|
||||
impl<I2C, E> Ds323x<I2cInterface<I2C>, ic::DS3232>
|
||||
where
|
||||
I2C: blocking::i2c::Write<Error = E> + blocking::i2c::WriteRead<Error = E>
|
||||
I2C: blocking::i2c::Write<Error = E> + blocking::i2c::WriteRead<Error = E>,
|
||||
{
|
||||
/// Create a new instance of the DS3232 device.
|
||||
pub fn new_ds3232(i2c: I2C) -> Self {
|
||||
const STATUS_POR_VALUE : u8 = BitFlags::OSC_STOP | BitFlags::BB32KHZ | BitFlags::EN32KHZ;
|
||||
const STATUS_POR_VALUE: u8 = BitFlags::OSC_STOP | BitFlags::BB32KHZ | BitFlags::EN32KHZ;
|
||||
Ds323x {
|
||||
iface: I2cInterface {
|
||||
i2c,
|
||||
},
|
||||
iface: I2cInterface { i2c },
|
||||
control: CONTROL_POR_VALUE,
|
||||
status: STATUS_POR_VALUE,
|
||||
_ic: PhantomData
|
||||
_ic: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,13 +55,16 @@ where
|
|||
/// temperature changes will not be compensated for.
|
||||
///
|
||||
/// Note: This is only available for DS3232 and DS3234 devices.
|
||||
pub fn set_temperature_conversion_rate(&mut self, rate: TempConvRate) -> Result<(), Error<E, ()>> {
|
||||
pub fn set_temperature_conversion_rate(
|
||||
&mut self,
|
||||
rate: TempConvRate,
|
||||
) -> Result<(), Error<E, ()>> {
|
||||
let status;
|
||||
match rate {
|
||||
TempConvRate::_64s => status = self.status & !BitFlags::CRATE1 & !BitFlags::CRATE0,
|
||||
TempConvRate::_128s => status = self.status & !BitFlags::CRATE1 | BitFlags::CRATE0,
|
||||
TempConvRate::_256s => status = self.status | BitFlags::CRATE1 & !BitFlags::CRATE0,
|
||||
TempConvRate::_512s => status = self.status | BitFlags::CRATE1 | BitFlags::CRATE0,
|
||||
TempConvRate::_64s => status = self.status & !BitFlags::CRATE1 & !BitFlags::CRATE0,
|
||||
TempConvRate::_128s => status = self.status & !BitFlags::CRATE1 | BitFlags::CRATE0,
|
||||
TempConvRate::_256s => status = self.status | BitFlags::CRATE1 & !BitFlags::CRATE0,
|
||||
TempConvRate::_512s => status = self.status | BitFlags::CRATE1 | BitFlags::CRATE0,
|
||||
}
|
||||
self.write_status_without_clearing_alarm(status)
|
||||
}
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
//! Functions exclusive of DS3234
|
||||
|
||||
extern crate embedded_hal as hal;
|
||||
use hal::blocking;
|
||||
use super::{ic, BitFlags, Ds323x, Error, Register, TempConvRate, CONTROL_POR_VALUE};
|
||||
use core::marker::PhantomData;
|
||||
use super::{ Ds323x, TempConvRate, Register, BitFlags, Error, ic, CONTROL_POR_VALUE };
|
||||
use interface::{ SpiInterface, WriteData };
|
||||
use hal::blocking;
|
||||
use interface::{SpiInterface, WriteData};
|
||||
|
||||
impl<SPI, CS, CommE, PinE> Ds323x<SpiInterface<SPI, CS>, ic::DS3234>
|
||||
where
|
||||
SPI: blocking::spi::Transfer<u8, Error = CommE> + blocking::spi::Write<u8, Error = CommE>,
|
||||
CS: hal::digital::v2::OutputPin<Error = PinE>
|
||||
CS: hal::digital::v2::OutputPin<Error = PinE>,
|
||||
{
|
||||
/// Create a new instance.
|
||||
pub fn new_ds3234(spi: SPI, chip_select: CS) -> Self {
|
||||
const STATUS_POR_VALUE : u8 = BitFlags::OSC_STOP | BitFlags::BB32KHZ | BitFlags::EN32KHZ;
|
||||
const STATUS_POR_VALUE: u8 = BitFlags::OSC_STOP | BitFlags::BB32KHZ | BitFlags::EN32KHZ;
|
||||
Ds323x {
|
||||
iface: SpiInterface {
|
||||
spi,
|
||||
cs: chip_select
|
||||
cs: chip_select,
|
||||
},
|
||||
control: CONTROL_POR_VALUE,
|
||||
status: STATUS_POR_VALUE,
|
||||
_ic: PhantomData
|
||||
_ic: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,13 +59,16 @@ where
|
|||
/// temperature changes will not be compensated for.
|
||||
///
|
||||
/// Note: This is only available for DS3232 and DS3234 devices.
|
||||
pub fn set_temperature_conversion_rate(&mut self, rate: TempConvRate) -> Result<(), Error<CommE, PinE>> {
|
||||
pub fn set_temperature_conversion_rate(
|
||||
&mut self,
|
||||
rate: TempConvRate,
|
||||
) -> Result<(), Error<CommE, PinE>> {
|
||||
let status;
|
||||
match rate {
|
||||
TempConvRate::_64s => status = self.status & !BitFlags::CRATE1 & !BitFlags::CRATE0,
|
||||
TempConvRate::_128s => status = self.status & !BitFlags::CRATE1 | BitFlags::CRATE0,
|
||||
TempConvRate::_256s => status = self.status | BitFlags::CRATE1 & !BitFlags::CRATE0,
|
||||
TempConvRate::_512s => status = self.status | BitFlags::CRATE1 | BitFlags::CRATE0,
|
||||
TempConvRate::_64s => status = self.status & !BitFlags::CRATE1 & !BitFlags::CRATE0,
|
||||
TempConvRate::_128s => status = self.status & !BitFlags::CRATE1 | BitFlags::CRATE0,
|
||||
TempConvRate::_256s => status = self.status | BitFlags::CRATE1 & !BitFlags::CRATE0,
|
||||
TempConvRate::_512s => status = self.status | BitFlags::CRATE1 | BitFlags::CRATE0,
|
||||
}
|
||||
self.write_status_without_clearing_alarm(status)
|
||||
}
|
||||
|
@ -81,6 +84,7 @@ where
|
|||
///
|
||||
/// Note: This is only available for DS3234 devices.
|
||||
pub fn disable_temperature_conversions_on_battery(&mut self) -> Result<(), Error<CommE, PinE>> {
|
||||
self.iface.write_register(Register::TEMP_CONV, BitFlags::TEMP_CONV_BAT)
|
||||
self.iface
|
||||
.write_register(Register::TEMP_CONV, BitFlags::TEMP_CONV_BAT)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
//! Alarm support
|
||||
|
||||
extern crate embedded_hal as hal;
|
||||
use super::super::{ Ds323x, Hours, Register, BitFlags, Error };
|
||||
use interface::{ ReadData, WriteData };
|
||||
use super::{ decimal_to_packed_bcd, hours_to_register };
|
||||
use super::super::{BitFlags, Ds323x, Error, Hours, Register};
|
||||
use super::{decimal_to_packed_bcd, hours_to_register};
|
||||
use interface::{ReadData, WriteData};
|
||||
|
||||
/// Parameters for setting Alarm1 on a day of the month
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
|
@ -15,7 +15,7 @@ pub struct DayAlarm1 {
|
|||
/// Minute [0-59]
|
||||
pub minute: u8,
|
||||
/// Second [0-59]
|
||||
pub second: u8
|
||||
pub second: u8,
|
||||
}
|
||||
|
||||
/// Parameters for setting Alarm1 on a weekday
|
||||
|
@ -28,7 +28,7 @@ pub struct WeekdayAlarm1 {
|
|||
/// Minute [0-59]
|
||||
pub minute: u8,
|
||||
/// Second [0-59]
|
||||
pub second: u8
|
||||
pub second: u8,
|
||||
}
|
||||
|
||||
/// Alarm1 trigger rate
|
||||
|
@ -43,10 +43,9 @@ pub enum Alarm1Matching {
|
|||
/// Alarm when hours, minutes and seconds match.
|
||||
HoursMinutesAndSecondsMatch,
|
||||
/// Alarm when date/weekday, hours, minutes and seconds match.
|
||||
AllMatch
|
||||
AllMatch,
|
||||
}
|
||||
|
||||
|
||||
/// Parameters for setting Alarm2 on a day of the month
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct DayAlarm2 {
|
||||
|
@ -55,7 +54,7 @@ pub struct DayAlarm2 {
|
|||
/// Hour
|
||||
pub hour: Hours,
|
||||
/// Minute [0-59]
|
||||
pub minute: u8
|
||||
pub minute: u8,
|
||||
}
|
||||
|
||||
/// Parameters for setting Alarm2 on a weekday
|
||||
|
@ -66,7 +65,7 @@ pub struct WeekdayAlarm2 {
|
|||
/// Hour
|
||||
pub hour: Hours,
|
||||
/// Minute [0-59]
|
||||
pub minute: u8
|
||||
pub minute: u8,
|
||||
}
|
||||
|
||||
/// Alarm2 trigger rate
|
||||
|
@ -79,100 +78,117 @@ pub enum Alarm2Matching {
|
|||
/// Alarm when hours and minutes match.
|
||||
HoursAndMinutesMatch,
|
||||
/// Alarm when date/weekday, hours and minutes match.
|
||||
AllMatch
|
||||
AllMatch,
|
||||
}
|
||||
|
||||
fn get_matching_mask_alarm1(matching: Alarm1Matching) -> [u8; 4] {
|
||||
const AM : u8 = BitFlags::ALARM_MATCH;
|
||||
const AM: u8 = BitFlags::ALARM_MATCH;
|
||||
match matching {
|
||||
Alarm1Matching::OncePerSecond => [AM, AM, AM, AM],
|
||||
Alarm1Matching::SecondsMatch => [ 0, AM, AM, AM],
|
||||
Alarm1Matching::MinutesAndSecondsMatch => [ 0, 0, AM, AM],
|
||||
Alarm1Matching::HoursMinutesAndSecondsMatch => [ 0, 0, 0, AM],
|
||||
Alarm1Matching::AllMatch => [ 0, 0, 0, 0],
|
||||
Alarm1Matching::OncePerSecond => [AM, AM, AM, AM],
|
||||
Alarm1Matching::SecondsMatch => [0, AM, AM, AM],
|
||||
Alarm1Matching::MinutesAndSecondsMatch => [0, 0, AM, AM],
|
||||
Alarm1Matching::HoursMinutesAndSecondsMatch => [0, 0, 0, AM],
|
||||
Alarm1Matching::AllMatch => [0, 0, 0, 0],
|
||||
}
|
||||
}
|
||||
|
||||
fn get_matching_mask_alarm2(matching: Alarm2Matching) -> [u8; 3] {
|
||||
const AM : u8 = BitFlags::ALARM_MATCH;
|
||||
const AM: u8 = BitFlags::ALARM_MATCH;
|
||||
match matching {
|
||||
Alarm2Matching::OncePerMinute => [AM, AM, AM],
|
||||
Alarm2Matching::MinutesMatch => [ 0, AM, AM],
|
||||
Alarm2Matching::HoursAndMinutesMatch => [ 0, 0, AM],
|
||||
Alarm2Matching::AllMatch => [ 0, 0, 0],
|
||||
Alarm2Matching::OncePerMinute => [AM, AM, AM],
|
||||
Alarm2Matching::MinutesMatch => [0, AM, AM],
|
||||
Alarm2Matching::HoursAndMinutesMatch => [0, 0, AM],
|
||||
Alarm2Matching::AllMatch => [0, 0, 0],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<DI, IC, CommE, PinE> Ds323x<DI, IC>
|
||||
where
|
||||
DI: ReadData<Error = Error<CommE, PinE>> + WriteData<Error = Error<CommE, PinE>>
|
||||
DI: ReadData<Error = Error<CommE, PinE>> + WriteData<Error = Error<CommE, PinE>>,
|
||||
{
|
||||
/// Set Alarm1 for day of the month.
|
||||
///
|
||||
/// Will return an `Error::InvalidInputData` if any of the parameters is out of range.
|
||||
pub fn set_alarm1_day(&mut self, when: DayAlarm1, matching: Alarm1Matching) -> Result<(), Error<CommE, PinE>> {
|
||||
if when.day < 1 || when.day > 31 ||
|
||||
when.minute > 59 ||
|
||||
when.second > 59 {
|
||||
pub fn set_alarm1_day(
|
||||
&mut self,
|
||||
when: DayAlarm1,
|
||||
matching: Alarm1Matching,
|
||||
) -> Result<(), Error<CommE, PinE>> {
|
||||
if when.day < 1 || when.day > 31 || when.minute > 59 || when.second > 59 {
|
||||
return Err(Error::InvalidInputData);
|
||||
}
|
||||
let match_mask = get_matching_mask_alarm1(matching);
|
||||
let mut data = [ Register::ALARM1_SECONDS,
|
||||
decimal_to_packed_bcd(when.second) | match_mask[0],
|
||||
decimal_to_packed_bcd(when.minute) | match_mask[1],
|
||||
hours_to_register(when.hour)? | match_mask[2],
|
||||
decimal_to_packed_bcd(when.day) | match_mask[3]];
|
||||
let mut data = [
|
||||
Register::ALARM1_SECONDS,
|
||||
decimal_to_packed_bcd(when.second) | match_mask[0],
|
||||
decimal_to_packed_bcd(when.minute) | match_mask[1],
|
||||
hours_to_register(when.hour)? | match_mask[2],
|
||||
decimal_to_packed_bcd(when.day) | match_mask[3],
|
||||
];
|
||||
self.iface.write_data(&mut data)
|
||||
}
|
||||
|
||||
/// Set Alarm1 for weekday.
|
||||
///
|
||||
/// Will return an `Error::InvalidInputData` if any of the parameters is out of range.
|
||||
pub fn set_alarm1_weekday(&mut self, when: WeekdayAlarm1, matching: Alarm1Matching) -> Result<(), Error<CommE, PinE>> {
|
||||
if when.weekday < 1 || when.weekday > 7 ||
|
||||
when.minute > 59 ||
|
||||
when.second > 59 {
|
||||
pub fn set_alarm1_weekday(
|
||||
&mut self,
|
||||
when: WeekdayAlarm1,
|
||||
matching: Alarm1Matching,
|
||||
) -> Result<(), Error<CommE, PinE>> {
|
||||
if when.weekday < 1 || when.weekday > 7 || when.minute > 59 || when.second > 59 {
|
||||
return Err(Error::InvalidInputData);
|
||||
}
|
||||
let match_mask = get_matching_mask_alarm1(matching);
|
||||
let mut data = [ Register::ALARM1_SECONDS,
|
||||
decimal_to_packed_bcd(when.second) | match_mask[0],
|
||||
decimal_to_packed_bcd(when.minute) | match_mask[1],
|
||||
hours_to_register(when.hour)? | match_mask[2],
|
||||
decimal_to_packed_bcd(when.weekday) | match_mask[3] | BitFlags::WEEKDAY];
|
||||
let mut data = [
|
||||
Register::ALARM1_SECONDS,
|
||||
decimal_to_packed_bcd(when.second) | match_mask[0],
|
||||
decimal_to_packed_bcd(when.minute) | match_mask[1],
|
||||
hours_to_register(when.hour)? | match_mask[2],
|
||||
decimal_to_packed_bcd(when.weekday) | match_mask[3] | BitFlags::WEEKDAY,
|
||||
];
|
||||
self.iface.write_data(&mut data)
|
||||
}
|
||||
|
||||
/// Set Alarm2 for date (day of month).
|
||||
///
|
||||
/// Will return an `Error::InvalidInputData` if any of the parameters is out of range.
|
||||
pub fn set_alarm2_day(&mut self, when: DayAlarm2, matching: Alarm2Matching) -> Result<(), Error<CommE, PinE>> {
|
||||
if when.day < 1 || when.day > 31 ||
|
||||
when.minute > 59 {
|
||||
pub fn set_alarm2_day(
|
||||
&mut self,
|
||||
when: DayAlarm2,
|
||||
matching: Alarm2Matching,
|
||||
) -> Result<(), Error<CommE, PinE>> {
|
||||
if when.day < 1 || when.day > 31 || when.minute > 59 {
|
||||
return Err(Error::InvalidInputData);
|
||||
}
|
||||
let match_mask = get_matching_mask_alarm2(matching);
|
||||
let mut data = [ Register::ALARM2_MINUTES,
|
||||
decimal_to_packed_bcd(when.minute) | match_mask[0],
|
||||
hours_to_register(when.hour)? | match_mask[1],
|
||||
decimal_to_packed_bcd(when.day) | match_mask[2]];
|
||||
let mut data = [
|
||||
Register::ALARM2_MINUTES,
|
||||
decimal_to_packed_bcd(when.minute) | match_mask[0],
|
||||
hours_to_register(when.hour)? | match_mask[1],
|
||||
decimal_to_packed_bcd(when.day) | match_mask[2],
|
||||
];
|
||||
self.iface.write_data(&mut data)
|
||||
}
|
||||
|
||||
/// Set Alarm2 for weekday.
|
||||
///
|
||||
/// Will return an `Error::InvalidInputData` if any of the parameters is out of range.
|
||||
pub fn set_alarm2_weekday(&mut self, when: WeekdayAlarm2, matching: Alarm2Matching) -> Result<(), Error<CommE, PinE>> {
|
||||
if when.weekday < 1 || when.weekday > 7 ||
|
||||
when.minute > 59 {
|
||||
pub fn set_alarm2_weekday(
|
||||
&mut self,
|
||||
when: WeekdayAlarm2,
|
||||
matching: Alarm2Matching,
|
||||
) -> Result<(), Error<CommE, PinE>> {
|
||||
if when.weekday < 1 || when.weekday > 7 || when.minute > 59 {
|
||||
return Err(Error::InvalidInputData);
|
||||
}
|
||||
let match_mask = get_matching_mask_alarm2(matching);
|
||||
let mut data = [ Register::ALARM2_MINUTES,
|
||||
decimal_to_packed_bcd(when.minute) | match_mask[0],
|
||||
hours_to_register(when.hour)? | match_mask[1],
|
||||
decimal_to_packed_bcd(when.weekday) | match_mask[2] | BitFlags::WEEKDAY];
|
||||
let mut data = [
|
||||
Register::ALARM2_MINUTES,
|
||||
decimal_to_packed_bcd(when.minute) | match_mask[0],
|
||||
hours_to_register(when.hour)? | match_mask[1],
|
||||
decimal_to_packed_bcd(when.weekday) | match_mask[2] | BitFlags::WEEKDAY,
|
||||
];
|
||||
self.iface.write_data(&mut data)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
//! Device configuration
|
||||
|
||||
extern crate embedded_hal as hal;
|
||||
use super::super::{ Ds323x, SqWFreq, Register, BitFlags, Error };
|
||||
use interface::{ ReadData, WriteData };
|
||||
use super::super::{BitFlags, Ds323x, Error, Register, SqWFreq};
|
||||
use interface::{ReadData, WriteData};
|
||||
|
||||
impl<DI, IC, CommE, PinE> Ds323x<DI, IC>
|
||||
where
|
||||
DI: ReadData<Error = Error<CommE, PinE>> + WriteData<Error = Error<CommE, PinE>>
|
||||
DI: ReadData<Error = Error<CommE, PinE>> + WriteData<Error = Error<CommE, PinE>>,
|
||||
{
|
||||
/// Enable the oscillator (set the clock running) (default).
|
||||
pub fn enable(&mut self) -> Result<(), Error<CommE, PinE>> {
|
||||
|
@ -27,7 +27,8 @@ where
|
|||
let control = self.iface.read_register(Register::CONTROL)?;
|
||||
// do not overwrite if a conversion is in progress
|
||||
if (control & BitFlags::TEMP_CONV) == 0 {
|
||||
self.iface.write_register(Register::CONTROL, control | BitFlags::TEMP_CONV)?;
|
||||
self.iface
|
||||
.write_register(Register::CONTROL, control | BitFlags::TEMP_CONV)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -46,7 +47,8 @@ where
|
|||
|
||||
/// Set the aging offset.
|
||||
pub fn set_aging_offset(&mut self, offset: i8) -> Result<(), Error<CommE, PinE>> {
|
||||
self.iface.write_register(Register::AGING_OFFSET, offset as u8)
|
||||
self.iface
|
||||
.write_register(Register::AGING_OFFSET, offset as u8)
|
||||
}
|
||||
|
||||
/// Read the aging offset.
|
||||
|
@ -83,10 +85,10 @@ where
|
|||
pub fn set_square_wave_frequency(&mut self, freq: SqWFreq) -> Result<(), Error<CommE, PinE>> {
|
||||
let new_control;
|
||||
match freq {
|
||||
SqWFreq::_1Hz => new_control = self.control & !BitFlags::RS2 & !BitFlags::RS1,
|
||||
SqWFreq::_1_024Hz => new_control = self.control & !BitFlags::RS2 | BitFlags::RS1,
|
||||
SqWFreq::_4_096Hz => new_control = self.control | BitFlags::RS2 & !BitFlags::RS1,
|
||||
SqWFreq::_8_192Hz => new_control = self.control | BitFlags::RS2 | BitFlags::RS1,
|
||||
SqWFreq::_1Hz => new_control = self.control & !BitFlags::RS2 & !BitFlags::RS1,
|
||||
SqWFreq::_1_024Hz => new_control = self.control & !BitFlags::RS2 | BitFlags::RS1,
|
||||
SqWFreq::_4_096Hz => new_control = self.control | BitFlags::RS2 & !BitFlags::RS1,
|
||||
SqWFreq::_8_192Hz => new_control = self.control | BitFlags::RS2 | BitFlags::RS1,
|
||||
}
|
||||
self.write_control(new_control)
|
||||
}
|
||||
|
@ -121,7 +123,10 @@ where
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn write_status_without_clearing_alarm(&mut self, status: u8) -> Result<(), Error<CommE, PinE>> {
|
||||
pub(crate) fn write_status_without_clearing_alarm(
|
||||
&mut self,
|
||||
status: u8,
|
||||
) -> Result<(), Error<CommE, PinE>> {
|
||||
// avoid clearing alarm flags
|
||||
let new_status = status | BitFlags::ALARM2F | BitFlags::ALARM1F;
|
||||
self.iface.write_register(Register::STATUS, new_status)?;
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
//! Common implementation
|
||||
|
||||
extern crate embedded_hal as hal;
|
||||
use super::super::{ Ds323x, Register, BitFlags, Error };
|
||||
use super::{ decimal_to_packed_bcd, packed_bcd_to_decimal, hours_to_register };
|
||||
use interface::{ ReadData, WriteData };
|
||||
use super::super::{BitFlags, Ds323x, Error, Register};
|
||||
use super::{decimal_to_packed_bcd, hours_to_register, packed_bcd_to_decimal};
|
||||
use interface::{ReadData, WriteData};
|
||||
|
||||
/// Date and time
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct DateTime {
|
||||
/// Year [2000-2099]
|
||||
pub year : u16,
|
||||
pub year: u16,
|
||||
/// Month [1-12]
|
||||
pub month : u8,
|
||||
pub month: u8,
|
||||
/// Day [1-31]
|
||||
pub day : u8,
|
||||
pub day: u8,
|
||||
/// Weekday [1-7]
|
||||
pub weekday : u8,
|
||||
pub weekday: u8,
|
||||
/// Hour in 24h/12h format
|
||||
pub hour : Hours,
|
||||
pub hour: Hours,
|
||||
/// Minute [0-59]
|
||||
pub minute : u8,
|
||||
pub minute: u8,
|
||||
/// Second [0-59]
|
||||
pub second : u8,
|
||||
pub second: u8,
|
||||
}
|
||||
|
||||
/// Hours in either 12-hour (AM/PM) or 24-hour format
|
||||
|
@ -37,7 +37,7 @@ pub enum Hours {
|
|||
|
||||
impl<DI, IC, CommE, PinE> Ds323x<DI, IC>
|
||||
where
|
||||
DI: ReadData<Error = Error<CommE, PinE>> + WriteData<Error = Error<CommE, PinE>>
|
||||
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>> {
|
||||
|
@ -85,13 +85,16 @@ where
|
|||
let mut data = [0; 8];
|
||||
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])
|
||||
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]),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -173,14 +176,18 @@ where
|
|||
let data = self.iface.read_register(Register::MONTH)?;
|
||||
let month_bcd = data & !BitFlags::CENTURY;
|
||||
if year > 2099 {
|
||||
let mut data = [ Register::MONTH,
|
||||
BitFlags::CENTURY | month_bcd,
|
||||
decimal_to_packed_bcd((year - 2100) as u8) ];
|
||||
let mut data = [
|
||||
Register::MONTH,
|
||||
BitFlags::CENTURY | month_bcd,
|
||||
decimal_to_packed_bcd((year - 2100) as u8),
|
||||
];
|
||||
self.iface.write_data(&mut data)
|
||||
}
|
||||
else {
|
||||
let mut data = [ Register::MONTH, month_bcd,
|
||||
decimal_to_packed_bcd((year - 2000) as u8) ];
|
||||
} else {
|
||||
let mut data = [
|
||||
Register::MONTH,
|
||||
month_bcd,
|
||||
decimal_to_packed_bcd((year - 2000) as u8),
|
||||
];
|
||||
self.iface.write_data(&mut data)
|
||||
}
|
||||
}
|
||||
|
@ -189,39 +196,54 @@ where
|
|||
///
|
||||
/// 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 {
|
||||
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
|
||||
{
|
||||
return Err(Error::InvalidInputData);
|
||||
}
|
||||
let (month, year) = month_year_to_registers(datetime.month, datetime.year);
|
||||
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),
|
||||
month, year];
|
||||
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),
|
||||
month,
|
||||
year,
|
||||
];
|
||||
self.iface.write_data(&mut payload)
|
||||
}
|
||||
}
|
||||
|
||||
fn write_register_decimal(&mut self, register: u8, decimal_number: u8) -> Result<(), Error<CommE, PinE>> {
|
||||
self.iface.write_register(register, decimal_to_packed_bcd(decimal_number))
|
||||
fn write_register_decimal(
|
||||
&mut self,
|
||||
register: u8,
|
||||
decimal_number: u8,
|
||||
) -> Result<(), Error<CommE, PinE>> {
|
||||
self.iface
|
||||
.write_register(register, decimal_to_packed_bcd(decimal_number))
|
||||
}
|
||||
}
|
||||
|
||||
fn hours_from_register(data: u8) -> Hours {
|
||||
if is_24h_format(data) {
|
||||
Hours::H24(packed_bcd_to_decimal(data & !BitFlags::H24_H12))
|
||||
}
|
||||
else if is_am(data) {
|
||||
Hours::AM(packed_bcd_to_decimal(data & !(BitFlags::H24_H12 | BitFlags::AM_PM)))
|
||||
}
|
||||
else {
|
||||
Hours::PM(packed_bcd_to_decimal(data & !(BitFlags::H24_H12 | BitFlags::AM_PM)))
|
||||
} else if is_am(data) {
|
||||
Hours::AM(packed_bcd_to_decimal(
|
||||
data & !(BitFlags::H24_H12 | BitFlags::AM_PM),
|
||||
))
|
||||
} else {
|
||||
Hours::PM(packed_bcd_to_decimal(
|
||||
data & !(BitFlags::H24_H12 | BitFlags::AM_PM),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,8 +252,7 @@ fn year_from_registers(month: u8, year: u8) -> u16 {
|
|||
let year = packed_bcd_to_decimal(year);
|
||||
if century != 0 {
|
||||
2100 + u16::from(year)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
2000 + u16::from(year)
|
||||
}
|
||||
}
|
||||
|
@ -240,9 +261,11 @@ fn month_year_to_registers(month: u8, year: u16) -> (u8, u8) {
|
|||
if year > 2099 {
|
||||
let month = BitFlags::CENTURY | decimal_to_packed_bcd(month);
|
||||
(month, decimal_to_packed_bcd((year - 2100) as u8))
|
||||
}
|
||||
else {
|
||||
(decimal_to_packed_bcd(month), decimal_to_packed_bcd((year - 2000) as u8))
|
||||
} else {
|
||||
(
|
||||
decimal_to_packed_bcd(month),
|
||||
decimal_to_packed_bcd((year - 2000) as u8),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,4 +276,3 @@ fn is_24h_format(hours_data: u8) -> bool {
|
|||
fn is_am(hours_data: u8) -> bool {
|
||||
hours_data & BitFlags::AM_PM == 0
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
mod alarms;
|
||||
mod configuration;
|
||||
mod status;
|
||||
mod alarms;
|
||||
pub use self::alarms::{ DayAlarm1, WeekdayAlarm1, Alarm1Matching,
|
||||
DayAlarm2, WeekdayAlarm2, Alarm2Matching };
|
||||
pub use self::alarms::{
|
||||
Alarm1Matching, Alarm2Matching, DayAlarm1, DayAlarm2, WeekdayAlarm1, WeekdayAlarm2,
|
||||
};
|
||||
mod datetime;
|
||||
pub use self::datetime::{ Hours, DateTime };
|
||||
use super::{ BitFlags, Error };
|
||||
pub use self::datetime::{DateTime, Hours};
|
||||
use super::{BitFlags, Error};
|
||||
|
||||
// Transforms a decimal number to packed BCD format
|
||||
fn decimal_to_packed_bcd(dec: u8) -> u8 {
|
||||
|
@ -22,22 +23,21 @@ fn hours_to_register<CommE, PinE>(hours: Hours) -> Result<u8, Error<CommE, PinE>
|
|||
Hours::H24(h) if h > 23 => Err(Error::InvalidInputData),
|
||||
Hours::H24(h) => Ok(decimal_to_packed_bcd(h)),
|
||||
Hours::AM(h) if h < 1 || h > 12 => Err(Error::InvalidInputData),
|
||||
Hours::AM(h) => Ok(BitFlags::H24_H12 | decimal_to_packed_bcd(h)),
|
||||
Hours::AM(h) => Ok(BitFlags::H24_H12 | decimal_to_packed_bcd(h)),
|
||||
Hours::PM(h) if h < 1 || h > 12 => Err(Error::InvalidInputData),
|
||||
Hours::PM(h) => Ok(BitFlags::H24_H12 | BitFlags::AM_PM | decimal_to_packed_bcd(h)),
|
||||
Hours::PM(h) => Ok(BitFlags::H24_H12 | BitFlags::AM_PM | decimal_to_packed_bcd(h)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn can_convert_packed_bcd_to_decimal() {
|
||||
assert_eq!(0, packed_bcd_to_decimal(0b0000_0000));
|
||||
assert_eq!(1, packed_bcd_to_decimal(0b0000_0001));
|
||||
assert_eq!(9, packed_bcd_to_decimal(0b0000_1001));
|
||||
assert_eq!(0, packed_bcd_to_decimal(0b0000_0000));
|
||||
assert_eq!(1, packed_bcd_to_decimal(0b0000_0001));
|
||||
assert_eq!(9, packed_bcd_to_decimal(0b0000_1001));
|
||||
assert_eq!(10, packed_bcd_to_decimal(0b0001_0000));
|
||||
assert_eq!(11, packed_bcd_to_decimal(0b0001_0001));
|
||||
assert_eq!(19, packed_bcd_to_decimal(0b0001_1001));
|
||||
|
@ -48,9 +48,9 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn can_convert_decimal_to_packed_bcd() {
|
||||
assert_eq!(0b0000_0000, decimal_to_packed_bcd( 0));
|
||||
assert_eq!(0b0000_0001, decimal_to_packed_bcd( 1));
|
||||
assert_eq!(0b0000_1001, decimal_to_packed_bcd( 9));
|
||||
assert_eq!(0b0000_0000, decimal_to_packed_bcd(0));
|
||||
assert_eq!(0b0000_0001, decimal_to_packed_bcd(1));
|
||||
assert_eq!(0b0000_1001, decimal_to_packed_bcd(9));
|
||||
assert_eq!(0b0001_0000, decimal_to_packed_bcd(10));
|
||||
assert_eq!(0b0001_0001, decimal_to_packed_bcd(11));
|
||||
assert_eq!(0b0001_1001, decimal_to_packed_bcd(19));
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
//! Device status
|
||||
|
||||
extern crate embedded_hal as hal;
|
||||
use super::super::{ Ds323x, Register, BitFlags, Error };
|
||||
use interface::{ ReadData, WriteData };
|
||||
use super::super::{BitFlags, Ds323x, Error, Register};
|
||||
use interface::{ReadData, WriteData};
|
||||
|
||||
impl<DI, IC, CommE, PinE> Ds323x<DI, IC>
|
||||
where
|
||||
DI: ReadData<Error = Error<CommE, PinE>> + WriteData<Error = Error<CommE, PinE>>
|
||||
DI: ReadData<Error = Error<CommE, PinE>> + WriteData<Error = Error<CommE, PinE>>,
|
||||
{
|
||||
/// Read whether the oscillator is running
|
||||
pub fn is_running(&mut self) -> Result<bool, Error<CommE, PinE>> {
|
||||
|
@ -87,8 +87,7 @@ where
|
|||
if is_negative {
|
||||
let temp_sign_extended = temp | 0b1111_1100_0000_0000;
|
||||
Ok(f32::from(temp_sign_extended as i16) * 0.25)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Ok(f32::from(temp) * 0.25)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
#![deny(missing_docs)]
|
||||
|
||||
extern crate embedded_hal as hal;
|
||||
use super::{Error, DEVICE_ADDRESS};
|
||||
use hal::blocking;
|
||||
use super::{ DEVICE_ADDRESS, Error };
|
||||
|
||||
/// I2C interface
|
||||
#[derive(Debug, Default)]
|
||||
|
@ -16,7 +16,7 @@ pub struct I2cInterface<I2C> {
|
|||
#[derive(Debug, Default)]
|
||||
pub struct SpiInterface<SPI, CS> {
|
||||
pub(crate) spi: SPI,
|
||||
pub(crate) cs: CS
|
||||
pub(crate) cs: CS,
|
||||
}
|
||||
|
||||
/// Write data
|
||||
|
@ -31,7 +31,7 @@ pub trait WriteData {
|
|||
|
||||
impl<I2C, E> WriteData for I2cInterface<I2C>
|
||||
where
|
||||
I2C: blocking::i2c::Write<Error = E>
|
||||
I2C: blocking::i2c::Write<Error = E>,
|
||||
{
|
||||
type Error = Error<E, ()>;
|
||||
fn write_register(&mut self, register: u8, data: u8) -> Result<(), Self::Error> {
|
||||
|
@ -51,16 +51,14 @@ where
|
|||
impl<SPI, CS, CommE, PinE> WriteData for SpiInterface<SPI, CS>
|
||||
where
|
||||
SPI: blocking::spi::Write<u8, Error = CommE>,
|
||||
CS: hal::digital::v2::OutputPin<Error = PinE>
|
||||
CS: hal::digital::v2::OutputPin<Error = PinE>,
|
||||
{
|
||||
type Error = Error<CommE, PinE>;
|
||||
fn write_register(&mut self, register: u8, data: u8) -> Result<(), Self::Error> {
|
||||
self.cs.set_low().map_err(Error::Pin)?;
|
||||
|
||||
let payload: [u8; 2] = [register + 0x80, data];
|
||||
let result = self.spi
|
||||
.write(&payload)
|
||||
.map_err(Error::Comm);
|
||||
let result = self.spi.write(&payload).map_err(Error::Comm);
|
||||
|
||||
self.cs.set_high().map_err(Error::Pin)?;
|
||||
result
|
||||
|
@ -69,16 +67,13 @@ where
|
|||
fn write_data(&mut self, payload: &mut [u8]) -> Result<(), Self::Error> {
|
||||
self.cs.set_low().map_err(Error::Pin)?;
|
||||
payload[0] += 0x80;
|
||||
let result = self.spi
|
||||
.write(&payload)
|
||||
.map_err(Error::Comm);
|
||||
let result = self.spi.write(&payload).map_err(Error::Comm);
|
||||
|
||||
self.cs.set_high().map_err(Error::Pin)?;
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Read data
|
||||
pub trait ReadData {
|
||||
/// Error type
|
||||
|
@ -91,7 +86,7 @@ pub trait ReadData {
|
|||
|
||||
impl<I2C, E> ReadData for I2cInterface<I2C>
|
||||
where
|
||||
I2C: blocking::i2c::WriteRead<Error = E>
|
||||
I2C: blocking::i2c::WriteRead<Error = E>,
|
||||
{
|
||||
type Error = Error<E, ()>;
|
||||
fn read_register(&mut self, register: u8) -> Result<u8, Self::Error> {
|
||||
|
@ -113,24 +108,20 @@ where
|
|||
impl<SPI, CS, CommE, PinE> ReadData for SpiInterface<SPI, CS>
|
||||
where
|
||||
SPI: blocking::spi::Transfer<u8, Error = CommE>,
|
||||
CS: hal::digital::v2::OutputPin<Error = PinE>
|
||||
CS: hal::digital::v2::OutputPin<Error = PinE>,
|
||||
{
|
||||
type Error = Error<CommE, PinE>;
|
||||
fn read_register(&mut self, register: u8) -> Result<u8, Self::Error> {
|
||||
self.cs.set_low().map_err(Error::Pin)?;
|
||||
let mut data = [register, 0];
|
||||
let result = self.spi
|
||||
.transfer(&mut data)
|
||||
.map_err(Error::Comm);
|
||||
let result = self.spi.transfer(&mut data).map_err(Error::Comm);
|
||||
self.cs.set_high().map_err(Error::Pin)?;
|
||||
Ok(result?[1])
|
||||
}
|
||||
|
||||
fn read_data(&mut self, mut payload: &mut [u8]) -> Result<(), Self::Error> {
|
||||
self.cs.set_low().map_err(Error::Pin)?;
|
||||
let result = self.spi
|
||||
.transfer(&mut payload)
|
||||
.map_err(Error::Comm);
|
||||
let result = self.spi.transfer(&mut payload).map_err(Error::Comm);
|
||||
self.cs.set_high().map_err(Error::Pin)?;
|
||||
result?;
|
||||
Ok(())
|
||||
|
|
89
src/lib.rs
89
src/lib.rs
|
@ -439,7 +439,6 @@
|
|||
//! # }
|
||||
//! ```
|
||||
|
||||
|
||||
#![deny(unsafe_code, missing_docs)]
|
||||
#![no_std]
|
||||
|
||||
|
@ -460,7 +459,7 @@ pub enum Error<CommE, PinE> {
|
|||
/// Pin setting error
|
||||
Pin(PinE),
|
||||
/// Invalid input data provided
|
||||
InvalidInputData
|
||||
InvalidInputData,
|
||||
}
|
||||
|
||||
/// Square-wave output frequency
|
||||
|
@ -494,50 +493,50 @@ pub enum TempConvRate {
|
|||
struct Register;
|
||||
|
||||
impl Register {
|
||||
const SECONDS : u8 = 0x00;
|
||||
const MINUTES : u8 = 0x01;
|
||||
const HOURS : u8 = 0x02;
|
||||
const DOW : u8 = 0x03;
|
||||
const DOM : u8 = 0x04;
|
||||
const MONTH : u8 = 0x05;
|
||||
const YEAR : u8 = 0x06;
|
||||
const ALARM1_SECONDS : u8 = 0x07;
|
||||
const ALARM2_MINUTES : u8 = 0x0B;
|
||||
const CONTROL : u8 = 0x0E;
|
||||
const STATUS : u8 = 0x0F;
|
||||
const AGING_OFFSET : u8 = 0x10;
|
||||
const TEMP_MSB : u8 = 0x11;
|
||||
const TEMP_CONV : u8 = 0x13;
|
||||
const SECONDS: u8 = 0x00;
|
||||
const MINUTES: u8 = 0x01;
|
||||
const HOURS: u8 = 0x02;
|
||||
const DOW: u8 = 0x03;
|
||||
const DOM: u8 = 0x04;
|
||||
const MONTH: u8 = 0x05;
|
||||
const YEAR: u8 = 0x06;
|
||||
const ALARM1_SECONDS: u8 = 0x07;
|
||||
const ALARM2_MINUTES: u8 = 0x0B;
|
||||
const CONTROL: u8 = 0x0E;
|
||||
const STATUS: u8 = 0x0F;
|
||||
const AGING_OFFSET: u8 = 0x10;
|
||||
const TEMP_MSB: u8 = 0x11;
|
||||
const TEMP_CONV: u8 = 0x13;
|
||||
}
|
||||
|
||||
struct BitFlags;
|
||||
|
||||
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 BBSQW : u8 = 0b0100_0000;
|
||||
const TEMP_CONV : u8 = 0b0010_0000;
|
||||
const RS2 : u8 = 0b0001_0000;
|
||||
const RS1 : u8 = 0b0000_1000;
|
||||
const INTCN : u8 = 0b0000_0100;
|
||||
const ALARM2_INT_EN : u8 = 0b0000_0010;
|
||||
const ALARM1_INT_EN : u8 = 0b0000_0001;
|
||||
const OSC_STOP : u8 = 0b1000_0000;
|
||||
const BB32KHZ : u8 = 0b0100_0000;
|
||||
const CRATE1 : u8 = 0b0010_0000;
|
||||
const CRATE0 : u8 = 0b0001_0000;
|
||||
const EN32KHZ : u8 = 0b0000_1000;
|
||||
const BUSY : u8 = 0b0000_0100;
|
||||
const ALARM2F : u8 = 0b0000_0010;
|
||||
const ALARM1F : u8 = 0b0000_0001;
|
||||
const TEMP_CONV_BAT : u8 = 0b0000_0001;
|
||||
const ALARM_MATCH : u8 = 0b1000_0000;
|
||||
const WEEKDAY : u8 = 0b0100_0000;
|
||||
const H24_H12: u8 = 0b0100_0000;
|
||||
const AM_PM: u8 = 0b0010_0000;
|
||||
const CENTURY: u8 = 0b1000_0000;
|
||||
const EOSC: u8 = 0b1000_0000;
|
||||
const BBSQW: u8 = 0b0100_0000;
|
||||
const TEMP_CONV: u8 = 0b0010_0000;
|
||||
const RS2: u8 = 0b0001_0000;
|
||||
const RS1: u8 = 0b0000_1000;
|
||||
const INTCN: u8 = 0b0000_0100;
|
||||
const ALARM2_INT_EN: u8 = 0b0000_0010;
|
||||
const ALARM1_INT_EN: u8 = 0b0000_0001;
|
||||
const OSC_STOP: u8 = 0b1000_0000;
|
||||
const BB32KHZ: u8 = 0b0100_0000;
|
||||
const CRATE1: u8 = 0b0010_0000;
|
||||
const CRATE0: u8 = 0b0001_0000;
|
||||
const EN32KHZ: u8 = 0b0000_1000;
|
||||
const BUSY: u8 = 0b0000_0100;
|
||||
const ALARM2F: u8 = 0b0000_0010;
|
||||
const ALARM1F: u8 = 0b0000_0001;
|
||||
const TEMP_CONV_BAT: u8 = 0b0000_0001;
|
||||
const ALARM_MATCH: u8 = 0b1000_0000;
|
||||
const WEEKDAY: u8 = 0b0100_0000;
|
||||
}
|
||||
|
||||
const DEVICE_ADDRESS : u8 = 0b110_1000;
|
||||
const DEVICE_ADDRESS: u8 = 0b110_1000;
|
||||
const CONTROL_POR_VALUE: u8 = 0b0001_1100;
|
||||
|
||||
/// IC markers
|
||||
|
@ -555,14 +554,16 @@ pub mod ic {
|
|||
pub struct Ds323x<DI, IC> {
|
||||
iface: DI,
|
||||
control: u8,
|
||||
status : u8,
|
||||
_ic: PhantomData<IC>
|
||||
status: u8,
|
||||
_ic: PhantomData<IC>,
|
||||
}
|
||||
|
||||
pub mod interface;
|
||||
mod ds323x;
|
||||
pub use ds323x::{ Hours, DateTime, DayAlarm1, WeekdayAlarm1, Alarm1Matching,
|
||||
DayAlarm2, WeekdayAlarm2, Alarm2Matching };
|
||||
pub mod interface;
|
||||
pub use ds323x::{
|
||||
Alarm1Matching, Alarm2Matching, DateTime, DayAlarm1, DayAlarm2, Hours, WeekdayAlarm1,
|
||||
WeekdayAlarm2,
|
||||
};
|
||||
mod ds3231;
|
||||
mod ds3232;
|
||||
mod ds3234;
|
||||
|
|
|
@ -2,12 +2,15 @@ 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, new_ds3231,
|
||||
new_ds3232, new_ds3234, destroy_ds3231, destroy_ds3232,
|
||||
destroy_ds3234, BitFlags as BF };
|
||||
use common::{
|
||||
destroy_ds3231, destroy_ds3232, destroy_ds3234, new_ds3231, new_ds3232, new_ds3234,
|
||||
BitFlags as BF, Register, DEVICE_ADDRESS as DEV_ADDR,
|
||||
};
|
||||
extern crate ds323x;
|
||||
use ds323x::{ DayAlarm1, WeekdayAlarm1, Alarm1Matching as A1M, DayAlarm2,
|
||||
WeekdayAlarm2, Alarm2Matching as A2M, Hours, Error };
|
||||
use ds323x::{
|
||||
Alarm1Matching as A1M, Alarm2Matching as A2M, DayAlarm1, DayAlarm2, Error, Hours,
|
||||
WeekdayAlarm1, WeekdayAlarm2,
|
||||
};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! _set_invalid_alarm_test {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
extern crate embedded_hal;
|
||||
extern crate ds323x;
|
||||
use self::ds323x::{ Ds323x, interface, ic };
|
||||
extern crate embedded_hal;
|
||||
use self::ds323x::{ic, interface, Ds323x};
|
||||
extern crate embedded_hal_mock as hal;
|
||||
use self::hal::i2c::{ Mock as I2cMock, Transaction as I2cTrans };
|
||||
use self::hal::spi::{ Mock as SpiMock, Transaction as SpiTrans };
|
||||
use self::hal::i2c::{Mock as I2cMock, Transaction as I2cTrans};
|
||||
use self::hal::spi::{Mock as SpiMock, Transaction as SpiTrans};
|
||||
|
||||
#[allow(unused)]
|
||||
pub const DEVICE_ADDRESS : u8 = 0b110_1000;
|
||||
pub const DEVICE_ADDRESS: u8 = 0b110_1000;
|
||||
#[allow(unused)]
|
||||
pub const CONTROL_POR_VALUE: u8 = 0b0001_1100;
|
||||
#[allow(unused)]
|
||||
|
@ -18,65 +18,73 @@ pub struct Register;
|
|||
|
||||
#[allow(unused)]
|
||||
impl Register {
|
||||
pub const SECONDS : u8 = 0x00;
|
||||
pub const MINUTES : u8 = 0x01;
|
||||
pub const HOURS : u8 = 0x02;
|
||||
pub const DOW : u8 = 0x03;
|
||||
pub const DOM : u8 = 0x04;
|
||||
pub const MONTH : u8 = 0x05;
|
||||
pub const ALARM1_SECONDS : u8 = 0x07;
|
||||
pub const ALARM2_MINUTES : u8 = 0x0B;
|
||||
pub const CONTROL : u8 = 0x0E;
|
||||
pub const STATUS : u8 = 0x0F;
|
||||
pub const AGING_OFFSET : u8 = 0x10;
|
||||
pub const TEMP_MSB : u8 = 0x11;
|
||||
pub const TEMP_CONV : u8 = 0x13;
|
||||
pub const SECONDS: u8 = 0x00;
|
||||
pub const MINUTES: u8 = 0x01;
|
||||
pub const HOURS: u8 = 0x02;
|
||||
pub const DOW: u8 = 0x03;
|
||||
pub const DOM: u8 = 0x04;
|
||||
pub const MONTH: u8 = 0x05;
|
||||
pub const ALARM1_SECONDS: u8 = 0x07;
|
||||
pub const ALARM2_MINUTES: u8 = 0x0B;
|
||||
pub const CONTROL: u8 = 0x0E;
|
||||
pub const STATUS: u8 = 0x0F;
|
||||
pub const AGING_OFFSET: u8 = 0x10;
|
||||
pub const TEMP_MSB: u8 = 0x11;
|
||||
pub const TEMP_CONV: u8 = 0x13;
|
||||
}
|
||||
|
||||
pub struct BitFlags;
|
||||
|
||||
#[allow(unused)]
|
||||
impl BitFlags {
|
||||
pub const EOSC : u8 = 0b1000_0000;
|
||||
pub const BBSQW : u8 = 0b0100_0000;
|
||||
pub const TEMP_CONV : u8 = 0b0010_0000;
|
||||
pub const RS2 : u8 = 0b0001_0000;
|
||||
pub const RS1 : u8 = 0b0000_1000;
|
||||
pub const INTCN : u8 = 0b0000_0100;
|
||||
pub const ALARM2_INT_EN : u8 = 0b0000_0010;
|
||||
pub const ALARM1_INT_EN : u8 = 0b0000_0001;
|
||||
pub const OSC_STOP : u8 = 0b1000_0000;
|
||||
pub const BB32KHZ : u8 = 0b0100_0000;
|
||||
pub const CRATE1 : u8 = 0b0010_0000;
|
||||
pub const CRATE0 : u8 = 0b0001_0000;
|
||||
pub const EN32KHZ : u8 = 0b0000_1000;
|
||||
pub const BUSY : u8 = 0b0000_0100;
|
||||
pub const ALARM2F : u8 = 0b0000_0010;
|
||||
pub const ALARM1F : u8 = 0b0000_0001;
|
||||
pub const TEMP_CONV_BAT : u8 = 0b0000_0001;
|
||||
pub const ALARM_MATCH : u8 = 0b1000_0000;
|
||||
pub const WEEKDAY : u8 = 0b0100_0000;
|
||||
pub const EOSC: u8 = 0b1000_0000;
|
||||
pub const BBSQW: u8 = 0b0100_0000;
|
||||
pub const TEMP_CONV: u8 = 0b0010_0000;
|
||||
pub const RS2: u8 = 0b0001_0000;
|
||||
pub const RS1: u8 = 0b0000_1000;
|
||||
pub const INTCN: u8 = 0b0000_0100;
|
||||
pub const ALARM2_INT_EN: u8 = 0b0000_0010;
|
||||
pub const ALARM1_INT_EN: u8 = 0b0000_0001;
|
||||
pub const OSC_STOP: u8 = 0b1000_0000;
|
||||
pub const BB32KHZ: u8 = 0b0100_0000;
|
||||
pub const CRATE1: u8 = 0b0010_0000;
|
||||
pub const CRATE0: u8 = 0b0001_0000;
|
||||
pub const EN32KHZ: u8 = 0b0000_1000;
|
||||
pub const BUSY: u8 = 0b0000_0100;
|
||||
pub const ALARM2F: u8 = 0b0000_0010;
|
||||
pub const ALARM1F: u8 = 0b0000_0001;
|
||||
pub const TEMP_CONV_BAT: u8 = 0b0000_0001;
|
||||
pub const ALARM_MATCH: u8 = 0b1000_0000;
|
||||
pub const WEEKDAY: u8 = 0b0100_0000;
|
||||
}
|
||||
|
||||
pub struct DummyOutputPin;
|
||||
|
||||
impl embedded_hal::digital::v2::OutputPin for DummyOutputPin {
|
||||
type Error = ();
|
||||
fn set_low(&mut self) -> Result<(), Self::Error> { Ok(()) }
|
||||
fn set_high(&mut self) -> Result<(), Self::Error> { Ok(()) }
|
||||
fn set_low(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
fn set_high(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn new_ds3231(transactions: &[I2cTrans]) -> Ds323x<interface::I2cInterface<I2cMock>, ic::DS3231> {
|
||||
pub fn new_ds3231(
|
||||
transactions: &[I2cTrans],
|
||||
) -> Ds323x<interface::I2cInterface<I2cMock>, ic::DS3231> {
|
||||
Ds323x::new_ds3231(I2cMock::new(&transactions))
|
||||
}
|
||||
|
||||
pub fn new_ds3232(transactions: &[I2cTrans]) -> Ds323x<interface::I2cInterface<I2cMock>, ic::DS3232> {
|
||||
pub fn new_ds3232(
|
||||
transactions: &[I2cTrans],
|
||||
) -> Ds323x<interface::I2cInterface<I2cMock>, ic::DS3232> {
|
||||
Ds323x::new_ds3232(I2cMock::new(&transactions))
|
||||
}
|
||||
|
||||
pub fn new_ds3234(transactions: &[SpiTrans])
|
||||
-> Ds323x<interface::SpiInterface<SpiMock, DummyOutputPin>, ic::DS3234> {
|
||||
pub fn new_ds3234(
|
||||
transactions: &[SpiTrans],
|
||||
) -> Ds323x<interface::SpiInterface<SpiMock, DummyOutputPin>, ic::DS3234> {
|
||||
Ds323x::new_ds3234(SpiMock::new(&transactions), DummyOutputPin)
|
||||
}
|
||||
|
||||
|
@ -123,7 +131,7 @@ macro_rules! assert_invalid_input_data {
|
|||
($result:expr) => {
|
||||
match $result {
|
||||
Err(Error::InvalidInputData) => (),
|
||||
_ => panic!("InvalidInputData error not returned.")
|
||||
_ => panic!("InvalidInputData error not returned."),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -158,9 +166,30 @@ macro_rules! _get_param_test {
|
|||
($name:ident, $method:ident, $value:expr, $i2c_transactions:expr, $spi_transactions:expr) => {
|
||||
mod $name {
|
||||
use super::*;
|
||||
get_test!(can_get_ds3231, $method, new_ds3231, destroy_ds3231, $value, $i2c_transactions);
|
||||
get_test!(can_get_ds3232, $method, new_ds3232, destroy_ds3232, $value, $i2c_transactions);
|
||||
get_test!(can_get_ds3234, $method, new_ds3234, destroy_ds3234, $value, $spi_transactions);
|
||||
get_test!(
|
||||
can_get_ds3231,
|
||||
$method,
|
||||
new_ds3231,
|
||||
destroy_ds3231,
|
||||
$value,
|
||||
$i2c_transactions
|
||||
);
|
||||
get_test!(
|
||||
can_get_ds3232,
|
||||
$method,
|
||||
new_ds3232,
|
||||
destroy_ds3232,
|
||||
$value,
|
||||
$i2c_transactions
|
||||
);
|
||||
get_test!(
|
||||
can_get_ds3234,
|
||||
$method,
|
||||
new_ds3234,
|
||||
destroy_ds3234,
|
||||
$value,
|
||||
$spi_transactions
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -168,9 +197,20 @@ macro_rules! _get_param_test {
|
|||
#[macro_export]
|
||||
macro_rules! get_param_test {
|
||||
($name:ident, $method:ident, $register:ident, $value:expr, $binary_value:expr) => {
|
||||
_get_param_test!($name, $method, $value,
|
||||
[ I2cTrans::write_read(DEV_ADDR, vec![Register::$register], vec![$binary_value]) ],
|
||||
[ SpiTrans::transfer(vec![Register::$register, 0], vec![Register::$register, $binary_value]) ]);
|
||||
_get_param_test!(
|
||||
$name,
|
||||
$method,
|
||||
$value,
|
||||
[I2cTrans::write_read(
|
||||
DEV_ADDR,
|
||||
vec![Register::$register],
|
||||
vec![$binary_value]
|
||||
)],
|
||||
[SpiTrans::transfer(
|
||||
vec![Register::$register, 0],
|
||||
vec![Register::$register, $binary_value]
|
||||
)]
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -188,9 +228,30 @@ macro_rules! _set_param_test {
|
|||
($name:ident, $method:ident, $value:expr, $i2c_transactions:expr, $spi_transactions:expr) => {
|
||||
mod $name {
|
||||
use super::*;
|
||||
set_test!(can_set_ds3231, $method, new_ds3231, destroy_ds3231, $value, $i2c_transactions);
|
||||
set_test!(can_set_ds3232, $method, new_ds3232, destroy_ds3232, $value, $i2c_transactions);
|
||||
set_test!(can_set_ds3234, $method, new_ds3234, destroy_ds3234, $value, $spi_transactions);
|
||||
set_test!(
|
||||
can_set_ds3231,
|
||||
$method,
|
||||
new_ds3231,
|
||||
destroy_ds3231,
|
||||
$value,
|
||||
$i2c_transactions
|
||||
);
|
||||
set_test!(
|
||||
can_set_ds3232,
|
||||
$method,
|
||||
new_ds3232,
|
||||
destroy_ds3232,
|
||||
$value,
|
||||
$i2c_transactions
|
||||
);
|
||||
set_test!(
|
||||
can_set_ds3234,
|
||||
$method,
|
||||
new_ds3234,
|
||||
destroy_ds3234,
|
||||
$value,
|
||||
$spi_transactions
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -198,8 +259,18 @@ macro_rules! _set_param_test {
|
|||
#[macro_export]
|
||||
macro_rules! set_param_test {
|
||||
($name:ident, $method:ident, $register:ident, $value:expr, $binary_value:expr) => {
|
||||
_set_param_test!($name, $method, $value,
|
||||
[ I2cTrans::write(DEV_ADDR, vec![Register::$register, $binary_value]) ],
|
||||
[ SpiTrans::write(vec![Register::$register + 0x80, $binary_value]) ]);
|
||||
_set_param_test!(
|
||||
$name,
|
||||
$method,
|
||||
$value,
|
||||
[I2cTrans::write(
|
||||
DEV_ADDR,
|
||||
vec![Register::$register, $binary_value]
|
||||
)],
|
||||
[SpiTrans::write(vec![
|
||||
Register::$register + 0x80,
|
||||
$binary_value
|
||||
])]
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,27 +6,55 @@ extern crate ds323x;
|
|||
use ds323x::SqWFreq;
|
||||
|
||||
mod common;
|
||||
use common::{ DEVICE_ADDRESS as DEV_ADDR, Register, new_ds3231,
|
||||
new_ds3232, new_ds3234, destroy_ds3231, destroy_ds3232,
|
||||
destroy_ds3234, BitFlags as BF, CONTROL_POR_VALUE,
|
||||
DS3231_POR_STATUS, DS323X_POR_STATUS };
|
||||
use common::{
|
||||
destroy_ds3231, destroy_ds3232, destroy_ds3234, new_ds3231, new_ds3232, new_ds3234,
|
||||
BitFlags as BF, Register, CONTROL_POR_VALUE, DEVICE_ADDRESS as DEV_ADDR, DS3231_POR_STATUS,
|
||||
DS323X_POR_STATUS,
|
||||
};
|
||||
|
||||
macro_rules! call_triple_test {
|
||||
($name:ident, $method:ident, $i2c_transactions:expr, $spi_transactions:expr) => {
|
||||
mod $name {
|
||||
use super::*;
|
||||
call_test!(can_call_ds3231, $method, new_ds3231, destroy_ds3231, $i2c_transactions);
|
||||
call_test!(can_call_ds3232, $method, new_ds3232, destroy_ds3232, $i2c_transactions);
|
||||
call_test!(can_call_ds3234, $method, new_ds3234, destroy_ds3234, $spi_transactions);
|
||||
call_test!(
|
||||
can_call_ds3231,
|
||||
$method,
|
||||
new_ds3231,
|
||||
destroy_ds3231,
|
||||
$i2c_transactions
|
||||
);
|
||||
call_test!(
|
||||
can_call_ds3232,
|
||||
$method,
|
||||
new_ds3232,
|
||||
destroy_ds3232,
|
||||
$i2c_transactions
|
||||
);
|
||||
call_test!(
|
||||
can_call_ds3234,
|
||||
$method,
|
||||
new_ds3234,
|
||||
destroy_ds3234,
|
||||
$spi_transactions
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! call_method_test {
|
||||
($name:ident, $method:ident, $register:ident, $value_enabled:expr) => {
|
||||
call_triple_test!($name, $method,
|
||||
[ I2cTrans::write(DEV_ADDR, vec![Register::$register, $value_enabled]) ],
|
||||
[ SpiTrans::write(vec![Register::$register + 0x80, $value_enabled]) ]);
|
||||
call_triple_test!(
|
||||
$name,
|
||||
$method,
|
||||
[I2cTrans::write(
|
||||
DEV_ADDR,
|
||||
vec![Register::$register, $value_enabled]
|
||||
)],
|
||||
[SpiTrans::write(vec![
|
||||
Register::$register + 0x80,
|
||||
$value_enabled
|
||||
])]
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -34,12 +62,36 @@ macro_rules! call_method_status_test {
|
|||
($name:ident, $method:ident, $value_ds3231:expr, $value_ds323x:expr) => {
|
||||
mod $name {
|
||||
use super::*;
|
||||
call_test!(can_call_ds3231, $method, new_ds3231, destroy_ds3231,
|
||||
[ I2cTrans::write(DEV_ADDR, vec![Register::STATUS, $value_ds3231]) ]);
|
||||
call_test!(can_call_ds3232, $method, new_ds3232, destroy_ds3232,
|
||||
[ I2cTrans::write(DEV_ADDR, vec![Register::STATUS, $value_ds323x]) ]);
|
||||
call_test!(can_call_ds3234, $method, new_ds3234, destroy_ds3234,
|
||||
[ SpiTrans::write(vec![Register::STATUS + 0x80, $value_ds323x]) ]);
|
||||
call_test!(
|
||||
can_call_ds3231,
|
||||
$method,
|
||||
new_ds3231,
|
||||
destroy_ds3231,
|
||||
[I2cTrans::write(
|
||||
DEV_ADDR,
|
||||
vec![Register::STATUS, $value_ds3231]
|
||||
)]
|
||||
);
|
||||
call_test!(
|
||||
can_call_ds3232,
|
||||
$method,
|
||||
new_ds3232,
|
||||
destroy_ds3232,
|
||||
[I2cTrans::write(
|
||||
DEV_ADDR,
|
||||
vec![Register::STATUS, $value_ds323x]
|
||||
)]
|
||||
);
|
||||
call_test!(
|
||||
can_call_ds3234,
|
||||
$method,
|
||||
new_ds3234,
|
||||
destroy_ds3234,
|
||||
[SpiTrans::write(vec![
|
||||
Register::STATUS + 0x80,
|
||||
$value_ds323x
|
||||
])]
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -48,16 +100,39 @@ macro_rules! change_if_necessary_test {
|
|||
($name:ident, $method:ident, $register:ident, $value_enabled:expr, $value_disabled:expr) => {
|
||||
mod $name {
|
||||
use super::*;
|
||||
call_triple_test!(do_nothing_if_not_necessary, $method,
|
||||
[ I2cTrans::write_read(DEV_ADDR, vec![Register::$register], vec![$value_enabled]) ],
|
||||
[ SpiTrans::transfer(vec![Register::$register, 0], vec![Register::$register, $value_enabled]) ]);
|
||||
call_triple_test!(
|
||||
do_nothing_if_not_necessary,
|
||||
$method,
|
||||
[I2cTrans::write_read(
|
||||
DEV_ADDR,
|
||||
vec![Register::$register],
|
||||
vec![$value_enabled]
|
||||
)],
|
||||
[SpiTrans::transfer(
|
||||
vec![Register::$register, 0],
|
||||
vec![Register::$register, $value_enabled]
|
||||
)]
|
||||
);
|
||||
|
||||
call_triple_test!(change, $method,
|
||||
[ I2cTrans::write_read(DEV_ADDR, vec![Register::$register], vec![$value_disabled]),
|
||||
I2cTrans::write(DEV_ADDR, vec![Register::$register, $value_enabled]) ],
|
||||
|
||||
[ SpiTrans::transfer(vec![Register::$register, 0], vec![Register::$register, $value_disabled]),
|
||||
SpiTrans::write(vec![Register::$register + 0x80, $value_enabled]) ]);
|
||||
call_triple_test!(
|
||||
change,
|
||||
$method,
|
||||
[
|
||||
I2cTrans::write_read(
|
||||
DEV_ADDR,
|
||||
vec![Register::$register],
|
||||
vec![$value_disabled]
|
||||
),
|
||||
I2cTrans::write(DEV_ADDR, vec![Register::$register, $value_enabled])
|
||||
],
|
||||
[
|
||||
SpiTrans::transfer(
|
||||
vec![Register::$register, 0],
|
||||
vec![Register::$register, $value_disabled]
|
||||
),
|
||||
SpiTrans::write(vec![Register::$register + 0x80, $value_enabled])
|
||||
]
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
mod common;
|
||||
use common::{ new_ds3231, destroy_ds3231, new_ds3232, destroy_ds3232,
|
||||
new_ds3234, destroy_ds3234 };
|
||||
use common::{destroy_ds3231, destroy_ds3232, destroy_ds3234, new_ds3231, new_ds3232, new_ds3234};
|
||||
|
||||
macro_rules! construction_test {
|
||||
($name:ident, $create:ident, $destroy:ident) => {
|
||||
|
|
|
@ -2,11 +2,12 @@ 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, new_ds3231,
|
||||
new_ds3232, new_ds3234, destroy_ds3231, destroy_ds3232,
|
||||
destroy_ds3234 };
|
||||
use common::{
|
||||
destroy_ds3231, destroy_ds3232, destroy_ds3234, new_ds3231, new_ds3232, new_ds3234, Register,
|
||||
DEVICE_ADDRESS as DEV_ADDR,
|
||||
};
|
||||
extern crate ds323x;
|
||||
use ds323x::{ Hours, DateTime, Error };
|
||||
use ds323x::{DateTime, Error, Hours};
|
||||
|
||||
macro_rules! set_param_write_array_test {
|
||||
($name:ident, $method:ident, $value:expr, $register:ident, [ $( $exp_bin:expr ),+ ] ) => {
|
||||
|
@ -18,23 +19,51 @@ macro_rules! set_param_write_array_test {
|
|||
|
||||
macro_rules! read_set_param_write_two_test {
|
||||
($name:ident, $method:ident, $value:expr, $register:ident, $binary_value1_read:expr, $bin1:expr, $bin2:expr) => {
|
||||
_set_param_test!($name, $method, $value,
|
||||
[ I2cTrans::write_read(DEV_ADDR, vec![Register::$register], vec![$binary_value1_read]),
|
||||
I2cTrans::write(DEV_ADDR, vec![Register::$register, $bin1, $bin2]) ],
|
||||
|
||||
[ SpiTrans::transfer(vec![Register::$register, 0], vec![Register::$register, $binary_value1_read]),
|
||||
SpiTrans::write(vec![Register::$register + 0x80, $bin1, $bin2]) ]);
|
||||
_set_param_test!(
|
||||
$name,
|
||||
$method,
|
||||
$value,
|
||||
[
|
||||
I2cTrans::write_read(
|
||||
DEV_ADDR,
|
||||
vec![Register::$register],
|
||||
vec![$binary_value1_read]
|
||||
),
|
||||
I2cTrans::write(DEV_ADDR, vec![Register::$register, $bin1, $bin2])
|
||||
],
|
||||
[
|
||||
SpiTrans::transfer(
|
||||
vec![Register::$register, 0],
|
||||
vec![Register::$register, $binary_value1_read]
|
||||
),
|
||||
SpiTrans::write(vec![Register::$register + 0x80, $bin1, $bin2])
|
||||
]
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! read_set_param_test {
|
||||
($name:ident, $method:ident, $register:ident, $value:expr, $binary_value_read:expr, $binary_value_write:expr) => {
|
||||
_set_param_test!($name, $method, $value,
|
||||
[ I2cTrans::write_read(DEV_ADDR, vec![Register::$register], vec![$binary_value_read]),
|
||||
I2cTrans::write(DEV_ADDR, vec![Register::$register, $binary_value_write]) ],
|
||||
|
||||
[ SpiTrans::transfer(vec![Register::$register, 0], vec![Register::$register, $binary_value_read]),
|
||||
SpiTrans::write(vec![Register::$register + 0x80, $binary_value_write]) ]);
|
||||
_set_param_test!(
|
||||
$name,
|
||||
$method,
|
||||
$value,
|
||||
[
|
||||
I2cTrans::write_read(
|
||||
DEV_ADDR,
|
||||
vec![Register::$register],
|
||||
vec![$binary_value_read]
|
||||
),
|
||||
I2cTrans::write(DEV_ADDR, vec![Register::$register, $binary_value_write])
|
||||
],
|
||||
[
|
||||
SpiTrans::transfer(
|
||||
vec![Register::$register, 0],
|
||||
vec![Register::$register, $binary_value_read]
|
||||
),
|
||||
SpiTrans::write(vec![Register::$register + 0x80, $binary_value_write])
|
||||
]
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -42,9 +71,27 @@ macro_rules! set_invalid_param_test {
|
|||
($name:ident, $method:ident, $value:expr) => {
|
||||
mod $name {
|
||||
use super::*;
|
||||
set_invalid_test!(cannot_set_invalid_ds3231, $method, new_ds3231, destroy_ds3231, $value);
|
||||
set_invalid_test!(cannot_set_invalid_ds3232, $method, new_ds3232, destroy_ds3232, $value);
|
||||
set_invalid_test!(cannot_set_invalid_ds3234, $method, new_ds3234, destroy_ds3234, $value);
|
||||
set_invalid_test!(
|
||||
cannot_set_invalid_ds3231,
|
||||
$method,
|
||||
new_ds3231,
|
||||
destroy_ds3231,
|
||||
$value
|
||||
);
|
||||
set_invalid_test!(
|
||||
cannot_set_invalid_ds3232,
|
||||
$method,
|
||||
new_ds3232,
|
||||
destroy_ds3232,
|
||||
$value
|
||||
);
|
||||
set_invalid_test!(
|
||||
cannot_set_invalid_ds3234,
|
||||
$method,
|
||||
new_ds3234,
|
||||
destroy_ds3234,
|
||||
$value
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -54,7 +101,7 @@ macro_rules! set_invalid_param_range_test {
|
|||
mod $name {
|
||||
use super::*;
|
||||
set_invalid_param_test!(too_small, $method, $too_small_value);
|
||||
set_invalid_param_test!(too_big, $method, $too_big_value);
|
||||
set_invalid_param_test!(too_big, $method, $too_big_value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -123,11 +170,41 @@ mod month {
|
|||
|
||||
mod year {
|
||||
use super::*;
|
||||
get_param_read_array_test!(century0_get, get_year, 2099, MONTH, [ 0, 0b1001_1001 ], [0, 0]);
|
||||
read_set_param_write_two_test!(century0_set, set_year, 2099, MONTH, 0b1001_0010, 0b0001_0010, 0b1001_1001);
|
||||
get_param_read_array_test!(
|
||||
century0_get,
|
||||
get_year,
|
||||
2099,
|
||||
MONTH,
|
||||
[0, 0b1001_1001],
|
||||
[0, 0]
|
||||
);
|
||||
read_set_param_write_two_test!(
|
||||
century0_set,
|
||||
set_year,
|
||||
2099,
|
||||
MONTH,
|
||||
0b1001_0010,
|
||||
0b0001_0010,
|
||||
0b1001_1001
|
||||
);
|
||||
|
||||
get_param_read_array_test!(century1_get, get_year, 2100, MONTH, [ 0b1000_0000, 0 ], [0, 0]);
|
||||
read_set_param_write_two_test!(century1_set, set_year, 2100, MONTH, 0b0001_0010, 0b1001_0010, 0);
|
||||
get_param_read_array_test!(
|
||||
century1_get,
|
||||
get_year,
|
||||
2100,
|
||||
MONTH,
|
||||
[0b1000_0000, 0],
|
||||
[0, 0]
|
||||
);
|
||||
read_set_param_write_two_test!(
|
||||
century1_set,
|
||||
set_year,
|
||||
2100,
|
||||
MONTH,
|
||||
0b0001_0010,
|
||||
0b1001_0010,
|
||||
0
|
||||
);
|
||||
|
||||
set_invalid_param_range_test!(invalid, set_year, 1999, 2101);
|
||||
}
|
||||
|
@ -137,8 +214,15 @@ macro_rules! invalid_dt_test {
|
|||
$hour:expr, $minute:expr, $second:expr) => {
|
||||
mod $name {
|
||||
use super::*;
|
||||
const DT : DateTime = DateTime { year: $year, month: $month, day: $day, weekday: $weekday,
|
||||
hour: $hour, minute: $minute, second: $second };
|
||||
const DT: DateTime = DateTime {
|
||||
year: $year,
|
||||
month: $month,
|
||||
day: $day,
|
||||
weekday: $weekday,
|
||||
hour: $hour,
|
||||
minute: $minute,
|
||||
second: $second,
|
||||
};
|
||||
set_invalid_param_test!($name, set_datetime, &DT);
|
||||
}
|
||||
};
|
||||
|
@ -146,26 +230,57 @@ macro_rules! invalid_dt_test {
|
|||
|
||||
mod datetime {
|
||||
use super::*;
|
||||
const DT : DateTime = DateTime { year: 2018, month: 8, day: 13, weekday: 2,
|
||||
hour: Hours::H24(23), minute: 59, second: 58 };
|
||||
get_param_read_array_test!(get, get_datetime, DT, SECONDS,
|
||||
[0b0101_1000, 0b0101_1001, 0b0010_0011, 0b0000_0010,
|
||||
0b0001_0011, 0b0000_1000, 0b0001_1000],
|
||||
[0, 0, 0, 0, 0, 0, 0]);
|
||||
const DT: DateTime = DateTime {
|
||||
year: 2018,
|
||||
month: 8,
|
||||
day: 13,
|
||||
weekday: 2,
|
||||
hour: Hours::H24(23),
|
||||
minute: 59,
|
||||
second: 58,
|
||||
};
|
||||
get_param_read_array_test!(
|
||||
get,
|
||||
get_datetime,
|
||||
DT,
|
||||
SECONDS,
|
||||
[
|
||||
0b0101_1000,
|
||||
0b0101_1001,
|
||||
0b0010_0011,
|
||||
0b0000_0010,
|
||||
0b0001_0011,
|
||||
0b0000_1000,
|
||||
0b0001_1000
|
||||
],
|
||||
[0, 0, 0, 0, 0, 0, 0]
|
||||
);
|
||||
|
||||
set_param_write_array_test!(set, set_datetime, &DT, SECONDS,
|
||||
[0b0101_1000, 0b0101_1001, 0b0010_0011, 0b0000_0010,
|
||||
0b0001_0011, 0b0000_1000, 0b0001_1000]);
|
||||
set_param_write_array_test!(
|
||||
set,
|
||||
set_datetime,
|
||||
&DT,
|
||||
SECONDS,
|
||||
[
|
||||
0b0101_1000,
|
||||
0b0101_1001,
|
||||
0b0010_0011,
|
||||
0b0000_0010,
|
||||
0b0001_0011,
|
||||
0b0000_1000,
|
||||
0b0001_1000
|
||||
]
|
||||
);
|
||||
|
||||
invalid_dt_test!(too_small_year, 1999, 8, 13, 2, Hours::H24(23), 59, 58);
|
||||
invalid_dt_test!(too_big_year, 2101, 8, 13, 2, Hours::H24(23), 59, 58);
|
||||
invalid_dt_test!(too_small_month, 2018, 0, 13, 2, Hours::H24(23), 59, 58);
|
||||
invalid_dt_test!(too_big_month, 2018, 13, 13, 2, Hours::H24(23), 59, 58);
|
||||
invalid_dt_test!(too_small_day, 2018, 8, 0, 2, Hours::H24(23), 59, 58);
|
||||
invalid_dt_test!(too_big_day, 2018, 8, 32, 2, Hours::H24(23), 59, 58);
|
||||
invalid_dt_test!(too_small_wd, 2018, 8, 13, 0, Hours::H24(23), 59, 58);
|
||||
invalid_dt_test!(too_big_wd, 2018, 8, 13, 8, Hours::H24(23), 59, 58);
|
||||
invalid_dt_test!(too_big_hours, 2018, 8, 13, 2, Hours::H24(24), 59, 58);
|
||||
invalid_dt_test!(too_big_min, 2018, 8, 13, 2, Hours::H24(24), 60, 58);
|
||||
invalid_dt_test!(too_big_seconds, 2018, 8, 13, 2, Hours::H24(24), 59, 60);
|
||||
invalid_dt_test!(too_small_year, 1999, 8, 13, 2, Hours::H24(23), 59, 58);
|
||||
invalid_dt_test!(too_big_year, 2101, 8, 13, 2, Hours::H24(23), 59, 58);
|
||||
invalid_dt_test!(too_small_month, 2018, 0, 13, 2, Hours::H24(23), 59, 58);
|
||||
invalid_dt_test!(too_big_month, 2018, 13, 13, 2, Hours::H24(23), 59, 58);
|
||||
invalid_dt_test!(too_small_day, 2018, 8, 0, 2, Hours::H24(23), 59, 58);
|
||||
invalid_dt_test!(too_big_day, 2018, 8, 32, 2, Hours::H24(23), 59, 58);
|
||||
invalid_dt_test!(too_small_wd, 2018, 8, 13, 0, Hours::H24(23), 59, 58);
|
||||
invalid_dt_test!(too_big_wd, 2018, 8, 13, 8, Hours::H24(23), 59, 58);
|
||||
invalid_dt_test!(too_big_hours, 2018, 8, 13, 2, Hours::H24(24), 59, 58);
|
||||
invalid_dt_test!(too_big_min, 2018, 8, 13, 2, Hours::H24(24), 60, 58);
|
||||
invalid_dt_test!(too_big_seconds, 2018, 8, 13, 2, Hours::H24(24), 59, 60);
|
||||
}
|
||||
|
|
|
@ -7,18 +7,29 @@ use ds323x::TempConvRate;
|
|||
|
||||
#[allow(unused)]
|
||||
mod common;
|
||||
use common::{ DEVICE_ADDRESS as DEV_ADDR, Register,
|
||||
new_ds3232, new_ds3234, destroy_ds3232,
|
||||
destroy_ds3234, BitFlags as BF, DS323X_POR_STATUS };
|
||||
use common::{
|
||||
destroy_ds3232, destroy_ds3234, new_ds3232, new_ds3234, BitFlags as BF, Register,
|
||||
DEVICE_ADDRESS as DEV_ADDR, DS323X_POR_STATUS,
|
||||
};
|
||||
|
||||
macro_rules! call_method_status_test {
|
||||
($name:ident, $method:ident, $value:expr) => {
|
||||
mod $name {
|
||||
use super::*;
|
||||
call_test!(can_call_ds3232, $method, new_ds3232, destroy_ds3232,
|
||||
[ I2cTrans::write(DEV_ADDR, vec![Register::STATUS, $value]) ]);
|
||||
call_test!(can_call_ds3234, $method, new_ds3234, destroy_ds3234,
|
||||
[ SpiTrans::write(vec![Register::STATUS + 0x80, $value]) ]);
|
||||
call_test!(
|
||||
can_call_ds3232,
|
||||
$method,
|
||||
new_ds3232,
|
||||
destroy_ds3232,
|
||||
[I2cTrans::write(DEV_ADDR, vec![Register::STATUS, $value])]
|
||||
);
|
||||
call_test!(
|
||||
can_call_ds3234,
|
||||
$method,
|
||||
new_ds3234,
|
||||
destroy_ds3234,
|
||||
[SpiTrans::write(vec![Register::STATUS + 0x80, $value])]
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -28,8 +39,22 @@ macro_rules! _set_param_test_2_4 {
|
|||
($name:ident, $method:ident, $value:expr, $i2c_transactions:expr, $spi_transactions:expr) => {
|
||||
mod $name {
|
||||
use super::*;
|
||||
set_test!(can_set_ds3232, $method, new_ds3232, destroy_ds3232, $value, $i2c_transactions);
|
||||
set_test!(can_set_ds3234, $method, new_ds3234, destroy_ds3234, $value, $spi_transactions);
|
||||
set_test!(
|
||||
can_set_ds3232,
|
||||
$method,
|
||||
new_ds3232,
|
||||
destroy_ds3232,
|
||||
$value,
|
||||
$i2c_transactions
|
||||
);
|
||||
set_test!(
|
||||
can_set_ds3234,
|
||||
$method,
|
||||
new_ds3234,
|
||||
destroy_ds3234,
|
||||
$value,
|
||||
$spi_transactions
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -37,9 +62,19 @@ macro_rules! _set_param_test_2_4 {
|
|||
#[macro_export]
|
||||
macro_rules! set_param_test_2_4 {
|
||||
($name:ident, $method:ident, $register:ident, $value:expr, $binary_value:expr) => {
|
||||
_set_param_test_2_4!($name, $method, $value,
|
||||
[ I2cTrans::write(DEV_ADDR, vec![Register::$register, $binary_value]) ],
|
||||
[ SpiTrans::write(vec![Register::$register + 0x80, $binary_value]) ]);
|
||||
_set_param_test_2_4!(
|
||||
$name,
|
||||
$method,
|
||||
$value,
|
||||
[I2cTrans::write(
|
||||
DEV_ADDR,
|
||||
vec![Register::$register, $binary_value]
|
||||
)],
|
||||
[SpiTrans::write(vec![
|
||||
Register::$register + 0x80,
|
||||
$binary_value
|
||||
])]
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -3,10 +3,23 @@ use hal::spi::Transaction as SpiTrans;
|
|||
|
||||
#[allow(unused)]
|
||||
mod common;
|
||||
use common::{ new_ds3234, destroy_ds3234, Register, BitFlags };
|
||||
use common::{destroy_ds3234, new_ds3234, BitFlags, Register};
|
||||
|
||||
call_test!(can_en_temp_conv_bat, enable_temperature_conversions_on_battery, new_ds3234, destroy_ds3234,
|
||||
[ SpiTrans::write(vec![Register::TEMP_CONV + 0x80, 0]) ]);
|
||||
call_test!(
|
||||
can_en_temp_conv_bat,
|
||||
enable_temperature_conversions_on_battery,
|
||||
new_ds3234,
|
||||
destroy_ds3234,
|
||||
[SpiTrans::write(vec![Register::TEMP_CONV + 0x80, 0])]
|
||||
);
|
||||
|
||||
call_test!(can_dis_temp_conv_bat, disable_temperature_conversions_on_battery, new_ds3234, destroy_ds3234,
|
||||
[ SpiTrans::write(vec![Register::TEMP_CONV + 0x80, BitFlags::TEMP_CONV_BAT]) ]);
|
||||
call_test!(
|
||||
can_dis_temp_conv_bat,
|
||||
disable_temperature_conversions_on_battery,
|
||||
new_ds3234,
|
||||
destroy_ds3234,
|
||||
[SpiTrans::write(vec![
|
||||
Register::TEMP_CONV + 0x80,
|
||||
BitFlags::TEMP_CONV_BAT
|
||||
])]
|
||||
);
|
||||
|
|
|
@ -2,25 +2,52 @@ 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, new_ds3231,
|
||||
new_ds3232, new_ds3234, destroy_ds3231, destroy_ds3232,
|
||||
destroy_ds3234, BitFlags as BF };
|
||||
use common::{
|
||||
destroy_ds3231, destroy_ds3232, destroy_ds3234, new_ds3231, new_ds3232, new_ds3234,
|
||||
BitFlags as BF, Register, DEVICE_ADDRESS as DEV_ADDR,
|
||||
};
|
||||
|
||||
get_param_test!(is_running, is_running, CONTROL, true, 0);
|
||||
get_param_test!(is_running, is_running, CONTROL, true, 0);
|
||||
get_param_test!(is_not_running, is_running, CONTROL, false, BF::EOSC);
|
||||
|
||||
get_param_test!(is_busy, is_busy, STATUS, true, 0xFF);
|
||||
get_param_test!(is_busy, is_busy, STATUS, true, 0xFF);
|
||||
get_param_test!(is_not_busy, is_busy, STATUS, false, !BF::BUSY);
|
||||
|
||||
get_param_test!(stopped, has_been_stopped, STATUS, true, 0xFF);
|
||||
get_param_test!(stopped, has_been_stopped, STATUS, true, 0xFF);
|
||||
get_param_test!(not_stopped, has_been_stopped, STATUS, false, !BF::OSC_STOP);
|
||||
|
||||
get_param_test!(alarm1_matched, has_alarm1_matched, STATUS, true, 0xFF);
|
||||
get_param_test!(alarm1_not_matched, has_alarm1_matched, STATUS, false, !BF::ALARM1F);
|
||||
get_param_test!(alarm1_matched, has_alarm1_matched, STATUS, true, 0xFF);
|
||||
get_param_test!(
|
||||
alarm1_not_matched,
|
||||
has_alarm1_matched,
|
||||
STATUS,
|
||||
false,
|
||||
!BF::ALARM1F
|
||||
);
|
||||
|
||||
get_param_test!(alarm2_matched, has_alarm2_matched, STATUS, true, 0xFF);
|
||||
get_param_test!(alarm2_not_matched, has_alarm2_matched, STATUS, false, !BF::ALARM2F);
|
||||
get_param_test!(alarm2_matched, has_alarm2_matched, STATUS, true, 0xFF);
|
||||
get_param_test!(
|
||||
alarm2_not_matched,
|
||||
has_alarm2_matched,
|
||||
STATUS,
|
||||
false,
|
||||
!BF::ALARM2F
|
||||
);
|
||||
|
||||
get_param_read_array_test!(temp_0, get_temperature, 0.0, TEMP_MSB, [0, 0], [0, 0]);
|
||||
get_param_read_array_test!(temp_min, get_temperature, -128.0, TEMP_MSB, [0b1000_0000, 0], [0, 0]);
|
||||
get_param_read_array_test!(temp_max, get_temperature, 127.75, TEMP_MSB, [0b0111_1111, 0b1100_0000], [0, 0]);
|
||||
get_param_read_array_test!(temp_0, get_temperature, 0.0, TEMP_MSB, [0, 0], [0, 0]);
|
||||
get_param_read_array_test!(
|
||||
temp_min,
|
||||
get_temperature,
|
||||
-128.0,
|
||||
TEMP_MSB,
|
||||
[0b1000_0000, 0],
|
||||
[0, 0]
|
||||
);
|
||||
get_param_read_array_test!(
|
||||
temp_max,
|
||||
get_temperature,
|
||||
127.75,
|
||||
TEMP_MSB,
|
||||
[0b0111_1111, 0b1100_0000],
|
||||
[0, 0]
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue