I'm writing for a very limited resource embedded processor. I have a struct that captures a time series of events, and I'd like to use the same graphing function against different values of different types. Something like (very stripped down; don't sweat uninitialized values, etc):
#define GRAPH_ONE 1
#define GRAPH_TWO 2
struct _event_t {
unsigned long timestamp;
int sensorOne;
float sensorTwo;
}
typedef struct _event_t event_t;
event_t[10] MyEvents;
void GraphSensor(byte graphType) {
for (unsigned int i = 0; i < 9; i++) {
// Get minimum value from series
if (MyEvents[i].?????) ...
}
}
How can I have my function operate on different members of the struct? I can see doing it with a ton of switch (graphType)
statements, but that's pretty ugly. There could easily be 8 or 10 members of the struct. I could move all of those to a separate function and make every bit of data access call that function, always returning a float (which should be OK for my graph). Finally I could convert to C++ classes, which opens other means.
None of those feel right. Is there a better approach, preferably a very lightweight one?
You could wrap the accessor you need in a function, and pass that to the function that walks the array and aggregates the results. For example
float getSensor1(const event_t* t)
{
return t->sensorOne;
}
float getSensor2(const event_t* t)
{
return t->sensorTwo;
}
void GraphSensor(float (*accessor)(const event_t*)) {
// Get minimum value from series
float min_value = MAX_FLOAT;
for (unsigned int i = 0; i < 9; i++) {
float x = accessor(MyEvents + i);
if (x < min_value)
min_value = x;
}
}
/* later on . . . */
GraphSensor(getSensor1);
GraphSensor(getsensor2);
You are basically decoupling the access of the data from the operation on it, and homogenizing it all to floats. The aggregation operation could also be encapsulated into a function, too. But that's getting pretty close to map-reduce. :)
You could change the struct to an array which uses perhaps all floats. In that way the data handling is completely homogeneous.
#define N_SENSORS 12
#define N_EVENTS 10
float MyEvents [N_EVENTS] [N_SENSORS];
void GraphSensor(byte graphType)
{
float min = 1e38;
for (unsigned int i = 0; i < N_EVENTS; i++)
{
// Get minimum value from series
if (MyEvents[i][graphType] < min)
min = MyEvents[i][graphType];
}
}
Perhaps the timestamp could be there too in element zero maybe using spreadsheet conventions: integer part is days since 1970 or 1900 and fractional part is portion of the day (so noon = .5).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With