fix: an alarm clear keeps the other alarm's flag, and arming keeps BBSQW

A1F and A2F ignore a written 1, so the status write-back now writes the
flag not being cleared as 1: an alarm firing between the read and the
write was cleared with the other. BBSQW gates the alarm interrupt on
battery as well as the square wave (19-5170 rev. 4), so arming an alarm
no longer clears it. Both register computations are consteval-tested.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
BlackMarkandClaude Opus 5.5 committed 2026-10-23 21:42:32 +02:00
1 parent 50c424d3d2
commit 4df536d0a5
2 files changed
+52 -22

No files matched your search

+18
View File
@@ -79,4 +79,22 @@ static_assert(static_cast<std::uint8_t>(alarm2_rate::once_per_minute) ==
static_assert(static_cast<std::uint8_t>(alarm2_rate::weekday_time_match) ==
static_cast<std::uint8_t>(alarm1_rate::weekday_time_match) >> 1);
// A1F and A2F ignore a written 1 and OSF holds until written 0 (19-5170,
// Status Register): clearing one alarm must write the other as 1, or an alarm
// firing between the read and the write is lost.
using ds3231::detail::status_clearing;
static_assert(status_clearing(0x00, 0x01) == 0x02); // A2F set after the read survives
static_assert(status_clearing(0x03, 0x02) == 0x01);
static_assert(status_clearing(0x88, 0x01) == 0x8a); // OSF and EN32kHz kept as read
static_assert(status_clearing(0x80, 0x80) == 0x03);
// BBSQW keeps INT/SQW driven on battery for the alarm interrupt as well as the
// square wave (19-5170, Control Register and rev. 4), so arming an alarm must
// leave it as found.
using ds3231::alarm_interrupt;
using ds3231::detail::control_with;
static_assert(control_with(0x40, 0x01, alarm_interrupt::on) == 0x45);
static_assert(control_with(0x00, 0x02, alarm_interrupt::on) == 0x06);
static_assert(control_with(0x47, 0x01, alarm_interrupt::off) == 0x46);
} // namespace