ds3231_rtc/
square_wave.rs

1//! DS3231 Square Wave Output Support
2//!
3//! This module provides an implementation of the [`SquareWave`] trait for the
4//! [`Ds3231`] RTC.
5//!
6//! The DS3231 supports four square wave output frequencies on the INT/SQW pin:
7//! 1 Hz, 1.024 kHz, 4.096 kHz, and 8.192 kHz. Other frequencies defined in
8//! [`SquareWaveFreq`] will result in an error.
9//!
10//! Note: The DS3231's dedicated 32 kHz output pin is not controlled by this
11//! implementation, only the configurable INT/SQW pin frequencies.
12
13pub use rtc_hal::square_wave::SquareWave;
14pub use rtc_hal::square_wave::SquareWaveFreq;
15
16use crate::Ds3231;
17use crate::error::Error;
18use crate::registers::{INTCN_BIT, RS_MASK, Register};
19
20/// Convert a [`SquareWaveFreq`] into the corresponding Ds3231 RS bits.
21///
22/// Returns an error if the frequency is not supported by the Ds3231.
23fn freq_to_bits<E>(freq: SquareWaveFreq) -> Result<u8, Error<E>>
24where
25    E: core::fmt::Debug,
26{
27    match freq {
28        SquareWaveFreq::Hz1 => Ok(0b0000_0000),
29        SquareWaveFreq::Hz1024 => Ok(0b0000_1000),
30        SquareWaveFreq::Hz4096 => Ok(0b0001_0000),
31        SquareWaveFreq::Hz8192 => Ok(0b0001_1000),
32        _ => Err(Error::UnsupportedSqwFrequency),
33    }
34}
35
36impl<I2C> SquareWave for Ds3231<I2C>
37where
38    I2C: embedded_hal::i2c::I2c,
39{
40    /// Enable the square wave output
41    fn enable_square_wave(&mut self) -> Result<(), Self::Error> {
42        // Clear INTCN bit to enable square wave mode (0 = square wave, 1 = interrupt)
43        self.clear_register_bits(Register::Control, INTCN_BIT)
44    }
45
46    /// Disable the square wave output.
47    fn disable_square_wave(&mut self) -> Result<(), Self::Error> {
48        // Set INTCN bit to enable interrupt mode (disable square wave)
49        self.set_register_bits(Register::Control, INTCN_BIT)
50    }
51
52    fn set_square_wave_frequency(&mut self, freq: SquareWaveFreq) -> Result<(), Self::Error> {
53        // Convert frequency to RS bits
54        let rs_bits = freq_to_bits(freq)?;
55
56        // Read current control register
57        let current = self.read_register(Register::Control)?;
58        let mut new_value = current;
59
60        // Clear existing RS bits and set new ones
61        new_value &= !RS_MASK;
62        new_value |= rs_bits; // Set the new RS bits
63
64        // Only write if changed
65        if new_value != current {
66            self.write_register(Register::Control, new_value)
67        } else {
68            Ok(())
69        }
70    }
71
72    fn start_square_wave(&mut self, freq: SquareWaveFreq) -> Result<(), Self::Error> {
73        let rs_bits = freq_to_bits(freq)?;
74        let current = self.read_register(Register::Control)?;
75        let mut new_value = current;
76
77        // Clear frequency bits and set new ones
78        new_value &= !RS_MASK;
79        new_value |= rs_bits;
80
81        // Enable square wave
82        new_value &= !INTCN_BIT;
83
84        // Only write if changed
85        if new_value != current {
86            self.write_register(Register::Control, new_value)
87        } else {
88            Ok(())
89        }
90    }
91}
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96    use embedded_hal_mock::eh1::i2c::{Mock as I2cMock, Transaction as I2cTransaction};
97    use rtc_hal::square_wave::{SquareWave, SquareWaveFreq};
98
99    const DS3231_ADDR: u8 = 0x68;
100
101    #[test]
102    fn test_freq_to_bits_supported_frequencies() {
103        assert_eq!(
104            freq_to_bits::<()>(SquareWaveFreq::Hz1).unwrap(),
105            0b0000_0000
106        );
107        assert_eq!(
108            freq_to_bits::<()>(SquareWaveFreq::Hz1024).unwrap(),
109            0b0000_1000
110        );
111        assert_eq!(
112            freq_to_bits::<()>(SquareWaveFreq::Hz4096).unwrap(),
113            0b0001_0000
114        );
115        assert_eq!(
116            freq_to_bits::<()>(SquareWaveFreq::Hz8192).unwrap(),
117            0b0001_1000
118        );
119    }
120
121    #[test]
122    fn test_freq_to_bits_unsupported_frequency() {
123        let result = freq_to_bits::<()>(SquareWaveFreq::Hz32768);
124        assert!(matches!(result, Err(Error::UnsupportedSqwFrequency)));
125    }
126
127    #[test]
128    fn test_enable_square_wave() {
129        let expectations = vec![
130            // transaction related to the reading the control register
131            I2cTransaction::write_read(
132                DS3231_ADDR,
133                vec![Register::Control.addr()],
134                vec![0b0000_0100],
135            ),
136            // transaction related to the writing the control register back
137            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0000_0000]),
138        ];
139
140        let mut i2c_mock = I2cMock::new(&expectations);
141        let mut ds3231 = Ds3231::new(&mut i2c_mock);
142
143        let result = ds3231.enable_square_wave();
144        assert!(result.is_ok());
145
146        i2c_mock.done();
147    }
148
149    #[test]
150    fn test_enable_square_wave_already_enabled() {
151        let expectations = vec![I2cTransaction::write_read(
152            DS3231_ADDR,
153            vec![Register::Control.addr()],
154            vec![0b0000_0000],
155        )];
156
157        let mut i2c_mock = I2cMock::new(&expectations);
158        let mut ds3231 = Ds3231::new(&mut i2c_mock);
159
160        let result = ds3231.enable_square_wave();
161        assert!(result.is_ok());
162
163        i2c_mock.done();
164    }
165
166    #[test]
167    fn test_disable_square_wave() {
168        let expectations = vec![
169            I2cTransaction::write_read(
170                DS3231_ADDR,
171                vec![Register::Control.addr()],
172                vec![0b0000_0000],
173            ),
174            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0000_0100]),
175        ];
176
177        let mut i2c_mock = I2cMock::new(&expectations);
178        let mut ds3231 = Ds3231::new(&mut i2c_mock);
179
180        let result = ds3231.disable_square_wave();
181        assert!(result.is_ok());
182
183        i2c_mock.done();
184    }
185
186    #[test]
187    fn test_set_square_wave_frequency_1hz() {
188        let expectations = vec![
189            I2cTransaction::write_read(
190                DS3231_ADDR,
191                vec![Register::Control.addr()],
192                vec![0b0001_1000],
193            ),
194            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0000_0000]),
195        ];
196
197        let mut i2c_mock = I2cMock::new(&expectations);
198        let mut ds3231 = Ds3231::new(&mut i2c_mock);
199
200        let result = ds3231.set_square_wave_frequency(SquareWaveFreq::Hz1);
201        assert!(result.is_ok());
202
203        i2c_mock.done();
204    }
205
206    #[test]
207    fn test_set_square_wave_frequency_1024hz() {
208        let expectations = vec![
209            I2cTransaction::write_read(
210                DS3231_ADDR,
211                vec![Register::Control.addr()],
212                vec![0b0000_0000],
213            ),
214            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0000_1000]),
215        ];
216
217        let mut i2c_mock = I2cMock::new(&expectations);
218        let mut ds3231 = Ds3231::new(&mut i2c_mock);
219
220        let result = ds3231.set_square_wave_frequency(SquareWaveFreq::Hz1024);
221        assert!(result.is_ok());
222
223        i2c_mock.done();
224    }
225
226    #[test]
227    fn test_set_square_wave_frequency_4096hz() {
228        let expectations = vec![
229            I2cTransaction::write_read(
230                DS3231_ADDR,
231                vec![Register::Control.addr()],
232                vec![0b0000_1000],
233            ),
234            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0001_0000]),
235        ];
236
237        let mut i2c_mock = I2cMock::new(&expectations);
238        let mut ds3231 = Ds3231::new(&mut i2c_mock);
239
240        let result = ds3231.set_square_wave_frequency(SquareWaveFreq::Hz4096);
241        assert!(result.is_ok());
242
243        i2c_mock.done();
244    }
245
246    #[test]
247    fn test_set_square_wave_frequency_8192hz() {
248        let expectations = vec![
249            I2cTransaction::write_read(
250                DS3231_ADDR,
251                vec![Register::Control.addr()],
252                vec![0b0000_0000],
253            ),
254            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0001_1000]),
255        ];
256
257        let mut i2c_mock = I2cMock::new(&expectations);
258        let mut ds3231 = Ds3231::new(&mut i2c_mock);
259
260        let result = ds3231.set_square_wave_frequency(SquareWaveFreq::Hz8192);
261        assert!(result.is_ok());
262
263        i2c_mock.done();
264    }
265
266    #[test]
267    fn test_set_square_wave_frequency_no_change_needed() {
268        let expectations = vec![I2cTransaction::write_read(
269            DS3231_ADDR,
270            vec![Register::Control.addr()],
271            vec![0b0001_0000], // The rs bits are for 4.096kHz
272        )];
273
274        let mut i2c_mock = I2cMock::new(&expectations);
275        let mut ds3231 = Ds3231::new(&mut i2c_mock);
276
277        let result = ds3231.set_square_wave_frequency(SquareWaveFreq::Hz4096);
278        assert!(result.is_ok());
279
280        i2c_mock.done();
281    }
282
283    #[test]
284    fn test_set_square_wave_frequency_preserves_other_bits() {
285        let expectations = vec![
286            I2cTransaction::write_read(
287                DS3231_ADDR,
288                vec![Register::Control.addr()],
289                vec![0b1100_0100],
290            ),
291            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b1100_1100]),
292        ];
293
294        let mut i2c_mock = I2cMock::new(&expectations);
295        let mut ds3231 = Ds3231::new(&mut i2c_mock);
296
297        let result = ds3231.set_square_wave_frequency(SquareWaveFreq::Hz1024);
298        assert!(result.is_ok());
299
300        i2c_mock.done();
301    }
302
303    #[test]
304    fn test_set_square_wave_frequency_unsupported() {
305        let expectations = vec![];
306
307        let mut i2c_mock = I2cMock::new(&expectations);
308        let mut ds3231 = Ds3231::new(&mut i2c_mock);
309
310        let result = ds3231.set_square_wave_frequency(SquareWaveFreq::Hz32768);
311        assert!(matches!(result, Err(Error::UnsupportedSqwFrequency)));
312
313        i2c_mock.done();
314    }
315
316    #[test]
317    fn test_start_square_wave_1hz() {
318        let expectations = vec![
319            I2cTransaction::write_read(
320                DS3231_ADDR,
321                vec![Register::Control.addr()],
322                vec![0b0001_1100],
323            ),
324            // Sets the bit 2 to 0
325            // Set RS1 & RS2 bit value to 0 for 1 Hz
326            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0000_0000]),
327        ];
328
329        let mut i2c_mock = I2cMock::new(&expectations);
330        let mut ds3231 = Ds3231::new(&mut i2c_mock);
331
332        let result = ds3231.start_square_wave(SquareWaveFreq::Hz1);
333        assert!(result.is_ok());
334
335        i2c_mock.done();
336    }
337
338    #[test]
339    fn test_start_square_wave_1024hz() {
340        let expectations = vec![
341            I2cTransaction::write_read(
342                DS3231_ADDR,
343                vec![Register::Control.addr()],
344                vec![0b1000_0100],
345            ),
346            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b1000_1000]),
347        ];
348
349        let mut i2c_mock = I2cMock::new(&expectations);
350        let mut ds3231 = Ds3231::new(&mut i2c_mock);
351
352        let result = ds3231.start_square_wave(SquareWaveFreq::Hz1024);
353        assert!(result.is_ok());
354
355        i2c_mock.done();
356    }
357
358    #[test]
359    fn test_start_square_wave_4096hz() {
360        let expectations = vec![
361            I2cTransaction::write_read(
362                DS3231_ADDR,
363                vec![Register::Control.addr()],
364                vec![0b0100_1100],
365            ),
366            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0101_0000]),
367        ];
368
369        let mut i2c_mock = I2cMock::new(&expectations);
370        let mut ds3231 = Ds3231::new(&mut i2c_mock);
371
372        let result = ds3231.start_square_wave(SquareWaveFreq::Hz4096);
373        assert!(result.is_ok());
374
375        i2c_mock.done();
376    }
377
378    #[test]
379    fn test_start_square_wave_8192hz() {
380        let expectations = vec![
381            I2cTransaction::write_read(
382                DS3231_ADDR,
383                vec![Register::Control.addr()],
384                vec![0b0000_0100],
385            ),
386            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0001_1000]),
387        ];
388
389        let mut i2c_mock = I2cMock::new(&expectations);
390        let mut ds3231 = Ds3231::new(&mut i2c_mock);
391
392        let result = ds3231.start_square_wave(SquareWaveFreq::Hz8192);
393        assert!(result.is_ok());
394
395        i2c_mock.done();
396    }
397
398    #[test]
399    fn test_start_square_wave_already_configured() {
400        let expectations = vec![I2cTransaction::write_read(
401            DS3231_ADDR,
402            vec![Register::Control.addr()],
403            vec![0b0000_1000],
404        )];
405
406        let mut i2c_mock = I2cMock::new(&expectations);
407        let mut ds3231 = Ds3231::new(&mut i2c_mock);
408
409        let result = ds3231.start_square_wave(SquareWaveFreq::Hz1024);
410        assert!(result.is_ok());
411
412        i2c_mock.done();
413    }
414
415    #[test]
416    fn test_start_square_wave_preserves_other_bits() {
417        let expectations = vec![
418            I2cTransaction::write_read(
419                DS3231_ADDR,
420                vec![Register::Control.addr()],
421                vec![0b1010_0100],
422            ),
423            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b1010_0000]),
424        ];
425
426        let mut i2c_mock = I2cMock::new(&expectations);
427        let mut ds3231 = Ds3231::new(&mut i2c_mock);
428
429        let result = ds3231.start_square_wave(SquareWaveFreq::Hz1);
430        assert!(result.is_ok());
431
432        i2c_mock.done();
433    }
434
435    #[test]
436    fn test_start_square_wave_unsupported_frequency() {
437        let expectations = vec![];
438
439        let mut i2c_mock = I2cMock::new(&expectations);
440        let mut ds3231 = Ds3231::new(&mut i2c_mock);
441
442        let result = ds3231.start_square_wave(SquareWaveFreq::Hz32768);
443        assert!(matches!(result, Err(Error::UnsupportedSqwFrequency)));
444
445        i2c_mock.done();
446    }
447
448    #[test]
449    fn test_i2c_read_error_handling() {
450        let expectations = vec![
451            I2cTransaction::write_read(DS3231_ADDR, vec![Register::Control.addr()], vec![0x00])
452                .with_error(embedded_hal::i2c::ErrorKind::Other),
453        ];
454
455        let mut i2c_mock = I2cMock::new(&expectations);
456        let mut ds3231 = Ds3231::new(&mut i2c_mock);
457
458        let result = ds3231.enable_square_wave();
459        assert!(result.is_err());
460
461        i2c_mock.done();
462    }
463
464    #[test]
465    fn test_i2c_write_error_handling() {
466        let expectations = vec![
467            I2cTransaction::write_read(
468                DS3231_ADDR,
469                vec![Register::Control.addr()],
470                vec![0b0000_0100],
471            ),
472            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b0000_0000])
473                .with_error(embedded_hal::i2c::ErrorKind::Other),
474        ];
475
476        let mut i2c_mock = I2cMock::new(&expectations);
477        let mut ds3231 = Ds3231::new(&mut i2c_mock);
478
479        let result = ds3231.enable_square_wave();
480        assert!(result.is_err());
481
482        i2c_mock.done();
483    }
484
485    #[test]
486    fn test_rs_mask_coverage() {
487        let expectations = vec![
488            I2cTransaction::write_read(
489                DS3231_ADDR,
490                vec![Register::Control.addr()],
491                vec![0b1111_1111],
492            ),
493            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b1110_1111]),
494        ];
495
496        let mut i2c_mock = I2cMock::new(&expectations);
497        let mut ds3231 = Ds3231::new(&mut i2c_mock);
498
499        let result = ds3231.set_square_wave_frequency(SquareWaveFreq::Hz1024);
500        assert!(result.is_ok());
501
502        i2c_mock.done();
503    }
504
505    #[test]
506    fn test_intcn_bit_manipulation() {
507        let expectations = vec![
508            I2cTransaction::write_read(
509                DS3231_ADDR,
510                vec![Register::Control.addr()],
511                vec![0b1111_1111],
512            ),
513            I2cTransaction::write(DS3231_ADDR, vec![Register::Control.addr(), 0b1111_1011]),
514        ];
515
516        let mut i2c_mock = I2cMock::new(&expectations);
517        let mut ds3231 = Ds3231::new(&mut i2c_mock);
518
519        let result = ds3231.enable_square_wave();
520        assert!(result.is_ok());
521
522        i2c_mock.done();
523    }
524}