mirror of https://github.com/eldruin/ds323x-rs
Add methods to get/set the hours
parent
c1b02cb3c0
commit
b9610b6e73
|
@ -8,6 +8,7 @@ extremely accurate real-time clocks, based on the [`embedded-hal`] traits.
|
|||
This driver allows you to:
|
||||
- Read/write the seconds.
|
||||
- Read/write the minutes.
|
||||
- Read/write the hours in 24h or AM/PM format.
|
||||
|
||||
## The devices
|
||||
|
||||
|
|
|
@ -1,9 +1,20 @@
|
|||
//! Common implementation
|
||||
|
||||
extern crate embedded_hal as hal;
|
||||
use super::super::{ Ds323x, Register, Error };
|
||||
use super::super::{ Ds323x, Register, BitFlags, Error };
|
||||
use interface::{ ReadRegister, WriteRegister };
|
||||
|
||||
/// Hours in either 12-hour (AM/PM) or 24-hour format
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Hours {
|
||||
/// AM [1-12]
|
||||
AM(u8),
|
||||
/// PM [1-12]
|
||||
PM(u8),
|
||||
/// 24H format [0-23]
|
||||
H24(u8),
|
||||
}
|
||||
|
||||
impl<DI, IC, E> Ds323x<DI, IC>
|
||||
where
|
||||
DI: ReadRegister<Error = E>
|
||||
|
@ -18,6 +29,24 @@ where
|
|||
self.read_register_decimal(Register::MINUTES)
|
||||
}
|
||||
|
||||
/// Read the hours.
|
||||
pub fn get_hours(&mut self) -> Result<Hours, Error<E>> {
|
||||
let data = self.iface.read_register(Register::HOURS)?;
|
||||
self.get_hours_from_register(data)
|
||||
}
|
||||
|
||||
fn get_hours_from_register(&self, data: u8) -> Result<Hours, Error<E>> {
|
||||
if is_24h_format(data) {
|
||||
Ok(Hours::H24(packed_bcd_to_decimal(data & !BitFlags::H24_H12)))
|
||||
}
|
||||
else if is_am(data) {
|
||||
Ok(Hours::AM(packed_bcd_to_decimal(data & !(BitFlags::H24_H12 | BitFlags::AM_PM))))
|
||||
}
|
||||
else {
|
||||
Ok(Hours::PM(packed_bcd_to_decimal(data & !(BitFlags::H24_H12 | BitFlags::AM_PM))))
|
||||
}
|
||||
}
|
||||
|
||||
fn read_register_decimal(&mut self, register: u8) -> Result<u8, Error<E>> {
|
||||
let data = self.iface.read_register(register)?;
|
||||
Ok(packed_bcd_to_decimal(data))
|
||||
|
@ -48,11 +77,40 @@ where
|
|||
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<E>> {
|
||||
let value = self.get_hours_register_value(&hours)?;
|
||||
self.iface.write_register(Register::HOURS, value)
|
||||
}
|
||||
|
||||
fn get_hours_register_value(&mut self, hours: &Hours) -> Result<u8, Error<E>> {
|
||||
match *hours {
|
||||
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::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)),
|
||||
}
|
||||
}
|
||||
|
||||
fn write_register_decimal(&mut self, register: u8, decimal_number: u8) -> Result<(), Error<E>> {
|
||||
self.iface.write_register(register, decimal_to_packed_bcd(decimal_number))
|
||||
}
|
||||
}
|
||||
|
||||
fn is_24h_format(hours_data: u8) -> bool {
|
||||
hours_data & BitFlags::H24_H12 == 0
|
||||
}
|
||||
|
||||
fn is_am(hours_data: u8) -> bool {
|
||||
hours_data & BitFlags::AM_PM == 0
|
||||
}
|
||||
|
||||
// Transforms a decimal number to packed BCD format
|
||||
fn decimal_to_packed_bcd(dec: u8) -> u8 {
|
||||
((dec / 10) << 4) | (dec % 10)
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
mod datetime;
|
||||
pub use self::datetime::Hours;
|
||||
|
|
10
src/lib.rs
10
src/lib.rs
|
@ -6,6 +6,7 @@
|
|||
//! This driver allows you to:
|
||||
//! - Read/write the seconds.
|
||||
//! - Read/write the minutes.
|
||||
//! - Read/write the hours in 24h or AM/PM format.
|
||||
//!
|
||||
//! ## The devices
|
||||
//!
|
||||
|
@ -179,6 +180,14 @@ struct Register;
|
|||
impl Register {
|
||||
const SECONDS : u8 = 0x00;
|
||||
const MINUTES : u8 = 0x01;
|
||||
const HOURS : u8 = 0x02;
|
||||
}
|
||||
|
||||
struct BitFlags;
|
||||
|
||||
impl BitFlags {
|
||||
const H24_H12 : u8 = 0b0100_0000;
|
||||
const AM_PM : u8 = 0b0010_0000;
|
||||
}
|
||||
|
||||
const DEVICE_ADDRESS: u8 = 0b110_1000;
|
||||
|
@ -265,3 +274,4 @@ where
|
|||
}
|
||||
|
||||
mod ds323x;
|
||||
pub use ds323x::Hours;
|
||||
|
|
|
@ -11,6 +11,7 @@ pub struct Register;
|
|||
impl Register {
|
||||
pub const SECONDS : u8 = 0x00;
|
||||
pub const MINUTES : u8 = 0x01;
|
||||
pub const HOURS : u8 = 0x02;
|
||||
}
|
||||
|
||||
pub struct DummyOutputPin;
|
||||
|
|
|
@ -6,6 +6,8 @@ use hal::spi::Transaction as SpiTrans;
|
|||
mod common;
|
||||
use common::{ DEVICE_ADDRESS, Register, new_ds3231,
|
||||
new_ds3232, new_ds3234 };
|
||||
extern crate ds323x;
|
||||
use ds323x::{ Hours };
|
||||
|
||||
mod seconds {
|
||||
use super::*;
|
||||
|
@ -49,4 +51,25 @@ mod minutes {
|
|||
|
||||
set_test!(can_set_ds3234, set_minutes, new_ds3234, 1,
|
||||
SpiTrans::write(vec![Register::MINUTES + 0x80, 1]));
|
||||
}
|
||||
|
||||
mod hours {
|
||||
use super::*;
|
||||
get_test!(can_get_ds3231, get_hours, new_ds3231, Hours::H24(21),
|
||||
I2cTrans::write_read(DEVICE_ADDRESS, vec![Register::HOURS], vec![0b0010_0001]));
|
||||
|
||||
get_test!(can_get_ds3232, get_hours, new_ds3232, Hours::H24(21),
|
||||
I2cTrans::write_read(DEVICE_ADDRESS, vec![Register::HOURS], vec![0b0010_0001]));
|
||||
|
||||
get_test!(can_get_ds3234, get_hours, new_ds3234, Hours::H24(21),
|
||||
SpiTrans::transfer(vec![Register::HOURS, 0], vec![Register::HOURS, 0b0010_0001]));
|
||||
|
||||
|
||||
set_test!(can_set_ds3231, set_hours, new_ds3231, Hours::H24(21),
|
||||
I2cTrans::write(DEVICE_ADDRESS, vec![Register::HOURS, 0b0010_0001]));
|
||||
|
||||
set_test!(can_set_ds3232, set_hours, new_ds3232, Hours::H24(21),
|
||||
I2cTrans::write(DEVICE_ADDRESS, vec![Register::HOURS, 0b0010_0001]));
|
||||
|
||||
set_test!(can_set_ds3234, set_hours, new_ds3234, Hours::H24(21),
|
||||
SpiTrans::write(vec![Register::HOURS + 0x80, 0b0010_0001]));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue