// Motorola 68HC12 Test Program TEST.C
// Lee Rosenberg
// January 13, 1999
//
// This a series of test routines to check the functionality of the Motorola
// HC12 and to determine if errors that are reported by the TAs and students.
// The program will allow for differentiation between errors that are due to
// hardware faults and those that result form errors in the students code.
// The program tests the Ports, Timer Module, A/D Converter and Key Wakeups.  
// This is not fully comprehensive but should provide verifiation of most major
// faults.
//
// This code was written and tested using Introl C 4.0.
 

// #includes

#include <hc812a4.h>
#include <introl.h>
#include <dbug12.h>

// function prototypes
void keywakeup(void);
void adconverter(void);
void timer(void);
void portio(void);

// Global Interrupts
int flag;

// interrupt service routine declarations
__mod2__ void RTIInt();
__mod2__ void AtoDInt();
__mod2__ void IRQInt();
__mod2__ void PortHKeyInt();
__mod2__ void PortJKeyInt();

void __main ()
{
	int choice;
	
	
	
	while(1)
	{	
	DB12->printf("1 = Port I/O\n\r"); // Menu of choices
	DB12->printf("2 = Timer\n\r");
	DB12->printf("3 = A/D converter\n\r");
	DB12->printf("4 = Key wake up\n\n\r");
	
	choice=DB12->getchar();
	
	// select which option to run
	
	if (choice == 0x31)
		portio();
	else if(choice == 0x32)
		timer();
	else if(choice == 0x33)
		adconverter();
	else if(choice == 0x34)
		keywakeup();
	else
		DB12->printf("That is not a valid choice\n\r");  // inform the user how bright he is
	}	
} 

void portio(void)
{
// This function tests the port I/O operations

	int port;
	int direction;
	
	DB12->printf("Select the direction of the port being checked\n\r");
	DB12->printf("Enter 1 for output and 2 for input\n\r");
	
	direction=DB12->getchar();
	
	if (direction == 0x31) // Check output
	{
		_H12DDRG=0xFF;		// Set ports for output
		_H12DDRH=0xFF;
		_H12DDRJ=0xFF;
		_H12DDRS=0xFF;
		_H12DDRTT=0xFF;
		
		_H12PORTG=0xFF;		// Output all ones
		_H12PORTH=0xFF;
		_H12PORTJ=0xFF;
		_H12PORTS=0xFF;
		_H12PORTT=0xFF;
	}	
	else if(direction == 0x32)	// Check input
	{
		DB12->printf("1 = Port G\n\r");
		DB12->printf("2 = Port H\n\r");
		DB12->printf("3 = Port J\n\r");
		DB12->printf("4 = Port S\n\r");
		DB12->printf("5 = Port T\n\r");
		DB12->printf("0 = exit\n\r");
		
		port=DB12->getchar();

		while(port != 0x30)
		{		 
		// select the port to read and display it
		_H12DDRG=0x00;
		_H12DDRH=0x00;
		_H12DDRJ=0x00;
		_H12DDRS=0x00;
		_H12DDRTT=0x00;
		
		if (port==0x31)
			DB12->out2hex(_H12PORTG);
		else if(port==0x32)
			DB12->out2hex(_H12PORTH);
		else if(port==0x33)
			DB12->out2hex(_H12PORTJ);
		else if(port==0x34)
			DB12->out2hex(_H12PORTS);
		else if(port==0x35)
			DB12->out2hex(_H12PORTT);
		else
			DB12->printf("That is not a valid choice\n\r");  // inform the user how bright he is
		
		port=DB12->getchar();		
	}
	}	
	
	}
	
void timer(void)
{
// This module tests the timer module of the HC12.
// The IRQ is used to exit this module

// Set up interrupt vectors
	DB12->SetUserVector(RTI, RTIInt);
	DB12->SetUserVector(IRQ, IRQInt);
	
	DB12->printf("Use the IRQ to exit");
	
	_H12RTICTL=0x87;	//  Set up RTI 
	_H12INTCR=0xC0;		// IRQ falling edge triggered
	
// Timer output compare	
	_H12TIOS=0xFF;		// Select Timer Output Compare
	_H12TMSK1=0x00;		// no hardware interrupts	   	
	_H12TCTL1=0x55;   	// Set output pins to toggle
	_H12TCTL2=0x55;	  		
	_H12TC0=0x0000;		// Trigger timer at TCNT=0000
	_H12TC1=0x0000;
	_H12TC2=0x0000;
	_H12TC3=0x0000;
	_H12TC4=0x0000;
	_H12TC5=0x0000;
	_H12TC6=0x0000;
	_H12TC7=0x0000;

	
	_H12TSCR=0x80;		// turn on the timer module
	flag=0;
	
	while(1)
	{
	if(flag==1)		// when the IRQ is triggered
		{
		_H12TSCR=0x00;	// turn off the timer
		_H12RTICTL=0x00; // Turn off the RTI
		return;
		}	
	}

}

void adconverter(void)
{
// This module tests the A/D converter on the HC12
// The IRQ is used to exit.

	_H12ADTCTL2=0x80;   //  turn on ATD and off the interrupt 
	_H12ADTCTL3=0x00;  // don't stop at breakpoints
	_H12ADTCTL4=0x43;
	
	   
	DB12->printf("Use the IRQ to exit\n\r");
	DB12->printf("AD0 AD1 AD2 AD3 AD4 AD5 AD6 AD7\n\r");
	_H12INTCR=0xC0;		// IRQ falling edge triggered
	flag=0;
	while(1)
	{
	
	if(flag==1)		// if the IRQ is triggered exit
		return;
	
		
	_H12ADTCTL5=0x50;  // check AD port     
	while(!(_H12ADTSTAT & 0x8000));  // when conversion is complete....
	DB12->out2hex(_H12ADR0H);		// Display the values to the screen
	DB12->printf("  ");
	DB12->out2hex(_H12ADR1H);
	DB12->printf("  ");
	DB12->out2hex(_H12ADR2H);
	DB12->printf("  ");
	DB12->out2hex(_H12ADR3H);
	DB12->printf("  ");
	DB12->out2hex(_H12ADR4H);
	DB12->printf("  ");
	DB12->out2hex(_H12ADR5H);
	DB12->printf("  ");
	DB12->out2hex(_H12ADR6H);
	DB12->printf("  ");
	DB12->out2hex(_H12ADR7H);
	DB12->printf("\r");
	}

}

void keywakeup(void)
{
// This module tests the Key Wakeup Interrupts.
// q is used to exit.
	

	int key;
	key=0;
	
	//Set up the interrupt vectors
	DB12->SetUserVector(PortHKey, PortHKeyInt);
	DB12->SetUserVector(PortJKey, PortJKeyInt);
	DB12->printf("type q to exit");
	_H12KWIEH=0x0F;	// setup the keypad for the low bits 

	_H12KPOLJ=0x0F;	// rising edge	
	_H12PUPSJ=0x00;	// pulldown
	_H12PULEJ=0x0F;	// pulldown enabled
	_H12KWIEJ=0x0F;		// enable interrupt

	while(1)
	{
	key=DB12->getchar();	// when q is entered exit
	if(key==0x71)
		{
		_H12KWIEJ=0x00;		// Turn off the interrupt.
		_H12KWIEH=0x00;
		return;
		}
	}

}	

// RTI Interrupt routine	 
__mod2__ void RTIInt()
{
	DB12->printf("RTI triggered\n\r"); // display message when triggered
	_H12RTIFLG=0x80;		// Clear flag
}

// IRQ interrupt routine
__mod2__ void IRQInt()
{
	flag=1;  // Set flag for use in main program
}

// Port H Key Wakeup Interrupt routine
__mod2__ void PortHKeyInt()
{
	DB12->printf("Port H: ");	// Display value on Port H
	DB12->out2hex(_H12KWIFH);
	DB12->printf("\n\r");
	_H12KWIFH=_H12KWIFH;		// Clear Flag
}	

//Port J Key Wakeup Intteruptm routine
__mod2__ void PortJKeyInt()
{
	DB12->printf("Port J: ");	// Display Value on Port J
	DB12->out2hex(_H12KWIFJ);
	DB12->printf("\n\r");
	_H12KWIFJ=_H12KWIFJ;		// Clear Flag
}
