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:
@@ -10,13 +10,40 @@
|
|||||||
|
|
||||||
namespace secsgem::gem {
|
namespace secsgem::gem {
|
||||||
|
|
||||||
|
// ALCD bit-flag categories (E5 §10.3 / E30 §6.13). The lower 7 bits
|
||||||
|
// of ALCD are a bitmap — an alarm may carry multiple categories at
|
||||||
|
// once (e.g. an irrecoverable equipment-safety fault is 0x10 | 0x02).
|
||||||
|
// Bit 7 is the alarm SET/CLEAR flag, applied at emit time and not
|
||||||
|
// part of the category bitmap.
|
||||||
|
enum class AlarmSeverity : uint8_t {
|
||||||
|
PersonalSafety = 0x01,
|
||||||
|
EquipmentSafety = 0x02,
|
||||||
|
ParameterError = 0x04, // parameter control error
|
||||||
|
ParameterWarning = 0x08, // parameter control warning
|
||||||
|
Irrecoverable = 0x10,
|
||||||
|
EquipmentStatus = 0x20, // equipment status warning
|
||||||
|
Attention = 0x40, // attention flag (lowest-priority)
|
||||||
|
};
|
||||||
|
|
||||||
|
inline constexpr uint8_t severity_mask = 0x7F;
|
||||||
|
|
||||||
|
inline bool has_severity(uint8_t alcd, AlarmSeverity bit) {
|
||||||
|
return (alcd & static_cast<uint8_t>(bit)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint8_t severity_bits(uint8_t alcd) { return alcd & severity_mask; }
|
||||||
|
|
||||||
struct Alarm {
|
struct Alarm {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
std::string text;
|
std::string text;
|
||||||
// Lower 7 bits of ALCD: severity category (1=personal safety,
|
// Lower 7 bits of ALCD: severity bitmap (see AlarmSeverity). Bit 7
|
||||||
// 2=equipment safety, 4=parameter control error, ...). Bit 7 marks
|
// marks set vs cleared and is applied at emit time.
|
||||||
// set vs cleared and is applied at emit time.
|
|
||||||
uint8_t severity_category;
|
uint8_t severity_category;
|
||||||
|
|
||||||
|
bool has(AlarmSeverity bit) const { return has_severity(severity_category, bit); }
|
||||||
|
bool is_safety() const {
|
||||||
|
return has(AlarmSeverity::PersonalSafety) || has(AlarmSeverity::EquipmentSafety);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class AlarmAck : uint8_t {
|
enum class AlarmAck : uint8_t {
|
||||||
|
|||||||
@@ -169,6 +169,34 @@ TEST_CASE("alarm enable / set / clear / list") {
|
|||||||
CHECK(r.all().size() == 2);
|
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 ----------------------------------------------------
|
// ---- Process programs ----------------------------------------------------
|
||||||
|
|
||||||
TEST_CASE("recipe CRUD") {
|
TEST_CASE("recipe CRUD") {
|
||||||
|
|||||||
Reference in New Issue
Block a user