SensorLib 0.5.0
Multi-platform sensor driver library for Arduino, PlatformIO, and ESP-IDF
Loading...
Searching...
No Matches
time/pcf85063/SensorPCF85063.hpp
Go to the documentation of this file.
1
30#pragma once
31
32#include "../../SensorBuildOpt.h"
33#if !SENSORLIB_EXCLUDE_PCF85063
34
35#include "../../platform/comm/I2CDeviceNoHal.hpp"
36#include "../SensorRTC.h"
37
42const uint8_t PCF85063_SLAVE_ADDRESS = 0x51;
43
49{
50public:
53
69
75 SensorPCF85063() = default;
76
80 ~SensorPCF85063() = default;
81
82#if defined(ARDUINO)
91 bool begin(TwoWire &wire, int sda = -1, int scl = -1)
92 {
93 return I2CDeviceNoHal::begin(wire, PCF85063_SLAVE_ADDRESS, sda, scl);
94 }
95#elif defined(ESP_PLATFORM)
96
97#if defined(SENSORLIB_USE_I2C_LEGACY)
106 bool begin(i2c_port_t port_num, int sda = -1, int scl = -1)
107 {
108 return I2CDeviceNoHal::begin(port_num, PCF85063_SLAVE_ADDRESS, sda, scl);
109 }
110#else
117 bool begin(i2c_master_bus_handle_t handle)
118 {
120 }
121#endif // SENSORLIB_USE_I2C_LEGACY
122#endif // ESP_PLATFORM
123
134
143 void setDateTime(RTC_DateTime datetime) override
144 {
145 uint8_t buffer[7];
146 buffer[0] = DEC2BCD(datetime.getSecond()) & 0x7F; // seconds (mask OS flag)
147 buffer[1] = DEC2BCD(datetime.getMinute()); // minutes
148 buffer[2] = DEC2BCD(datetime.getHour()); // hours
149 buffer[3] = DEC2BCD(datetime.getDay()); // day of month
150 buffer[4] = getDayOfWeek(datetime.getDay(), datetime.getMonth(), datetime.getYear()); // weekday
151 buffer[5] = DEC2BCD(datetime.getMonth()); // month
152 buffer[6] = DEC2BCD(datetime.getYear() % 100); // year (00-99)
153
154 writeRegBuff(PCF85063_SEC_REG, buffer, 7);
155 }
156
166 {
167 // Note: variable kept for compatibility with existing style (not used)
168 RTC_DateTime datetime;
169
170 uint8_t buffer[7];
171 uint8_t hour = 0;
172
173 readRegBuff(PCF85063_SEC_REG, buffer, 7);
174
175 uint8_t second = BCD2DEC(buffer[0] & 0x7F);
176 uint8_t minute = BCD2DEC(buffer[1] & 0x7F);
177
178 if (is24Hour) {
179 hour = BCD2DEC(buffer[2] & 0x3F); // 24-hour mode
180 } else {
181 // datetime.AMPM = (buffer[2] & 0x20) == 0x20 ? 'A' : 'P';
182 hour = BCD2DEC(buffer[2] & 0x1F); // 12-hour mode (AM/PM bit not exposed here)
183 }
184
185 uint8_t day = BCD2DEC(buffer[3] & 0x3F);
186 uint8_t week = BCD2DEC(buffer[4] & 0x07);
187 uint8_t month = BCD2DEC(buffer[5] & 0x1F);
188 uint16_t year = BCD2DEC(buffer[6]) + 2000;
189
190 return RTC_DateTime(year, month, day, hour, minute, second, week);
191 }
192
202 {
203 return getRegBit(PCF85063_SEC_REG, 7) == 0;
204 }
205
206 /*
207 * 24H/12H mode APIs were intentionally kept disabled in original code.
208 * If needed, enable and document them similarly.
209 */
210
216 void stop()
217 {
219 }
220
226 void start()
227 {
229 }
230
237 {
238 return !getRegBit(PCF85063_CTRL1_REG, 5);
239 }
240
245 {
247 }
248
253 {
255 }
256
261 {
263 }
264
271 {
272 return getRegBit(PCF85063_CTRL2_REG, 6);
273 }
274
284 {
285 uint8_t buffer[5];
287 buffer[0] = BCD2DEC(buffer[0] & 0x80); // second
288 buffer[1] = BCD2DEC(buffer[1] & 0x40); // minute
289 buffer[2] = BCD2DEC(buffer[2] & 0x40); // hour
290 buffer[3] = BCD2DEC(buffer[3] & 0x08); // day
291 buffer[4] = BCD2DEC(buffer[4] & 0x08); // weekday
292
293 return RTC_Alarm(buffer[2], buffer[1], buffer[0], buffer[3], buffer[4]);
294 }
295
301 void setAlarm(RTC_Alarm alarm)
302 {
303 setAlarm(alarm.getHour(), alarm.getMinute(), alarm.getSecond(),
304 alarm.getDay(), alarm.getWeek());
305 }
306
319 void setAlarm(uint8_t hour, uint8_t minute, uint8_t second, uint8_t day, uint8_t week)
320 {
321 uint8_t buffer[5] = {0};
322
323 RTC_DateTime datetime = getDateTime();
324 uint8_t daysInMonth = getDaysInMonth(datetime.getMonth(), datetime.getYear());
325
326 // Seconds
327 if (second != PCF85063_NO_ALARM) {
328 if (second > 59) {
329 second = 59;
330 }
331 buffer[0] = DEC2BCD(second);
332 buffer[0] &= ~PCF85063_ALARM_ENABLE;
333 } else {
334 buffer[0] = PCF85063_ALARM_ENABLE;
335 }
336
337 // Minutes
338 if (minute != PCF85063_NO_ALARM) {
339 if (minute > 59) {
340 minute = 59;
341 }
342 buffer[1] = DEC2BCD(minute);
343 buffer[1] &= ~PCF85063_ALARM_ENABLE;
344 } else {
345 buffer[1] = PCF85063_ALARM_ENABLE;
346 }
347
348 // Hours
349 if (hour != PCF85063_NO_ALARM) {
350 if (is24Hour) {
351 if (hour > 23) {
352 hour = 23;
353 }
354 buffer[2] = DEC2BCD(hour);
355 buffer[2] &= ~PCF85063_ALARM_ENABLE;
356 }
357 } else {
358 buffer[2] = PCF85063_ALARM_ENABLE;
359 }
360
361 // Day of month
362 if (day != PCF85063_NO_ALARM) {
363 buffer[3] = DEC2BCD(((day) < (1) ? (1) : ((day) > (daysInMonth) ? (daysInMonth) : (day))));
364 buffer[3] &= ~PCF85063_ALARM_ENABLE;
365 } else {
366 buffer[3] = PCF85063_ALARM_ENABLE;
367 }
368
369 // Weekday
370 if (week != PCF85063_NO_ALARM) {
371 if (week > 6) {
372 week = 6;
373 }
374 buffer[4] = DEC2BCD(week);
375 buffer[4] &= ~PCF85063_ALARM_ENABLE;
376 } else {
377 buffer[4] = PCF85063_ALARM_ENABLE;
378 }
379
380 // Write alarm registers
382 }
383
389 void setAlarmByHours(uint8_t hour)
390 {
391 setAlarm(hour,
396 }
397
403 void setAlarmBySecond(uint8_t second)
404 {
407 second,
410 }
411
417 void setAlarmByMinutes(uint8_t minute)
418 {
420 minute,
424 }
425
431 void setAlarmByDays(uint8_t day)
432 {
436 day,
438 }
439
445 void setAlarmByWeekDay(uint8_t week)
446 {
451 week);
452 }
453
460 {
461 int val = readReg(PCF85063_CTRL2_REG);
462 if (val == -1) return;
463
464 val &= 0xF8; // clear frequency bits
465 val |= hz; // set new frequency
467 }
468
474 const char *getChipName() override
475 {
476 return "PCF85063";
477 }
478
482 void reset() override
483 {
485 }
486
487private:
498 bool initImpl(uint8_t param) override
499 {
500 // Check device is online
501 int val = readReg(PCF85063_RAM_REG);
502 if (val < 0) {
503 SENSORLIB_LOG_E("Device is offline!");
504 return false;
505 }
506
507 // Backup original RAM register value
508 uint8_t tmp = readReg(PCF85063_RAM_REG);
509
510 bool rlst = false;
511
512 // Determine whether this is PCF85063 by testing RAM register bit writability:
513 // If bit 7 can be set/cleared, it is likely PCF85063.
516 if (val & 0x80) {
519 if ((val & 0x80) == 0) {
520 rlst = true;
521 }
522 }
523
524 if (!rlst) {
525 SENSORLIB_LOG_E("Failed to write to RAM memory register. Maybe this chip is pcf8563.");
526 return false;
527 }
528
529 // Restore RAM register
531
532 // Default to 24-hour mode
534 if (!is24Hour) {
535 // Force 24H Mode
537 is24Hour = true;
538 }
539
540 // Turn on RTC
541 start();
542
543 return isRunning();
544 }
545
546protected:
553
554 // Register addresses
555 static constexpr uint8_t PCF85063_CTRL1_REG = 0x00;
556 static constexpr uint8_t PCF85063_CTRL2_REG = 0x01;
557 static constexpr uint8_t PCF85063_OFFSET_REG = 0x02;
558 static constexpr uint8_t PCF85063_RAM_REG = 0x03;
559 static constexpr uint8_t PCF85063_SEC_REG = 0x04;
560 static constexpr uint8_t PCF85063_MIN_REG = 0x05;
561 static constexpr uint8_t PCF85063_HR_REG = 0x06;
562 static constexpr uint8_t PCF85063_DAY_REG = 0x07;
563 static constexpr uint8_t PCF85063_WEEKDAY_REG = 0x08;
564 static constexpr uint8_t PCF85063_MONTH_REG = 0x09;
565 static constexpr uint8_t PCF85063_YEAR_REG = 0x0A;
566 static constexpr uint8_t PCF85063_ALRM_SEC_REG = 0x0B;
567 static constexpr uint8_t PCF85063_ALRM_MIN_REG = 0x0C;
568 static constexpr uint8_t PCF8563_ALRM_HR_REG = 0x0D;
569 static constexpr uint8_t PCF85063_ALRM_DAY_REG = 0x0E;
570 static constexpr uint8_t PCF85063_ALRM_WEEK_REG = 0x0F;
571 static constexpr uint8_t PCF85063_TIMER_VAL_REG = 0x10;
572 static constexpr uint8_t PCF85063_TIMER_MD_REG = 0x11;
573
574 // Mask values
575 static constexpr uint8_t PCF85063_CTRL1_TEST_EN_MASK = (1 << 7u);
576 static constexpr uint8_t PCF85063_CTRL1_CLOCK_EN_MASK = (1 << 5u);
577 static constexpr uint8_t PCF85063_CTRL1_SOFTRST_EN_MASK = (1 << 4u);
578 static constexpr uint8_t PCF85063_CTRL1_CIE_EN_MASK = (1 << 2u);
579 static constexpr uint8_t PCF85063_CTRL1_HOUR_FORMAT_12H_MASK = (1 << 1u);
580
581 // Other constants
582 static constexpr uint8_t PCF85063_NO_ALARM = 0xFF;
583 static constexpr uint8_t PCF85063_ALARM_ENABLE = 0x80;
584};
585
586#endif
#define SENSORLIB_LOG_E(...)
bool begin(SensorCommCustom::CustomCallback callback, uint8_t addr)
Initialize the sensor using custom callback interface.
uint8_t getDay() const
Definition SensorRTC.h:199
uint8_t getMinute() const
Definition SensorRTC.h:201
uint8_t getHour() const
Definition SensorRTC.h:200
uint8_t getWeek() const
Definition SensorRTC.h:203
uint8_t getSecond() const
Definition SensorRTC.h:202
uint8_t getMinute() const
Definition SensorRTC.h:149
uint8_t getMonth() const
Definition SensorRTC.h:146
uint8_t getDay() const
Definition SensorRTC.h:147
uint16_t getYear() const
Definition SensorRTC.h:145
uint8_t getHour() const
Definition SensorRTC.h:148
uint8_t getSecond() const
Definition SensorRTC.h:150
bool(*)(uint8_t addr, uint8_t reg, uint8_t *buf, size_t len, bool writeReg, bool isWrite) CustomCallback
bool clrRegBit(uint8_t reg, uint8_t bit)
bool getRegBit(uint8_t reg, uint8_t bit)
int readReg(uint8_t reg) const
int writeRegBuff(uint8_t reg, uint8_t *buf, size_t len)
int writeReg(uint8_t reg, uint8_t val)
int readRegBuff(uint8_t reg, uint8_t *buf, size_t len) const
bool setRegBit(uint8_t reg, uint8_t bit)
Driver for the PCF85063 real-time clock (RTC) over I2C.
ClockHz
Clock output frequency selection.
@ CLK_LOW
Lowest/low-power output option (chip-specific)
void resetAlarm()
Clear/reset the alarm flag.
static constexpr uint8_t PCF85063_CTRL1_SOFTRST_EN_MASK
static constexpr uint8_t PCF85063_CTRL1_CIE_EN_MASK
static constexpr uint8_t PCF85063_MONTH_REG
static constexpr uint8_t PCF85063_SEC_REG
static constexpr uint8_t PCF85063_CTRL1_REG
static constexpr uint8_t PCF8563_ALRM_HR_REG
bool isRunning()
Check whether the RTC oscillator is currently running.
static constexpr uint8_t PCF85063_ALRM_MIN_REG
static constexpr uint8_t PCF85063_CTRL1_CLOCK_EN_MASK
bool isAlarmActive()
Check whether the alarm flag is active.
void setDateTime(RTC_DateTime datetime) override
Set the RTC date and time.
void setAlarmByHours(uint8_t hour)
Convenience: enable only hour alarm.
const char * getChipName() override
Get RTC chip name.
void start()
Start the RTC oscillator (timekeeping runs).
RTC_Alarm getAlarm()
Read current alarm configuration from the device.
static constexpr uint8_t PCF85063_HR_REG
SensorPCF85063()=default
Construct a SensorPCF85063 instance.
void reset() override
Reset the RTC.
bool begin(SensorCommCustom::CustomCallback callback)
Initialize device using a custom transport callback.
static constexpr uint8_t PCF85063_ALARM_ENABLE
static constexpr uint8_t PCF85063_CTRL1_HOUR_FORMAT_12H_MASK
static constexpr uint8_t PCF85063_RAM_REG
static constexpr uint8_t PCF85063_YEAR_REG
void disableAlarm()
Disable alarm interrupt/event generation.
static constexpr uint8_t PCF85063_ALRM_WEEK_REG
static constexpr uint8_t PCF85063_MIN_REG
void enableAlarm()
Enable alarm interrupt/event generation.
static constexpr uint8_t PCF85063_NO_ALARM
static constexpr uint8_t PCF85063_CTRL2_REG
RTC_DateTime getDateTime() override
Read the RTC date and time.
static constexpr uint8_t PCF85063_ALRM_SEC_REG
~SensorPCF85063()=default
Destructor.
static constexpr uint8_t PCF85063_DAY_REG
bool isClockIntegrityGuaranteed()
Check whether the clock integrity is guaranteed.
void setAlarmByMinutes(uint8_t minute)
Convenience: enable only minute alarm.
void setAlarmBySecond(uint8_t second)
Convenience: enable only second alarm.
void setAlarm(RTC_Alarm alarm)
Set alarm using RTC_Alarm object.
static constexpr uint8_t PCF85063_OFFSET_REG
bool is24Hour
Hour mode flag (true = 24-hour mode).
void setAlarmByWeekDay(uint8_t week)
Convenience: enable only weekday alarm.
void setClockOutput(ClockHz hz)
Configure the clock output frequency.
static constexpr uint8_t PCF85063_WEEKDAY_REG
static constexpr uint8_t PCF85063_TIMER_MD_REG
static constexpr uint8_t PCF85063_CTRL1_TEST_EN_MASK
static constexpr uint8_t PCF85063_TIMER_VAL_REG
static constexpr uint8_t PCF85063_ALRM_DAY_REG
void setAlarm(uint8_t hour, uint8_t minute, uint8_t second, uint8_t day, uint8_t week)
Set the alarm fields (hour/minute/second/day/weekday).
void setAlarmByDays(uint8_t day)
Convenience: enable only day-of-month alarm.
void stop()
Stop the RTC oscillator (timekeeping stops).
uint32_t getDayOfWeek(uint32_t day, uint32_t month, uint32_t year)
Calculate the day of the week for a given date using Zeller's congruence.
Definition SensorRTC.h:483
virtual void setDateTime(RTC_DateTime datetime)=0
Set the date and time of the RTC using an RTC_DateTime object.
static uint8_t BCD2DEC(uint8_t val)
Convert a Binary Coded Decimal (BCD) number to a decimal number.
Definition SensorRTC.h:657
uint8_t getDaysInMonth(uint8_t month, uint16_t year)
Get the number of days in a given month of a specific year, considering leap years.
Definition SensorRTC.h:552
virtual RTC_DateTime getDateTime()=0
Get the current date and time from the RTC.
static uint8_t DEC2BCD(uint8_t val)
Convert a decimal number to a Binary Coded Decimal (BCD) number.
Definition SensorRTC.h:667
constexpr uint32_t _bv(uint8_t b)
Definition SensorLib.h:62
const uint8_t PCF85063_SLAVE_ADDRESS