§ Coverage
1/*2 * sc_pid.c -- implementation. Blocks are tagged with the low-level3 * requirement they satisfy; see requirements/sc_pid.md.4 */5#include "sc_pid.h"675sc_status_t sc_pid_config_valid(const sc_pid_config_t *cfg)8{9 sc_status_t status;10115 if (cfg == NULL)condition outcomes covered 2/212 {131 status = SC_ERR_NULL; /* LLR-PID-11 */14 }154 else if (cfg->out_min > cfg->out_max)condition outcomes covered 2/216 {171 status = SC_ERR_PARAM; /* LLR-PID-12 */18 }193 else if ((cfg->d_filter < 0) || (cfg->d_filter >= SC_Q16_ONE))condition outcomes covered 4/420 {212 status = SC_ERR_PARAM; /* LLR-PID-13 */22 }23 else24 {251 status = SC_OK; /* LLR-PID-14 */26 }27285 return status;29}303111sc_status_t sc_pid_init(sc_pid_state_t *state,32 sc_q16_t initial_output,33 sc_q16_t initial_measurement)34{35 sc_status_t status;363711 if (state == NULL)condition outcomes covered 2/238 {391 status = SC_ERR_NULL; /* LLR-PID-15 */40 }41 else42 {4310 state->integrator = initial_output; /* LLR-PID-16 */4410 state->prev_measurement = initial_measurement;4510 state->prev_derivative = 0;4610 status = SC_OK;47 }484911 return status;50}5152416sc_q16_t sc_pid_update(const sc_pid_config_t *cfg,53 sc_pid_state_t *state,54 sc_q16_t setpoint,55 sc_q16_t measurement)56{57 sc_q16_t result;5859416 if ((cfg == NULL) || (state == NULL))condition outcomes covered 4/460 {612 result = 0; /* LLR-PID-1 */62 }63 else64 {65414 sc_q16_t error = sc_q16_sub(setpoint, measurement); /* LLR-PID-2 */66414 sc_q16_t p_term = sc_q16_mul(cfg->kp, error); /* LLR-PID-3 */6768414 sc_q16_t d_meas = sc_q16_sub(measurement, state->prev_measurement);69414 sc_q16_t d_raw = sc_q16_mul(cfg->kd, sc_q16_sub(0, d_meas)); /* LLR-PID-4 */70828 sc_q16_t d_term = sc_q16_add(71414 sc_q16_mul(cfg->d_filter, state->prev_derivative),72414 sc_q16_mul(sc_q16_sub(SC_Q16_ONE, cfg->d_filter), d_raw)); /* LLR-PID-5 */7374414 sc_q16_t i_new = sc_q16_add(state->integrator,75414 sc_q16_mul(cfg->ki, error)); /* LLR-PID-6 */7677414 sc_q16_t out_raw = sc_q16_add(sc_q16_add(p_term, i_new), d_term); /* LLR-PID-7 */7879414 if (out_raw > cfg->out_max)condition outcomes covered 2/280 {813 result = cfg->out_max; /* LLR-PID-8 */823 if (i_new <= state->integrator) /* only integrate off the rail */condition outcomes covered 2/283 {842 state->integrator = i_new;85 }86 }87411 else if (out_raw < cfg->out_min)condition outcomes covered 2/288 {893 result = cfg->out_min; /* LLR-PID-9 */903 if (i_new >= state->integrator)condition outcomes covered 2/291 {922 state->integrator = i_new;93 }94 }95 else96 {97408 result = out_raw; /* LLR-PID-10 */98408 state->integrator = i_new;99 }100101414 state->prev_measurement = measurement;102414 state->prev_derivative = d_term;103 }104105416 return result;106}