#![allow(dead_code)] ///None of this code is mine. It's https://crates.io/crates/pcf85063a /// I just needed a synchronous version so did a local clone and pulled the async and awaits pub mod alarm; pub mod datetime; use embedded_hal_1::i2c::I2c; /// All possible errors in this crate #[derive(Debug, defmt::Format)] pub enum Error { /// I2C bus error I2C(E), /// Invalid input data InvalidInputData, /// A time component was out of range ComponentRange, } impl From for Error { fn from(_: time::error::ComponentRange) -> Self { Self::ComponentRange } } pub struct Register; impl Register { // control and status registers pub const CONTROL_1: u8 = 0x00; pub const CONTROL_2: u8 = 0x01; pub const OFFSET: u8 = 0x02; pub const RAM_BYTE: u8 = 0x03; // time and date registers pub const SECONDS: u8 = 0x04; pub const MINUTES: u8 = 0x05; pub const HOURS: u8 = 0x06; pub const DAYS: u8 = 0x07; pub const WEEKDAYS: u8 = 0x08; pub const MONTHS: u8 = 0x09; pub const YEARS: u8 = 0x0A; // alarm registers pub const SECOND_ALARM: u8 = 0x0B; pub const MINUTE_ALARM: u8 = 0x0C; pub const HOUR_ALARM: u8 = 0x0D; pub const DAY_ALARM: u8 = 0x0E; pub const WEEKDAY_ALARM: u8 = 0x0F; // timer registers pub const TIMER_VALUE: u8 = 0x10; pub const TIMER_MODE: u8 = 0x11; } pub struct BitFlags; impl BitFlags { // control 1 pub const CAP_SEL: u8 = 0b0000_0001; // internal oscillator capacitor selection pub const MODE_12_24: u8 = 0b0000_0010; // 12 or 24-hour mode pub const CIE: u8 = 0b0000_0100; // connection interrupt enable // 3: UNUSED pub const SR: u8 = 0b0001_0000; // software reset pub const STOP: u8 = 0b0010_0000; // RTC clock stop bit // 6: UNUSED pub const EXT_TEST: u8 = 0b1000_0000; // external clock test mode // control 2 pub const COF: u8 = 0b0000_0111; // clkout control pub const TF: u8 = 0b0000_1000; // timer flag pub const HMI: u8 = 0b0001_0000; // half minute interrupt pub const MI: u8 = 0b0010_0000; // minute interrupt pub const AF: u8 = 0b0100_0000; // alarm flag pub const AIE: u8 = 0b1000_0000; // alarm interrupt enabled pub const AE: u8 = 0b1000_0000; // alarm enable/disable for all five (s/m/h/d/wd) settings } const DEVICE_ADDRESS: u8 = 0b1010001; /// Two possible choices, used for various enable/disable bit flags #[allow(non_camel_case_types)] #[derive(Copy, Clone, Debug, defmt::Format)] pub enum Control { /// Enable some feature, eg. timer On, /// Disable some feature, eg. timer Off, } /// PCF8563 driver #[derive(Debug, Default, defmt::Format)] pub struct PCF85063 { /// The concrete I2C device implementation. i2c: I2C, } impl PCF85063 where I2C: I2c, { /// Create a new instance of the PCF8563 driver. pub fn new(i2c: I2C) -> Self { PCF85063 { i2c } } /// Reset the RTC pub fn reset(&mut self) -> Result<(), Error> { self.set_register_bit_flag(Register::CONTROL_1, BitFlags::SR) } /// Destroy driver instance, return I2C bus instance. pub fn destroy(self) -> I2C { self.i2c } /// Let the device reset itself pub fn perform_software_reset(&mut self) -> Result<(), Error> { self.write_register(Register::CONTROL_1, 0b01011000) } /// Write to a register. pub fn write_register(&mut self, register: u8, data: u8) -> Result<(), Error> { let payload: [u8; 2] = [register, data]; self.i2c.write(DEVICE_ADDRESS, &payload).map_err(Error::I2C) } /// Read from a register. pub fn read_register(&mut self, register: u8) -> Result> { let mut data = [0]; self.i2c .write_read(DEVICE_ADDRESS, &[register], &mut data) .map_err(Error::I2C) .and(Ok(data[0])) } /// Check if specific bits are set. pub fn is_register_bit_flag_high( &mut self, address: u8, bitmask: u8, ) -> Result> { let data = self.read_register(address)?; Ok((data & bitmask) != 0) } /// Set specific bits. pub fn set_register_bit_flag(&mut self, address: u8, bitmask: u8) -> Result<(), Error> { let data = self.read_register(address)?; if (data & bitmask) == 0 { self.write_register(address, data | bitmask) } else { Ok(()) } } /// Clear specific bits. pub fn clear_register_bit_flag(&mut self, address: u8, bitmask: u8) -> Result<(), Error> { let data = self.read_register(address)?; if (data & bitmask) != 0 { self.write_register(address, data & !bitmask) } else { Ok(()) } } } impl PCF85063 where I2C: I2c, { pub fn read_ram_byte(&mut self) -> Result> { self.read_register(Register::RAM_BYTE) } pub fn write_ram_byte(&mut self, byte: u8) -> Result<(), Error> { self.write_register(Register::RAM_BYTE, byte) } } impl PCF85063 where I2C: I2c, { pub fn stop_clock(&mut self) -> Result<(), Error> { self.set_register_bit_flag(Register::CONTROL_1, BitFlags::STOP) } pub fn start_clock(&mut self) -> Result<(), Error> { self.clear_register_bit_flag(Register::CONTROL_1, BitFlags::STOP) } } #[derive(Debug, Clone, Copy, PartialEq, Eq, defmt::Format)] #[repr(u8)] pub enum OutputFrequency { Hz32768 = 0b000, Hz16384 = 0b001, Hz8192 = 0b010, Hz4096 = 0b011, Hz2048 = 0b100, Hz1024 = 0b101, Hz1 = 0b110, Hz0 = 0b111, } impl Default for OutputFrequency { fn default() -> Self { OutputFrequency::Hz32768 } } impl OutputFrequency { pub const fn bits(self) -> u8 { self as u8 } } impl PCF85063 where I2C: I2c, { pub fn read_clock_output_frequency(&mut self) -> Result> { let value = self.read_register(Register::CONTROL_2)? & BitFlags::COF; Ok(unsafe { core::mem::transmute(value) }) } pub fn write_clock_output_frequency(&mut self, freq: OutputFrequency) -> Result<(), Error> { let value = self.read_register(Register::CONTROL_2)?; let cleared = value ^ BitFlags::COF; let set = cleared | freq as u8; self.write_register(Register::CONTROL_2, set) } } /// Convert the Binary Coded Decimal value to decimal (only the lowest 7 bits). fn decode_bcd(input: u8) -> u8 { let digits: u8 = input & 0xf; let tens: u8 = (input >> 4) & 0x7; 10 * tens + digits } /// Convert the decimal value to Binary Coded Decimal. fn encode_bcd(input: u8) -> u8 { let digits: u8 = input % 10; let tens: u8 = input / 10; let tens = tens << 4; tens + digits }