This is my complete code, it's working like 90%, I just need to do some improvements.
It's a console simulation for Arduino code. Because I want to design the main FSM code in codeblocks then move the actual implementation to Arduino code.
Code:
/* Title: function pointers Date: Thu, 30 July 2020
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <malloc.h>
#include <math.h>
// definitions
#define CURSOR_MOVE 0
#define PIXEL_WRITE 1
#define CHARS_WRITE 2
#define GRAPHICS_SET 3
// enumerations
enum TASK_STATES{CMD, DATA, STRING};
enum TASK_STATES state;
// delay variables
uint32_t dly_st, delay_period;
bool dly_lock, lock;
bool write_lock;
uint16_t i, counter, counts, str_counts, cmd_state;
// command / data variables
char * str_buf;
const char *str_ptr;
const char *str1 = {"hi how are you ?"};
// basic pixel variables
uint8_t y,x, task_buffer[16];
bool row2_4, graphics;
// functions
void task_switcher(void);
void task1(void);
void task2(void);
void write_chars(uint8_t row, uint8_t col, const char *str);
void graphics_set_mode(bool mode);
void transmit(uint8_t cmd);
void delay_routine(void);
// function pointers
void (*fun_ptr)(void); // main function pointer
int main(){
//graphics_set_mode(1); // not finished !
task1();printf("\n\n>>2nd function>>\n\n\n");task2();
//write_chars(0,0,str1);
return 0;
}
//////////////////////////////////////////////////////
// lcd transmission commands/data, locks and callback functions
void task_switcher(void){
if(!dly_lock){
switch(state){
case CMD:
if(counter < counts){
transmit(task_buffer[counter]);
counter++;
}
else{
if(cmd_state == PIXEL_WRITE){
counts = 4; // counter = 2 at this point
state = DATA;
}
else if(cmd_state == CURSOR_MOVE || cmd_state == GRAPHICS_SET){
write_lock = 0;
}
else if(cmd_state == CHARS_WRITE){
counter = 0;
counts = str_counts;
state = DATA;
strcpy(task_buffer,str_ptr);
}
}
break;
case DATA:
if(counter < counts){
transmit(task_buffer[counter]);
counter++;
}
else{
write_lock = 0;
counter = 0; // cleared for multiple pixels writes
if(cmd_state == PIXEL_WRITE){
counts = 2;
state = CMD; // multiple pixels writes
printf("\n"); // for this program data display
}
if(cmd_state == CHARS_WRITE){
}
}
break;
}
}
else {delay_routine();} // first check delay flag
if(write_lock){task_switcher();} // still between cmd1-data2
else if(lock){fun_ptr();} // method2 function pointer
//else if(!write_lock){lock = 0;} // finished writes ? : clear lock
}
void write_chars(uint8_t row, uint8_t col, const char *str){
if(!lock){
state = CMD;
cmd_state = CHARS_WRITE;
if(graphics){graphics_set_mode(0);}
counter = 0; counts = 1;
str_counts = strlen(str);
str_ptr = str;
lock = 1;
}
// identify row/column location
else{
if (row == 1)task_buffer[0] = (0x80 + (col - 1));
else if (row == 2)task_buffer[0] = (0x90 + (col - 1));
else if (row == 3)task_buffer[0] = (0x88 + (col - 1));
else if (row == 4)task_buffer[0] = (0x98 + (col - 1));
}
write_lock = 1;
task_switcher();
}
// graphics mode
void graphics_set_mode(bool mode){
if(!lock){
state = CMD;
cmd_state = GRAPHICS_SET;
task_buffer[0] = 1;
counter = 0; counts = 3;
write_lock = 0;
if(mode){
task_buffer[1] = 11;
task_buffer[2] = 22;
graphics = 1;
}
else{
task_buffer[1] = 33;
task_buffer[2] = 44;
graphics = 0;
}
write_lock = 1;
lock = 1;
task_switcher();
}
}
void task2(void){
if(!lock){
fun_ptr = &task2;
state = CMD;
cmd_state = PIXEL_WRITE;
x = 0; y = 0;
counter = 0; counts = 2;
lock = 1; row2_4 = 0; write_lock = 0;
}
if(y<2 && !row2_4){ // 1st half of lcd
task_buffer[0] = y; task_buffer[1] = x;
task_buffer[2] = 'E'; task_buffer[3] = 'F';
}
if(y<4 && row2_4){ // 2nd half of lcd
task_buffer[0] = y; task_buffer[1] = x;
task_buffer[2] = 'G'; task_buffer[3] = 'H';
}
x++; if(x>7){y++;x=0;}
if(y>1){row2_4 = 1;}
if(y>3){row2_4 = 0;lock = 0;}
write_lock = 1;
task_switcher();
}
void task1(void){
if(!lock){
fun_ptr = &task1;
state = CMD;
cmd_state = PIXEL_WRITE;
x = 0; y = 0;
counter = 0; counts = 2;
lock = 1; row2_4 = 0; write_lock = 0;
}
if(y<2 && !row2_4){ // 1st half of lcd
task_buffer[0] = y; task_buffer[1] = x;
task_buffer[2] = 'A'; task_buffer[3] = 'B';
}
if(y<4 && row2_4){ // 2nd half of lcd
task_buffer[0] = y; task_buffer[1] = x;
task_buffer[2] = 'C'; task_buffer[3] = 'D';
}
x++; if(x>7){y++;x=0;}
if(y>1){row2_4 = 1;}
if(y>3){row2_4 = 0;lock = 0;}
write_lock = 1;
task_switcher();
}
// command tx
void transmit(uint8_t cmd){
if(state == CMD) {printf("%d ",cmd);}
else {printf("%c ",cmd);}
}
// delay routine
void delay_routine(void){if(dly_lock){dly_lock = 0;}}