Thanks for all your feedback. It helped.
I rewrote this yet another time and this time it works perfectly. I included three variations: a simple example using an array of function pointers, a Lambda version and a complex version like what I started with.
#define TASK_COUNT 3
typedef void ( *taskPointer ) ( );
// Simple Version:
void taskS1 () { Serial.println ( ( char* )"SIMPLE TASK 1" ); }
void taskS2 () { Serial.println ( ( char* )"SIMPLE TASK 2" ); }
void taskS3 () { Serial.println ( ( char* )"SIMPLE TASK 3" ); }
// Array of pointers to tasks
taskPointer callSimpleTask [ ] = {
taskS1,
taskS2,
taskS3,
};
// Run the simple test
void showSimpleVersion () {
Serial.println ( F ( "\nSimple Version:" ) );
for (uint8_t i = 0; i < TASK_COUNT; i++) {
callSimpleTask [ i ] ();
}
}
// Lambda Version: No separate task definitoins
void ( *callLambdaTask [ ] ) ( ) = {
[ ] {Serial.println ( ( char* )"LAMBDA TASK 1" ); },
[ ] {Serial.println ( ( char* )"LAMBDA TASK 2" ); },
[ ] {Serial.println ( ( char* )"LAMBDA TASK 3" ); },
};
// Run the Lambda test
void showLambdaVersion () {
Serial.println ( F ( "\nLambda Version:" ) );
for (uint8_t i = 0; i < TASK_COUNT; i++) {
callLambdaTask [ i ] ();
}
}
// Complex Version: Each array element is a struct containing a
// pointer to the corresponding task and related properties
struct complexTaskDefinition {
taskPointer task;
bool repeat; // Repeat flashing after delay
int32_t iterations; // # times to repeat... -1 = forever
uint32_t delay; // MS to wait before execution
};
// Create a pointer to a task definition
complexTaskDefinition *task;
// Prove that called function can call other functions:
void taskC1 () { showTaskC1(); }
void taskC2 () { showTaskC1 (); }
void taskC3 () { showTaskC1 (); }
void showTaskC1 () {
Serial.println ( ( char* )"COMPLEX TASK 1" );
}
void showTaskC2 () {
Serial.println ( ( char* )"COMPLEX TASK 2" );
}
void showTaskC3 () {
Serial.println ( ( char* )"COMPLEX TASK 3" );
}
complexTaskDefinition tasks [ ] [4] = {
{taskC1, true, -1, 1000 }, // taskC1 repeats forever every second
{taskC2, true, 10, 2000 }, // taskC2 runs 10 times pausing for 2 seconds between iterations
{taskC3, false, 3, 3000 }, // taskC3 runs 3 times with 3 second delays between each, then dies
};
void showComplexTaskList () {
Serial.println ( F ( "\nComplex Task List:" ) );
for (uint8_t i = 0; i < TASK_COUNT; i++) {
task = tasks [ i ];
Serial.print ( '[' );
Serial.print ( i );
Serial.print ( F ( "] REPEAT:" ));
Serial.print ( ( task->repeat ) ? "YES" : "NO" );
Serial.print ( F ( ", DELAY:" ) );
Serial.print ( task->delay );
Serial.print ( F ( ", ITERATIONS:" ) );
Serial.print ( task->iterations );
Serial.println ();
}
}
void showComplexVersion () {
Serial.println ( F ( "\nComplex Version:" ) );
for (uint8_t i = 0; i < TASK_COUNT; i++) {
task = tasks [ i ];
task->task ();
// (( *tasks ) [ i ]).task ();
}
}
void setup () {
Serial.begin ( 115200 );
while (!Serial.availableForWrite ()) {}
showSimpleVersion ();
showLambdaVersion ();
showComplexVersion ();
showComplexTaskList ();
}
void loop () {
}
Here is the output: Simple Version:
SIMPLE TASK 1
SIMPLE TASK 2
SIMPLE TASK 3
Lambda Version:
LAMBDA TASK 1
LAMBDA TASK 2
LAMBDA TASK 3
Complex Version:
COMPLEX TASK 1
COMPLEX TASK 1
COMPLEX TASK 1
Complex Task List:
[0] REPEAT:YES, DELAY:1000, ITERATIONS:-1
[1] REPEAT:YES, DELAY:2000, ITERATIONS:10
[2] REPEAT:NO, DELAY:3000, ITERATIONS:3
I want to run one more experiment, this time with the complex version as a class.
&task1, &task2, &task3
is more correct.&
is entirely optional for function pointers. Neither is "more correct" than the other, they are both completely correct.