/********************************************************************
* FileName:        Lab Exam Winter 0708.c
* Processor:       PIC18F4520
* Compiler:        MPLAB C18 v.3.06 
*
* This program displays the tenths of a second information on the LCD
* The lights flash like a police car lights, the buzzer changes pitch,
* and the timer counts.
* A press to RA4 turns off the lights and buzzer and resets the timer to 0                                                                    
**                                                                     
*
* Author               Date        Comment
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// A student solution			1/29/2008


/** Processor Header Files ****************************************/     
#include <p18f4520.h> 
#include <pwm.h>
#include <delays.h>
#include <timers.h>
#include "PICDEM 2 LCD module.h"
#include <stdio.h>

/** Define Constants Here ******************************************/
#define sample 100

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

// ============================================================
// Configuration Bits 
// ============================================================
#pragma config OSC = EC  // External 4MHz crystal for PICDEM board only
#pragma config WDT = OFF
#pragma config LVP = OFF
#pragma config BOREN = OFF

/** 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 *********************************************/
	char start[] = "Seconds = ";
	char tens_digit = '0';
	char ones_digit = '0';
	
	
/*****************************************************************
* Function:        void main(void)
******************************************************************/
#pragma code
void main (void)
{
	LCDInit();
	DisplayClr();
	LCDLine1();
	
	ADCON1 = 0b00001111;		// Sets all the pins to digital
	TRISB = 0b00000000;		// Sets all the dital PORTB pins to outputs
	TRISA = 0b11111111;     // Sets all dital PORTA pins to inputs
	PORTB = 0b00001001;     // Turns RB3 and RB0 on

    INTCONbits.GIE = 1;		// Enable Interrupts
	
	OpenTimer0( TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_16 );
	OpenTimer2( TIMER_INT_OFF &	T2_PS_1_16 );
	
	while (1)
    {
		if(PORTAbits.RA4 == 0)
		{
			INTCONbits.GIE = 0;		// Disable Interrupts
			PORTB = 0b00000000;		// Turn off lights
			SetDCPWM1(0);			// Turn off buzzer
			ones_digit = '0';		// Display 0 seconds
			tens_digit = '0';
			LCDLine1();
			text_display(start);
			LCDwrite(tens_digit);
			LCDwrite(ones_digit);
		}
		else
		{
			INTCONbits.GIE = 1;		// Enable Interrupts
			
			PORTB = 0b00000110;
			SetDCPWM1(15);			// Set volume of buzzer
			OpenPWM1(77);			// Set frq of buzzer				
			Delay10KTCYx(25);		// Delay for .25 seconds
		
			PORTB = 0b00001001;
			SetDCPWM1(15);			// Set volume of buzzer
			OpenPWM1(124);			// Set frq of buzzer				
			Delay10KTCYx(25);		// Delay for .25 seconds
		}
    }
}

/*****************************************************************
* Local functions go after main but before the interrupts if needed
******************************************************************/

/*****************************************************************
* Function:			void sample(void)
* Input Variables:	
* Output return:	
* Overview:			You change this template of a function if needed
******************************************************************/
void sampleFunction(){
	// Some function that does a specific task
}	


/*****************************************************************
* Function:        void high_isr(void)
* Purpose:			
******************************************************************/
#pragma interrupt high_isr
void high_isr(void)
{
	if(INTCONbits.TMR0IF)
	{
		INTCONbits.TMR0IF = 0;				// Reset flag
		WriteTimer0(3035);					// 62500 ticks until next overflow
		if (ones_digit == '9')				// update time
		{
			ones_digit = 0x30;
			tens_digit = tens_digit + 1;
		}
		else
			ones_digit = ones_digit+1;
	
		LCDLine1();
		text_display(start);
		LCDwrite(tens_digit);
		LCDwrite(ones_digit);
	    
	}
}
/******************************************************************
* Function:        void low_isr(void)
* Purpose:			
********************************************************************/
#pragma interruptlow low_isr
void low_isr(void)
{
	// Low Priority Interrupt Service Routine (Low ISR)
}