16#if PC_ENABLE_SAFETY_SCL
22void trip(SclConn *c, SclFault why)
26 if (c->state != SclState::FAILSAFE)
28 c->state = SclState::FAILSAFE;
33uint32_t wrap(uint32_t v, uint32_t mod)
35 return mod ? (v % mod) : v;
39void pc_scl_init(SclConn *c, uint32_t first_counter, uint32_t counter_mod, uint32_t watchdog_ms, uint32_t now)
45 c->state = SclState::INIT;
46 c->fault = SclFault::PC_NONE;
47 c->counter_mod = counter_mod;
48 c->expected = wrap(first_counter, counter_mod);
49 c->watchdog_ms = watchdog_ms;
55bool pc_scl_on_frame(SclConn *c,
bool signature_ok, uint32_t counter, uint32_t now)
61 if (c->state == SclState::FAILSAFE)
72 trip(c, SclFault::SIGNATURE);
75 if (wrap(counter, c->counter_mod) != c->expected)
78 trip(c, SclFault::COUNTER);
82 c->expected = pc_scl_next_counter(c->expected, c->counter_mod);
85 c->state = SclState::RUNNING;
89bool pc_scl_poll(SclConn *c, uint32_t now)
95 if (c->state == SclState::FAILSAFE)
101 if (c->state == SclState::RUNNING && c->watchdog_ms && (now - c->last_ok_ms) >= c->watchdog_ms)
103 trip(c, SclFault::TIMEOUT);
109void pc_scl_reset(SclConn *c, uint32_t first_counter, uint32_t now)
115 c->state = SclState::INIT;
116 c->fault = SclFault::PC_NONE;
117 c->expected = wrap(first_counter, c->counter_mod);
123bool pc_scl_ok(
const SclConn *c)
125 return c && c->state != SclState::FAILSAFE;
128SclState pc_scl_state(
const SclConn *c)
130 return c ? c->state : SclState::FAILSAFE;
133SclFault pc_scl_fault(
const SclConn *c)
135 return c ? c->fault : SclFault::PC_NONE;
138uint32_t pc_scl_next_counter(uint32_t counter, uint32_t counter_mod)
140 uint32_t n = counter + 1u;
141 return counter_mod ? (n % counter_mod) : n;
IEC 61784-3 black-channel Safety Communication Layer - the shared primitives (PC_ENABLE_SAFETY_SCL).