/************************************************
Configura a porta serial UART com interrupcao
Sistemas Embarcados 2010/2
Marcos Augusto Stemmer
*************************************************/
#include <arch/nxp/lpc24xx.h>
#include "vic_cpsr.h"
#include "uart.h"
#define TAMFILA 0x100

char filarx[TAMFILA];	/* Fila de recebimento */
char filatx[TAMFILA];	/* Fila de transmissao */
volatile int rx_ini, rx_fim, tx_ini, tx_fim;
/* Declara que a funcao uart_irq e' um atendimento de IRQ */
void uart_irq(void) __attribute__ ((interrupt("IRQ")));

/* Atendimento da IRQ 6 (UART0) */
void uart_irq(void)
{
int k;
k = U0IIR;
/* Caractere recebido: Le e coloca no fim da fila RX */
while(U0LSR & 1) {
	filarx[rx_fim++] = U0RBR;
	if(rx_fim == TAMFILA) rx_fim = 0;
	}
/* Transmissor livre e caractere na fila TX: Pega da fila e transmite */
while((U0LSR & 0x20) && (tx_fim != tx_ini)) {
	U0THR = filatx[tx_ini++];
	if(rx_ini == TAMFILA) rx_ini=0;
	}
#ifdef DEBUG
FIO4PIN2 = ~(rx_fim);	/* Mostra contagem nos LEDs [para debugging] */
#endif
VICVectAddr = 0;	/* Limpa IRQ no VIC */
}

/* Configuracao da Porta Serial 0 com interrupcao */
void U0init(int baudrate)
{
int divisor;
PINSEL0 |= 0x50;	/* Seleciona pinos TxD0 e RxD0 */
U0FCR   = 0x87;	/* Habilita as FIFOs e reset. Interrompe com 8 chars */
U0LCR   = 0x83;	/* Habilita acesso ao divisor de baud-rate (DLAB) */
divisor = (SYSCLK/baudrate + 8) >> 4;
U0DLL   = divisor & 0xff;
U0DLM   = (divisor >> 8);
U0LCR    = 0x03;	/* Configura UART0 como 8N1 */
/* Habilita a interrupcao 6 da UART0 no VIC	*/
desabilitaIRQ();	/* Definida no #include "vic_cpsr.h"	*/
rx_fim = rx_ini = 0;
tx_fim = tx_ini = 0;
VICIntSelect &= ~(1<< 6);	/* UART bit 6 como IRQ	*/
VICIntEnable = (1<< 6);		/* Habilita int 6 */
VICVectAddr6 = (int)uart_irq;	/* Vetor para a rotina de atendimento */
VICVectCntl6 = 14;	/* VICVectPriority6 = 14; // A prioridade pode ser 0 a 15 */
U0IER = 3;	/* Hbilita irq por recebimento e transmissao na UART0 */
habilitaIRQ();	/* Definida no #include "vic_cpsr.h"	*/
}

/* Recebe um caractere da porta serial */
int U0getchar(void)
{
int c;
while(rx_ini == rx_fim);	/* Fila vazia: espera	*/
c = filarx[rx_ini++];		/* Pega c da fila	*/
if(rx_ini == TAMFILA) rx_ini = 0;
return c;
}

/* Envia um caractere */
void U0putchar(int c)
{
filatx[tx_fim++]=c;	/* Coloca caractere na fila */
if(tx_fim == TAMFILA) tx_fim = 0;
if(U0LSR & 0x20) {	/* Se transmissor livre, transmite */
	U0THR = filatx[tx_ini++];
	if(tx_ini == TAMFILA) tx_ini = 0;
	}
}

/* Informa quantos caracteres tem na fila de recebimento */
int U0tem(void)
{
int n;
n = rx_fim - rx_ini;
if(n < 0) n += TAMFILA;
return n;
}

/* Envia uma mensagem pela UART0 */
void U0puts(char *txt)
{
while(*txt) U0putchar(*txt++);
}

/* Escreve um digito hexadecimal */
void U0prdig(int dig)
{
dig &= 0xf;
if(dig > 9) dig+='A'-'9'-1;
U0putchar(dig+'0');
}

/* Escreve um byte como 2 digitos hexadecimais */
void U0prbyte(int c)
{
U0prdig(c>>4); U0prdig(c);
}
