A personal rust firmware for the Badger 2040 W

wip:(

Changed files
+726 -71
src
+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
··· 99 99 tinybmp = "0.5.0" 100 100 shtcx = "1.0.0" 101 101 postcard = "1.0.8" 102 + time = { version = "0.3.17", default-features = false } 103 + #pcf85063a = "0.1.1" 102 104 103 105 [profile.release] 104 106 debug = 2
+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
··· 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
··· 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
··· 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 + }