/************************************************
Experiencia 4: Configura o Timer T0 e display LCD
Pisca um LED a cada segundo. Mostra contagem no LCD
Kit LPC2478 de Sistemas Embarcados 2012-1
Marcos Augusto Stemmer
*************************************************/
#include <arch/nxp/lpc23xx.h>
#define CCLK 12000000
/* LCD_E em P1.31 */
#define LCD_E	0x80
/* LCD_RS em P1.30 */
#define LCD_RS	0x40
/* LCD_RW no pino 23 da P4 */
#define LCD_RW	(1<<23)
/* LCD dados nos bits 0 a 7 da P2 */

/* Espera t milisegundos */
void espera(unsigned int t)
{
unsigned int tf;
tf = T0TC + t;          /* tf = Valor futuro do T0TC */
while(tf != T0TC);      /* espera ate que tf==T0TC */
}

void LCDcomando(int c)
{
FIO2PIN0=c;
FIO1CLR3=LCD_RS;
FIO1SET3=LCD_E;
FIO1CLR3=LCD_E;
espera(20);
}

void LCDputchar(int c)
{
FIO2PIN0=c;
FIO1SET3=LCD_RS;
FIO1SET3=LCD_E;
FIO1CLR3=LCD_E;
espera(10);
}

void LCDinit(void)
{
FIO2DIR |= 0xff;	/* P0.0 a P0.7 como saidas (dados do LCD) */
FIO1DIR |= (LCD_E | LCD_RS) << 24;
FIO4DIR |= LCD_RW;
FIO4CLR = LCD_RW;
FIO1CLR3=LCD_E;
espera(20);
LCDcomando(0x38);
LCDcomando(1);
LCDcomando(0x0e);
}

/* Envia uma mensagem no LCD */
void LCDputs(char *txt)
{
while(*txt) LCDputchar(*txt++);
}

/* Escreve numero decimal de 2 digitos */
void escreve2digs(int x)
{
LCDputchar((x/10) + '0');	/* Escreve dezena  */
LCDputchar((x%10) + '0');	/* Escreve unidade */
}

int main (void)
{
int c=0, tempo;
PCONP |= 2;	/* Liga energia do Timer 0 */
PCLKSEL0 = (PCLKSEL0 & (~0x0c)) | 0x04;	/* Divide CCLK por 1 no T0 */
T0TCR = 0;              /* Desabilita T0 */
T0PR = CCLK/1000 - 1; /* Incrementa T0TC 1000 vezes por segundo */
T0TCR = 2;      /* Inicializa T0 */
T0TCR = 1;      /* Habilita T0  */
FIO4DIR = (1 << 16);	/* LED1 como saida */
LCDinit();
LCDputs("Teste do Timer");
LCDcomando(0xc0);
LCDputs("e LCD:");
tempo=T0TC;
do	{
	if(T0TC == tempo+600) FIO4CLR2 = 1;	/* Liga LED1 em 600ms */
	if(T0TC == tempo+1000){
		FIO4SET2 = 1;		/* Desliga LED1 em 1000ms */
		tempo += 1000;		/* Atualiza o tempo */
		LCDcomando(0xc7);	/* Cursor no meio da linha 2 do LCD */
		escreve2digs(c++);	/* Escreve contagem a cada segundo */
		if(c==100) c=0;		/* Quando contagem = 100 volta para zero */
		}
	} while(1);
return 0;
}

/* Estas rotinas sao chamados pelo crt.S. 
Devem existir, mas ainda nao estao sendo usadas */
void UNDEF_Routine(){}
void SWI_Routine(){}
void FIQ_Routine(){}
