+40
Cargo.lock
+40
Cargo.lock
···
478
478
]
479
479
480
480
[[package]]
481
+
name = "deranged"
482
+
version = "0.5.4"
483
+
source = "registry+https://github.com/rust-lang/crates.io-index"
484
+
checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071"
485
+
dependencies = [
486
+
"powerfmt",
487
+
]
488
+
489
+
[[package]]
481
490
name = "diff"
482
491
version = "0.1.13"
483
492
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1501
1510
]
1502
1511
1503
1512
[[package]]
1513
+
name = "num-conv"
1514
+
version = "0.1.0"
1515
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1516
+
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
1517
+
1518
+
[[package]]
1504
1519
name = "num-traits"
1505
1520
version = "0.2.19"
1506
1521
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1785
1800
]
1786
1801
1787
1802
[[package]]
1803
+
name = "powerfmt"
1804
+
version = "0.2.0"
1805
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1806
+
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
1807
+
1808
+
[[package]]
1788
1809
name = "ppv-lite86"
1789
1810
version = "0.2.18"
1790
1811
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2071
2092
"serde-json-core",
2072
2093
"shtcx",
2073
2094
"static_cell",
2095
+
"time",
2074
2096
"tinybmp",
2075
2097
"uc8151",
2076
2098
]
···
2380
2402
"quote",
2381
2403
"syn 2.0.106",
2382
2404
]
2405
+
2406
+
[[package]]
2407
+
name = "time"
2408
+
version = "0.3.44"
2409
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2410
+
checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
2411
+
dependencies = [
2412
+
"deranged",
2413
+
"num-conv",
2414
+
"powerfmt",
2415
+
"time-core",
2416
+
]
2417
+
2418
+
[[package]]
2419
+
name = "time-core"
2420
+
version = "0.1.6"
2421
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2422
+
checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
2383
2423
2384
2424
[[package]]
2385
2425
name = "tiny-keccak"
+2
Cargo.toml
+2
Cargo.toml
+76
-71
src/main.rs
+76
-71
src/main.rs
···
1
-
//! This example test the RP Pico W on board LED.
2
-
//!
3
-
//! It does not work with the RP Pico board.
4
-
5
1
#![no_std]
6
2
#![no_main]
7
3
···
17
13
use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi};
18
14
use defmt::info;
19
15
use defmt::*;
16
+
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
20
17
use embassy_executor::Spawner;
21
18
use embassy_net::StackResources;
22
19
use embassy_net::dns::DnsSocket;
···
39
36
use gpio::{Level, Output, Pull};
40
37
use heapless::{String, Vec};
41
38
use helpers::easy_format;
39
+
use pcf85063a::PCF85063;
42
40
use reqwless::client::{HttpClient, TlsConfig, TlsVerify};
43
41
use reqwless::request::Method;
44
42
use save::{Save, read_postcard_from_flash, save_postcard_to_flash};
···
50
48
mod badge_display;
51
49
mod env;
52
50
mod helpers;
51
+
mod pcf85063a;
53
52
mod save;
54
53
mod temp_sensor;
55
54
···
213
212
&mut tls_write_buffer,
214
213
TlsVerify::None,
215
214
);
215
+
// let mut http_client = HttpClient::new(&tcp_client, &dns_client);
216
+
let mut http_client = HttpClient::new_with_tls(&tcp_client, &dns_client, tls_config);
216
217
217
-
let mut http_client = HttpClient::new_with_tls(&tcp_client, &dns_client, tls_config);
218
218
let url = env_value("TIME_API");
219
219
info!("connecting to {}", &url);
220
220
221
-
let mut request = match http_client.request(Method::GET, &url).await {
222
-
Ok(req) => req,
223
-
Err(e) => {
224
-
error!("Failed to make HTTP request: {:?}", e);
225
-
return; // handle the error
226
-
}
227
-
};
228
-
229
-
let response = match request.send(&mut rx_buffer).await {
230
-
Ok(resp) => resp,
231
-
Err(_e) => {
232
-
error!("Failed to send HTTP request");
233
-
return; // handle the error;
234
-
}
235
-
};
236
-
237
-
let body = match from_utf8(response.body().read_to_end().await.unwrap()) {
238
-
Ok(b) => b,
239
-
Err(_e) => {
240
-
error!("Failed to read response body");
241
-
return; // handle the error
242
-
}
243
-
};
244
-
info!("Response body: {:?}", &body);
221
+
//If the call goes through set the rtc
222
+
match http_client.request(Method::GET, &url).await {
223
+
Ok(mut request) => {
224
+
let response = match request.send(&mut rx_buffer).await {
225
+
Ok(resp) => resp,
226
+
Err(e) => {
227
+
error!("Failed to send HTTP request: {:?}", e);
228
+
// error!("Failed to send HTTP request");
229
+
return; // handle the error;
230
+
}
231
+
};
245
232
246
-
let bytes = body.as_bytes();
247
-
match serde_json_core::de::from_slice::<TimeApiResponse>(bytes) {
248
-
Ok((output, _used)) => {
249
-
//Deadlines am i right?
250
-
info!("Datetime: {:?}", output.datetime);
251
-
//split at T
252
-
let datetime = output.datetime.split('T').collect::<Vec<&str, 2>>();
253
-
//split at -
254
-
let date = datetime[0].split('-').collect::<Vec<&str, 3>>();
255
-
let year = date[0].parse::<u16>().unwrap();
256
-
let month = date[1].parse::<u8>().unwrap();
257
-
let day = date[2].parse::<u8>().unwrap();
258
-
//split at :
259
-
let time = datetime[1].split(':').collect::<Vec<&str, 4>>();
260
-
let hour = time[0].parse::<u8>().unwrap();
261
-
let minute = time[1].parse::<u8>().unwrap();
262
-
//split at .
263
-
let second_split = time[2].split('.').collect::<Vec<&str, 2>>();
264
-
let second = second_split[0].parse::<f64>().unwrap();
265
-
let rtc_time = DateTime {
266
-
year: year,
267
-
month: month,
268
-
day: day,
269
-
day_of_week: match output.day_of_week {
270
-
0 => DayOfWeek::Sunday,
271
-
1 => DayOfWeek::Monday,
272
-
2 => DayOfWeek::Tuesday,
273
-
3 => DayOfWeek::Wednesday,
274
-
4 => DayOfWeek::Thursday,
275
-
5 => DayOfWeek::Friday,
276
-
6 => DayOfWeek::Saturday,
277
-
_ => DayOfWeek::Sunday,
278
-
},
279
-
hour,
280
-
minute,
281
-
second: second as u8,
233
+
let body = match from_utf8(response.body().read_to_end().await.unwrap()) {
234
+
Ok(b) => b,
235
+
Err(_e) => {
236
+
error!("Failed to read response body");
237
+
return; // handle the error
238
+
}
282
239
};
283
-
rtc.set_datetime(rtc_time).unwrap();
284
-
time_was_set = true;
285
-
let _ = control.leave().await;
240
+
info!("Response body: {:?}", &body);
241
+
242
+
let bytes = body.as_bytes();
243
+
match serde_json_core::de::from_slice::<TimeApiResponse>(bytes) {
244
+
Ok((output, _used)) => {
245
+
//Deadlines am i right?
246
+
info!("Datetime: {:?}", output.datetime);
247
+
//split at T
248
+
let datetime = output.datetime.split('T').collect::<Vec<&str, 2>>();
249
+
//split at -
250
+
let date = datetime[0].split('-').collect::<Vec<&str, 3>>();
251
+
let year = date[0].parse::<u16>().unwrap();
252
+
let month = date[1].parse::<u8>().unwrap();
253
+
let day = date[2].parse::<u8>().unwrap();
254
+
//split at :
255
+
let time = datetime[1].split(':').collect::<Vec<&str, 4>>();
256
+
let hour = time[0].parse::<u8>().unwrap();
257
+
let minute = time[1].parse::<u8>().unwrap();
258
+
//split at .
259
+
let second_split = time[2].split('.').collect::<Vec<&str, 2>>();
260
+
let second = second_split[0].parse::<f64>().unwrap();
261
+
let rtc_time = DateTime {
262
+
year: year,
263
+
month: month,
264
+
day: day,
265
+
day_of_week: match output.day_of_week {
266
+
0 => DayOfWeek::Sunday,
267
+
1 => DayOfWeek::Monday,
268
+
2 => DayOfWeek::Tuesday,
269
+
3 => DayOfWeek::Wednesday,
270
+
4 => DayOfWeek::Thursday,
271
+
5 => DayOfWeek::Friday,
272
+
6 => DayOfWeek::Saturday,
273
+
_ => DayOfWeek::Sunday,
274
+
},
275
+
hour,
276
+
minute,
277
+
second: second as u8,
278
+
};
279
+
rtc.set_datetime(rtc_time).unwrap();
280
+
time_was_set = true;
281
+
let _ = control.leave().await;
282
+
}
283
+
Err(_e) => {
284
+
error!("Failed to parse response body");
285
+
// return; // handle the error
286
+
}
287
+
}
286
288
}
287
-
Err(_e) => {
288
-
error!("Failed to parse response body");
289
+
Err(e) => {
290
+
error!("Failed to make HTTP request: {:?}", e);
289
291
// return; // handle the error
290
292
}
291
-
}
293
+
};
292
294
}
293
295
294
296
//Set up saving
···
302
304
static I2C_BUS: StaticCell<I2c0Bus> = StaticCell::new();
303
305
let i2c_bus = NoopMutex::new(RefCell::new(i2c));
304
306
let i2c_bus = I2C_BUS.init(i2c_bus);
307
+
308
+
let i2c_dev = I2cDevice::new(i2c_bus);
309
+
let mut rtc_device = PCF85063::new(i2c_dev);
305
310
306
311
//Task spawning
307
312
spawner.must_spawn(run_the_temp_sensor(i2c_bus));
+281
src/pcf85063a/alarm.rs
+281
src/pcf85063a/alarm.rs
···
1
+
use super::{BitFlags, Control, DEVICE_ADDRESS, Error, PCF85063, Register, decode_bcd, encode_bcd};
2
+
use embedded_hal_async::i2c::I2c;
3
+
use time::Time;
4
+
5
+
impl<I2C, E> PCF85063<I2C>
6
+
where
7
+
I2C: I2c<Error = E>,
8
+
{
9
+
/// Set the alarm seconds, minutes and hours, keeping the AE bit unchanged.
10
+
pub async fn set_alarm_time(&mut self, time: Time) -> Result<(), Error<E>> {
11
+
self.set_alarm_seconds(time.second()).await?;
12
+
self.set_alarm_minutes(time.minute()).await?;
13
+
self.set_alarm_hours(time.hour()).await?;
14
+
Ok(())
15
+
}
16
+
17
+
/// Set the alarm seconds [0-59], keeping the AE bit unchanged.
18
+
pub fn set_alarm_seconds(&mut self, seconds: u8) -> Result<(), Error<E>> {
19
+
if seconds > 59 {
20
+
return Err(Error::InvalidInputData);
21
+
}
22
+
let data: u8 = self.read_register(Register::SECOND_ALARM)?; // read current value
23
+
let data: u8 = data & BitFlags::AE; // keep the AE bit as is
24
+
let setting: u8 = encode_bcd(seconds);
25
+
let data: u8 = data | setting;
26
+
self.write_register(Register::SECOND_ALARM, data).await
27
+
}
28
+
29
+
/// Set the alarm minutes [0-59], keeping the AE bit unchanged.
30
+
pub async fn set_alarm_minutes(&mut self, minutes: u8) -> Result<(), Error<E>> {
31
+
if minutes > 59 {
32
+
return Err(Error::InvalidInputData);
33
+
}
34
+
let data: u8 = self.read_register(Register::MINUTE_ALARM).await?; // read current value
35
+
let data: u8 = data & BitFlags::AE; // keep the AE bit as is
36
+
let setting: u8 = encode_bcd(minutes);
37
+
let data: u8 = data | setting;
38
+
self.write_register(Register::MINUTE_ALARM, data).await
39
+
}
40
+
41
+
/// Set the alarm hours [0-23], keeping the AE bit unchanged.
42
+
pub async fn set_alarm_hours(&mut self, hours: u8) -> Result<(), Error<E>> {
43
+
if hours > 23 {
44
+
return Err(Error::InvalidInputData);
45
+
}
46
+
let data: u8 = self.read_register(Register::HOUR_ALARM).await?; // read current value
47
+
let data: u8 = data & BitFlags::AE; // keep the AE bit as is
48
+
let setting: u8 = encode_bcd(hours);
49
+
let data: u8 = data | setting;
50
+
self.write_register(Register::HOUR_ALARM, data).await
51
+
}
52
+
53
+
/// Set the alarm day [1-31], keeping the AE bit unchanged.
54
+
pub async fn set_alarm_day(&mut self, day: u8) -> Result<(), Error<E>> {
55
+
if !(1..=31).contains(&day) {
56
+
return Err(Error::InvalidInputData);
57
+
}
58
+
let data: u8 = self.read_register(Register::DAY_ALARM).await?; // read current value
59
+
let data: u8 = data & BitFlags::AE; // keep the AE bit as is
60
+
let setting: u8 = encode_bcd(day);
61
+
let data: u8 = data | setting;
62
+
self.write_register(Register::DAY_ALARM, data).await
63
+
}
64
+
65
+
/// Set the alarm weekday [0-6], keeping the AE bit unchanged.
66
+
pub async fn set_alarm_weekday(&mut self, weekday: u8) -> Result<(), Error<E>> {
67
+
if weekday > 6 {
68
+
return Err(Error::InvalidInputData);
69
+
}
70
+
let data: u8 = self.read_register(Register::WEEKDAY_ALARM).await?; // read current value
71
+
let data: u8 = data & BitFlags::AE; // keep the AE bit as is
72
+
let setting: u8 = encode_bcd(weekday);
73
+
let data: u8 = data | setting;
74
+
self.write_register(Register::WEEKDAY_ALARM, data).await
75
+
}
76
+
77
+
/// Control alarm seconds (On: alarm enabled, Off: alarm disabled).
78
+
pub async fn control_alarm_seconds(&mut self, status: Control) -> Result<(), Error<E>> {
79
+
match status {
80
+
Control::Off => {
81
+
self.set_register_bit_flag(Register::SECOND_ALARM, BitFlags::AE)
82
+
.await
83
+
}
84
+
Control::On => {
85
+
self.clear_register_bit_flag(Register::SECOND_ALARM, BitFlags::AE)
86
+
.await
87
+
}
88
+
}
89
+
}
90
+
91
+
/// Is alarm seconds enabled?
92
+
pub async fn is_alarm_seconds_enabled(&mut self) -> Result<bool, Error<E>> {
93
+
Ok(!self
94
+
.is_register_bit_flag_high(Register::SECOND_ALARM, BitFlags::AE)
95
+
.await?)
96
+
}
97
+
98
+
/// Control alarm minutes (On: alarm enabled, Off: alarm disabled).
99
+
pub async fn control_alarm_minutes(&mut self, status: Control) -> Result<(), Error<E>> {
100
+
match status {
101
+
Control::Off => {
102
+
self.set_register_bit_flag(Register::MINUTE_ALARM, BitFlags::AE)
103
+
.await
104
+
}
105
+
Control::On => {
106
+
self.clear_register_bit_flag(Register::MINUTE_ALARM, BitFlags::AE)
107
+
.await
108
+
}
109
+
}
110
+
}
111
+
112
+
/// Is alarm minutes enabled?
113
+
pub async fn is_alarm_minutes_enabled(&mut self) -> Result<bool, Error<E>> {
114
+
Ok(!self
115
+
.is_register_bit_flag_high(Register::MINUTE_ALARM, BitFlags::AE)
116
+
.await?)
117
+
}
118
+
119
+
/// Control alarm hours (On: alarm enabled, Off: alarm disabled).
120
+
pub async fn control_alarm_hours(&mut self, status: Control) -> Result<(), Error<E>> {
121
+
match status {
122
+
Control::Off => {
123
+
self.set_register_bit_flag(Register::HOUR_ALARM, BitFlags::AE)
124
+
.await
125
+
}
126
+
Control::On => {
127
+
self.clear_register_bit_flag(Register::HOUR_ALARM, BitFlags::AE)
128
+
.await
129
+
}
130
+
}
131
+
}
132
+
133
+
/// Is alarm hours enabled?
134
+
pub async fn is_alarm_hours_enabled(&mut self) -> Result<bool, Error<E>> {
135
+
Ok(!self
136
+
.is_register_bit_flag_high(Register::HOUR_ALARM, BitFlags::AE)
137
+
.await?)
138
+
}
139
+
140
+
/// Control alarm day (On: alarm enabled, Off: alarm disabled).
141
+
pub async fn control_alarm_day(&mut self, status: Control) -> Result<(), Error<E>> {
142
+
match status {
143
+
Control::Off => {
144
+
self.set_register_bit_flag(Register::DAY_ALARM, BitFlags::AE)
145
+
.await
146
+
}
147
+
Control::On => {
148
+
self.clear_register_bit_flag(Register::DAY_ALARM, BitFlags::AE)
149
+
.await
150
+
}
151
+
}
152
+
}
153
+
154
+
/// Is alarm day enabled?
155
+
pub async fn is_alarm_day_enabled(&mut self) -> Result<bool, Error<E>> {
156
+
Ok(!self
157
+
.is_register_bit_flag_high(Register::DAY_ALARM, BitFlags::AE)
158
+
.await?)
159
+
}
160
+
161
+
/// Control alarm weekday (On: alarm enabled, Off: alarm disabled).
162
+
pub async fn control_alarm_weekday(&mut self, status: Control) -> Result<(), Error<E>> {
163
+
match status {
164
+
Control::Off => {
165
+
self.set_register_bit_flag(Register::WEEKDAY_ALARM, BitFlags::AE)
166
+
.await
167
+
}
168
+
Control::On => {
169
+
self.clear_register_bit_flag(Register::WEEKDAY_ALARM, BitFlags::AE)
170
+
.await
171
+
}
172
+
}
173
+
}
174
+
175
+
/// Is alarm weekday enabled?
176
+
pub async fn is_alarm_weekday_enabled(&mut self) -> Result<bool, Error<E>> {
177
+
Ok(!self
178
+
.is_register_bit_flag_high(Register::WEEKDAY_ALARM, BitFlags::AE)
179
+
.await?)
180
+
}
181
+
182
+
/// Enable or disable alarm interrupt.
183
+
pub async fn control_alarm_interrupt(&mut self, status: Control) -> Result<(), Error<E>> {
184
+
match status {
185
+
Control::On => {
186
+
self.set_register_bit_flag(Register::CONTROL_2, BitFlags::AIE)
187
+
.await
188
+
}
189
+
Control::Off => {
190
+
self.clear_register_bit_flag(Register::CONTROL_2, BitFlags::AIE)
191
+
.await
192
+
}
193
+
}
194
+
}
195
+
196
+
pub async fn get_alarm_time(&mut self) -> Result<Time, Error<E>> {
197
+
Ok(Time::from_hms(
198
+
self.get_alarm_hours().await?,
199
+
self.get_alarm_minutes().await?,
200
+
self.get_alarm_seconds().await?,
201
+
)?)
202
+
}
203
+
204
+
/// Read the alarm seconds setting.
205
+
pub async fn get_alarm_seconds(&mut self) -> Result<u8, Error<E>> {
206
+
let mut data = [0];
207
+
self.i2c
208
+
.write_read(DEVICE_ADDRESS, &[Register::SECOND_ALARM], &mut data)
209
+
.await
210
+
.map_err(Error::I2C)?;
211
+
Ok(decode_bcd(data[0]))
212
+
}
213
+
214
+
/// Read the alarm minutes setting.
215
+
pub async fn get_alarm_minutes(&mut self) -> Result<u8, Error<E>> {
216
+
let mut data = [0];
217
+
self.i2c
218
+
.write_read(DEVICE_ADDRESS, &[Register::MINUTE_ALARM], &mut data)
219
+
.await
220
+
.map_err(Error::I2C)?;
221
+
Ok(decode_bcd(data[0]))
222
+
}
223
+
224
+
/// Read the alarm hours setting.
225
+
pub async fn get_alarm_hours(&mut self) -> Result<u8, Error<E>> {
226
+
let mut data = [0];
227
+
self.i2c
228
+
.write_read(DEVICE_ADDRESS, &[Register::HOUR_ALARM], &mut data)
229
+
.await
230
+
.map_err(Error::I2C)?;
231
+
Ok(decode_bcd(data[0]))
232
+
}
233
+
234
+
/// Read the alarm day setting.
235
+
pub async fn get_alarm_day(&mut self) -> Result<u8, Error<E>> {
236
+
let mut data = [0];
237
+
self.i2c
238
+
.write_read(DEVICE_ADDRESS, &[Register::DAY_ALARM], &mut data)
239
+
.await
240
+
.map_err(Error::I2C)?;
241
+
Ok(decode_bcd(data[0]))
242
+
}
243
+
244
+
/// Read the alarm weekday setting.
245
+
pub async fn get_alarm_weekday(&mut self) -> Result<u8, Error<E>> {
246
+
let mut data = [0];
247
+
self.i2c
248
+
.write_read(DEVICE_ADDRESS, &[Register::WEEKDAY_ALARM], &mut data)
249
+
.await
250
+
.map_err(Error::I2C)?;
251
+
Ok(decode_bcd(data[0]))
252
+
}
253
+
254
+
/// Get the alarm flag (if true, alarm event happened).
255
+
pub async fn get_alarm_flag(&mut self) -> Result<bool, Error<E>> {
256
+
self.is_register_bit_flag_high(Register::CONTROL_2, BitFlags::AF)
257
+
.await
258
+
}
259
+
260
+
/// Clear the alarm flag.
261
+
pub async fn clear_alarm_flag(&mut self) -> Result<(), Error<E>> {
262
+
self.clear_register_bit_flag(Register::CONTROL_2, BitFlags::AF)
263
+
.await
264
+
}
265
+
266
+
/// Check if alarm interrupt is enabled.
267
+
pub async fn is_alarm_interrupt_enabled(&mut self) -> Result<bool, Error<E>> {
268
+
self.is_register_bit_flag_high(Register::CONTROL_2, BitFlags::AIE)
269
+
.await
270
+
}
271
+
272
+
/// Shut off the alarms at once.
273
+
pub async fn disable_all_alarms(&mut self) -> Result<(), Error<E>> {
274
+
self.control_alarm_seconds(Control::Off).await?;
275
+
self.control_alarm_minutes(Control::Off).await?;
276
+
self.control_alarm_hours(Control::Off).await?;
277
+
self.control_alarm_day(Control::Off).await?;
278
+
self.control_alarm_weekday(Control::Off).await?;
279
+
Ok(())
280
+
}
281
+
}
+72
src/pcf85063a/datetime.rs
+72
src/pcf85063a/datetime.rs
···
1
+
//! All date and time-related functions will be defined here.
2
+
//!
3
+
//! Reading and setting single elements (seconds, hours, months) will NOT be implemented
4
+
//! following the recommendations in the NXP datasheet to set and read all the seven date and time registers in one go.
5
+
//!
6
+
//! TO DO: As the chip may be used for devices that are clocks only, without the calendar function
7
+
//! a convenient set_time() function could be added (sets only seconds, minutes and hours)
8
+
9
+
use super::{DEVICE_ADDRESS, Error, PCF85063, Register, decode_bcd, encode_bcd};
10
+
use embedded_hal_async::i2c::I2c;
11
+
use time::{Date, PrimitiveDateTime, Time};
12
+
13
+
impl<I2C, E> PCF85063<I2C>
14
+
where
15
+
I2C: I2c<Error = E>,
16
+
{
17
+
/// Read date and time all at once.
18
+
pub async fn get_datetime(&mut self) -> Result<PrimitiveDateTime, Error<E>> {
19
+
let mut data = [0; 7];
20
+
self.i2c
21
+
.write_read(DEVICE_ADDRESS, &[Register::SECONDS], &mut data)
22
+
.await
23
+
.map_err(Error::I2C)?;
24
+
25
+
Ok(PrimitiveDateTime::new(
26
+
Date::from_calendar_date(
27
+
2000 + decode_bcd(data[6]) as i32,
28
+
decode_bcd(data[5] & 0x1f).try_into()?,
29
+
decode_bcd(data[3] & 0x3f),
30
+
)?,
31
+
Time::from_hms(
32
+
decode_bcd(data[2] & 0x3f),
33
+
decode_bcd(data[1] & 0b0111_1111),
34
+
decode_bcd(data[0] & 0b0111_1111),
35
+
)?,
36
+
))
37
+
}
38
+
39
+
/// Set date and time all at once.
40
+
pub async fn set_datetime(&mut self, datetime: &PrimitiveDateTime) -> Result<(), Error<E>> {
41
+
let payload = [
42
+
Register::SECONDS, //first register
43
+
encode_bcd(datetime.second()),
44
+
encode_bcd(datetime.minute()),
45
+
encode_bcd(datetime.hour()),
46
+
encode_bcd(datetime.day()),
47
+
encode_bcd(datetime.weekday().number_days_from_sunday()),
48
+
encode_bcd(datetime.month().into()),
49
+
encode_bcd((datetime.year() - 2000) as u8),
50
+
];
51
+
self.i2c
52
+
.write(DEVICE_ADDRESS, &payload)
53
+
.await
54
+
.map_err(Error::I2C)
55
+
}
56
+
57
+
/// Set only the time, date remains unchanged.
58
+
///
59
+
/// Will return an 'Error::InvalidInputData' if any of the parameters is out of range.
60
+
pub async fn set_time(&mut self, time: &Time) -> Result<(), Error<E>> {
61
+
let payload = [
62
+
Register::SECONDS, //first register
63
+
encode_bcd(time.second()),
64
+
encode_bcd(time.minute()),
65
+
encode_bcd(time.hour()),
66
+
];
67
+
self.i2c
68
+
.write(DEVICE_ADDRESS, &payload)
69
+
.await
70
+
.map_err(Error::I2C)
71
+
}
72
+
}
+255
src/pcf85063a/mod.rs
+255
src/pcf85063a/mod.rs
···
1
+
#![no_std]
2
+
3
+
mod alarm;
4
+
mod datetime;
5
+
6
+
use embedded_hal_1::i2c::I2c;
7
+
8
+
/// All possible errors in this crate
9
+
#[derive(Debug)]
10
+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
11
+
pub enum Error<E> {
12
+
/// I2C bus error
13
+
I2C(E),
14
+
/// Invalid input data
15
+
InvalidInputData,
16
+
/// A time component was out of range
17
+
ComponentRange,
18
+
}
19
+
20
+
impl<E> From<time::error::ComponentRange> for Error<E> {
21
+
fn from(_: time::error::ComponentRange) -> Self {
22
+
Self::ComponentRange
23
+
}
24
+
}
25
+
26
+
pub struct Register;
27
+
28
+
impl Register {
29
+
// control and status registers
30
+
pub const CONTROL_1: u8 = 0x00;
31
+
pub const CONTROL_2: u8 = 0x01;
32
+
pub const OFFSET: u8 = 0x02;
33
+
pub const RAM_BYTE: u8 = 0x03;
34
+
35
+
// time and date registers
36
+
pub const SECONDS: u8 = 0x04;
37
+
pub const MINUTES: u8 = 0x05;
38
+
pub const HOURS: u8 = 0x06;
39
+
pub const DAYS: u8 = 0x07;
40
+
pub const WEEKDAYS: u8 = 0x08;
41
+
pub const MONTHS: u8 = 0x09;
42
+
pub const YEARS: u8 = 0x0A;
43
+
44
+
// alarm registers
45
+
pub const SECOND_ALARM: u8 = 0x0B;
46
+
pub const MINUTE_ALARM: u8 = 0x0C;
47
+
pub const HOUR_ALARM: u8 = 0x0D;
48
+
pub const DAY_ALARM: u8 = 0x0E;
49
+
pub const WEEKDAY_ALARM: u8 = 0x0F;
50
+
51
+
// timer registers
52
+
pub const TIMER_VALUE: u8 = 0x10;
53
+
pub const TIMER_MODE: u8 = 0x11;
54
+
}
55
+
56
+
pub struct BitFlags;
57
+
58
+
impl BitFlags {
59
+
// control 1
60
+
pub const CAP_SEL: u8 = 0b0000_0001; // internal oscillator capacitor selection
61
+
pub const MODE_12_24: u8 = 0b0000_0010; // 12 or 24-hour mode
62
+
pub const CIE: u8 = 0b0000_0100; // connection interrupt enable
63
+
// 3: UNUSED
64
+
pub const SR: u8 = 0b0001_0000; // software reset
65
+
pub const STOP: u8 = 0b0010_0000; // RTC clock stop bit
66
+
// 6: UNUSED
67
+
pub const EXT_TEST: u8 = 0b1000_0000; // external clock test mode
68
+
69
+
// control 2
70
+
pub const COF: u8 = 0b0000_0111; // clkout control
71
+
pub const TF: u8 = 0b0000_1000; // timer flag
72
+
pub const HMI: u8 = 0b0001_0000; // half minute interrupt
73
+
pub const MI: u8 = 0b0010_0000; // minute interrupt
74
+
pub const AF: u8 = 0b0100_0000; // alarm flag
75
+
pub const AIE: u8 = 0b1000_0000; // alarm interrupt enabled
76
+
77
+
pub const AE: u8 = 0b1000_0000; // alarm enable/disable for all five (s/m/h/d/wd) settings
78
+
}
79
+
80
+
const DEVICE_ADDRESS: u8 = 0b1010001;
81
+
82
+
/// Two possible choices, used for various enable/disable bit flags
83
+
#[allow(non_camel_case_types)]
84
+
#[derive(Copy, Clone, Debug)]
85
+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
86
+
pub 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)]
95
+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
96
+
pub struct PCF85063<I2C> {
97
+
/// The concrete I2C device implementation.
98
+
i2c: I2C,
99
+
}
100
+
101
+
impl<I2C, E> PCF85063<I2C>
102
+
where
103
+
I2C: I2c<Error = E>,
104
+
{
105
+
/// Create a new instance of the PCF8563 driver.
106
+
pub fn new(i2c: I2C) -> Self {
107
+
PCF85063 { i2c }
108
+
}
109
+
110
+
/// Reset the RTC
111
+
pub fn reset(&mut self) -> Result<(), Error<E>> {
112
+
self.set_register_bit_flag(Register::CONTROL_1, BitFlags::SR)
113
+
}
114
+
115
+
/// Destroy driver instance, return I2C bus instance.
116
+
pub fn destroy(self) -> I2C {
117
+
self.i2c
118
+
}
119
+
120
+
/// Let the device reset itself
121
+
pub fn perform_software_reset(&mut self) -> Result<(), Error<E>> {
122
+
self.write_register(Register::CONTROL_1, 0b01011000)
123
+
}
124
+
125
+
/// Write to a register.
126
+
pub fn write_register(&mut self, register: u8, data: u8) -> Result<(), Error<E>> {
127
+
let payload: [u8; 2] = [register, data];
128
+
self.i2c.write(DEVICE_ADDRESS, &payload).map_err(Error::I2C)
129
+
}
130
+
131
+
/// Read from a register.
132
+
pub fn read_register(&mut self, register: u8) -> Result<u8, Error<E>> {
133
+
let mut data = [0];
134
+
self.i2c
135
+
.write_read(DEVICE_ADDRESS, &[register], &mut data)
136
+
.map_err(Error::I2C)
137
+
.and(Ok(data[0]))
138
+
}
139
+
140
+
/// Check if specific bits are set.
141
+
pub fn is_register_bit_flag_high(
142
+
&mut self,
143
+
address: u8,
144
+
bitmask: u8,
145
+
) -> Result<bool, Error<E>> {
146
+
let data = self.read_register(address)?;
147
+
Ok((data & bitmask) != 0)
148
+
}
149
+
150
+
/// Set specific bits.
151
+
pub fn set_register_bit_flag(&mut self, address: u8, bitmask: u8) -> Result<(), Error<E>> {
152
+
let data = self.read_register(address)?;
153
+
if (data & bitmask) == 0 {
154
+
self.write_register(address, data | bitmask)
155
+
} else {
156
+
Ok(())
157
+
}
158
+
}
159
+
160
+
/// Clear specific bits.
161
+
pub fn clear_register_bit_flag(&mut self, address: u8, bitmask: u8) -> Result<(), Error<E>> {
162
+
let data = self.read_register(address)?;
163
+
if (data & bitmask) != 0 {
164
+
self.write_register(address, data & !bitmask)
165
+
} else {
166
+
Ok(())
167
+
}
168
+
}
169
+
}
170
+
171
+
impl<I2C, E> PCF85063<I2C>
172
+
where
173
+
I2C: I2c<Error = E>,
174
+
{
175
+
pub fn read_ram_byte(&mut self) -> Result<u8, Error<E>> {
176
+
self.read_register(Register::RAM_BYTE)
177
+
}
178
+
179
+
pub fn write_ram_byte(&mut self, byte: u8) -> Result<(), Error<E>> {
180
+
self.write_register(Register::RAM_BYTE, byte)
181
+
}
182
+
}
183
+
184
+
impl<I2C, E> PCF85063<I2C>
185
+
where
186
+
I2C: I2c<Error = E>,
187
+
{
188
+
pub fn stop_clock(&mut self) -> Result<(), Error<E>> {
189
+
self.set_register_bit_flag(Register::CONTROL_1, BitFlags::STOP)
190
+
}
191
+
192
+
pub fn start_clock(&mut self) -> Result<(), Error<E>> {
193
+
self.clear_register_bit_flag(Register::CONTROL_1, BitFlags::STOP)
194
+
}
195
+
}
196
+
197
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
198
+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
199
+
#[repr(u8)]
200
+
pub enum OutputFrequency {
201
+
Hz32768 = 0b000,
202
+
Hz16384 = 0b001,
203
+
Hz8192 = 0b010,
204
+
Hz4096 = 0b011,
205
+
Hz2048 = 0b100,
206
+
Hz1024 = 0b101,
207
+
Hz1 = 0b110,
208
+
Hz0 = 0b111,
209
+
}
210
+
211
+
impl Default for OutputFrequency {
212
+
fn default() -> Self {
213
+
OutputFrequency::Hz32768
214
+
}
215
+
}
216
+
217
+
impl OutputFrequency {
218
+
pub const fn bits(self) -> u8 {
219
+
self as u8
220
+
}
221
+
}
222
+
223
+
impl<I2C, E> PCF85063<I2C>
224
+
where
225
+
I2C: I2c<Error = E>,
226
+
{
227
+
pub fn read_clock_output_frequency(&mut self) -> Result<OutputFrequency, Error<E>> {
228
+
let value = self.read_register(Register::CONTROL_2)? & BitFlags::COF;
229
+
230
+
Ok(unsafe { core::mem::transmute(value) })
231
+
}
232
+
233
+
pub fn write_clock_output_frequency(&mut self, freq: OutputFrequency) -> Result<(), Error<E>> {
234
+
let value = self.read_register(Register::CONTROL_2)?;
235
+
let cleared = value ^ BitFlags::COF;
236
+
let set = cleared | freq as u8;
237
+
238
+
self.write_register(Register::CONTROL_2, set)
239
+
}
240
+
}
241
+
242
+
/// Convert the Binary Coded Decimal value to decimal (only the lowest 7 bits).
243
+
fn decode_bcd(input: u8) -> u8 {
244
+
let digits: u8 = input & 0xf;
245
+
let tens: u8 = (input >> 4) & 0x7;
246
+
10 * tens + digits
247
+
}
248
+
249
+
/// Convert the decimal value to Binary Coded Decimal.
250
+
fn encode_bcd(input: u8) -> u8 {
251
+
let digits: u8 = input % 10;
252
+
let tens: u8 = input / 10;
253
+
let tens = tens << 4;
254
+
tens + digits
255
+
}