powerpic

Replacement board for a Casio CA-53W

/** @file isr.c
 * ISR Library for CasiOS.
*/

#include <xc.h>

#include "lib/isr.h"


#define LOG_TAG "ISR"
#include "lib/logging.h"


/** ISR function prototype. */
typedef void (*isr_func_t)(void);

/** Structure to hold information about each ISR.
 * 
*/
typedef struct
{
    unsigned char flag;
    unsigned char mask;
    isr_func_t isr_func;
} isr_t;

/** Pointer to the first of 8 peripherial interrupt flag bytes. */
static volatile unsigned char * pir_registers = &PIR0;

/** Pointer to the first of 8 peripherial interrupt enable bytes. */
static volatile unsigned char * pie_registers = &PIE0;

/** Array to hold currently registered ISRs. */
static volatile isr_t interrupts_service_routines[MAX_SERVICE_ROUTINES];

/** Number of ISRs currently registered. */
static volatile signed char interrupts_registered = 0;


signed char
isr_register (unsigned char int_flag, unsigned char int_mask, isr_func_t int_func)
{
    isr_t isr_to_register = {
        .flag = int_flag,
        .mask = int_mask,
        .isr_func = int_func
    };

    signed char isr_index = -1;
    if (MAX_SERVICE_ROUTINES >= interrupts_registered)
    {
        isr_index = interrupts_registered++;
        interrupts_service_routines[isr_index] = isr_to_register;
    }
    else
    {
        LOG_ERROR("Max ISRs added already!");
    }
    return isr_index;
}


void
isr_unregister (signed char isr_index)
{
    interrupts_global_disable();
    for (; isr_index < interrupts_registered; isr_index++)
    {
        interrupts_service_routines[isr_index] = \
            interrupts_service_routines[isr_index+1];
    }
    interrupts_registered--;
    interrupts_global_enable();
}

/**
 * XC8 specific way of defining an Interrupt Service Routine.
*/
static void __interrupt() isr_thread (void);

/**
 * Main Interrupt Service Routine.
 * 
 * Calls other ISRs as needed by the firmware.
*/
static void
isr_thread (void)
{
    isr_t isr_to_call;

    for (int isr = 0; isr < interrupts_registered; isr++)
    {
        isr_to_call = interrupts_service_routines[isr];
        if (isr_to_call.flag == 254)
        {
            isr_to_call.isr_func();
        }
        else
        {
            if ((pie_registers[isr_to_call.flag] & isr_to_call.mask) && \
                (pir_registers[isr_to_call.flag] & isr_to_call.mask))
            {
                isr_to_call.isr_func();
            }
        }
    }
}

// EOF //