Step 33 of 56
PCF85063A: a clock that tells you when not to trust it
BCD calendar registers, a programmable alarm, and one flag that answers the only question that matters after a power loss.
The typed calendar
A small fixed-address (0x51) real-time clock. The time is not a
blob of BCD bytes in the API — every field is a constrained subtype, so an
impossible date cannot be constructed:
subtype Year_Number is Natural range 2000 .. 2099;
subtype Month_Number is Natural range 1 .. 12;
subtype Day_Number is Natural range 1 .. 31;
subtype Hour_Number is Natural range 0 .. 23; -- 24-hour mode only
subtype Minute_Number is Natural range 0 .. 59;
subtype Second_Number is Natural range 0 .. 59;
type Weekday is (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday);
type Time is record ... end record;
Day-of-week is worth knowing about: in the chip it is just a free
0 .. 6 counter that nothing validates against the date. The
Weekday naming is a convention the driver applies, not something the
hardware enforces — so the chip will happily tell you a Tuesday that isn't
one if something wrote it wrong.
The flag that matters
procedure Get_Time (Dev : Device; T : out Time;
Valid : out Boolean; Result : out Status);
Valid is the whole point of using an RTC
chip. It reflects the oscillator-stop flag: False means
power was lost and the time it just handed you is meaningless. A clock that
returns a plausible-looking wrong time is worse than one that admits it does not
know, so branch on Valid before believing T — that is
the difference between resuming a schedule and corrupting a log.
Set_Time stops the clock around the write, as the datasheet
requires, and clears the flag.
The rest
- Alarm on second, minute, hour, day or weekday — any
subset — asserting an active-low open-drain INT line. Attach it with the
.Interruptschild, observing the callback rules: latch in the handler, do the I2C read in a task. Stop_Clockhalts the counters viaControl_1.STOPwithout changing the loaded time.Resetreturns every register to its power-on default, which also stops the clock.
Reads use the auto-incrementing pointer, and the pointer survives the STOP between the two transactions — so a one-byte write followed by a separate read streams correctly without needing repeated START. Up to 400 kHz.