ds1302_drv/
lib.rs

1//! DS1302 real time clock-calendar platform agnostic driver
2//!
3//! # About
4//!
5//!The DS1302 trickle-charge timekeeping chip contains a real-time clock/calendar and 31 bytes of static RAM. It
6//!communicates with a microprocessor via a simple serial interface. The real-time clock/calendar provides seconds,
7//!minutes, hours, day, date, month, and year information. The end of the month date is automatically adjusted for
8//!months with fewer than 31 days, including corrections for leap year. The clock operates in either the 24-hour or
9//!12-hour format with an AM/PM indicator. The chip driver is based on [`embedded-hal`] traits.
10//!
11//! [`embedded-hal`]: https://github.com/rust-embedded/embedded-hal
12//!
13//!Datasheet: [DS1302](https://datasheets.maximintegrated.com/en/ds/DS1302.pdf)
14//!
15//! ## Driver features:
16//! - Reading/setting clock/calendar data
17//! - 12-hour (AM/PM) or 24-hour format
18//! - Changing the time format while the chip is working
19//!
20//!
21//! NEW (4.0.0 release):
22//! - Programmable Trickle Charger configuration
23//! - 31 x 8 Battery-Backed General-Purpose RAM operations
24//!
25
26#![no_std]
27#![allow(non_camel_case_types)]
28
29#[cfg(all(feature = "rp2040", feature = "rp2350"))]
30compile_error!("You must not enable both the `rp2040` and `rp2350` Cargo features.");
31#[cfg(not(any(feature = "rp2040", feature = "rp2350")))]
32compile_error!("You must enable either the `rp2040` or the `rp2350` Cargo features.");
33
34use core::convert::From;
35
36mod registers;
37use crate::registers::{Ds, RegisterRead, RegisterWrite, Rs, TrickleCharger};
38
39//use embedded_hal::digital::v2::{InputPin, OutputPin};
40use embedded_hal::digital::{InputPin, OutputPin};
41
42use fugit::ExtU32;
43
44#[cfg(feature = "rp2350")]
45use rp235x_hal as hal;
46
47#[cfg(feature = "rp2040")]
48use rp2040_hal as hal;
49
50use hal::gpio::{
51    FunctionSio, FunctionSioOutput, Pin, PinId, PullDown, SioInput, SioOutput, ValidFunction,
52};
53#[cfg(feature = "rp2350")]
54use hal::timer::TimerDevice;
55
56use hal::Timer;
57
58/// CmdFlag definitions
59pub enum CmdFlag {
60    CLOCK_HALT,
61    DISABLE_WRITE_PROTECT,
62    WRITE_PROTECT,
63    HOUR_12_BIT,
64    HOUR_PM_BIT,
65}
66
67impl CmdFlag {
68    pub fn addr(self) -> u8 {
69        match self {
70            Self::DISABLE_WRITE_PROTECT => 0x0 as u8,
71            Self::HOUR_PM_BIT => 0x20 as u8,
72            Self::CLOCK_HALT => 0x80 as u8,
73            Self::WRITE_PROTECT => 0x80 as u8,
74            Self::HOUR_12_BIT => 0x80 as u8,
75        }
76    }
77}
78
79/// DS1302 error
80#[derive(Debug)]
81pub enum Ds1302Error {
82    Parameter,
83    Unknown,
84    ClockError,
85    ReadError,
86    ChipSelectError,
87}
88
89/// For timing `ds1302` uses [fugit](https://lib.rs/crates/fugit) crate which only provides `Duration` and `Instant` types.
90/// It does not provide any clock or timer traits.
91/// Therefore `ds1302` has its own `Delay` trait that provides all timing capabilities that are needed for the library.
92/// User must implement this trait for the timer by itself.
93pub trait Delay<const TIMER_HZ: u32> {
94    /// An error that might happen during waiting
95    type Error;
96
97    /// Return current time `Instant`
98    fn now(&mut self) -> fugit::TimerInstantU32<TIMER_HZ>;
99
100    /// Start countdown with a `duration`
101    fn start(&mut self, duration: fugit::TimerDurationU32<TIMER_HZ>) -> Result<(), Self::Error>;
102
103    /// Wait until countdown `duration` has expired.
104    /// Must return `nb::Error::WouldBlock` if countdown `duration` is not yet over.
105    /// Must return `OK(())` as soon as countdown `duration` has expired.
106    fn wait(&mut self) -> nb::Result<(), Self::Error>;
107}
108
109#[cfg(feature = "rp2040")]
110pub struct DSClock<const TIMER_HZ: u32> {
111    _timer: Timer,
112}
113
114#[cfg(feature = "rp2040")]
115impl<const TIMER_HZ: u32> DSClock<TIMER_HZ> {
116    pub fn new(timer: Timer) -> Self {
117        Self { _timer: timer }
118    }
119}
120
121#[cfg(feature = "rp2040")]
122impl<const TIMER_HZ: u32> Delay<TIMER_HZ> for DSClock<TIMER_HZ> {
123    type Error = core::convert::Infallible;
124
125    fn now(&mut self) -> fugit::TimerInstantU32<TIMER_HZ> {
126        fugit::TimerInstantU32::from_ticks(0)
127    }
128
129    fn start(&mut self, _duration: fugit::TimerDurationU32<TIMER_HZ>) -> Result<(), Self::Error> {
130        Ok(())
131    }
132
133    fn wait(&mut self) -> nb::Result<(), Self::Error> {
134        Ok(())
135    }
136}
137
138#[cfg(feature = "rp2350")]
139pub struct DSClock<TIM: TimerDevice, const TIMER_HZ: u32> {
140    _timer: Timer<TIM>,
141}
142
143#[cfg(feature = "rp2350")]
144impl<TIM: TimerDevice, const TIMER_HZ: u32> DSClock<TIM, TIMER_HZ> {
145    pub fn new(timer: Timer<TIM>) -> Self {
146        Self { _timer: timer }
147    }
148}
149
150#[cfg(feature = "rp2350")]
151impl<TIM: TimerDevice, const TIMER_HZ: u32> Delay<TIMER_HZ> for DSClock<TIM, TIMER_HZ> {
152    type Error = core::convert::Infallible;
153
154    fn now(&mut self) -> fugit::TimerInstantU32<TIMER_HZ> {
155        fugit::TimerInstantU32::from_ticks(0)
156    }
157
158    fn start(&mut self, _duration: fugit::TimerDurationU32<TIMER_HZ>) -> Result<(), Self::Error> {
159        Ok(())
160    }
161
162    fn wait(&mut self) -> nb::Result<(), Self::Error> {
163        Ok(())
164    }
165}
166
167///Hour format: 12-hour (AM/PM) or 24-hour
168#[derive(PartialEq, Copy, Clone)]
169pub enum Mode {
170    Hour24,
171    Hour12,
172}
173///Hour information: 12-hour (AM/PM) or 24-hour
174#[derive(Debug, Copy, Clone)]
175pub enum Hours {
176    Hour24(u8),
177    Hour12am(u8),
178    Hour12pm(u8),
179}
180
181impl Hours {
182    fn convert(&self) -> Self {
183        match *self {
184            Hours::Hour24(h) => {
185                if h >= 12 {
186                    Hours::Hour12pm(h - 12)
187                } else {
188                    Hours::Hour12am(h)
189                }
190            }
191            Hours::Hour12pm(h) => Hours::Hour24(h + 12),
192            Hours::Hour12am(h) => Hours::Hour24(h),
193        }
194    }
195
196    /// Get the hour.
197    /// return.1: None => Hour24 mode; Some(false) => pm; Some(true) => am;
198    pub fn hour(&self) -> (u8, Option<bool>) {
199        match *self {
200            Hours::Hour24(h) => (h, None),
201            Hours::Hour12am(h) => (h, Some(false)),
202            Hours::Hour12pm(h) => (h, Some(true)),
203        }
204    }
205}
206
207impl From<u8> for Hours {
208    fn from(byte: u8) -> Self {
209        if (byte & CmdFlag::HOUR_12_BIT.addr()) != 0 {
210            //In case 12-hour format
211            let hour = bcd_to_decimal(
212                byte & (!(CmdFlag::HOUR_12_BIT.addr() | CmdFlag::HOUR_PM_BIT.addr())),
213            );
214            if (byte & CmdFlag::HOUR_PM_BIT.addr()) != 0 {
215                // It's PM
216                Hours::Hour12pm(hour)
217            } else {
218                // It's AM
219                Hours::Hour12am(hour)
220            }
221        } else {
222            let hour = bcd_to_decimal(byte);
223            Hours::Hour24(hour)
224        }
225    }
226}
227
228impl From<Hours> for u8 {
229    fn from(h: Hours) -> Self {
230        match h {
231            Hours::Hour24(hour) => decimal_to_bcd(hour),
232            Hours::Hour12am(hour) => decimal_to_bcd(hour) | CmdFlag::HOUR_12_BIT.addr(),
233            Hours::Hour12pm(hour) => {
234                decimal_to_bcd(hour) | CmdFlag::HOUR_12_BIT.addr() | CmdFlag::HOUR_PM_BIT.addr()
235            }
236        }
237    }
238}
239
240///Clock information
241#[derive(Debug, Copy, Clone)]
242pub struct Clock {
243    pub hours: Hours,
244    pub minutes: u8,
245    pub seconds: u8,
246}
247///Calendar information
248
249#[derive(Debug, Copy, Clone)]
250pub struct Calendar {
251    pub day: u8,
252    pub date: u8,
253    pub month: u8,
254    pub year: u16,
255}
256
257// Swap format from bcd to decmial
258pub(crate) fn bcd_to_decimal(bcd: u8) -> u8 {
259    ((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F)
260}
261
262// Swap format from decimal to bcd
263pub(crate) fn decimal_to_bcd(decimal: u8) -> u8 {
264    ((decimal / 10) << 4) + (decimal % 10)
265}
266
267///Input. CE signal must be asserted high during a read or a write
268///Note: Previous data sheet revisions referred to CE as RST
269pub struct DS1302<I1, I2, I3, D, const TIMER_HZ: u32>
270where
271    I1: PinId + ValidFunction<FunctionSio<SioInput>> + ValidFunction<FunctionSio<SioOutput>>,
272    I2: PinId + ValidFunction<FunctionSio<SioOutput>>,
273    I3: PinId + ValidFunction<FunctionSio<SioOutput>>,
274{
275    pub io: Option<Pin<I1, FunctionSioOutput, PullDown>>,
276    pub ce: Pin<I2, FunctionSioOutput, PullDown>,
277    pub sclk: Pin<I3, FunctionSioOutput, PullDown>,
278    pub delay: D,
279}
280
281impl<I1, I2, I3, D, const TIMER_HZ: u32> DS1302<I1, I2, I3, D, TIMER_HZ>
282where
283    I1: PinId + ValidFunction<FunctionSio<SioInput>> + ValidFunction<FunctionSio<SioOutput>>,
284    I2: PinId + ValidFunction<FunctionSio<SioOutput>>,
285    I3: PinId + ValidFunction<FunctionSio<SioOutput>>,
286    D: Delay<TIMER_HZ>,
287{
288    pub fn new(
289        ce: Pin<I2, FunctionSioOutput, PullDown>,
290        io: Pin<I1, FunctionSioOutput, PullDown>,
291        sclk: Pin<I3, FunctionSioOutput, PullDown>,
292        mode: Mode,
293        delay: D,
294    ) -> Result<Self, Ds1302Error> {
295        let mut ds1302 = DS1302 {
296            io: Some(io),
297            ce,
298            sclk,
299            delay,
300        };
301        // Check CLOCK HALT FLAG bit
302        let byte = ds1302.read_reg(RegisterRead::SECONDS.addr())?;
303        // Reset CLOCK HALT FLAG bit, power on device
304        if (byte & CmdFlag::CLOCK_HALT.addr()) != 0 {
305            ds1302.write_reg(RegisterWrite::SECONDS.addr(), 0)?;
306            let byte = ds1302.read_reg(RegisterRead::SECONDS.addr())?;
307            if (byte & CmdFlag::CLOCK_HALT.addr()) != 0 {
308                Err(Ds1302Error::Unknown)
309            } else {
310                ds1302.set_clock_mode(mode)?;
311                Ok(ds1302)
312            }
313        } else {
314            ds1302.set_clock_mode(mode)?;
315            Ok(ds1302)
316        }
317    }
318
319    pub fn set_running(&mut self, is_running: bool) -> Result<(), Ds1302Error> {
320        let mut seconds = self.read_reg(RegisterRead::SECONDS.addr())?;
321        if is_running {
322            seconds &= 0b0111_1111;
323        } else {
324            seconds |= 0b1000_0000;
325        }
326        self.write_reg(RegisterWrite::SECONDS.addr(), seconds)?;
327        Ok(())
328    }
329
330    fn read_reg(&mut self, reg: u8) -> Result<u8, Ds1302Error> {
331        self.sclk.set_low().map_err(|_| Ds1302Error::ClockError)?;
332        self.ce
333            .set_high()
334            .map_err(|_| Ds1302Error::ChipSelectError)?;
335        self.delay.start(4.micros()).ok(); // tCC = 4us for 2V
336        self.write_byte(reg)?;
337        let data = self.read_byte()?;
338        self.delay.start(300.nanos()).ok(); // tCCH = 240ns for 2V
339        self.ce
340            .set_low()
341            .map_err(|_| Ds1302Error::ChipSelectError)?;
342        self.delay.start(4.micros()).ok(); // tCC = 4us for 2V
343                                           // println!("read:  addr: {:02X}({:08b} <=> {:08b}), data: {:02X}({:08b})", addr, addr, command_byte, data, data);
344        Ok(data)
345    }
346
347    fn read_byte(&mut self) -> Result<u8, Ds1302Error> {
348        let mut data = 0;
349        self.sclk.set_low().map_err(|_| Ds1302Error::ClockError)?;
350        let mut pin = self.io.take().unwrap().into_pull_up_input();
351        for i in 0..8 {
352            let bit = self.read_bit(&mut pin)?;
353            data |= match bit {
354                true => 1,
355                false => 0,
356            } << i;
357        }
358
359        let io: Pin<_, FunctionSioOutput, PullDown> = pin.reconfigure(); //RecConfigure the PinState
360        self.io = Some(io);
361        Ok(data)
362    }
363
364    fn read_bit(&mut self, pin: &mut impl InputPin) -> Result<bool, Ds1302Error> {
365        self.delay.start(300.nanos()).ok(); // tCCZ = 280ns for 2V
366        self.sclk.set_high().map_err(|_| Ds1302Error::ClockError)?;
367        let bit = pin.is_high().map_err(|_| Ds1302Error::ReadError)?;
368        self.delay.start(2000.nanos()).ok(); // tCH = 1000ns for 2V
369        self.sclk.set_low().map_err(|_| Ds1302Error::ClockError)?;
370        self.delay.start(1700.nanos()).ok(); // tCL = 1000ns for 2V
371        Ok(bit)
372    }
373
374    fn write_byte(&mut self, byte: u8) -> Result<(), Ds1302Error> {
375        self.sclk.set_low().map_err(|_| Ds1302Error::ClockError)?;
376        let mut pin = self.io.take().unwrap();
377        for i in 0..8 {
378            self.write_bit(&mut pin, ((byte >> i) & 1) == 1)?;
379        }
380        self.io = Some(pin);
381        Ok(())
382    }
383
384    fn write_bit(&mut self, pin: &mut impl OutputPin, bit: bool) -> Result<(), Ds1302Error> {
385        let _ = pin.set_state(bit.into());
386        self.delay.start(350.nanos()).ok(); // tDC = 200ns for 2V
387        self.sclk.set_high().map_err(|_| Ds1302Error::ClockError)?;
388        self.delay.start(2000.nanos()).ok(); // tCH = 1000ns for 2V
389        self.sclk.set_low().map_err(|_| Ds1302Error::ClockError)?;
390        self.delay.start(1700.nanos()).ok(); // tCL = 1000ns for 2V
391        Ok(())
392    }
393
394    fn write_reg(&mut self, reg: u8, byte: u8) -> Result<(), Ds1302Error> {
395        //Firstly Check WRITE_PROTECT_BIT
396        let wp_read = self.read_reg(RegisterRead::WP.addr())?;
397        if (wp_read & CmdFlag::WRITE_PROTECT.addr()) != 0 {
398            //let bytes = [RegisterWrite::WP.addr(), 0];
399            self.sclk.set_low().map_err(|_| Ds1302Error::ClockError)?;
400            self.ce
401                .set_high()
402                .map_err(|_| Ds1302Error::ChipSelectError)?;
403            self.delay.start(4.micros()).ok(); // tCC = 4us for 2V
404            self.write_byte(RegisterWrite::WP.addr())?;
405            self.write_byte(0x0)?; // Disable Write_Protect
406            self.delay.start(300.nanos()).ok(); //tCCH = 240ns for 2V
407            self.ce.set_low().ok();
408            self.delay.start(4.micros()).ok();
409        }
410        //Then write current data to registers
411        //nb::block!(self.delay.wait()).ok(); // wait CE inactive time min 4us
412        self.sclk.set_low().map_err(|_| Ds1302Error::ClockError)?;
413        self.ce
414            .set_high()
415            .map_err(|_| Ds1302Error::ChipSelectError)?;
416        self.delay.start(4.micros()).ok(); // tCC = 4us for 2V
417        self.write_byte(reg)?;
418        self.write_byte(byte)?;
419        self.delay.start(300.nanos()).ok(); //tCCH = 240ns for 2V
420        self.ce.set_low().ok();
421        self.delay.start(4.micros()).ok();
422        Ok(())
423    }
424
425    /// write_protect(true: bool) -> Enable Write_Protect
426    /// write_protect(false: bool) -> Disable Write_Protect
427    pub fn write_protect(&mut self, enable: bool) -> Result<(), Ds1302Error> {
428        //Firstly Check WRITE_PROTECT_BIT
429        let wp_read = self.read_reg(RegisterRead::WP.addr())?;
430        // wp_state == 0 -> disable_write_protect
431        // wp_state != 0 (== 0x80) -> enable_write_protect
432        let wp_state = wp_read & CmdFlag::WRITE_PROTECT.addr();
433
434        if enable {
435            if wp_state == 0 {
436                self.sclk.set_low().map_err(|_| Ds1302Error::ClockError)?;
437                self.ce
438                    .set_high()
439                    .map_err(|_| Ds1302Error::ChipSelectError)?;
440                self.delay.start(4.micros()).ok(); // tCC = 4us for 2V
441                self.write_byte(RegisterWrite::WP.addr())?;
442                self.write_byte(CmdFlag::WRITE_PROTECT.addr())?; // Enable Write_Protect
443                self.delay.start(300.nanos()).ok(); //tCCH = 240ns for 2V
444                self.ce.set_low().ok();
445                self.delay.start(4.micros()).ok();
446            }
447        } else {
448            if wp_state != 0 {
449                self.sclk.set_low().map_err(|_| Ds1302Error::ClockError)?;
450                self.ce
451                    .set_high()
452                    .map_err(|_| Ds1302Error::ChipSelectError)?;
453                self.delay.start(4.micros()).ok(); // tCC = 4us for 2V
454                self.write_byte(RegisterWrite::WP.addr())?;
455                self.write_byte(CmdFlag::DISABLE_WRITE_PROTECT.addr())?; // Disable Write_Protect
456                self.delay.start(300.nanos()).ok(); //tCCH = 240ns for 2V
457                self.ce.set_low().ok();
458                self.delay.start(4.micros()).ok();
459            }
460        }
461
462        Ok(())
463    }
464
465    ///Return current information about seconds
466    pub fn get_seconds(&mut self) -> Result<u8, Ds1302Error> {
467        self.read_reg(RegisterRead::SECONDS.addr())
468            .map(|b| bcd_to_decimal(b))
469    }
470    ///Return current information about minutes
471    pub fn get_minutes(&mut self) -> Result<u8, Ds1302Error> {
472        self.read_reg(RegisterRead::MINUTES.addr())
473            .map(|b| bcd_to_decimal(b))
474    }
475    ///Return current information about hours
476    pub fn get_hours(&mut self) -> Result<Hours, Ds1302Error> {
477        self.read_reg(RegisterRead::HOURS.addr()).map(|b| b.into())
478    }
479    ///Return current information about date
480    pub fn get_date(&mut self) -> Result<u8, Ds1302Error> {
481        self.read_reg(RegisterRead::DATE.addr())
482            .map(|b| bcd_to_decimal(b))
483    }
484    ///Return current information about month
485    pub fn get_month(&mut self) -> Result<u8, Ds1302Error> {
486        self.read_reg(RegisterRead::MONTH.addr())
487            .map(|b| bcd_to_decimal(b))
488    }
489    ///Return current information about year
490    pub fn get_year(&mut self) -> Result<u16, Ds1302Error> {
491        self.read_reg(RegisterRead::YEAR.addr())
492            .map(|b| 2000_u16 + (bcd_to_decimal(b) as u16))
493    }
494    ///Return current information about day of the week
495    pub fn get_day(&mut self) -> Result<u8, Ds1302Error> {
496        self.read_reg(RegisterRead::DAY.addr())
497            .map(|b| bcd_to_decimal(b))
498    }
499
500    ///Return current information about hours, minutes and seconds
501    pub fn get_clock(&mut self) -> Result<Clock, Ds1302Error> {
502        let mut status_response: [u8; 3] = [0; 3];
503        self.sclk.set_low().ok();
504        //nb::block!(self.delay.wait()).ok(); // wait CE inactive time min 4us
505        self.ce.set_high().ok();
506        self.delay.start(4.micros()).ok();
507        self.write_byte(RegisterRead::CLKBURS.addr())?;
508
509        for idx in 0..3 {
510            status_response[idx] = self.read_byte()?;
511        }
512
513        self.sclk.set_high().ok();
514        self.ce.set_low().ok();
515        self.delay.start(4.micros()).ok();
516
517        let clock = Clock {
518            seconds: bcd_to_decimal(status_response[0]),
519            minutes: bcd_to_decimal(status_response[1]),
520            hours: status_response[2].into(),
521        };
522
523        Ok(clock)
524    }
525
526    ///Return current information about date, day of the week, month and year
527    pub fn get_calendar(&mut self) -> Result<Calendar, Ds1302Error> {
528        let mut status_response: [u8; 7] = [0; 7];
529        self.sclk.set_low().ok();
530        self.ce.set_high().ok();
531        self.delay.start(4.micros()).ok(); // wait CE inactive time min 4us
532        self.write_byte(RegisterRead::CLKBURS.addr())?;
533
534        for idx in 0..7 {
535            status_response[idx] = self.read_byte()?;
536        }
537
538        self.delay.start(300.nanos()).ok(); //tCCH = 240ns for 2V
539        self.ce.set_low().ok();
540        self.delay.start(4.micros()).ok();
541
542        let calendar = Calendar {
543            date: bcd_to_decimal(status_response[3]),
544            month: bcd_to_decimal(status_response[4]),
545            day: bcd_to_decimal(status_response[5]),
546            year: (2000_u16 + (bcd_to_decimal(status_response[6]) as u16)),
547        };
548
549        Ok(calendar)
550    }
551
552    ///Return current information date and time
553    pub fn get_clock_calendar(&mut self) -> Result<(Clock, Calendar), Ds1302Error> {
554        let mut status_response: [u8; 7] = [0; 7];
555        self.sclk.set_low().ok();
556        self.ce.set_high().ok();
557        self.delay.start(4.micros()).ok(); // wait CE inactive time min 4us
558
559        self.write_byte(RegisterRead::CLKBURS.addr())?;
560
561        for idx in 0..7 {
562            status_response[idx] = self.read_byte()?;
563        }
564
565        self.delay.start(300.nanos()).ok(); //tCCH = 240ns for 2V
566        self.ce.set_low().ok();
567        self.delay.start(4.micros()).ok(); // tCWH = 4us for 2V
568
569        let clock = Clock {
570            seconds: bcd_to_decimal(status_response[0]),
571            minutes: bcd_to_decimal(status_response[1]),
572            hours: status_response[2].into(),
573        };
574
575        let calendar = Calendar {
576            date: bcd_to_decimal(status_response[3]),
577            month: bcd_to_decimal(status_response[4]),
578            day: bcd_to_decimal(status_response[5]),
579            year: (2000_u16 + (bcd_to_decimal(status_response[6]) as u16)),
580        };
581
582        Ok((clock, calendar))
583    }
584
585    ///Set seconds to defined value
586    pub fn set_seconds(&mut self, seconds: u8) -> Result<(), Ds1302Error> {
587        self.write_reg(RegisterWrite::SECONDS.addr(), decimal_to_bcd(seconds))
588    }
589    ///Set minutes to defined value
590    pub fn set_minutes(&mut self, minutes: u8) -> Result<(), Ds1302Error> {
591        self.write_reg(RegisterWrite::MINUTES.addr(), decimal_to_bcd(minutes))
592    }
593    ///Set hours to defined value
594    pub fn set_hours(&mut self, hours: Hours) -> Result<(), Ds1302Error> {
595        self.write_reg(RegisterWrite::HOURS.addr(), hours.into())
596    }
597    ///Set date to defined value
598    pub fn set_date(&mut self, date: u8) -> Result<(), Ds1302Error> {
599        self.write_reg(RegisterWrite::DATE.addr(), decimal_to_bcd(date))
600    }
601    ///Set month to defined value
602    pub fn set_month(&mut self, month: u8) -> Result<(), Ds1302Error> {
603        self.write_reg(RegisterWrite::MONTH.addr(), decimal_to_bcd(month))
604    }
605    ///Set day of the week to defined value
606    pub fn set_day(&mut self, day: u8) -> Result<(), Ds1302Error> {
607        self.write_reg(RegisterWrite::DAY.addr(), decimal_to_bcd(day))
608    }
609    ///Set year to defined value
610    pub fn set_year(&mut self, year: u16) -> Result<(), Ds1302Error> {
611        let y = if year < 2000 { 0 } else { year - 2000 };
612        self.write_reg(RegisterWrite::YEAR.addr(), decimal_to_bcd(y as u8))
613    }
614    ///Set clock to defined values
615    pub fn set_clock(&mut self, clock: Clock) -> Result<(), Ds1302Error> {
616        //Not burst mode, because it changes the calendar registers
617        self.set_hours(clock.hours)?;
618        self.set_minutes(clock.minutes)?;
619        self.set_seconds(clock.seconds)
620    }
621
622    ///Set calendar to defined values
623    pub fn set_calendar(&mut self, calendar: Calendar) -> Result<(), Ds1302Error> {
624        //Not burst mode, because it changes the clock registers
625        self.set_year(calendar.year)?;
626        self.set_month(calendar.month)?;
627        self.set_date(calendar.date)?;
628        self.set_day(calendar.day)
629    }
630    ///Set clock and calendar to defined values
631    pub fn set_clock_calendar(
632        &mut self,
633        clock: Clock,
634        calendar: Calendar,
635    ) -> Result<(), Ds1302Error> {
636        //Writing in burst mode, it changes all the clock and calendar registers
637        let mut bytes = [0_u8; 9];
638        bytes[0] = RegisterWrite::CLKBURS.addr();
639        bytes[1] = decimal_to_bcd(clock.seconds);
640        bytes[2] = decimal_to_bcd(clock.minutes);
641        bytes[3] = clock.hours.into();
642        bytes[4] = decimal_to_bcd(calendar.date);
643        bytes[5] = decimal_to_bcd(calendar.month);
644        bytes[6] = decimal_to_bcd(calendar.day);
645        let y = if calendar.year < 2000 {
646            0
647        } else {
648            calendar.year - 2000
649        };
650        bytes[7] = decimal_to_bcd(y as u8);
651
652        self.sclk.set_low().ok();
653        //nb::block!(self.delay.wait()).ok(); // wait CE inactive time min 4us
654        self.ce.set_high().ok();
655        self.delay.start(4.micros()).ok();
656        self.write_byte(RegisterWrite::CLKBURS.addr())?;
657
658        for idx in 1..=7 {
659            self.write_byte(bytes[idx])?;
660        }
661
662        // self.sclk.set_high().ok();
663        self.delay.start(300.nanos()).ok(); //tCCH = 240ns for 2V
664        self.ce.set_low().ok();
665        self.delay.start(4.micros()).ok();
666        Ok(())
667    }
668
669    ///Switch between 12-hour (AM/PM) and 24-hour mode
670    pub fn set_clock_mode(&mut self, mode: Mode) -> Result<(), Ds1302Error> {
671        let hr = self.get_hours()?; // save current hours data
672        match hr {
673            Hours::Hour24(_h) => {
674                if mode == Mode::Hour12 {
675                    self.set_hours(hr.convert())
676                } else {
677                    Ok(())
678                }
679            }
680            _ => {
681                if mode == Mode::Hour24 {
682                    self.set_hours(hr.convert())
683                } else {
684                    Ok(())
685                }
686            }
687        }
688    }
689
690    /// Enable trickle-charge.
691    /// Ds (diode drop voltage 0.7 or 1.4)
692    /// Rs (2k or 4k or 8k)
693    /// The maximum current = (Vcc - Ds) / Rs.
694    pub fn tc_enable(&mut self, ds: Ds, rs: Rs) -> Result<(), Ds1302Error> {
695        self.write_reg(RegisterWrite::TCS.addr(), TrickleCharger::enable(ds, rs))
696    }
697
698    /// Disable trickle-charge.
699    pub fn tc_disable(&mut self) -> Result<(), Ds1302Error> {
700        self.write_reg(RegisterWrite::TCS.addr(), TrickleCharger::disable())
701    }
702
703    /// Get the configuration of the trickle-charge register.
704    pub fn tc_get(&mut self) -> Result<(bool, Option<Ds>, Option<Rs>), Ds1302Error> {
705        let v = self.read_reg(RegisterRead::TCS.addr())?;
706        Ok(TrickleCharger::from(v).get())
707    }
708
709    /// Whether to enable charging.
710    pub fn tc_is_enabled(&mut self) -> Result<bool, Ds1302Error> {
711        let v = self.read_reg(RegisterRead::TCS.addr())?;
712        Ok(TrickleCharger::from(v).is_enabled())
713    }
714
715    /// Read DS1302 internal RAM. The static RAM is 31 x 8 bytes, index 0..=30.
716    pub fn read_ram(&mut self, index: u8) -> Result<u8, Ds1302Error> {
717        if index > 30 {
718            return Err(Ds1302Error::Parameter);
719        }
720        self.read_reg(RegisterRead::RAM.addr() + index * 2)
721    }
722
723    /// Write DS1302 internal RAM. The static RAM is 31 x 8 bytes, index 0..=31.
724    pub fn write_ram(&mut self, index: u8, value: u8) -> Result<(), Ds1302Error> {
725        if index > 30 {
726            return Err(Ds1302Error::Parameter);
727        }
728        self.write_reg(RegisterWrite::RAM.addr() + index * 2, value)
729    }
730
731    /// Read DS1302 internal RAM burst mode. Start at 0 index.
732    /// The length is determined by the buf, but cannot exceed 31.
733    pub fn read_ram_burst(&mut self, buf: &mut [u8]) -> Result<(), Ds1302Error> {
734        let mut status_response = [0_u8; 32];
735        self.sclk.set_low().ok();
736        //nb::block!(self.delay.wait()).ok(); // wait CE inactive time min 4us
737        self.ce.set_high().ok();
738        self.delay.start(4.micros()).ok();
739        self.write_byte(RegisterRead::RAMBURS.addr())?;
740
741        for idx in 0..buf.len() + 1 {
742            status_response[idx] = self.read_byte()?;
743        }
744
745        //self.sclk.set_high().ok();
746        self.delay.start(300.nanos()).ok(); //tCCH = 240ns for 2V
747        self.ce.set_low().ok();
748        self.delay.start(4.micros()).ok();
749
750        buf.copy_from_slice(&status_response[1..(buf.len() + 1)]);
751        Ok(())
752    }
753
754    /// Write DS1302 internal RAM burst mode. Start at 0 index.
755    /// The length is determined by the buf, but cannot exceed 31.
756    pub fn write_ram_burst(&mut self, buf: &[u8]) -> Result<usize, Ds1302Error> {
757        let mut bytes = [0_u8; 32];
758        bytes[0] = RegisterWrite::RAMBURS.addr();
759        let ll = buf.len();
760        let ll = if ll > 31 { 31 } else { ll };
761
762        self.sclk.set_low().ok();
763        //nb::block!(self.delay.wait()).ok(); // wait CE inactive time min 4us
764        self.ce.set_high().ok();
765        self.delay.start(4.micros()).ok();
766        self.write_byte(RegisterWrite::RAMBURS.addr())?;
767
768        for idx in 0..ll + 1 {
769            self.write_byte(buf[idx])?;
770        }
771
772        //self.sclk.set_high().ok();
773        self.delay.start(300.nanos()).ok(); //tCCH = 240ns for 2V
774        self.ce.set_low().ok();
775        self.delay.start(4.micros()).ok();
776
777        Ok(ll)
778    }
779}