/************************************************************************/
/* CQBBEL GNU CC Common Control Software / (C) Toshio MURAI 2011, 2012	*/
/*      This is Free Software;   You can redistribute this software     */
/*      and/or modify it under the terms of the GNU General Public      */
/*      License version 3, or (at your option) any later version.       */
/************************************************************************/

//***********************************************************************/
//*	GNU Linker .text/.bss Initialize routine before main function.		*/
//***********************************************************************/
extern char etext[], sdata[], edata[], sbss[] , ebss[];

initializeMemory()
{
	char *src, *dst;
	
	for( src = etext, dst = sdata ; dst< edata ; ) 
		*dst++ = *src++;
		
	for( dst=sbss                 ; dst< ebss  ; ) 
		*dst++ =0;
}


//***********************************************************************/
#include "macro.h"
//***********************************************************************/

static volatile int out;

void main(void){		//void main(int ac, char av[] ) {

// 	You Can not use the initialized variables before this function and also
//	can not use the initialized auto variables in main function even after this function.
//	initializeMemory();	

	initializeHardware();	
	
//	putsUart("\n\nProgram Start!\n\n");	// Starting Message

	out = getDipSwitchValue();	// load Dip Switch Value for Initial Data

	while(1) {
		;
	}
}

//*************************************************************************/
initializeHardware() {
	DISABLEINTERRUPT();
	// CPU Initialize	Some of this part might be done at the first of crt0.s
	SETCPU();
	//	Board LED Initialize.
	SETBOARDLED();
	//	Dip Switch port Initialize for Input
	SETDIPSWITCH();
	//	7segment LED port Initialize for Output
	SET7SEGLED();
	//	IRQ port Initialize for Interrupt Input
	SETIRQ();
	//	AD Converter Initialize
	SETAD();
	//	Timer Initialize for 500msec	(1/10 msec)
	SETTIMER();
	//	RS232C serial port Initialize (bitrate 9600bps)
	//SETUART();
	//	After All HW setup, Enable the interrupt
	ENABLEINTERRUPT();
}
//*************************************************************************/

int getDipSwitchValue() {
	return	GETDIPSWITCH();
}

#define	BLACK7SEG	0xFF
unsigned char digit7seg[] = {	//	a(d0),b(d1),c(d2),d(d3),e(d4),f(d5),g(d6),dp(d7)
	0xC0,		// 0:	a,b,c,d,e,f, , 0000 0011
	0xF9,		// 1:	 ,b,c, , , , , 1001 1111 
	0xA4,		// 2:	a,b, ,d,e, ,g, 0010 0101
	0xB0,		// 3:	a,b,c,d, , ,g, 0000 1101
	0x99,		// 4:	 ,b,c, , ,f,g, 1001 1001
	0x92,		// 5:	a, ,c,d, ,f,g, 0100 1001
	0x82,		// 6:	a, ,c,d,e,f,g, 0100 0001
	0xF8,		// 7:	a,b,c, , , , , 0001 1111
	0x80,		// 8:	a,b,c,d,e,f,g, 0000 0001
	0x98,		// 9:   a,b,c, , ,f,g, 0001 1001
	0x88,		// A:	a,b,c, ,e,f,g, 0001 0001
	0x83,		// B:	 , ,c,d,e,f,g, 1100 0001
	0xC6,		// C:	a, , ,d,e,f, , 0110 0011
	0xA1,		// D:	 ,b,c,d,e, ,g, 1000 0101
	0x86,		// E:	a, , ,d,e,f,g, 0110 0001
	0x8E,		// F:	a, , , ,e,f,g, 0111 0001
	0x7F,		// .:	 , , , , , , ,.1111 1110
	BLACK7SEG,	//  :	Black Out
};

put7segLED(int value){
	if( (0x00 <= value) && (value <= 0xFF) ) {
		PUT7SEGHIGH( digit7seg[(value/16) & 0x0F] );  //value/16
		PUT7SEGLOW ( digit7seg[ value%16] );
	} else {
		PUT7SEGHIGH(BLACK7SEG);		// Black Out=0xFF .=0x7F
		PUT7SEGLOW (BLACK7SEG);		// Black Out=0xFF .=0x7F
	}
}

int get7segLED()
{
	int value = GET7SEGHIGH();
	if (value == BLACK7SEG )
		value = 0;
	return value;
}

int	getAD0Value() {
	STARTAD0();
	return GETAD0();
}

//*************************************************************************/
//*		Interrupt Handler	***/
//*************************************************************************/

static volatile int state = 0;

#ifndef	COUNTER	
#define	COUNTER	500
#endif

void INTERRUPTATTRIBUTE timer0Interrupt() {	// 1 msec Timer Interrupt (If Possible)
	static int	count =0;

	CLEARTIMERINTERRUPT();
	if(count++ < COUNTER){//(makes 500msec Interval)
		return;
	} 
	count = 0;
	REVERSELED();
	if(state) {
		put7segLED(out++);
	} else {	// Blink Data ( read io and if value is non 0 , black out else put out)
		if(get7segLED()) {
			put7segLED(-1);		//	Black out
		} else {
			put7segLED(out);	//	put Current Data
		}
	}
	if(out>=256)
		out = 0;
}

void INTERRUPTATTRIBUTE interruptRequest0(void) {		// IRQ0	Start - Stop		
	state = !state;						// Reverse the state
	CLEARIRQ0();
}

void INTERRUPTATTRIBUTE interruptRequest1(void) {		// IRQ1	Clear Counter
	state = 0;						// Stop Timer Increment
	out = 0;
	CLEARIRQ1();
}

void INTERRUPTATTRIBUTE interruptRequest2(void) {		// IRQ2	load DIP SWITCH
	state = 0;						// Stop Timer Increment
	out = getDipSwitchValue();
	CLEARIRQ2();
}

void INTERRUPTATTRIBUTE interruptRequest3(void) {		// IRQ3	load AD0 Converter Value
	state = 0;						// Stop Timer Increment
	out = getAD0Value();
	CLEARIRQ3();
}

#ifdef	ARMINTERRUPTATTRIBUTE
void ARMINTERRUPTATTRIBUTE interrupt(void) {		// IRQ Handler for ARM CPU	

	if(TIMEINTR())	//TIMER
		timer0Interrupt() ;
	
	if(IRQ0INTR()) 	//IRQ0
		interruptRequest0();
	
	if(IRQ1INTR())	//IRQ1
		interruptRequest1();
	
	if(IRQ2INTR())	//IRQ2
		interruptRequest2();
	
	if(IRQ3INTR())	//IRQ3
		interruptRequest3();
		
}
#endif

void INTERRUPTATTRIBUTE dummy(void) {
	DUMMYINTERRUPT();
}

void INTERRUPTATTRIBUTE nonMaskable(void) {
	DUMMYINTERRUPT();
}

void INTERRUPTATTRIBUTE sci0Recive(void) {
	DUMMYINTERRUPT();
}

void INTERRUPTATTRIBUTE sci0Send(void) {
	DUMMYINTERRUPT();
}

void putChar(int data)
{
//	PUTCHAR(data);
//	CLEARSENDFLAG();
}

char getChar(void)
{
//	WAITUART();
//	CLEARRECFLAG();
//	return GETCHAR();
}
