/*
 * port_intr.c
 *
 * notes:
 *
 * - pins 22 and 23 are shifted into pins 9 and 10,
 *   so configure these pins if you want to use them.
 *
 * - maximum real possible then is 22 entries.
 *   I have no need above 15 so that's the maximum I set.
 *
 */

#include "CH59x_common.h"
#include "port_intr.h"

#include "hw/ch32sub.h"

#include <stdint.h>



#define MAX_PIN     15+1



static void (*cb[2][MAX_PIN-4])(void) = {0};



void port_intr_cb_register(uint8_t port, uint8_t idx, void (*fn)(void))
{
    if (idx == 22) idx = 9;
    if (idx == 23) idx = 10;

    if (idx < 4) return;
    if (idx > MAX_PIN) return;

    if (port > 2) return;

    cb[port][idx - 4] = fn;
}

void port_intr_init()
{
    // clear state
    R16_PB_INT_IF = 0xff;

    // then enable interrupt as low priority
    PFIC_SetPriority(RTC_IRQn, 0x30);
    PFIC_EnableIRQ(GPIO_B_IRQn);
}



/* interrupt handlers */
__INTERRUPT
__HIGH_CODE
void GPIOA_IRQHandler(void)
{
    uint16_t flag = R16_PA_INT_IF;

    // clear flags
    R16_PA_INT_IF = flag;
}

__INTERRUPT
__HIGH_CODE
void GPIOB_IRQHandler(void)
{
    //uint8_t i;
    //uint8_t offset;
    uint16_t flag = R16_PB_INT_IF;

    // clear flags
    R16_PB_INT_IF = flag;

    // high priority actions
    // ch32sub interrupt
    if (flag & SUB_INTR_PIN) {
        ch32sub_isr();
    }

    // general purpose fallback
    /*
    for (i = 4; i < MAX_PIN; i++) {
        offset = i - 4;
        if (flag & (1 << i)) {
            if (cb[PORT_INTR_GPIOB][offset]) {
                cb[PORT_INTR_GPIOB][offset]();
            }
        }
    }
    */
}
