//==========================================================================
//
//      drawmenu.c
//
//      For draw the main menu and some test function
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos 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 or (at your option) any later version.
//
// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):    Ray Wang
// Contributors:
// Date:         2008-03-29
// Current Ver : 0.1
// Purpose:
// Description:  For draw the main menu and some test function.
// Copyright:    2008 Kinpo Beijing, Inc.
//
//####DESCRIPTIONEND####
//
//==========================================================================

//#include <cyg/io/disk_ms.h>
#include <cyg/io/drawmenu.h>
#include <cyg/io/paint_lcd.h>
#include <redboot.h>
#include <string.h>
#include <stdlib.h>
#include <cyg/infra/cyg_ass.h>
#include <cyg/hal/kinpo_g23.h>

/* The globle variable          */

#define LINE_W 20
bool exit_diagnostic = false;

char *teststr[] = {
	" .) KEY Test!              ...",
	" .) LED Test!              ...",
	" .) LCD Test!              ...",
	" .) RAM Test!              ...",
	" .) LBA Test!              ...",
#ifdef LBA_IQC_TEST_ENABLE
	" .) LBA iqc Test!          ...",
	" .) LBA iqc Check!         ...",
#endif
	" .) Exit Diagnostic!       ...",
};

char *testing[] = {
	" .) KEY Test!       Testing...",
	" .) LED Test!       Testing...",
	" .) LCD Test!       Testing...",
	" .) RAM Test!       Testing...",
	" .) LBA Test!       Testing...",
#ifdef LBA_IQC_TEST_ENABLE
	" .) LBA iqc Test!   Testing...",
	" .) LBA iqc Check!  Checking..",
#endif
	" .)                 Leaving...",
};

char *test_ng[] = {
	" .) KEY Test!       Test NG...",
	" .) LED Test!       Test NG...",
	" .) LCD Test!       Test NG...",
	" .) RAM Test!       Test NG...",
	" .) LBA Test!       Test NG...",
#ifdef LBA_IQC_TEST_ENABLE
	" .) LBA iqc Test!   Test NG...",
	" .) LBA iqc Check!  Check NG..",
#endif
};

char *test_ok[] = {
	" .) KEY Test!       Test OK...",
	" .) LED Test!       Test OK...",
	" .) LCD Test!       Test OK...",
	" .) RAM Test!       Test OK...",
	" .) LBA Test!       Test OK...",
#ifdef LBA_IQC_TEST_ENABLE
	" .) LBA iqc Test!   Test OK...",
	" .) LBA iqc Check!  Check END.",
#endif
};

#define Y_W	(SCREEN_HEIGHT/16*1) // W-AXIS WIDTH

#define Y1	0//(SCREEN_HEIGHT/16*0)
#define Y2	(SCREEN_HEIGHT/16*1)
#define Y3	(SCREEN_HEIGHT/16*2)
#define Y4	(SCREEN_HEIGHT/16*3)
#define Y5	(SCREEN_HEIGHT/16*4)
#define Y6	(SCREEN_HEIGHT/16*5)
#define Y7	(SCREEN_HEIGHT/16*6)
#define Y8	(SCREEN_HEIGHT/16*7)
#define Y9	(SCREEN_HEIGHT/16*8)
#define Y10	(SCREEN_HEIGHT/16*9)
#define Y11	(SCREEN_HEIGHT/16*10)
#define Y12	(SCREEN_HEIGHT/16*11)
#define Y13	(SCREEN_HEIGHT/16*12)
#define Y14	(SCREEN_HEIGHT/16*13)
#define Y15	(SCREEN_HEIGHT/16*14)
#define Y16	(SCREEN_HEIGHT/16*15)

#define IQC_TEST_MDA_RANGE	0x3b9c00

int choice_yes_or_no(void);
void diagnostic_ram_test(void);
void diagnostic_lba_test(void);

#ifdef LBA_IQC_TEST_ENABLE
void diagnostic_lba_iqc_test(void);
void diagnostic_lba_iqc_check(void);
#endif

void draw_up(void);
void draw_down(void);

void reboot_test(bool isFirst);

externC unsigned int pmic_reg_set(unsigned int reg, unsigned int val,
                                  unsigned int mask);
externC unsigned int pmic_reg(unsigned int reg, unsigned int val, unsigned int write);
extern void ipu_enable_sdc_bg(bool flag);
extern void ipu_dma_channel_enable(cyg_uint32 channel,bool flag);

extern void led_shine(bool enable);
extern cyg_uint8 mxc_kpp_scan(void);
extern cyg_bool check_power_key(void);
extern void lcd_on(void);
extern void lcd_off(void);
extern int run_lba_format(void);
extern int run_lba_test(void);
extern cyg_uint32 run_lba_iqc_test(cyg_uint32 start, cyg_uint32 end, cyg_uint32 *cks);
extern cyg_uint32 run_lba_iqc_check(cyg_uint32 start, cyg_uint32 end, cyg_uint32 *cks);
extern int run_ram_test(void);
extern cyg_uint8 mxc_kpp_scan(void);

extern cyg_uint16 read_eeprom(cyg_addrword_t base, cyg_uint16 offset);
extern void write_eeprom(cyg_addrword_t base, cyg_uint16 offset, cyg_uint16 data);

void SetMiliSecond(cyg_uint32 timer);
/*
 * Purpose:     draw the main menu
 *
 * Parameter:   NULL
 *
 * Return:      NULL
 */
void main_menu(void)
{
	int i = 0;
	color_t c_color,b_color;

	/* for title block */
	paint_rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, RED);

	/* for menu block */
	paint_rect(0, Y3, SCREEN_WIDTH, Y13, BLUE);

	/* title */
	c_color = YELLOW;
	b_color = RED;
	print_fmt(SCREEN_WIDTH/2-(strlen(TITLE))*4, (SCREEN_HEIGHT/8)/2-8, c_color, b_color, TITLE);
	/* menu */
	c_color = WHITE;
	b_color = BLUE;
	for (i=0; i<end_; i++) {
		print_fmt(0, Y3+(Y_W*i), 
				c_color, b_color, teststr[i]);
	}
}

/*
 * Purpose:     choice a menu.
 *
 * Parameter:   NULL
 *
 * Return:      NULL
 */
void choice_menu(int choice, int is_run)
{
	int i = 0;
	color_t c_color, b_color;

	c_color = WHITE;
	b_color = BLUE;

	for (i=0; i<end_; i++) {
		print_fmt(0, Y3+(Y_W*i),
			c_color, b_color, teststr[i]);
	}

	c_color = BLACK;
	b_color = YELLOW;

	if(is_run) {
		print_fmt(0, Y3+(Y_W*(choice-1)),
			c_color, b_color, testing[(choice-1)]);
	} else {
		print_fmt(0, Y3+(Y_W*(choice-1)),
			c_color, b_color, teststr[(choice-1)]);
		return;
	}

	if(is_run) {
		switch((choice-1))
		{
		case ram:
			diagnostic_ram_test();
			break;
		case key:
			key_test();
			break;
		case led:
			led_test();
			break;
		case lcd:
			lcd_test();
			break;
		case lba:
			//diagnostic_lba_test();
			reboot_test(true);
			break;
			
#ifdef LBA_IQC_TEST_ENABLE
		case lba_iqc_test:
			diagnostic_lba_iqc_test();
			break;
#endif

#ifdef LBA_IQC_TEST_ENABLE
		case lba_iqc_check:
			diagnostic_lba_iqc_check();
			break;
#endif

		case exit_d:
			paint_rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GRAY);
			print_fmt(80, 100, YELLOW, BLUE,"Leave Diagnostic Mode");
			exit_diagnostic = true;
			break;
		default:
			main_menu();
			break;
		}
	}
}

void led_test(void)
{
	led_shine(0);
	SetMiliSecond(500);
	led_shine(1);
	SetMiliSecond(500);
	led_shine(0);
	SetMiliSecond(500);
	led_shine(1);
	SetMiliSecond(500);
	led_shine(0);
	SetMiliSecond(500);
	led_shine(1);
	SetMiliSecond(500);
	led_shine(0);

	print_fmt(0, Y3+Y_W*led, 
			WHITE, GREEN, test_ok[led]);

	return;
}

void lcd_test(void)
{
	int i = 0;
	color_t c_color, b_color;
	unsigned short color[] = {
		WHITE,
		RED,
		GRAY,
		GREEN,
		BLACK,
		YELLOW,
		BLUE,
		MAGENT,
	};

	c_color=BLACK;
	b_color=YELLOW;

	for (i=0; i<8; i++) {
		paint_rect(60*i, 0, 60, SCREEN_HEIGHT, color[i]);
	}
	
	SetMiliSecond(500);

	while(!check_power_key());
	
	paint_rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, color[4]);

	SetMiliSecond(500);
	
	while(!check_power_key());
		
	paint_rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, color[0]);

	SetMiliSecond(500);
	
	while(!check_power_key());

	main_menu();

	print_fmt(0, Y3+Y_W*lcd, 
			WHITE, GREEN, test_ok[lcd]);

	SetMiliSecond(1000);
	
	return;
}
void key_test(void)
{
#define PK_CHECK	0	// remove power key test for diagnostic

	unsigned int i = 0xffffff;
	color_t c_color, b_color;
	unsigned char key_val = 0;
	int menu_res = 0;
	int area_res = 0;
	int all_res = 0;
#if PK_CHECK
	int pow_res = 0;
#endif

	c_color=BLACK;
	b_color=YELLOW;

	while (i--) {
#if PK_CHECK
		if (check_power_key()) {
			pow_res = 1;
        	print_fmt(0, Y3, c_color, b_color, 
					" .) KEY Test!         POWER...");
    	}
#endif

		key_val = mxc_kpp_scan();
		if (key_val != 0) {
			if (key_val == 0x8) {
				menu_res = 1;
				print_fmt(0, Y3, c_color, b_color, 
					" .) KEY Test!          MENU...");
				i = 0xffffff;
			} else if (key_val == 0x10) {
				area_res = 1;
				print_fmt(0, Y3, c_color, b_color, 
					" .) KEY Test!          POS....");
				i = 0xffffff;
			}
		}

#if PK_CHECK
		if (menu_res==1 && area_res==1 && pow_res==1) {
#else
		if (menu_res==1 && area_res==1) {
#endif
			break;
		}
	}

#if PK_CHECK
	if (menu_res!=1 && area_res!=1 && pow_res!=1) {
#else
	if (menu_res!=1 && area_res!=1) {
#endif
		print_fmt(0, Y3, c_color, b_color, test_ng[key]);
	} else if (menu_res!=1 && all_res!=1) {
		print_fmt(0, Y3, c_color, b_color, 
			" .) KEY Test!       MENU NG...");
	} else if (area_res!=1 && all_res!=1) {
		print_fmt(0, Y3, c_color, b_color, 
			" .) KEY Test!       POS NG....");
#if PK_CHECK
	} else if (pow_res!=1) {
		print_fmt(0, Y3, c_color, b_color, 
			" .) KEY Test!      POWER NG...");
#endif
	} else {
		print_fmt(0, Y3, WHITE, GREEN, test_ok[key]);
	}

	SetMiliSecond(1000);
	
	return;
}

int choice_yes_or_no(void)
{
	cyg_uint8 key;
	color_t c_color, b_color;
	int isYes=0;

	paint_rect(0, SCREEN_HEIGHT/2, SCREEN_WIDTH, SCREEN_HEIGHT/2, BLUE);
	
	c_color=WHITE;
	b_color=BLUE;
	print_fmt(SCREEN_WIDTH/2, Y13, c_color, b_color,"Yes");

	c_color=BLACK;
	b_color=YELLOW;
	print_fmt(SCREEN_WIDTH/2, Y15, c_color, b_color,"No");

	isYes=0; //choice No

	SetMiliSecond(800);
	
	while(1) {
		if(check_power_key())
			break;
		
		key = mxc_kpp_scan();

		if (key == 0x0) {
			// no key
			continue;
		}else if ((key&0x8) == 0x8) {
			// up key
			print_fmt(SCREEN_WIDTH/2, Y13, BLACK, YELLOW, "Yes");
			print_fmt(SCREEN_WIDTH/2, Y15, WHITE, BLUE,    "No");
			isYes=1; //choice Yes		
		} else if ((key&0x10) == 0x10) {
			// down key
			print_fmt(SCREEN_WIDTH/2, Y13, WHITE, BLUE,   "Yes");
			print_fmt(SCREEN_WIDTH/2, Y15, BLACK, YELLOW,  "No");
			isYes=0; //choice No		
		}

		SetMiliSecond(300);
	}

	return isYes;
}

void mems_test(void)
{
	int x = 0;
	color_t c_color, b_color;

	x = SCREEN_WIDTH/80;
	c_color=BLACK;
	b_color=YELLOW;

	/*if (ms_test_by_touch()) {
		print_fmt(x, 10+(SCREEN_HEIGHT/6)+LINE_W*mems, 
			c_color, b_color, test_ng[mems]);
	} else {
		print_fmt(x, 10+(SCREEN_HEIGHT/6)+LINE_W*mems,
			c_color, b_color, test_ok[mems]);
	}*/

	return;
}

void diagnostic_lba_test(void)
{
	color_t c_color, b_color;
	
	c_color=BLACK;
	b_color=YELLOW;
				
	if (run_lba_test()!=0) {
		print_fmt(0, Y3+Y_W*lba, 
			WHITE, GREEN, test_ok[lba]);
	} else {
		print_fmt(0, Y3+Y_W*lba, 
			WHITE, RED, test_ng[lba]);
	}
}

#ifdef LBA_IQC_TEST_ENABLE
void diagnostic_lba_iqc_test(void)
{
	color_t c_color, b_color;
	char cksstr[32];
	cyg_uint16 ans;
	cyg_uint32 start,end,cks;
	
	c_color=BLACK;
	b_color=YELLOW;

	paint_rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT/2, BLUE);

	print_fmt(0, Y4, RED, WHITE,
			"Format MDA & VFA!! You will not boot to KERNEL!!");
	
	print_fmt(0, Y5, RED, WHITE,"Are you agree?");
	
	if(!choice_yes_or_no()) {
		print_fmt(0, SCREEN_HEIGHT/2, c_color, b_color,"Leave LBA iqc test");
		SetMiliSecond(1000);
		goto leave_lba_iqc_test;
	}

	//LAN_BASE=0xb4000300
	//write_eeprom(0xb4000300, 1, 0x55aa);
	//ans = read_eeprom(0xb4000300, 1);
	//diag_printf("redboot: ans=0x%x\n",ans);

	paint_rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, YELLOW);
	
	print_fmt(0, Y3+Y_W*lba_iqc_test, RED, YELLOW,
		"Formating don't power off!! wait 10sec..");

	if(!run_lba_format()) {
		print_fmt(0, Y3+Y_W*lba_iqc_test, WHITE, RED,
			"Format NG!!");
		goto confirm_exit;
	}

	paint_rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, BLUE);
	
	paint_rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, BLUE);
	print_fmt(0, Y3+Y_W*lba_iqc_test, c_color, b_color, testing[lba_iqc_test]);

	cks=0;
	start=0;
	end=0x100;
	while(end<=IQC_TEST_MDA_RANGE) {
		ans = run_lba_iqc_test(start,end,&cks);
		if (0!=ans) {
			diag_sprintf(cksstr, "0x%X, 0x%X", end,cks);
			print_fmt(0, Y3+Y_W*(lba_iqc_test+1), c_color, b_color, cksstr);
		} else {
			print_fmt(0, Y3+Y_W*lba_iqc_test, 
				WHITE, RED, test_ng[lba_iqc_test]);
			break;
		}
		start+=0x100;
		end+=0x100;
	}

	if(end>IQC_TEST_MDA_RANGE)
		print_fmt(0, Y3+Y_W*lba_iqc_test, WHITE, GREEN, test_ok[lba_iqc_test]);

confirm_exit:
	SetMiliSecond(300);

	while(!check_power_key());
	
	SetMiliSecond(300);

leave_lba_iqc_test:
	
	main_menu();

	print_fmt(0, Y3+Y_W*lba_iqc_test,
			c_color, b_color, teststr[lba_iqc_test]);
		
}
#endif

#ifdef LBA_IQC_TEST_ENABLE
void diagnostic_lba_iqc_check(void)
{
	color_t c_color, b_color;
	char cksstr[32];
	cyg_uint32 ans;
	cyg_uint32 start,end,cks;
	
	c_color=BLACK;
	b_color=YELLOW;

	paint_rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT/2, BLUE);

	paint_rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, BLUE);
	print_fmt(0, Y3+Y_W*lba_iqc_test, c_color, b_color, testing[lba_iqc_check]);

	cks=0;
	start=0;
	end=0x100;
	while(end<=IQC_TEST_MDA_RANGE) {
		ans = run_lba_iqc_check(start,end,&cks);
		if (0!=ans) {
			diag_sprintf(cksstr, "0x%X, 0x%X", end,cks);
			print_fmt(0, Y3+Y_W*(lba_iqc_test+1), c_color, b_color, cksstr);
		} else {
			print_fmt(0, Y3+Y_W*lba_iqc_test, 
				WHITE, RED, test_ng[lba_iqc_check]);
			break;
		}
		start+=0x100;
		end+=0x100;
	}

	if(end>IQC_TEST_MDA_RANGE)
		print_fmt(0, Y3+Y_W*lba_iqc_test, WHITE, GREEN, test_ok[lba_iqc_check]);
	
	SetMiliSecond(300);

	while(!check_power_key());

	SetMiliSecond(300);
	
	main_menu();

	print_fmt(0, Y3+Y_W*lba_iqc_check,
			c_color, b_color, teststr[lba_iqc_check]);
		
}
#endif

void diagnostic_ram_test(void)
{
	color_t c_color, b_color;
	
	c_color=BLACK;
	b_color=YELLOW;
				
	if (run_ram_test()!=0) {
		print_fmt(0, Y3+Y_W*ram, 
			WHITE, GREEN, test_ok[ram]);
	} else {
		print_fmt(0, Y3+Y_W*ram, 
			WHITE, RED, test_ng[ram]);
	}
}

void draw_up(void)
{
	paint_rect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,BLACK);
	paint_rect(0, 0, SCREEN_WIDTH, 90, RED);
}

void draw_down(void)
{
	paint_rect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,BLACK);
	paint_rect(0,SCREEN_HEIGHT-90, SCREEN_WIDTH, 90, RED);
}

void reboot_test(bool isFirst)
{
	cyg_uint32 rtc_time;
	char str[16];
	
	pmic_reg_set( 3,0,0x2);
	pmic_reg_set( 4,0,0x2);

	if(isFirst) {
		// first test , clean rtc time.
		pmic_reg_set(20,0,0xffffff);
		pmic_reg_set(21,0,0xffffff);
	}
	
	rtc_time = pmic_reg(20,0,0);
	paint_rect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,BLACK);

	// because the lba test time=4sec.
	diag_sprintf(str, "  %d  ",(rtc_time/4));
	print_fmt(SCREEN_WIDTH/2, SCREEN_HEIGHT/2, WHITE, BLUE, str);
	SetMiliSecond(800);
	rtc_time+=2;
	pmic_reg_set(21,rtc_time,0xffffff);
	pmic_reg_set(22,0x7ff0,0x7fff);
	pmic_reg_set(23,0x7ff0,0xffffff);
	insb(CPLD_CCR_WDI, CPLD_BASE + CPLD_CCR, CPLD_CCR_WDI);
}

#if 0
/*
 * Purpose:     test ram.
 *
 * Parameter:   NULL
 *
 * Return:      NULL
 */
void ram_test(void)
{
	char *p_ram = NULL;
	char *p_tmp;
	int buf_sz = 1024*1024;
	int count =0;
	int i = 0;
	int x = 0;
	color_t c_color, b_color;

	x = SCREEN_WIDTH/80;
	c_color=BLACK;
	b_color=YELLOW;

	do {
		p_ram = (char *) malloc(buf_sz);
	} while (p_ram==NULL);
	p_tmp = p_ram;
	i++;
	while( p_tmp - p_ram < buf_sz){
		*p_tmp = 0x5A;
		*(p_tmp+1) = 0xA5;
		p_tmp += 2;
	}
	p_tmp = p_ram;

	while( p_tmp - p_ram < buf_sz){
		if( *p_tmp != 0x5A || *(p_tmp+1) != 0xA5){
			count++;
		}
		p_tmp += 2;
	}

	if (count == 0) {
		print_fmt(x, 10+(SCREEN_HEIGHT/6)+LINE_W*ram, 
			c_color, b_color, test_ok[ram]);
		i++;
	} else {
		print_fmt(x, 10+(SCREEN_HEIGHT/6)+LINE_W*ram, 
			c_color, b_color, test_ng[ram]);
		i++;
	}
	free(p_ram);
	return;
}
#endif
