A personal rust firmware for the Badger 2040 W
at main 253 lines 7.0 kB view raw
1#![allow(dead_code)] 2 3///None of this code is mine. It's https://crates.io/crates/pcf85063a 4/// I just needed a synchronous version so did a local clone and pulled the async and awaits 5pub mod alarm; 6pub mod datetime; 7 8use embedded_hal_1::i2c::I2c; 9 10/// All possible errors in this crate 11#[derive(Debug, defmt::Format)] 12pub enum Error<E> { 13 /// I2C bus error 14 I2C(E), 15 /// Invalid input data 16 InvalidInputData, 17 /// A time component was out of range 18 ComponentRange, 19} 20 21impl<E> From<time::error::ComponentRange> for Error<E> { 22 fn from(_: time::error::ComponentRange) -> Self { 23 Self::ComponentRange 24 } 25} 26 27pub struct Register; 28 29impl Register { 30 // control and status registers 31 pub const CONTROL_1: u8 = 0x00; 32 pub const CONTROL_2: u8 = 0x01; 33 pub const OFFSET: u8 = 0x02; 34 pub const RAM_BYTE: u8 = 0x03; 35 36 // time and date registers 37 pub const SECONDS: u8 = 0x04; 38 pub const MINUTES: u8 = 0x05; 39 pub const HOURS: u8 = 0x06; 40 pub const DAYS: u8 = 0x07; 41 pub const WEEKDAYS: u8 = 0x08; 42 pub const MONTHS: u8 = 0x09; 43 pub const YEARS: u8 = 0x0A; 44 45 // alarm registers 46 pub const SECOND_ALARM: u8 = 0x0B; 47 pub const MINUTE_ALARM: u8 = 0x0C; 48 pub const HOUR_ALARM: u8 = 0x0D; 49 pub const DAY_ALARM: u8 = 0x0E; 50 pub const WEEKDAY_ALARM: u8 = 0x0F; 51 52 // timer registers 53 pub const TIMER_VALUE: u8 = 0x10; 54 pub const TIMER_MODE: u8 = 0x11; 55} 56 57pub struct BitFlags; 58 59impl BitFlags { 60 // control 1 61 pub const CAP_SEL: u8 = 0b0000_0001; // internal oscillator capacitor selection 62 pub const MODE_12_24: u8 = 0b0000_0010; // 12 or 24-hour mode 63 pub const CIE: u8 = 0b0000_0100; // connection interrupt enable 64 // 3: UNUSED 65 pub const SR: u8 = 0b0001_0000; // software reset 66 pub const STOP: u8 = 0b0010_0000; // RTC clock stop bit 67 // 6: UNUSED 68 pub const EXT_TEST: u8 = 0b1000_0000; // external clock test mode 69 70 // control 2 71 pub const COF: u8 = 0b0000_0111; // clkout control 72 pub const TF: u8 = 0b0000_1000; // timer flag 73 pub const HMI: u8 = 0b0001_0000; // half minute interrupt 74 pub const MI: u8 = 0b0010_0000; // minute interrupt 75 pub const AF: u8 = 0b0100_0000; // alarm flag 76 pub const AIE: u8 = 0b1000_0000; // alarm interrupt enabled 77 78 pub const AE: u8 = 0b1000_0000; // alarm enable/disable for all five (s/m/h/d/wd) settings 79} 80 81const DEVICE_ADDRESS: u8 = 0b1010001; 82 83/// Two possible choices, used for various enable/disable bit flags 84#[allow(non_camel_case_types)] 85#[derive(Copy, Clone, Debug, defmt::Format)] 86pub enum Control { 87 /// Enable some feature, eg. timer 88 On, 89 /// Disable some feature, eg. timer 90 Off, 91} 92 93/// PCF8563 driver 94#[derive(Debug, Default, defmt::Format)] 95pub struct PCF85063<I2C> { 96 /// The concrete I2C device implementation. 97 i2c: I2C, 98} 99 100impl<I2C, E> PCF85063<I2C> 101where 102 I2C: I2c<Error = E>, 103{ 104 /// Create a new instance of the PCF8563 driver. 105 pub fn new(i2c: I2C) -> Self { 106 PCF85063 { i2c } 107 } 108 109 /// Reset the RTC 110 pub fn reset(&mut self) -> Result<(), Error<E>> { 111 self.set_register_bit_flag(Register::CONTROL_1, BitFlags::SR) 112 } 113 114 /// Destroy driver instance, return I2C bus instance. 115 pub fn destroy(self) -> I2C { 116 self.i2c 117 } 118 119 /// Let the device reset itself 120 pub fn perform_software_reset(&mut self) -> Result<(), Error<E>> { 121 self.write_register(Register::CONTROL_1, 0b01011000) 122 } 123 124 /// Write to a register. 125 pub fn write_register(&mut self, register: u8, data: u8) -> Result<(), Error<E>> { 126 let payload: [u8; 2] = [register, data]; 127 self.i2c.write(DEVICE_ADDRESS, &payload).map_err(Error::I2C) 128 } 129 130 /// Read from a register. 131 pub fn read_register(&mut self, register: u8) -> Result<u8, Error<E>> { 132 let mut data = [0]; 133 self.i2c 134 .write_read(DEVICE_ADDRESS, &[register], &mut data) 135 .map_err(Error::I2C) 136 .and(Ok(data[0])) 137 } 138 139 /// Check if specific bits are set. 140 pub fn is_register_bit_flag_high( 141 &mut self, 142 address: u8, 143 bitmask: u8, 144 ) -> Result<bool, Error<E>> { 145 let data = self.read_register(address)?; 146 Ok((data & bitmask) != 0) 147 } 148 149 /// Set specific bits. 150 pub fn set_register_bit_flag(&mut self, address: u8, bitmask: u8) -> Result<(), Error<E>> { 151 let data = self.read_register(address)?; 152 if (data & bitmask) == 0 { 153 self.write_register(address, data | bitmask) 154 } else { 155 Ok(()) 156 } 157 } 158 159 /// Clear specific bits. 160 pub fn clear_register_bit_flag(&mut self, address: u8, bitmask: u8) -> Result<(), Error<E>> { 161 let data = self.read_register(address)?; 162 if (data & bitmask) != 0 { 163 self.write_register(address, data & !bitmask) 164 } else { 165 Ok(()) 166 } 167 } 168} 169 170impl<I2C, E> PCF85063<I2C> 171where 172 I2C: I2c<Error = E>, 173{ 174 pub fn read_ram_byte(&mut self) -> Result<u8, Error<E>> { 175 self.read_register(Register::RAM_BYTE) 176 } 177 178 pub fn write_ram_byte(&mut self, byte: u8) -> Result<(), Error<E>> { 179 self.write_register(Register::RAM_BYTE, byte) 180 } 181} 182 183impl<I2C, E> PCF85063<I2C> 184where 185 I2C: I2c<Error = E>, 186{ 187 pub fn stop_clock(&mut self) -> Result<(), Error<E>> { 188 self.set_register_bit_flag(Register::CONTROL_1, BitFlags::STOP) 189 } 190 191 pub fn start_clock(&mut self) -> Result<(), Error<E>> { 192 self.clear_register_bit_flag(Register::CONTROL_1, BitFlags::STOP) 193 } 194} 195 196#[derive(Debug, Clone, Copy, PartialEq, Eq, defmt::Format)] 197#[repr(u8)] 198pub enum OutputFrequency { 199 Hz32768 = 0b000, 200 Hz16384 = 0b001, 201 Hz8192 = 0b010, 202 Hz4096 = 0b011, 203 Hz2048 = 0b100, 204 Hz1024 = 0b101, 205 Hz1 = 0b110, 206 Hz0 = 0b111, 207} 208 209impl Default for OutputFrequency { 210 fn default() -> Self { 211 OutputFrequency::Hz32768 212 } 213} 214 215impl OutputFrequency { 216 pub const fn bits(self) -> u8 { 217 self as u8 218 } 219} 220 221impl<I2C, E> PCF85063<I2C> 222where 223 I2C: I2c<Error = E>, 224{ 225 pub fn read_clock_output_frequency(&mut self) -> Result<OutputFrequency, Error<E>> { 226 let value = self.read_register(Register::CONTROL_2)? & BitFlags::COF; 227 228 Ok(unsafe { core::mem::transmute(value) }) 229 } 230 231 pub fn write_clock_output_frequency(&mut self, freq: OutputFrequency) -> Result<(), Error<E>> { 232 let value = self.read_register(Register::CONTROL_2)?; 233 let cleared = value ^ BitFlags::COF; 234 let set = cleared | freq as u8; 235 236 self.write_register(Register::CONTROL_2, set) 237 } 238} 239 240/// Convert the Binary Coded Decimal value to decimal (only the lowest 7 bits). 241fn decode_bcd(input: u8) -> u8 { 242 let digits: u8 = input & 0xf; 243 let tens: u8 = (input >> 4) & 0x7; 244 10 * tens + digits 245} 246 247/// Convert the decimal value to Binary Coded Decimal. 248fn encode_bcd(input: u8) -> u8 { 249 let digits: u8 = input % 10; 250 let tens: u8 = input / 10; 251 let tens = tens << 4; 252 tens + digits 253}