#include <msp430.h>
#include <stdint.h>
#include <stdio.h>
#include <ctype.h>

#include "strutils.h"
#include "mw_main.h"

#include "mw_uart.h"

static char UART_RX_CHAR = 0;

#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART

void debug_uart_tx_char(char c);

#pragma vector=USCI_A3_VECTOR
__interrupt void UCA_ISR (void)
{
	switch (UCA3IV) {
		case 2: // RXIFG
			/* clear IRQ flag */
			UCA3IFG  &= ~UCRXIFG;
			UART_RX_CHAR = UCA3RXBUF;
			_event_src |= DBG_UART_RCV_EVENT;
			/* wake up to handle the received char */
			// LPM3_EXIT;
			LPM3_EXIT_ISR();
			break;
		case 4: // TXIFG
			break;
		default:
			break;
	}
}

void init_debug_uart(void)
{
	/* assert reset */
	UCA3CTL1 = UCSWRST;

	/* reset default SMCLK = 1.048MHz */
	UCA3CTL1 |= UCSSEL__SMCLK;
	/* CLK        baud   BRx  BRSx  BRFx */
	/* 1,048,576  115200 9    1     0 */
	/* 16,000,000 115200 138  7     0 */

	UCA3BR0 = 138;
	UCA3MCTL = UCBRS_7 | UCBRF_0;

	/* set P10.4 & P10.5 to UCA function */
	P10SEL |= BIT4;
	P10SEL |= BIT5;

	UCA3STAT = 0;

	/* deassert reset */
	UCA3CTL1 &= ~UCSWRST;

	/* enable receive interrupt */
	UCA3IE = UCRXIE;
	/* clear interrup flags */
	UCA3IFG = 0;
}

void debug_uart_tx_char(const char c)
{
	while (UCA3STAT & UCBUSY)
		nop();
	UCA3TXBUF = c;
	while ((UCA3IFG & UCTXIFG) == 0 )
		nop();
}

void debug_uart_tx(const char *buf)
{
	unsigned char i = 0;

	while (buf[i] != 0) {
		debug_uart_tx_char(buf[i]);
		if (buf[i++] == '\n')
			debug_uart_tx_char('\r');
	}
	while (UCA3STAT & UCBUSY)
		nop();
}

void debug_dump_hex(const uint16_t len, const void *buf)
{
	int i;
	char tstr[8];

	for (i=0; i<len; i++) {
		debug_uart_tx("0x");
		hexnum2str(*(uint8_t *)(buf+i),tstr,2);
		debug_uart_tx(tstr);
		debug_uart_tx(" ");
	}
	debug_uart_tx("\n");
}

void debug_dump_ascii(const uint16_t len, const void *buf)
{
	int i;

	for (i=0; i<len; i++) {
		debug_uart_tx_char(isprint(*(uint8_t *)(buf+i)) ? *(uint8_t *)(buf+i) : '.');
	}
	debug_uart_tx("\n");
}

char debug_uart_rx_char(char *c)
{
	if (UART_RX_CHAR != 0) {
		*c = UART_RX_CHAR;
		UART_RX_CHAR = 0;
		return 1;
	} else {
		*c = 0;
		return 0;
	}
}
#endif