/*
 * $Id: uart.c 176 2005-09-27 17:19:21Z anders $
 * 
 * Copyright (C) 2005 Anders Dubgaard <anders@dubgaard.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "uart.h"
#include "radio/protocol.h"

/* ATmega128 compatibility, choose UART0 */
#if defined(__AVR_ATmega128__)
#define UDR	UDR0
#define UCSRA	UCSR0A
#define UCSRB	UCSR0B
#define UCSRC	UCSR0C
#define UBRRH UBRR0H
#define UBRRL UBRR0L

#define SIG_UART_RECV SIG_UART0_RECV
#define SIG_UART_DATA SIG_UART0_DATA
#endif

void UART_init(void) {
	UCSRA |= 1<<U2X;
#ifdef _DEBUG
	UBRRL = 7; /* 115200 Baud at 7.3728MHz clk - U2X must be set. */
#else
	UBRRL = 3; /* 230400 Baud at 7.3728MHz clk - U2X must be set. */
#endif
	UCSRB = (1<<RXEN | 1<<TXEN);
	UCSRC = 0x86;

	fdevopen(&UART_putc, &UART_getc, 0);
}

void print_package(volatile uint8_t *pkg) {
	int n;
	uint8_t *pkg_arr = (uint8_t *) package;
  for(n = 0; n < PACKAGE_LEN; n++) {
    printbyte(pkg_arr[n]);
  }
  putchar('\n');
  putchar('\r');
}

void printbyte_n(uint8_t a) {
	int i;
	for(i=0; i<8; i++) {
		(a & 0x80)? putchar('1'): putchar('0');
		a <<= 1;
	}
}

void printbyte(uint8_t a) {
  printbyte_n(a);
	putchar(' ');
}

int UART_putc(char c) {
	loop_until_bit_is_set(UCSRA, UDRE);
	UDR = c;

	return 0;
}

int UART_getc(void) {
  while( !(UCSRA & 1<<RXC) )
    ;
  return (int) UDR;
}

#ifdef _VERBOSE_DEBUG
void print_data_verbose(volatile psx_data *psx){
	uint8_t mask;
	volatile int unreg_cnt;

	UART_putc('\r');  /* Rewrite on top of previous line */
	UART_putc('\n');

	/* controller type */
	if((*psx).type == DIGIPAD)
		printf("Dig (0x%x): ", (*psx).type);
	else if((*psx).type == ANALOG_RED)
		printf("Ana (0x%x): ", (*psx).type);
	else{
		printf("Unrecognised controller... ");
		for(unreg_cnt=0;unreg_cnt<30000;unreg_cnt++);
	}
	/* buttons */
	mask = 1;
	printf("%s",((*psx).buttons & mask)? "sel":"SEL");
	mask <<= 1;
	printf("%s",((*psx).buttons & mask)? "jr":"JR");
	mask <<= 1;
	printf("%s",((*psx).buttons & mask)? "jl":"JL");
	mask <<= 1;
	printf("%s",((*psx).buttons & mask)? "str":"STR");
	mask <<= 1;
	printf("%s",((*psx).buttons & mask)? "_":"^");
	mask <<= 1;
	printf("%s",((*psx).buttons & mask)? "_":">");
	mask <<= 1;
	printf("%s",((*psx).buttons & mask)? "_":"v");
	mask <<= 1;
	printf("%s",((*psx).buttons & mask)? "_":"<");
	/* buttons2 */
	mask = 1;
	printf("%s",((*psx).buttons2 & mask)? "__":"L2");
	mask <<= 1;
	printf("%s",((*psx).buttons2 & mask)? "__":"R2");
	mask <<= 1;
	printf("%s",((*psx).buttons2 & mask)? "__":"L1");
	mask <<= 1;
	printf("%s",((*psx).buttons2 & mask)? "__":"R1");
	mask <<= 1;
	printf("%s",((*psx).buttons2 & mask)? "__":"/\\");
	mask <<= 1;
	printf("%s",((*psx).buttons2 & mask)? "_":"O");
	mask <<= 1;
	printf("%s",((*psx).buttons2 & mask)? "_":"X");
	mask <<= 1;
	printf("%s",((*psx).buttons2 & mask)? "__":"[]");
	/* left + right analogue sticks: r and l horz/vert */
	if((*psx).type == ANALOG_RED){
		printf(" Right x:%3d, y:%3d",(*psx).r_horz,(*psx).r_vert);
		printf(" Left x:%3d, y:%3d",(*psx).l_horz,(*psx).l_vert);
	}
	printf(" ");
}
#endif // _VERBOSE_DEBUG
