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:
|
This driver allows you to:
|
||||||
- Read/write the seconds.
|
- Read/write the seconds.
|
||||||
- Read/write the minutes.
|
- Read/write the minutes.
|
||||||
|
- Read/write the hours in 24h or AM/PM format.
|
||||||
|
|
||||||
## The devices
|
## The devices
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,20 @@
|
||||||
//! Common implementation
|
//! Common implementation
|
||||||
|
|
||||||
extern crate embedded_hal as hal;
|
extern crate embedded_hal as hal;
|
||||||
use super::super::{ Ds323x, Register, Error };
|
use super::super::{ Ds323x, Register, BitFlags, Error };
|
||||||
use interface::{ ReadRegister, WriteRegister };
|
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>
|
impl<DI, IC, E> Ds323x<DI, IC>
|
||||||
where
|
where
|
||||||
DI: ReadRegister<Error = E>
|
DI: ReadRegister<Error = E>
|
||||||
|
@ -18,6 +29,24 @@ where
|
||||||
self.read_register_decimal(Register::MINUTES)
|
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>> {
|
fn read_register_decimal(&mut self, register: u8) -> Result<u8, Error<E>> {
|
||||||
let data = self.iface.read_register(register)?;
|
let data = self.iface.read_register(register)?;
|
||||||
Ok(packed_bcd_to_decimal(data))
|
Ok(packed_bcd_to_decimal(data))
|
||||||
|
@ -48,11 +77,40 @@ where
|
||||||
self.write_register_decimal(Register::MINUTES, minutes)
|
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>> {
|
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))
|
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
|
// Transforms a decimal number to packed BCD format
|
||||||
fn decimal_to_packed_bcd(dec: u8) -> u8 {
|
fn decimal_to_packed_bcd(dec: u8) -> u8 {
|
||||||
((dec / 10) << 4) | (dec % 10)
|
((dec / 10) << 4) | (dec % 10)
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
mod datetime;
|
mod datetime;
|
||||||
|
pub use self::datetime::Hours;
|
||||||
|
|
10
src/lib.rs
10
src/lib.rs
|
@ -6,6 +6,7 @@
|
||||||
//! This driver allows you to:
|
//! This driver allows you to:
|
||||||
//! - Read/write the seconds.
|
//! - Read/write the seconds.
|
||||||
//! - Read/write the minutes.
|
//! - Read/write the minutes.
|
||||||
|
//! - Read/write the hours in 24h or AM/PM format.
|
||||||
//!
|
//!
|
||||||
//! ## The devices
|
//! ## The devices
|
||||||
//!
|
//!
|
||||||
|
@ -179,6 +180,14 @@ struct Register;
|
||||||
impl Register {
|
impl Register {
|
||||||
const SECONDS : u8 = 0x00;
|
const SECONDS : u8 = 0x00;
|
||||||
const MINUTES : u8 = 0x01;
|
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;
|
const DEVICE_ADDRESS: u8 = 0b110_1000;
|
||||||
|
@ -265,3 +274,4 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
mod ds323x;
|
mod ds323x;
|
||||||
|
pub use ds323x::Hours;
|
||||||
|
|
|
@ -11,6 +11,7 @@ pub struct Register;
|
||||||
impl Register {
|
impl Register {
|
||||||
pub const SECONDS : u8 = 0x00;
|
pub const SECONDS : u8 = 0x00;
|
||||||
pub const MINUTES : u8 = 0x01;
|
pub const MINUTES : u8 = 0x01;
|
||||||
|
pub const HOURS : u8 = 0x02;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DummyOutputPin;
|
pub struct DummyOutputPin;
|
||||||
|
|
|
@ -6,6 +6,8 @@ use hal::spi::Transaction as SpiTrans;
|
||||||
mod common;
|
mod common;
|
||||||
use common::{ DEVICE_ADDRESS, Register, new_ds3231,
|
use common::{ DEVICE_ADDRESS, Register, new_ds3231,
|
||||||
new_ds3232, new_ds3234 };
|
new_ds3232, new_ds3234 };
|
||||||
|
extern crate ds323x;
|
||||||
|
use ds323x::{ Hours };
|
||||||
|
|
||||||
mod seconds {
|
mod seconds {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -49,4 +51,25 @@ mod minutes {
|
||||||
|
|
||||||
set_test!(can_set_ds3234, set_minutes, new_ds3234, 1,
|
set_test!(can_set_ds3234, set_minutes, new_ds3234, 1,
|
||||||
SpiTrans::write(vec![Register::MINUTES + 0x80, 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