/*
 * File      : board.c
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2006, RT-Thread Develop Team
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://openlab.rt-thread.com/license/LICENSE
 *
 * Change Logs:
 * Date           Author       Notes
 * 2006-09-23     Bernard      first version
 * 2006-09-24     Bernard      add rt_hw_finsh_init implementation
 */

#include <rtthread.h>
#include <rthw.h>

#include <s3c44b0.h>
#include "board.h"

/* #define BOARD_DEBUG */
extern void rt_serial_putc(const char ch);

#define DATA_COUNT 0xfff

/**
 * @addtogroup wh44b0
 */
/*@{*/

void rt_timer_handler(int vector)
{
#ifdef BOARD_DEBUG
	rt_kprintf("timer handler, increase a tick\n");
#endif

	rt_tick_increase();
}

void rt_hw_port_init(void)
{
	/* PORT A GROUP */
	/* BIT 9	8	7	6	5	4	3	2	1	0	*/
	/* A24	  A23	A22	A21	A20	A19	A18	A17	A16	A0	*/	      
	/* 1		1	1	1	1	1	1	1	1	1	*/
	PCONA = 0x1ff;
	PDATA = 0x2db;

	/* PORT B GROUP */
	/* BIT 10   9    8       7      6        5     4     3     2     1     0    */
	/* /CS5 /CS4 /CS3    /CS2   /CS1     nWBE3 nWBE2 /SRAS /SCAS SCLS  SCKE	*/
	/* NC   NC   RTL8019 USBD12 NV_Flash NC    NC    Sdram Sdram Sdram Sdram*/
	/* 0,   0,   1,      1,     1,       0,    0,    1,    1,    1,    1    */
	PDATB = 0x4f;
	PCONB = 0x7cf;

	/* PORT C GROUP */
	/* BUSWIDTH=16													*/
	/* PC15		14		13		12		11		10		9		8	*/
	/* o		o		RXD1	TXD1	o		o		o		o	*/
	/* NC		NC		Uart1	Uart1	NC		NC		NC		NC	*/
	/* 01		01		11		11		01		01		01		00	*/

	/* PC7		6		5		4		3		2		1		0	*/
	/* o		o		o		o		o		o		o		o	*/
	/* NC		NC		NC		NC		NFALE 	NFCLE 	NFCE 	NFRB*/
	/* 01		01		01		01		01		01		01		00	*/
	PDATC = 0x3001;	/* All IO is low */
	PCONC = 0x5f555555;
	PUPC  = 0x3000;	/* PULL UP RESISTOR should be enabled to I/O */

	/* PORT D GROUP */
	/* PORT D GROUP(I/O OR LCD)										*/
	/* BIT7		6		5		4		3		2		1		0	*/
	/* VF		VM		VLINE	VCLK	VD3		VD2		VD1		VD0	*/
	/* 01		01		01		01		01		01		01		01	*/
	PDATD= 0x0;
	PCOND= 0xaaaa;	
	PUPD = 0x00; /* These pins must be set only after CPU's internal LCD controller is enable */
	
	/* PORT E GROUP  */
	/* Bit 8		7		6		5		4		3		2		1		0		*/
	/* ENDLAN	LED3	LED2	LED1	LED0	BEEP	RXD0	TXD0	CLKOUT	*/ 
	/* 00		01		01		01		01		01		10		10		11		*/
	PCONE	= 0x556b;	/*0->input, 1 2->TXD0 RXD0, 3 4->input, 5->led, 6->buzzer, 7->led, 8->CODECLK */
	PDATE	= 0x57;
	PUPE	= 0x006;	/* disable all pull-up */
	
	/* PORT F GROUP */
	/* Bit8		7		6		5		 4		3		2		1		0		*/   
	/* IISCLK	IISDI	IISDO	IISLRCK	Input	Input	Input	IICSDA	IICSCL	*/
	/* 100		010		010		001		00		01		01		10		10		*/
	PDATF = 0x2f;
	PCONF = 0x24900a;
	PUPF  = 0x1d3;

	/* PORT G GROUP */
	/* BIT7		6		5		4		3		2		1		0	 */
	/* INT7		INT6		INT5		INT4		INT3		INT2		INT1		INT0	*/
	/* S3		S4		S5		S6		NIC		EXT		IDE		USB	*/
	/* 11      11      11      11      11      11      11      11       */
	PDATG = 0xfc;
	PCONG = 0x000f; /* eint1 is eth interrupt in WH44B0 */
	PUPG  = 0x00;	/* should be enabled   */

	SPUCR=0x7;  /* D15-D0 pull-up disable */

	/* all external interrupts are triggered by low level */
	EXTINT=0x0;
}

/**
 * This function will init lumit4510 board
 */
void rt_hw_board_init()
{
	/* init port setting */
	rt_hw_port_init();

	/* set timer0 register */
	/* stop timer */
	TCON 	&= ~(0x00000001);

	/* dead zone = 0, pre = 150 */
	TCFG0 = 0x00000095;
	/* all are interrupt mode */
	TCFG1 = 0x00000003;

	TCNTB0 = DATA_COUNT;
	TCMPB0 = 0;

	/* manual update */
	TCON	|= 0x00000002;

	/* auto reload on,output inverter off */
	TCON 	&= ~(0x0000000f);
	TCON 	|= (0x00000008);

	/* install timer handler */
	rt_hw_interrupt_install(INT_TIMER0, rt_timer_handler, RT_NULL);
	rt_hw_interrupt_umask(INT_TIMER0);

	/* start timer */
	TCON 	|=(0x00000001);
}

void rt_hw_led_set(rt_uint32_t led)
{
	if((led & 0x01)==0x01)		/* D1 */
		PDATC = PDATC | (1<<1) ;
	else 
		PDATC = PDATC & (~(1<<1)) ;
	
	if((led & 0x02)==0x02)		/* D2 */
		PDATC = PDATC | (1<<2) ;
	else
		PDATC = PDATC & (~(1<<2)) ;

	if((led & 0x04)==0x04)		/* D3 */
		PDATC = PDATC | (1<<3) ;
	else
		PDATC = PDATC & (~(1<<3)) ;
}

/* led loop */
void rt_hw_led_flash(void)
{
	register int i;

	rt_hw_led_set(0x01);
	for ( i = 0; i < 2000000; i++);
	
	rt_hw_led_set(0x02);
	for ( i = 0; i < 2000000; i++);
	
	rt_hw_led_set(0x04);
	for ( i = 0; i < 2000000; i++);
}

#ifdef RT_USING_FINSH
extern void finsh_notify(void);
void rt_serial_isr(int vector)
{
	finsh_notify();
}

void rt_hw_finsh_init()
{
	/* install UART isr */
	rt_hw_interrupt_install(INT_URXD0, rt_serial_isr, RT_NULL);
	rt_hw_interrupt_umask(INT_URXD0);
}
#endif

void rt_hw_console_output(const char* string)
{
	while (*string)
	{
		rt_serial_putc(*string++);
	}
}

/*@}*/