ds3231_rtc/
ds3231.rs

1//! DS3231 Real-Time Clock Driver
2
3use embedded_hal::i2c::I2c;
4
5use crate::{error::Error, registers::Register};
6
7/// DS3231 I2C device address (fixed)
8pub const I2C_ADDR: u8 = 0x68;
9
10/// Default base century for year calculations (2000-2099).
11/// Since the DS3231's century bit meaning is ambiguous, we assume
12/// years 00-99 represent the 21st century by default.
13pub const DEFAULT_BASE_CENTURY: u8 = 20;
14
15/// DS3231 Real-Time Clock driver
16pub struct Ds3231<I2C> {
17    i2c: I2C,
18    pub(crate) base_century: u8,
19}
20
21impl<I2C: embedded_hal::i2c::I2c> rtc_hal::error::ErrorType for Ds3231<I2C> {
22    type Error = crate::error::Error<I2C::Error>;
23}
24
25impl<I2C, E> Ds3231<I2C>
26where
27    I2C: I2c<Error = E>,
28    E: core::fmt::Debug,
29{
30    /// Create a new DS3231 driver instance
31    ///
32    /// # Parameters
33    /// * `i2c` - I2C peripheral that implements the embedded-hal I2c trait
34    ///
35    /// # Returns
36    /// New DS3231 driver instance
37    pub fn new(i2c: I2C) -> Self {
38        Self {
39            i2c,
40            base_century: DEFAULT_BASE_CENTURY,
41        }
42    }
43
44    /// Sets the base century for year calculations.
45    ///
46    /// The DS3231 stores years as 00-99 in BCD format. This base century
47    /// determines how those 2-digit years are interpreted as full 4-digit years.
48    ///
49    /// # Arguments
50    ///
51    /// * `base_century` - The century to use (e.g., 20 for 2000-2099, 21 for 2100-2199)
52    ///
53    /// # Returns
54    ///
55    /// Returns `Err(Error::InvalidBaseCentury)` if base_century is less than 19.
56    ///
57    /// # Examples
58    ///
59    /// ```
60    /// // Years 00-99 will be interpreted as 2000-2099
61    /// let rtc = Ds3231::new(i2c).with_base_century(20)?;
62    ///
63    /// // Years 00-99 will be interpreted as 2100-2199
64    /// let rtc = Ds3231::new(i2c).with_base_century(21)?;
65    /// ```
66    pub fn set_base_century(&mut self, base_century: u8) -> Result<(), Error<E>> {
67        if base_century < 19 {
68            return Err(Error::InvalidBaseCentury);
69        }
70        self.base_century = base_century;
71        Ok(())
72    }
73
74    /// Returns the underlying I2C bus instance, consuming the driver.
75    ///
76    /// This allows the user to reuse the I2C bus for other purposes
77    /// after the driver is no longer needed.
78    ///
79    /// However, if you are using [`embedded-hal-bus`](https://crates.io/crates/embedded-hal-bus),
80    /// you typically do not need `release_i2c`.
81    /// In that case the crate takes care of the sharing
82    pub fn release_i2c(self) -> I2C {
83        self.i2c
84    }
85
86    /// Write a single byte to a DS3231 register
87    pub(crate) fn write_register(&mut self, register: Register, value: u8) -> Result<(), Error<E>> {
88        self.i2c.write(I2C_ADDR, &[register.addr(), value])?;
89
90        Ok(())
91    }
92
93    /// Read a single byte from a DS3231 register
94    pub(crate) fn read_register(&mut self, register: Register) -> Result<u8, Error<E>> {
95        let mut data = [0u8; 1];
96        self.i2c
97            .write_read(I2C_ADDR, &[register.addr()], &mut data)
98            .map_err(Error::I2c)?;
99
100        Ok(data[0])
101    }
102
103    /// Read multiple bytes from DS3231 starting at a register
104    pub(crate) fn read_register_bytes(
105        &mut self,
106        register: Register,
107        buffer: &mut [u8],
108    ) -> Result<(), Error<E>> {
109        self.i2c.write_read(I2C_ADDR, &[register.addr()], buffer)?;
110
111        Ok(())
112    }
113
114    // Read multiple bytes from DS3231 starting at a raw address
115    // pub(crate) fn read_bytes_at_address(
116    //     &mut self,
117    //     register_addr: u8,
118    //     buffer: &mut [u8],
119    // ) -> Result<(), Error<E>> {
120    //     self.i2c.write_read(I2C_ADDR, &[register_addr], buffer)?;
121
122    //     Ok(())
123    // }
124
125    /// Write raw bytes directly to DS3231 via I2C (register address must be first byte)
126    pub(crate) fn write_raw_bytes(&mut self, data: &[u8]) -> Result<(), Error<E>> {
127        self.i2c.write(I2C_ADDR, data).map_err(Error::I2c)
128    }
129
130    /// Read-modify-write operation for setting bits
131    ///
132    /// Performs a read-modify-write operation to set the bits specified by the mask
133    /// while preserving all other bits in the register. Only performs a write if
134    /// the register value would actually change, optimizing I2C bus usage.
135    ///
136    /// # Parameters
137    /// - `register`: The DS3231 register to modify
138    /// - `mask`: Bit mask where `1` bits will be set, `0` bits will be ignored
139    ///
140    /// # Example
141    /// ```ignore
142    /// // Set bits 2 and 4 in the control register
143    /// self.set_register_bits(Register::Control, 0b0001_0100)?;
144    /// ```
145    ///
146    /// # I2C Operations
147    /// - 1 read + 1 write (if change needed)
148    /// - 1 read only (if no change needed)
149    pub(crate) fn set_register_bits(
150        &mut self,
151        register: Register,
152        mask: u8,
153    ) -> Result<(), Error<E>> {
154        let current = self.read_register(register)?;
155        let new_value = current | mask;
156        if new_value != current {
157            self.write_register(register, new_value)
158        } else {
159            Ok(())
160        }
161    }
162
163    /// Read-modify-write operation for clearing bits
164    ///
165    /// Performs a read-modify-write operation to clear the bits specified by the mask
166    /// while preserving all other bits in the register. Only performs a write if
167    /// the register value would actually change, optimizing I2C bus usage.
168    ///
169    /// # Parameters
170    /// - `register`: The DS3231 register to modify
171    /// - `mask`: Bit mask where `1` bits will be cleared, `0` bits will be ignored
172    ///
173    /// # Example
174    /// ```ignore
175    /// // Clear the Clock Halt bit (bit 7) in seconds register
176    /// self.clear_register_bits(Register::Seconds, 0b1000_0000)?;
177    /// ```
178    ///
179    /// # I2C Operations
180    /// - 1 read + 1 write (if change needed)
181    /// - 1 read only (if no change needed)
182    pub(crate) fn clear_register_bits(
183        &mut self,
184        register: Register,
185        mask: u8,
186    ) -> Result<(), Error<E>> {
187        let current = self.read_register(register)?;
188        let new_value = current & !mask;
189        if new_value != current {
190            self.write_register(register, new_value)
191        } else {
192            Ok(())
193        }
194    }
195}
196
197#[cfg(test)]
198mod tests {
199    use super::*;
200    use crate::error::Error;
201    use crate::registers::Register;
202    use embedded_hal_mock::eh1::i2c::{Mock as I2cMock, Transaction as I2cTransaction};
203
204    const DS3231_ADDR: u8 = 0x68;
205
206    #[test]
207    fn test_new() {
208        let i2c_mock = I2cMock::new(&[]);
209        let ds3231 = Ds3231::new(i2c_mock);
210
211        assert_eq!(ds3231.base_century, DEFAULT_BASE_CENTURY);
212
213        let mut i2c_mock = ds3231.release_i2c();
214        i2c_mock.done();
215    }
216
217    #[test]
218    fn test_set_base_century_valid() {
219        let i2c_mock = I2cMock::new(&[]);
220        let mut ds3231 = Ds3231::new(i2c_mock);
221
222        let result = ds3231.set_base_century(21);
223        assert!(result.is_ok());
224        assert_eq!(ds3231.base_century, 21);
225
226        let mut i2c_mock = ds3231.release_i2c();
227        i2c_mock.done();
228    }
229
230    #[test]
231    fn test_set_base_century_minimum_valid() {
232        let i2c_mock = I2cMock::new(&[]);
233        let mut ds3231 = Ds3231::new(i2c_mock);
234
235        let result = ds3231.set_base_century(19);
236        assert!(result.is_ok());
237        assert_eq!(ds3231.base_century, 19);
238
239        let mut i2c_mock = ds3231.release_i2c();
240        i2c_mock.done();
241    }
242
243    #[test]
244    fn test_set_base_century_invalid() {
245        let i2c_mock = I2cMock::new(&[]);
246        let mut ds3231 = Ds3231::new(i2c_mock);
247
248        let result = ds3231.set_base_century(18);
249        assert!(matches!(result, Err(Error::InvalidBaseCentury)));
250        assert_eq!(ds3231.base_century, DEFAULT_BASE_CENTURY);
251
252        let mut i2c_mock = ds3231.release_i2c();
253        i2c_mock.done();
254    }
255
256    #[test]
257    fn test_write_register() {
258        let expectations = vec![I2cTransaction::write(
259            DS3231_ADDR,
260            vec![Register::Control.addr(), 0x42],
261        )];
262
263        let i2c_mock = I2cMock::new(&expectations);
264        let mut ds3231 = Ds3231::new(i2c_mock);
265
266        let result = ds3231.write_register(Register::Control, 0x42);
267        assert!(result.is_ok());
268
269        let mut i2c_mock = ds3231.release_i2c();
270        i2c_mock.done();
271    }
272
273    #[test]
274    fn test_write_register_error() {
275        let expectations = vec![
276            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0x42])
277                .with_error(embedded_hal::i2c::ErrorKind::Other),
278        ];
279
280        let i2c_mock = I2cMock::new(&expectations);
281        let mut ds3231 = Ds3231::new(i2c_mock);
282
283        let result = ds3231.write_register(Register::Control, 0x42);
284        assert!(result.is_err());
285
286        let mut i2c_mock = ds3231.release_i2c();
287        i2c_mock.done();
288    }
289
290    #[test]
291    fn test_read_register() {
292        let expectations = vec![I2cTransaction::write_read(
293            DS3231_ADDR,
294            vec![Register::Control.addr()],
295            vec![0x55],
296        )];
297
298        let i2c_mock = I2cMock::new(&expectations);
299        let mut ds3231 = Ds3231::new(i2c_mock);
300
301        let result = ds3231.read_register(Register::Control);
302        assert_eq!(result.unwrap(), 0x55);
303
304        let mut i2c_mock = ds3231.release_i2c();
305        i2c_mock.done();
306    }
307
308    #[test]
309    fn test_read_register_error() {
310        let expectations = vec![
311            I2cTransaction::write_read(DS3231_ADDR, vec![Register::Control.addr()], vec![0x00])
312                .with_error(embedded_hal::i2c::ErrorKind::Other),
313        ];
314
315        let i2c_mock = I2cMock::new(&expectations);
316        let mut ds3231 = Ds3231::new(i2c_mock);
317
318        let result = ds3231.read_register(Register::Control);
319        assert!(result.is_err());
320
321        let mut i2c_mock = ds3231.release_i2c();
322        i2c_mock.done();
323    }
324
325    #[test]
326    fn test_read_register_bytes() {
327        let expectations = vec![I2cTransaction::write_read(
328            DS3231_ADDR,
329            vec![Register::Seconds.addr()],
330            vec![0x11, 0x22, 0x33],
331        )];
332
333        let i2c_mock = I2cMock::new(&expectations);
334        let mut ds3231 = Ds3231::new(i2c_mock);
335
336        let mut buffer = [0u8; 3];
337        let result = ds3231.read_register_bytes(Register::Seconds, &mut buffer);
338        assert!(result.is_ok());
339        assert_eq!(buffer, [0x11, 0x22, 0x33]);
340
341        let mut i2c_mock = ds3231.release_i2c();
342        i2c_mock.done();
343    }
344
345    #[test]
346    fn test_read_register_bytes_error() {
347        let expectations = vec![
348            I2cTransaction::write_read(
349                DS3231_ADDR,
350                vec![Register::Seconds.addr()],
351                vec![0x00, 0x00],
352            )
353            .with_error(embedded_hal::i2c::ErrorKind::Other),
354        ];
355
356        let i2c_mock = I2cMock::new(&expectations);
357        let mut ds3231 = Ds3231::new(i2c_mock);
358
359        let mut buffer = [0u8; 2];
360        let result = ds3231.read_register_bytes(Register::Seconds, &mut buffer);
361        assert!(result.is_err());
362
363        let mut i2c_mock = ds3231.release_i2c();
364        i2c_mock.done();
365    }
366
367    #[test]
368    fn test_write_raw_bytes() {
369        let expectations = vec![I2cTransaction::write(DS3231_ADDR, vec![0x0E, 0x1C, 0x00])];
370
371        let i2c_mock = I2cMock::new(&expectations);
372        let mut ds3231 = Ds3231::new(i2c_mock);
373
374        let result = ds3231.write_raw_bytes(&[0x0E, 0x1C, 0x00]);
375        assert!(result.is_ok());
376
377        let mut i2c_mock = ds3231.release_i2c();
378        i2c_mock.done();
379    }
380
381    #[test]
382    fn test_write_raw_bytes_error() {
383        let expectations = vec![
384            I2cTransaction::write(DS3231_ADDR, vec![0x0E, 0x1C])
385                .with_error(embedded_hal::i2c::ErrorKind::Other),
386        ];
387
388        let i2c_mock = I2cMock::new(&expectations);
389        let mut ds3231 = Ds3231::new(i2c_mock);
390
391        let result = ds3231.write_raw_bytes(&[0x0E, 0x1C]);
392        assert!(result.is_err());
393
394        let mut i2c_mock = ds3231.release_i2c();
395        i2c_mock.done();
396    }
397
398    #[test]
399    fn test_set_register_bits_change_needed() {
400        let expectations = vec![
401            I2cTransaction::write_read(
402                DS3231_ADDR,
403                vec![Register::Control.addr()],
404                vec![0b0000_1000],
405            ),
406            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0001_1000]),
407        ];
408
409        let i2c_mock = I2cMock::new(&expectations);
410        let mut ds3231 = Ds3231::new(i2c_mock);
411
412        let result = ds3231.set_register_bits(Register::Control, 0b0001_0000);
413        assert!(result.is_ok());
414
415        let mut i2c_mock = ds3231.release_i2c();
416        i2c_mock.done();
417    }
418
419    #[test]
420    fn test_set_register_bits_no_change_needed() {
421        let expectations = vec![I2cTransaction::write_read(
422            DS3231_ADDR,
423            vec![Register::Control.addr()],
424            vec![0b0001_1000],
425        )];
426
427        let i2c_mock = I2cMock::new(&expectations);
428        let mut ds3231 = Ds3231::new(i2c_mock);
429
430        let result = ds3231.set_register_bits(Register::Control, 0b0001_0000);
431        assert!(result.is_ok());
432
433        let mut i2c_mock = ds3231.release_i2c();
434        i2c_mock.done();
435    }
436
437    #[test]
438    fn test_set_register_bits_multiple_bits() {
439        let expectations = vec![
440            I2cTransaction::write_read(
441                DS3231_ADDR,
442                vec![Register::Control.addr()],
443                vec![0b0000_0000],
444            ),
445            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b1010_0101]),
446        ];
447
448        let i2c_mock = I2cMock::new(&expectations);
449        let mut ds3231 = Ds3231::new(i2c_mock);
450
451        let result = ds3231.set_register_bits(Register::Control, 0b1010_0101);
452        assert!(result.is_ok());
453
454        let mut i2c_mock = ds3231.release_i2c();
455        i2c_mock.done();
456    }
457
458    #[test]
459    fn test_set_register_bits_read_error() {
460        let expectations = vec![
461            I2cTransaction::write_read(DS3231_ADDR, vec![Register::Control.addr()], vec![0x00])
462                .with_error(embedded_hal::i2c::ErrorKind::Other),
463        ];
464
465        let i2c_mock = I2cMock::new(&expectations);
466        let mut ds3231 = Ds3231::new(i2c_mock);
467
468        let result = ds3231.set_register_bits(Register::Control, 0b0001_0000);
469        assert!(result.is_err());
470
471        let mut i2c_mock = ds3231.release_i2c();
472        i2c_mock.done();
473    }
474
475    #[test]
476    fn test_set_register_bits_write_error() {
477        let expectations = vec![
478            I2cTransaction::write_read(
479                DS3231_ADDR,
480                vec![Register::Control.addr()],
481                vec![0b0000_0000],
482            ),
483            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0001_0000])
484                .with_error(embedded_hal::i2c::ErrorKind::Other),
485        ];
486
487        let i2c_mock = I2cMock::new(&expectations);
488        let mut ds3231 = Ds3231::new(i2c_mock);
489
490        let result = ds3231.set_register_bits(Register::Control, 0b0001_0000);
491        assert!(result.is_err());
492
493        let mut i2c_mock = ds3231.release_i2c();
494        i2c_mock.done();
495    }
496
497    #[test]
498    fn test_clear_register_bits_change_needed() {
499        let expectations = vec![
500            I2cTransaction::write_read(
501                DS3231_ADDR,
502                vec![Register::Control.addr()],
503                vec![0b1111_1111],
504            ),
505            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b1110_1111]),
506        ];
507
508        let i2c_mock = I2cMock::new(&expectations);
509        let mut ds3231 = Ds3231::new(i2c_mock);
510
511        let result = ds3231.clear_register_bits(Register::Control, 0b0001_0000);
512        assert!(result.is_ok());
513
514        let mut i2c_mock = ds3231.release_i2c();
515        i2c_mock.done();
516    }
517
518    #[test]
519    fn test_clear_register_bits_no_change_needed() {
520        let expectations = vec![I2cTransaction::write_read(
521            DS3231_ADDR,
522            vec![Register::Control.addr()],
523            vec![0b1110_1111],
524        )];
525
526        let i2c_mock = I2cMock::new(&expectations);
527        let mut ds3231 = Ds3231::new(i2c_mock);
528
529        let result = ds3231.clear_register_bits(Register::Control, 0b0001_0000);
530        assert!(result.is_ok());
531
532        let mut i2c_mock = ds3231.release_i2c();
533        i2c_mock.done();
534    }
535
536    #[test]
537    fn test_clear_register_bits_multiple_bits() {
538        let expectations = vec![
539            I2cTransaction::write_read(
540                DS3231_ADDR,
541                vec![Register::Control.addr()],
542                vec![0b1111_1111],
543            ),
544            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0101_1010]),
545        ];
546
547        let i2c_mock = I2cMock::new(&expectations);
548        let mut ds3231 = Ds3231::new(i2c_mock);
549
550        let result = ds3231.clear_register_bits(Register::Control, 0b1010_0101);
551        assert!(result.is_ok());
552
553        let mut i2c_mock = ds3231.release_i2c();
554        i2c_mock.done();
555    }
556
557    #[test]
558    fn test_clear_register_bits_read_error() {
559        let expectations = vec![
560            I2cTransaction::write_read(DS3231_ADDR, vec![Register::Control.addr()], vec![0x00])
561                .with_error(embedded_hal::i2c::ErrorKind::Other),
562        ];
563
564        let i2c_mock = I2cMock::new(&expectations);
565        let mut ds3231 = Ds3231::new(i2c_mock);
566
567        let result = ds3231.clear_register_bits(Register::Control, 0b0001_0000);
568        assert!(result.is_err());
569
570        let mut i2c_mock = ds3231.release_i2c();
571        i2c_mock.done();
572    }
573
574    #[test]
575    fn test_clear_register_bits_write_error() {
576        let expectations = vec![
577            I2cTransaction::write_read(
578                DS3231_ADDR,
579                vec![Register::Control.addr()],
580                vec![0b1111_1111],
581            ),
582            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b1110_1111])
583                .with_error(embedded_hal::i2c::ErrorKind::Other),
584        ];
585
586        let i2c_mock = I2cMock::new(&expectations);
587        let mut ds3231 = Ds3231::new(i2c_mock);
588
589        let result = ds3231.clear_register_bits(Register::Control, 0b0001_0000);
590        assert!(result.is_err());
591
592        let mut i2c_mock = ds3231.release_i2c();
593        i2c_mock.done();
594    }
595
596    #[test]
597    fn test_constants() {
598        assert_eq!(I2C_ADDR, 0x68);
599        assert_eq!(DEFAULT_BASE_CENTURY, 20);
600    }
601
602    #[test]
603    fn test_set_register_bits_preserves_other_bits() {
604        let expectations = vec![
605            I2cTransaction::write_read(
606                DS3231_ADDR,
607                vec![Register::Control.addr()],
608                vec![0b1000_0010],
609            ),
610            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b1001_0010]),
611        ];
612
613        let i2c_mock = I2cMock::new(&expectations);
614        let mut ds3231 = Ds3231::new(i2c_mock);
615
616        let result = ds3231.set_register_bits(Register::Control, 0b0001_0000);
617        assert!(result.is_ok());
618
619        let mut i2c_mock = ds3231.release_i2c();
620        i2c_mock.done();
621    }
622
623    #[test]
624    fn test_clear_register_bits_preserves_other_bits() {
625        let expectations = vec![
626            I2cTransaction::write_read(
627                DS3231_ADDR,
628                vec![Register::Control.addr()],
629                vec![0b1001_0010],
630            ),
631            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b1000_0010]),
632        ];
633
634        let i2c_mock = I2cMock::new(&expectations);
635        let mut ds3231 = Ds3231::new(i2c_mock);
636
637        let result = ds3231.clear_register_bits(Register::Control, 0b0001_0000);
638        assert!(result.is_ok());
639
640        let mut i2c_mock = ds3231.release_i2c();
641        i2c_mock.done();
642    }
643}