//-----------------------------------------------------------------------------
// includes
//

#include <p24HJ128GP204.h>
#include "console.h"


//-----------------------------------------------------------------------------
//  globals
//

unsigned char txiptr;
unsigned char txoptr;
unsigned char rxiptr;
unsigned char rxoptr;
char txbuffer[U1TXBUFSIZE];
char rxbuffer[U1RXBUFSIZE];


//-----------------------------------------------------------------------------
// constants
//

const char tohex[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };


//-----------------------------------------------------------------------------
// functions
//

void ConsoleInit (void) 
{
	txiptr = 0;
	txoptr = 0;
	rxiptr = 0;
	rxoptr = 0;
	IPC3bits.U1TXIP = 2;
	IFS0bits.U1TXIF = 0;
	IEC0bits.U1TXIE = 1;
	IPC2bits.U1RXIP = 2;
	IFS0bits.U1RXIF = 0;
	IEC0bits.U1RXIE = 1;
}

void _ISR __attribute__((__no_auto_psv__)) _U1TXInterrupt(void)
{
	IFS0bits.U1TXIF = 0;

	if (!U1STAbits.UTXBF && (txoptr != txiptr)) {
		U1TXREG = txbuffer[txoptr++];
		if (txoptr >= U1TXBUFSIZE) {
			txoptr = 0;
		}
	}
}

void _ISR __attribute__((__no_auto_psv__)) _U1RXInterrupt(void)
{
	IFS0bits.U1RXIF = 0;

	while (U1STAbits.URXDA) {
		if (((rxiptr + 1) & (U1RXBUFSIZE - 1)) == (rxoptr & (U1RXBUFSIZE - 1))) {
			// discard character
			U1RXREG;
		} else {
			// receive character
			rxbuffer[rxiptr++] = U1RXREG;
			if (rxiptr >= U1RXBUFSIZE) {
				rxiptr = 0;
			}
		}
	}
}

void putchar (char ch)
{
	while (((txiptr + 1) & (U1TXBUFSIZE - 1)) == (txoptr & (U1TXBUFSIZE - 1))) {
	}

	IEC0bits.U1TXIE = 0;
	if (txiptr == txoptr) {
		IFS0bits.U1TXIF = 1;
	}
	txbuffer[txiptr++] = ch;
	if (txiptr == U1TXBUFSIZE) {
		txiptr = 0;
	}
	IEC0bits.U1TXIE = 1;
}

void putstring (char *s)
{
	while (*s) {
		putchar (*s++);
	}
}

void putstringcrlf (char *s)
{
	while (*s) {
		putchar (*s++);
	}
	putchar (0x0d);
	putchar (0x0a);
}

void puthex4 (unsigned char a)
{
	putchar (tohex[a & 0xf]);
}

void puthex8 (unsigned char a)
{
	putchar (tohex[(a >> 4) & 0xf]);
	putchar (tohex[a & 0xf]);
}

void puthex16 (unsigned short a)
{
	putchar (tohex[(a >> 12) & 0xf]);
	putchar (tohex[(a >> 8) & 0xf]);
	putchar (tohex[(a >> 4) & 0xf]);
	putchar (tohex[a & 0xf]);
}

void puthex32 (unsigned long a)
{
	putchar (tohex[(a >> 28) & 0xf]);
	putchar (tohex[(a >> 24) & 0xf]);
	putchar (tohex[(a >> 20) & 0xf]);
	putchar (tohex[(a >> 16) & 0xf]);
	putchar (tohex[(a >> 12) & 0xf]);
	putchar (tohex[(a >> 8) & 0xf]);
	putchar (tohex[(a >> 4) & 0xf]);
	putchar (tohex[a & 0xf]);
}

short getchar (void)
{
	unsigned ch;

	if (rxiptr == rxoptr) {
		return -1;
	}
	ch = rxbuffer[rxoptr++];
	if (rxoptr >= U1RXBUFSIZE) {
		rxoptr = 0;
	}
	return ch;
}



