Program Listing for File bal.c

Return to documentation for file (mainboard/Src/bal.c)

#include "bal.h"

#include <stddef.h>

#ifndef max
#define max(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif

uint8_t _max_index(uint16_t data[], size_t count) {
    uint8_t max = 0;
    for (uint8_t i = 0; i < count; i++) {
        if (data[i] > data[max])
            max = i;
    }

    return max;
}

uint16_t _min_index(voltage_t data[], size_t count) {
    uint16_t min_value_index = 0;
    for (uint16_t i = 0; i < count; i++) {
        if (data[i] < data[min_value_index])
            min_value_index = i;
    }

    return min_value_index;
}

void _bal_hateville_solution(uint16_t DP[], uint16_t i, uint16_t out[], uint16_t *out_index) {
    if (i == 0) {
        return;
    } else if (i == 1) {
        if (DP[1] > 0) {
            out[(*out_index)++] = 0;
        }
        return;
    } else if (DP[i] == DP[i - 1]) {
        _bal_hateville_solution(DP, i - 1, out, out_index);
        return;
    } else {
        _bal_hateville_solution(DP, i - 2, out, out_index);
        out[(*out_index)++] = i - 1;

        return;
    }
}

uint16_t _bal_hateville(uint16_t D[], uint16_t count, uint16_t solution[]) {
    uint16_t DP[count + 1];

    DP[0] = 0;
    DP[1] = D[0];

    for (uint16_t i = 2; i < count + 1; i++) {
        DP[i] = max(DP[i - 1], DP[i - 2] + D[i - 1]);
    }

    uint16_t out_index = 0;
    _bal_hateville_solution(DP, count, solution, &out_index);
    return out_index;
}

/* @section Public functions */

uint16_t bal_get_cells_to_discharge(voltage_t volts[], uint16_t count, voltage_t threshold, uint16_t cells[]) {
    voltage_t imbalance[count];

    uint16_t len = bal_compute_imbalance(volts, count, threshold, imbalance);
    if (len == 0) {
        return false;
    }

    return bal_exclude_neighbors(imbalance, len, cells);
}

uint16_t bal_compute_imbalance(voltage_t volts[], uint16_t count, voltage_t threshold, uint16_t cells[]) {
    uint16_t indexes = 0;
    uint16_t min_index = _min_index(volts, count);

    for (uint16_t i = 0; i < count; i++) {
        cells[i] = max(0, volts[i] - (volts[min_index] + threshold));
        if (cells[i] > 0) {
            indexes++;
        }
    }
    return indexes;
}

uint16_t bal_exclude_neighbors(uint16_t data[], uint16_t count, uint16_t cells[]) {
    for (uint16_t i = 0; i < PACK_CELL_COUNT; i++) {
        cells[i] = BAL_NULL_INDEX;
    }

    return _bal_hateville(data, PACK_CELL_COUNT, cells);
}