dal-c library ← coverage

§ Coverage

src/sc_pid.c

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}