#include <hidef.h>					// common defines and macros
#include <mc9s12hy64.h>				// derivative information
#include "cpu.h"						// CPU routines


/**********************************************************
*	CPMU_PBE
*
*	Setup clock module for PLL Bypass, External.  For DEMOHY64
*	using 8MH XTAL, 
*	Core Clk - 8MHz, Bus Clk - 4MHz
**********************************************************/
void CPMU_PBE(void){
	CPMUOSC_OSCE = 1;					// enable ext OSC
	while(!CPMUFLG_UPOSC);			// wait for ext osc to stabilize
	CPMUCLKS_PLLSEL = 0;				// select ext oscillator
}

/**********************************************************
*	CPMU_PEE_8MHz
*
*	Setup clock module for PLL Engaged using externals XTAL
*	For DEMOHY64 w/ 8MHz XTAL - 
*	VCOCLK - 32MHz, Core Clk - 8MHz, Bus Clk - 4MHz
**********************************************************/
void CPMU_PEE_8MHz(void){

	CPMUSYNR = 0x01;					// fVCO = 32MHz
	CPMUREFDIV = 0x80;				// OSC input is 8MHz
	CPMUPOSTDIV = 0x03;				// core clk - 8MHz, bus clk - 4MHz
	
	CPMUOSC_OSCE = 1;					// enable ext OSC
	while(!CPMUFLG_UPOSC || !CPMUFLG_LOCK);
											// wait for ext osc to stabilize and pll to lock
	CPMUFLG = 0xFF;					// clear CMPMU int flags - not needed but good practice
}


/**********************************************************
*	CPMU_PEE_4MHz
*
*	Setup clock module for PLL Engaged using externals XTAL
*	For DEMOHY64 w/ 4MHz XTAL - 
*	VCOCLK - 32MHz, Core Clk - 4MHz, Bus Clk - 4MHz
**********************************************************/
void CPMU_PEE_4MHz(void){

	CPMUSYNR = 0x03;					// fVCO = 32MHz
	CPMUREFDIV = 0x40;				// OSC input is 4MHz
	CPMUPOSTDIV = 0x03;				// core clk - 4MHz, bus clk - 4MHz
	
	CPMUOSC_OSCE = 1;					// enable ext OSC
	while(!CPMUFLG_UPOSC || !CPMUFLG_LOCK);
											// wait for ext osc to stabilize and pll to lock
	CPMUFLG = 0xFF;					// clear CMPMU int flags - not needed but good practice
}											// bus clk = 4MHz


/**********************************************************
*	Tim0_Dly
*
*	starts TIM0_C7 and waits for C7 flag to set, requires
*	user config TIM0 before calling
**********************************************************/
void Tim0_Dly(void){
	while(!TIM0_TFLG1_C7F); 
	TIM0_TFLG1_C7F = 1;
}


/**********************************************************
*	Init_Timer1
*
*	initialize TIM1 as free-running timer counting at bus
*	clock rate, configures T1_C7 as output compare
**********************************************************/
void Init_Timer1(void){
	TIM1_TIOS = 0x80;					// setup T1C7 as output compare
	TIM1_TCTL1 &= 0x3C;				// pin is GPIO
	TIM1_TSCR2_PR = 0x0;				// timer runs at bus clk rate
	TIM1_TSCR1_TEN = 1;				// enable timer1 as free-running
}

/**********************************************************
*	Delay_1ms
*
*	Uses Timer1, Ch7 to produce a 1ms Delay.  
* 	Get current TIM1 cnt and adds delay offset then waits 
*	for compare.  OVF cleared on exit from routine  
**********************************************************/
void Delay_1ms(void){
	dword t_count;
	
	t_count = TIM1_TCNT;				// get TIM1 count
	t_count += ms_Delay_Cnt;		// add offset count
	TIM1_TC7 = (word)t_count;		// load new mod value
	while(!TIM1_TFLG1_C7F);			// wait for timer flag to set
	TIM1_TFLG1_C7F = 1;				// clear overflow flag
}

/**********************************************************
*	Delay
*
*	add program Delay defined by user input.  Calls Delay_1ms()
*
*	input		- Delay in ms
**********************************************************/
void Delay(word count){
	word m;

	for(m=0; m<count; m++){
		Delay_1ms();
	}
}

// configure ports for COM demo
void Configure_Ports(void){
	
  	IRQCR = 0;							// IRQ responds to falling edge
  	
  /**************************
  *
  *	PORTS CONECTED TO LCD 
  *
  **************************/
  	//PULL ENABLES
  	PUCR = 0x03;						// en PTA, PTB pull ups
  	
  	// PORT A
  	PORTA	= ALL_LOW;	   
  	DDRA	= ALL_INPUTS;				// PORTA is input
	
  	// PORT B
  	PORTB	= ALL_LOW;	   
  	DDRB	= ALL_INPUTS;				// PORTB is input 
	
  	// PORT H
  	PTH	= ALL_LOW;	   	 	
  	DDRH	= ALL_OUTPUTS;				// PTH is output driving low
	
  	// PORT R							// PTR[7:4] only connected to LCD
  	PTR	= 0x0F;						// PTR[7:4] low, PTRp[3:0] high
  	DDRR	= ALL_OUTPUTS;				// PTR is output driving low
	
  	// PORT P
  	PTP	= ALL_LOW;	   
  	DDRP	= ALL_OUTPUTS;				// PTP is output driving low

  	// PORT T
  	PTT	= ALL_LOW;	   
  	DDRT	= ALL_OUTPUTS;				// PTT is output driving low

  /**************************
  *
  *	ALTERNATE USE PORTS 
  *
  **************************/
    // PORT S  
	PPSS 	= ALL_PULLED_DOWN;		// Configure Pull-polarity  
	PERS 	= ALL_PULLS_ON;			// Enable Pull devices  
	WOMS 	= 0x00;						// wired-or outputs disabled
	PTS 	= ALL_LOW;					// port data  
	DDRS	= ALL_INPUTS;				// port direction
	
  	// PORT U  
	PPSU 	= ALL_PULLED_DOWN;		// Configure Pull-polarity  
	PERU 	= ALL_PULLS_ON;			// Enable Pull devices  
	PTU  	= ALL_LOW;					// port data  
	DDRU 	= ALL_INPUTS ;				// port direction   
  	
  	// PORT V  
	PPSV 	= ALL_PULLED_DOWN;		// Configure Pull-polarity  
	PERV 	= ALL_PULLS_ON;			// Enable Pull devices  
	PTV   = ALL_LOW;					// port data  
	DDRV 	= ALL_INPUTS;				// port direction  

/**********************************************************
*	PORT AD SETUP
*
*	configure port as input w/ pull-ups enabled,  
*	key-wakeup enabled on PT1AD[7:4] for PBSW use
*  NOTE: to use the digital input function the ATDDIEN bit must be set  
*
*	NOTE: ATD port pull-ups are active for both digital and 
*	analog inputs !  
***********************************************************/
	PER1AD 	= ALL_PULLS_ON;		// Port AD Pull Enable  
	PT1AD 	= ALL_LOW;				// Port AD I/O Register
	DDR1AD 	= ALL_INPUTS;			// Port AD Data Direction Register
	ATDDIEN	= 0xF0;					// enable PT1AD[7:4] as digital input
}


/**********************************************************
*	init_atd_ch0
*
*	configure ATD Ch0 for continuos conversion
**********************************************************/
void init_atd_ch0(void){

	ATDCTL1 = 0x20;					// 10-bit result, select AN0
	ATDCTL3 = 0xA0;					//	right justify results, 4 conversions per sequence
	ATDCTL4 = 0x00;					// fATDCLK = 2.67MHz, 4 clks per sample
	ATDCTL5 = 0x20;					// continuous conversion
	ATDSTAT0_SCF = 0x01;				// clear conversion complete flag
}


/**********************************************************
*	read_atd_ch0
*
*	read and return current ATD, Ch0 value
**********************************************************/
word read_atd_ch0(void){
	word val;

	val = ATDDR0;						// get ADT result
	return (val);						// return
}


/**********************************************************
*	Toggle_Led
*
*	read and return current ATD, Ch0 value
**********************************************************/
void Toggle_Led(byte num){
	
	switch(num){
		case 1:  LED2 = LOFF;		// LED2 off
		case 2:	LED3 = LOFF;		// LED3 off
		case 3:	LED4 = LOFF;		// LED4 off
//		case 4:	LEDS_OFF;			// all LEDs off
	}

	switch(num){
		case 4:	LED4 ^= 1;			// toggle LED4
		case 3:	LED3 ^= 1;			// toggle LED3
		case 2:	LED2 ^= 1;			// toggle LED2
		case 1:	LED1 ^= 1;			// toggle LED1
					break;
	}
}


/**********************************************************
*	Get_Pot_Val
*
*	read POT and setup CAN frame to transmit data.  CAN frame
*	consists of 2 bytes - [cmd, data]
*********************************************************
void Get_Pot_Val(void){
	byte val, cmd;

	cmd = 0x30;
	val = read_atd_ch0();			// get POT value from ATD
	
	*txbuff = cmd;						// load tx buffer
	*(txbuff + 1) = val;
	tx_data_len = 0x02;				// set length
}*/


#pragma CODE_SEG NON_BANKED

/**********************************************************
*	sci_isr
*
*	interrupt handler for SCI module interrupts
*********************************************************
void interrupt 20 sci_isr(void){
	DisableInterrupts;
	echo_com();						// echo keybd data
	EnableInterrupts;
}
*/

/**********************************************************
*	kbi_isr
*
*	interrupt handler for PBSW interrupt
*********************************************************
void interrupt 24 kbi_isr(void){
	byte int_flag = 0;
	byte st = 0, n = 0;
	byte errorflag = NO_ERR;
	
	DisableInterrupts;
	int_flag = (PIF1AD >> 4);		// capture interrupt status and shift to low nibble
	PIF1AD = 0xF0;						// clear PBSW interrutps

	while(st<0x08){
		if(SW1 && SW2 && SW3 && SW4){ 
			st ++;						// incr count if all PBSW's high
		} else st = 0;
	}

	EnableInterrupts;
	
	switch(int_flag & 0x0F){
		case 1:	*txbuff = CAN_LED_1_ON;		// LED1 on if SW1 pressed
					break;

		case 2:	*txbuff = CAN_LED_2_ON;		// LED2 on if SW2 pressed
					break;

		case 4:	*txbuff = CAN_LED_3_ON;		// LED3 on if SW3 pressed
					break;	

		case 8:	*txbuff = CAN_LED_4_ON;		// LED4 on if SW4 pressed
					break;
		default:	break;
	}
	tx_data_len = 0x01;							// set data length
}*/


#pragma CODE_SEG DEFAULT


