/**  Header Files **************************************************/
#include <p18f4520.h>
#include <stdio.h>
#include <adc.h>
#include <timers.h> 
#include "LCD Module.h"

/** Configuration Bits *********************************************/
#pragma config OSC = INTIO67
#pragma config WDT = OFF
#pragma config LVP = OFF
#pragma config BOREN = OFF
#pragma config XINST = OFF

/** Define Constants Here ******************************************/
#define START_TIME 62606

/** Local Function Prototypes **************************************/
void low_isr(void);
void high_isr(void);
void update(void);

/** Declare Interrupt Vector Sections ****************************/
#pragma code high_vector=0x08

void interrupt_at_high_vector(void) {
    _asm goto high_isr _endasm
}

#pragma code low_vector=0x18

void interrupt_at_low_vector(void) {
    _asm goto low_isr _endasm
}

/** Global Variables ***********************************************/
int ra2Reading = 0;
char line2[17];

/*******************************************************************
 * Function:        void main(void)
 ********************************************************************/
#pragma code

void main(void) {
    // Set the clock to 4 MHz
    OSCCONbits.IRCF2 = 1;
    OSCCONbits.IRCF1 = 1;
    OSCCONbits.IRCF0 = 0;

    // Pin IO Setup
    OpenADC(ADC_FOSC_8 & ADC_RIGHT_JUST & ADC_12_TAD,
            ADC_CH2 & ADC_INT_OFF & ADC_REF_VDD_VSS,
            0x0B); // Four analog pins
    TRISA = 0xFF; // All of PORTA input
    TRISB = 0xFF; // All of PORTB input
    TRISC = 0x00; // All of PORTC output
    TRISD = 0x00; // All of PORTD output
    PORTC = 0x00; // Turn off all 8 Port C LEDs

    XLCDInit();
    XLCDClear();

    XLCDL1home();
    XLCDPutRomString("JOYSTICK");

    // Interrupt setup
    RCONbits.IPEN = 1; // Put the interrupts into Priority Mode
    OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_256);
    INTCON2bits.TMR0IP = 0;
    WriteTimer0(START_TIME);
    INTCONbits.GIEH = 1; // Turn on high priority interrupts
    INTCONbits.GIEL = 1; // Turn on low priority interrupts

    while (1) {
        // This area loops forever
        //updateDisplays();
    }
}

/*****************************************************************
 * Function:        void high_isr(void)
 ******************************************************************/
#pragma interrupt high_isr

void high_isr(void) {
}

/******************************************************************
 * Function:        void low_isr(void)
 ********************************************************************/
#pragma interruptlow low_isr

void low_isr(void) {
    if (INTCONbits.TMR0IF) { // Timer 0 interrupt
        INTCONbits.TMR0IF = 0;
        WriteTimer0(START_TIME);
        update();
    }
}

#pragma code
/*****************************************************************
 * Additional Helper Functions
 ******************************************************************/

void update() {
    SetChanADC(ADC_CH2); // Select the pin
    ConvertADC(); // Start conversion
    while (BusyADC()); // Wait for completion
    ra2Reading = ReadADC(); // Read result

    sprintf(line2, "RA2  = %4d", ra2Reading);
    XLCDL2home();
    XLCDPutRamString(line2);

    if (ra2Reading <= 100) {
        PORTC = 0x05;
    } else if (ra2Reading <= 450) {
        PORTC = 0x0A;
    } else if (ra2Reading <= 550) {
        PORTC = 0xAA;
    } else if (ra2Reading <= 900) {
        PORTC = 0xA0;
    } else {
        PORTC = 0x50;
    }
}