A personal rust firmware for the Badger 2040 W
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}