/*
 * fwbc.c - broadcast the betty tv original firmware via uart0
 *          use fwdump to write it onto your computers harddisk
 *
 * author: hackbard@hackdaworld.org
 *
 */

/*
 * include files
 */

#include "lpc2xxx.h"

/*
 * defines
 */

/* misc */
#define OSC_CLOCK		10000000
#define BAUDRATE		9600
#define P_DIV			4
#define P_CLOCK			(OSC_CLOCK/P_DIV)

/* memory mapping */
#define	MMAP_BL			0x00
#define MMAP_RAM		0x02
#define MMAP_EXT		0x03

/* band 0/2 & bootloader addr */
#define BANK0			0x80000000
#define BANK2			0x82000000
#define BOOTLOADER		0x7fffe000

/*
 * type definitions
 */

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;

/*
 * function prototypes
 */

void mmap_init(u8 memtype);
void uart0_init(void);
void uart0_send_string(char *txbuf);
void uart0_send_char(char send);

/*
 * main function
 */

int main(void) {

	/* variables */

	u16 *mem=0;
	u32 *bl=0;
	u32 i,len;
	u8 start;

	/* memory mapping of interrupt vectors to static ram */

	//mmap_init(MMAP_RAM);

	/* uart initialization */

	//uart0_init();

	PINSEL0=0x05;			// pin select -> tx, rx
	UART0_FCR=0x07;			// enable fifo
	UART0_LCR=0x83;			// set dlab + word length
	UART0_DLL=0x10;			// br: 9600 @ 10/4 mhz
	UART0_DLM=0x00;
	UART0_LCR=0x03;			// unset dlab

	/* external memory init */

	BCFG0=0x1000FBEF;		// no boot[1:0] influence? (thnx colibri)
					// BCFG2 should be fine as is

	while(1) {

	/* wait for fwdump to send transmit start character */
	start=0x23;
	while(1) {
		while(!(UART0_LSR&(1<<0)))
			continue;
		start=UART0_RBR;
		if(start=='0') {
			mem=(u16 *)BANK0;
			len=0x80000;
			break;
		}
		if(start=='2') {
			mem=(u16 *)BANK2;
			len=0x80000;
			break;
		}
		if(start=='b') {
			BCFG0=0x1000FBEF;	// 32 bit width
			bl=(u32 *)BOOTLOADER;
			len=0x800;
			break;
		}
	}

	/* transmit 1 mb of data */
	for(i=0;i<len;i++) {			// care for endianness

		while(!(UART0_LSR&(1<<5)))
			continue;
		if(start=='b')
			UART0_THR=(*bl&0xff);
		else
			UART0_THR=(*mem&0xff);

		while(!(UART0_LSR&(1<<5)))
			continue;
		if(start=='b')
			UART0_THR=((*bl&0xff00)>>8);
		else {
			UART0_THR=((*mem&0xff00)>>8);
			mem++;
		}

		if(start=='b') {
			while(!(UART0_LSR&(1<<5)))
				continue;
			UART0_THR=((*bl&0xff0000)>>16);
			while(!(UART0_LSR&(1<<5)))
				continue;
			UART0_THR=((*bl&0xff000000)>>24);
			bl++;
		}
	}

	}

	return 0;
}

/*
 * functions
 */

void mmap_init(u8 memtype) {

	MEMMAP=memtype;
}

void uart0_init(void) {

	PINSEL0=0x05;			// pin select -> tx, rx
	UART0_FCR=0x07;			// enable fifo
	UART0_LCR=0x83;			// set dlab + word length
	UART0_DLL=0x10;			// br: 9600 @ 10/4 mhz
	UART0_DLM=0x00;
	UART0_LCR=0x03;			// unset dlab
}

void uart0_send_string(char *txbuf) {

	int i;

	i=0;

	while(txbuf[i])
		UART0_THR=txbuf[i++];
	UART0_THR='\n';
	UART0_THR='\r';

	while(!(UART0_LSR&(1<<6))) {}
}

void uart0_send_char(char send) {

	while(!(UART0_LSR&(1<<5)))
		continue;

	UART0_THR=send;
}

