Subversion Repositories Code-Repo

Rev

Rev 107 | Rev 111 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "maindefs.h"
#include "timers.h"
#include "msg_queues.h"
#include "uart.h"
#include "i2c.h"
#include "adc.h"
#include "interrupts.h"
#include "xbee.h"
#include "pin_interrupts.h"

//----------------------------------------------------------------------------
// Note: This code for processing interrupts is configured to allow for high and
//       low priority interrupts.  The high priority interrupt can interrupt the
//       the processing of a low priority interrupt.  However, only one of each type
//       can be processed at the same time.  It is possible to enable nesting of low
//       priority interrupts, but this code is not setup for that and this nesting 
//       is not enabled.

void interrupt_init() {
    // Peripheral interrupts can have their priority set to high or low
    // Decide on the priority of the enabled peripheral interrupts (0 is low, 1 is high)
//    INTCON2bits.TMR0IP = 0; // Timer0 interrupt
//    IPR1bits.TMR1IP = 1;    // Timer1 interrupt
//    IPR1bits.RC1IP = 0;      // USART1 RX interrupt
    IPR3bits.RC2IP = 1;     // USART2 RX interrupt
    IPR1bits.SSPIP = 1;     // I2C interrupt
//    IPR1bits.ADIP = 0;      // ADC interupt
//    INTCON2bits.RBIP = 1;   // Port B interrupt
    INTCON3bits.INT1IP = 1; // INT1 interrupt
    // I2C interupts must be specifically enabled
    PIE1bits.SSPIE = 1;
}

void interrupt_enable() {
    // Peripheral interrupts can have their priority set to high or low.
    // Enable both high-priority interrupts and low-priority interrupts
    RCONbits.IPEN = 1;
    INTCONbits.GIEH = 1;
    INTCONbits.GIEL = 0;
}

int interrupt_in_high_interrupt_routine() {
    return (!INTCONbits.GIEH);
}

int interrupt_low_int_active() {
    return (!INTCONbits.GIEL);
}

int interrupt_in_low_interrupt_routine() {
    if (INTCONbits.GIEL == 1) {
        return (0);
    } else if (interrupt_in_high_interrupt_routine()) {
        return (0);
    } else {
        return (1);
    }
}

int interrupt_in_main_routine() {
    if ((!interrupt_in_low_interrupt_routine()) && (!interrupt_in_high_interrupt_routine())) {
        return (1);
    } else {
        return (0);
    }
}

// Set up the interrupt vectors
void InterruptHandlerHigh();
void InterruptHandlerLow();

#pragma code InterruptVectorLow = 0x18
void InterruptVectorLow(void) {
    _asm
    goto InterruptHandlerLow //jump to interrupt routine
    _endasm
}

#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh(void) {
    _asm
    goto InterruptHandlerHigh //jump to interrupt routine
    _endasm
}

//----------------------------------------------------------------------------
// High priority interrupt routine
// this parcels out interrupts to individual handlers

#pragma code
#pragma interrupt InterruptHandlerHigh
void InterruptHandlerHigh() {
    // We need to check the interrupt flag of each enabled high-priority interrupt to
    //  see which device generated this interrupt.  Then we can call the correct handler.
    
    // Check to see if we have an I2C interrupt
    if (PIR1bits.SSPIF) {
        // Nofity the xbee to stop sending serial data
        xbee_set_RTS(1);
        
        // Call the handler
        i2c_interrupt_handler();

        // Clear the interrupt flag
        PIR1bits.SSPIF = 0;

        // Notify xbee to resume sending serial data
        xbee_set_RTS(0);
    }

    // Check to see if we have an interrupt on USART2 RX
    if (PIR3bits.RC2IF) {
        // Call the interrupt handler
        uart_recv_interrupt_handler();

        // Clear the interrupt flag
        PIR3bits.RC2IF = 0;
    }

#ifdef _MASTER
    // Check to see if we have an interrupt on INT1
    if (INTCON3bits.INT1IF) {
        int1_interrupt_handler();

        INTCON3bits.INT1IF = 0;
    }
#endif

    // Check to see if we have an interrupt on any port B inputs <4:7>
    if (INTCONbits.RBIF) {
        port_b_int_interrupt_handler();

        INTCONbits.RBIF = 0;
    }
    
//    // Check to see if we have an interrupt on timer 1
//    if (PIR1bits.TMR1IF) {
//        // Clear the interrupt flag
//        PIR1bits.TMR1IF = 0;
//
//        // Call the interrupt handler
//        timer1_interrupt_handler();
//    }

    // The *last* thing I do here is check to see if we can
    // allow the processor to go to sleep
    // This code *DEPENDS* on the code in messages.c being
    // initialized using "init_queues()" -- if you aren't using
    // this, then you shouldn't have this call here
//    MQ_sleep_high_interrupt_if_okay();
}

//----------------------------------------------------------------------------
// Low priority interrupt routine
// this parcels out interrupts to individual handlers
#pragma code
#pragma interruptlow InterruptHandlerLow
// This works the same way as the "High" interrupt handler
void InterruptHandlerLow() {

//    // Check to see if we have an interrupt on timer 0
//    if (INTCONbits.TMR0IF) {
//        // Clear this interrupt flag
//        INTCONbits.TMR0IF = 0;
//
//        // Call the handler
//        timer0_interrupt_handler();
//    }

//    // Check to see if we have an interrupt on USART1 RX
//    if (PIR1bits.RC1IF) {
//        // Clear the interrupt flag
//        PIR1bits.RC1IF = 0;
//
//        // Call the interrupt handler
//        uart_recv_interrupt_handler();
//    }
    
//    // Check to see if we have an interrupt on ADC
//    if (PIR1bits.ADIF) {
//        // Clear the interrupt flag
//        PIR1bits.ADIF = 0;
//
//        // Call the interrupt handler
//        adc_interrupt_handler();
//    }
}