|
| 1 | +//! Example of communicating with a [DS3231] Real-Time Clock. |
| 2 | +//! |
| 3 | +//! [DS3231]: https://www.analog.com/media/en/technical-documentation/data-sheets/DS3231.pdf |
| 4 | +
|
| 5 | +#![no_main] |
| 6 | +#![no_std] |
| 7 | + |
| 8 | +// Required for panic handler |
| 9 | +extern crate flipperzero_rt; |
| 10 | + |
| 11 | +// Required for allocator |
| 12 | +#[cfg(feature = "alloc")] |
| 13 | +extern crate flipperzero_alloc; |
| 14 | + |
| 15 | +use flipperzero::{error, furi::time::Duration, gpio::i2c, println}; |
| 16 | +use flipperzero_rt::{entry, manifest}; |
| 17 | +use ufmt::derive::uDebug; |
| 18 | + |
| 19 | +manifest!(name = "I2C DS3231 Example"); |
| 20 | +entry!(main); |
| 21 | + |
| 22 | +#[derive(Debug, uDebug)] |
| 23 | +enum Hour { |
| 24 | + F12 { hour: u8, pm: bool }, |
| 25 | + F24(u8), |
| 26 | +} |
| 27 | + |
| 28 | +#[derive(Debug, uDebug)] |
| 29 | +struct RtcTime { |
| 30 | + year: u8, |
| 31 | + month: u8, |
| 32 | + date: u8, |
| 33 | + day: u8, |
| 34 | + hour: Hour, |
| 35 | + minutes: u8, |
| 36 | + seconds: u8, |
| 37 | +} |
| 38 | + |
| 39 | +impl RtcTime { |
| 40 | + fn parse(data: [u8; 7]) -> Self { |
| 41 | + let unbcd = |b: u8| 10 * (b >> 4) + (b & 0x0F); |
| 42 | + |
| 43 | + const FORMAT_12HR: u8 = 0b0100_0000; |
| 44 | + |
| 45 | + Self { |
| 46 | + year: unbcd(data[6]), |
| 47 | + month: unbcd(data[5] & 0x1F), |
| 48 | + date: unbcd(data[4] & 0x3F), |
| 49 | + day: data[3] & 0x07, |
| 50 | + hour: if data[2] & FORMAT_12HR != 0 { |
| 51 | + Hour::F12 { |
| 52 | + hour: unbcd(data[2] & 0x1F), |
| 53 | + pm: data[2] & 0b0010_0000 != 0, |
| 54 | + } |
| 55 | + } else { |
| 56 | + Hour::F24(unbcd(data[2] & 0x3F)) |
| 57 | + }, |
| 58 | + minutes: unbcd(data[1] & 0x7F), |
| 59 | + seconds: unbcd(data[0] & 0x7F), |
| 60 | + } |
| 61 | + } |
| 62 | +} |
| 63 | + |
| 64 | +fn main(_args: *mut u8) -> i32 { |
| 65 | + let mut bus = i2c::Bus::EXTERNAL.acquire(); |
| 66 | + let rtc = i2c::DeviceAddress::new(0x68); |
| 67 | + let timeout = Duration::from_millis(50); |
| 68 | + |
| 69 | + if bus.is_device_ready(rtc, timeout) { |
| 70 | + let mut data = [0; 7]; |
| 71 | + if bus.read_exact(rtc, 0x00, &mut data, timeout).is_ok() { |
| 72 | + println!("Time: {:?}", RtcTime::parse(data)); |
| 73 | + } else { |
| 74 | + error!("Could not read from DS3231"); |
| 75 | + } |
| 76 | + } else { |
| 77 | + error!("DS3231 is not connected and ready"); |
| 78 | + } |
| 79 | + |
| 80 | + 0 |
| 81 | +} |
0 commit comments