C3: AlarmSeverity bit-flag enum + classification helpers

ALCD's lower 7 bits are a bitmap of category flags per E5 §10.3 and
E30 §6.13; a single alarm may carry multiple categories at once
(e.g. an irrecoverable equipment-safety fault is 0x10 | 0x02).
Adds:

  enum class AlarmSeverity : uint8_t
    PersonalSafety  EquipmentSafety  ParameterError  ParameterWarning
    Irrecoverable   EquipmentStatus  Attention

  has_severity(alcd, bit), severity_bits(alcd)
  Alarm::has(bit), Alarm::is_safety()
  constexpr severity_mask = 0x7F

Tests cover single-category alarms, multi-category combos, and that
the bit-7 SET/CLEAR flag is correctly excluded from category bits.

Closes Tranche C (E5 alarm/exception state model).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 23:52:09 +02:00
parent af25bc8726
commit c163d2060f
2 changed files with 58 additions and 3 deletions
+28
View File
@@ -169,6 +169,34 @@ TEST_CASE("alarm enable / set / clear / list") {
CHECK(r.all().size() == 2);
}
TEST_CASE("AlarmSeverity bit-flag helpers (E5 §10.3 / E30 §6.13)") {
// Single-category alarms.
Alarm safety{1, "door open", static_cast<uint8_t>(AlarmSeverity::PersonalSafety)};
CHECK(safety.has(AlarmSeverity::PersonalSafety));
CHECK_FALSE(safety.has(AlarmSeverity::EquipmentSafety));
CHECK(safety.is_safety());
Alarm temp_warn{2, "chiller high",
static_cast<uint8_t>(AlarmSeverity::ParameterWarning)};
CHECK_FALSE(temp_warn.is_safety());
CHECK(temp_warn.has(AlarmSeverity::ParameterWarning));
// Multi-category alarms: combine Irrecoverable + EquipmentSafety.
Alarm combo{3, "spindle seized",
static_cast<uint8_t>(
static_cast<uint8_t>(AlarmSeverity::EquipmentSafety) |
static_cast<uint8_t>(AlarmSeverity::Irrecoverable))};
CHECK(combo.is_safety());
CHECK(combo.has(AlarmSeverity::Irrecoverable));
CHECK(combo.has(AlarmSeverity::EquipmentSafety));
CHECK_FALSE(combo.has(AlarmSeverity::PersonalSafety));
// The ALCD set-bit is *not* part of the category bitmap.
const uint8_t set_alcd = static_cast<uint8_t>(combo.severity_category | 0x80);
CHECK(severity_bits(set_alcd) == combo.severity_category);
CHECK(has_severity(set_alcd, AlarmSeverity::Irrecoverable));
}
// ---- Process programs ----------------------------------------------------
TEST_CASE("recipe CRUD") {