back to embedded

C Callback

 

#define TOPBTNDEBOUNCE 0x03
#define BOTBTNDEBOUNCE 0x04

unsigned char delayOp[10];
unsigned int delayOpTime[10];
unsigned int delayOpCheck[10];
unsigned char opPointer;

unsigned char opMax;

//this is the timer function called on interrupt every millisecond
void Timer_MS(void){
    //do delay op timer incrementing
    char i;
    for(i=0; i<opPointer; i++){
        delayOpTime[i]++;
    }
}

BOOL checkDelayOp(unsigned char opNum){
    char i;
    for(i=0; i<opPointer; i++){
        if(delayOp[i] == opNum){
            return TRUE;
        }
    }
    return FALSE;
}

void setDelayOp(unsigned char opNum, unsigned int ms){
    char i;
    for(i=0; i<opPointer; i++){
        //if the op is already registered then reset the count
        if(delayOp[i] == opNum){
            delayOpTime[i] = 0;
            delayOpCheck[i] = ms;
            return;
        }
    }
    if(opPointer >= opMax){
        return;
    }
    
    delayOp[opPointer] = opNum;
    delayOpTime[opPointer] = 0;
    delayOpCheck[opPointer] = ms;
    opPointer++;
}

void doDelayOp(unsigned char OpIndex){
    unsigned char op = delayOp[OpIndex];
    unsigned char i, newOp=0x00;
    unsigned int num;
    //remove and reseed delayOps
    if(OpIndex < (opPointer-1)){
        for(i=OpIndex; i<opPointer; i++){
            delayOp[i] = delayOp[i+1];
            delayOpTime[i] = delayOpTime[i+1];
            delayOpCheck[i] = delayOpCheck[i+1];
        }
    }
    opPointer--;
    
    switch(op){
        case TOPBTNDEBOUNCE:        //button 1 debounce
        case BOTBTNDEBOUNCE:        //button 2 debounce
        default:break;
    }
}

void main(void){
    BOOL Tbtn = FALSE, TbtnDebnce = TRUE, Bbtn = FALSE, BbtnDebnce = TRUE, opReady = FALSE;
    //set debounce for 20ms
    unsigned int dbnceTime = 20;
    opMax = 10;
    //initialize array
    for(i=0; i<CmdMax; i++){
        if(i < opMax){
            delayOp[i] = 0;
        }
    }
    opPointer = 10;
    while(1){
        for(i=0; i<opPointer; i++){
            if(delayOpTime[i] >= delayOpCheck[i]){
                doDelayOp(i);
            }
        }
        
        //P2[0] - top button
        if((!(PRT2DR & 0x01) || Tbtn) && !checkDelayOp(0x03)){
            //if the button is no longer pressed
            if(PRT2DR & 0x01){
                Tbtn = FALSE;
                TbtnDebnce = FALSE;
                setDelayOp(0x03,dbnceTime);
            }
            //if the button has just been pressed
            else if(!Tbtn){
                Tbtn = TRUE;
                TbtnDebnce = FALSE;
                setDelayOp(0x03,dbnceTime);
            }
            else if(!TbtnDebnce){
                TbtnDebnce = TRUE;
                
                //top button press handling here
                
            }
        }
        //P2[4] - bottom button
        if((!(PRT2DR & 0x10) || Bbtn) && !checkDelayOp(0x04)){
            //if the button is no longer pressed
            if(PRT2DR & 0x10){
                Bbtn = FALSE;
                BbtnDebnce = FALSE;
                setDelayOp(0x04,dbnceTime);
            }
            //if the button has just been pressed
            else if(!Bbtn){
                Bbtn = TRUE;
                BbtnDebnce = FALSE;
                setDelayOp(0x04,dbnceTime);
            }
            else if(!BbtnDebnce){
                BbtnDebnce = TRUE;
                
                //bottom button press handling here
                
            }
        }
    }
}

 

This is an implementation of the a callback system for embedded systems, written in C. It is fully asynchronous and is non-blocking for regular interrupts. Callbacks can be set at any desired interval, and are counted down based on your timing system.

 

The above example shows the callback system used for debouncing two buttons. This example is a pretty simple but useful case. A more complex usage might be for something like a time-consuming operation (like an lcd menu draw) that shouldn't block an interrupt.

 

Not much of a how-to for this one. The basic concept is an array of counters with corresponding codes in a complementary array. When one of the counters overflows the target, the corresponding code is processed in the switch statement in 'doDelayOp'.