package fabrik.simulator.pic16f84;

import fabrik.simulator.pic16f84.interfaces.InterruptInterface;

public class Interrupts extends PICComponent implements InterruptInterface {
    private final int INTCON = 0xB;
    private final int T0IF = 0x2;
    private final int ISR = 0x4;
    private final int GIE = 0x7;
    private final int T0IE = 0x5;
    private final int RBIE = 0x3;
    private final int RBIF = 0x0;
    private final int INTEDG = 0x6;
    private final int OPTION = 0x81;
    private final int INTE = 0x4;
    private final int INTF = 0x1;


    public Interrupts () {
    }

    public void triggerTMR0(boolean manual) {
        triggerInterrupt(T0IF, T0IE);
        if (manual)
            dataRegister.increasePC();
    }

    private void triggerInterrupt(int flag, int enableFlag) {
        dataRegister.setBit(INTCON, flag);
        enableFlag = dataRegister.getDirectBit(INTCON, enableFlag);
        int globalFlag = dataRegister.getDirectBit(INTCON, GIE);
        if (enableFlag == 1) {
            ExecutionState.wakeUp();
            if (globalFlag == 1) {
                dataRegister.clearBit(INTCON, GIE);
                commands.CALL(ISR);
            }
        }
    }


    public void triggerRBInterrupt(int oldValue, int newValue) {
        if (newValue != oldValue){
            triggerInterrupt(RBIF, RBIE);
            dataRegister.increasePC();
        }
    }

    public void triggerRB0Interrupt(int oldValue, int newValue){
        if (newValue != oldValue){
            int intedg = dataRegister.getDirectBit(OPTION, INTEDG);
            if (intedg == 1) {
                if (oldValue == 0 && newValue == 1)
                    triggerInterrupt(INTF, INTE);
            } else {
                if (oldValue == 1 && newValue == 0)
                    triggerInterrupt(INTF, INTE);
            }
            dataRegister.increasePC();
        }
    }


    @Override
    public void initialize(PICComponentLocator locator) {
        super.initialize(locator);
    }
}
