Design of a function that modifies from 1-4 values of a register

43 Views Asked by At

I'm writing a C program (library) to control an IC that performs voltage and current measurements - the INA260 mfd by TI. Part of this effort requires setting values in the Configuration Register; these values control how the IC performs its measurements. The Configuration Register is 16 bits, and contains four (4) three-bit values (let's call them tribbles) that control key aspects of the measurements (ref Fig. 30 & Table 5 on p. 22 of the PDF for those interested).

My initial approach to setting values in the Configuration Register has been to create separate functions to modify each of the 4 tribbles. This works, but it doesn't seem particularly efficient to me. One alternative I've considered is use of a 'variadic' function as they can support a variable number of arguments. IOW, the user may wish to use default values for three of the tribbles, and therefore needs to change only one - or - he may wish to change two tribble values. Fig. 30

As I started to write this function I realized it's not as straightforward as the examples for computing an average or sum of a set of numbers. Each tribble is defined by not only its value (0-7), but also its position in the Configuration Register.

I began researching possibilities for passing a 2x(1-4) array, but search results suggested this was a non-starter... then I hit on the idea of asking on SO, and here I am.

Given that all Configuration Register changes should be accomplished through a single function call, is there a way to accomplish that as a variadic function - or should I be looking at something else?

1

There are 1 best solutions below

1
KamilCuk On

or should I be looking at something else?

I would just represent the intention of setting the default as just an invalid or sentinel value. Variadic functions are really hard and error prone, just a normal function.

the user may wish to use default values for three of the tribbles, and therefore needs to change only one - or - he may wish to change two tribble values

Taking inspiration from https://github.com/thomoray/INA260/blob/master/INA260.h#L68 and from https://github.com/thomoray/INA260/blob/master/INA260.cpp , the user would:

union ConfigurationRegister {
    struct __attribute__((packed)) {
        uint16_t mode : 3;
        uint16_t ishct : 3;
        uint16_t vbusct : 3;
        uint16_t avg : 3;
        uint16_t : 3;
        uint16_t rst : 1;
    };
    uint16_t rawValue;
};

void changeConfigurationRegister(
       int8_t mode,
       int8_t ishct,
       int8_t vbusct,
       int8_t avg) {
    ConfigurationRegister reg = readConfigurationRegister();
    if (mode != -1) reg.mode = mode;
    if (ishct != -1) reg.ishct = ishct;
    if (vbusct != -1) reg.vbusct = vbusct;
    if (avg != -1) reg.avg = avg;
    return writeConfigurationRegister(reg);
}

And done - you have one function, and you can choose which settings stay. You can represent with -1 a "no change" action. You can realize your intention with the call:

 changeConfigurationRegister(-1, -1, -1, 0b101)

Alternatively, you could just add bools, but that would be more parameters.

Do not overcomplicate that it needs to be. KISS, prefer it simple, understandable, easy to use, readable.