/*****************************************************************************
 * FILE: lejos_osek_interface.c
 *
 * COPYRIGHT 2007 Takashi Chikamasa <takashic@cybernet.co.jp>
 *
 * DESCRIPTION:
 *   This is a glue code to execute Embedded Coder Robot NXT generated code
 *   by using LEJOS NXJ and TOPPERS OSEK. 
 *
 *   <About LEJOS NXJ>
 *    LEJOS NXJ is a full firmware replacement of LEGO Mindstorms NXT and 
 *   designed for Java programming environment for the NXT 
 *   ( For more detailed information, please see: http://lejos.sourceforge.net/ )
 *   In the LEJOS NXJ distribution, C source files for NXT platform layer is also
 *   included besides with the Java VM. The platform C source code is well
 *   structured, comprehensive, and achieved higher performance than the LEGO's
 *   one. Therefore, LEJOS NXJ (platform) is also the best GCC based C/C++  
 *   development platform for NXT.
 *
 *   The contents of this file are subject to the Mozilla Public License
 *   Version 1.0 (the "License"); you may not use this file except in
 *   compliance with the License. You may obtain a copy of the License at
 *   http://www.mozilla.org/MPL/
 *
 *   Software distributed under the License is distributed on an "AS IS"
 *   basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 *   License for the specific language governing rights and limitations
 *   under the License.
 *
 *   The Original Code is TinyVM code, first released March 6, 2000,
 *   later released as leJOS on September 23, 2000.
 *
 *   The Initial Developer of the Original Code is Jose H. Solorzano.
 *
 *   Contributor(s): see LEJOS NXJ ACKNOWLEDGEMENTS .
 *
 *
 *   <About TOPPERS OSEK>
 *    TOPPERS OSEK is an open source OSEK kernel and developed by TOPPERS project.
 *   TOPPERS(Toyohashi OPen Platform for Embedded Real-time Systems) has been managed 
 *   by a Non Profit Organization founded in Sep. 2003 and has been led by Professor
 *   Hiroaki Takada of Nagoya University in Japan. 
 *
 *   TOPPERS OSEK program is covered by the TOPPERS License as published
 *   by the TOPPERS PROJECT (http://www.toppers.jp/en/index.html).
 *
 *****************************************************************************/

/* LEJOS NXJ platform C */
#include "mytypes.h"
#include "interrupts.h"
#include "aic.h"
#include "AT91SAM7.h"
#include "uart.h"
#include "systick.h"
#include "nxt_avr.h"
#include "twi.h"
#include "platform_hooks.h"
#include "nxt_avr.h"
#include "nxt_lcd.h"
#include "nxt_motors.h"
#include "sensors.h"
#include "display.h"
#include "i2c.h"

/* TOPPERS OSEK */
#if 0
#include "kernel.h"
#include "kernel_id.h"
#include "cpu_insn.h"
#else /* patch */
#include "lejos_osek_interface.h"
#endif


/* ECRobot NXT */
#include "ecrobot_interface.h"
#include "lejos_osek_splash.txt"
#include "etrobocon_splash.txt"
#include "lejos_osek_menu.txt"
#include "lejos_osek_menu_bt.txt"


/*
 * Flag to notify OSEK was started
 */
#if 0
volatile U8 gStartOS_flag;
#else /* patch */
#endif

/*==============================================================================
 * LEJOS OSEK private functions
 *=============================================================================*/
static void show_ecrobot_splash(void)
{
	display_clear(0);
#ifdef ETROBOCON
	display_bitmap_copy(etrobocon_splash, 100, 8, 0, 0);
#else
	display_bitmap_copy(lejos_osek_splash, 100, 8, 0, 0);
#endif
	display_update();
}

static void show_ecrobot_instruction(U8 bt_status)
{
	display_clear(0);
	if (bt_status == BLUETOOTH_CONNECTED)
	{
		display_bitmap_copy(lejos_osek_menu_bt, 100, 8, 0, 0);
	}
	else
	{
		display_bitmap_copy(lejos_osek_menu, 100, 8, 0, 0);
	}
	display_update();
}

/*==============================================================================
 * LEJOS OSEK main functions
 *=============================================================================*/
/*
 * ecrobot_checkExitButton is invoked in a category 2 ISR systick_isr_C1 
 * every 1msec after StartOS was called
 */
void ecrobot_checkExitButton(void)
{
	register int st;
	static U32 last_act_time = 0;

	st = systick_get_ms();
	if (st >= last_act_time + 10) 
	{
		last_act_time = st;

		/* polling buttons and battery */
		ecrobot_poll_nxtstate();

		if (ecrobot_get_button_state() == STOP_PRESSED)
		{
			/* terminate ECRobot used devices */
			ecrobot_device_terminate();
			display_clear(1);
			
			/* reset the system */
#if 0
			start();
#else /* patch */
			lejos_osek_stop();
#endif
		}
		else if (ecrobot_get_button_state() == EXIT_PRESSED)
		{
			/* Terminate ECRobot used devices */
			ecrobot_device_terminate();
			display_clear(1);

			/* Send command to AVR to sleep ARM */
			nxt_avr_power_down();
		}
	}
}

int main(void)
{
	register int st;
	int last_nxtstate_time = 0;
	U8 device_status_old;

    /* When we get here:
	 * PLL and flash have been initialised and
	 * interrupts are off, but the AIC has not been initialised.
	 */
	aic_initialise();
	interrupts_enable();
	systick_init();
	nxt_avr_init();
	display_init();
	nxt_motor_init();
	i2c_init();
	init_sensors();

	/* show initial screen */
	systick_wait_ms(100);
	show_ecrobot_splash();
	systick_wait_ms(3000);

	gDevice_status = DEVICE_NO_INIT;
	while(1)
	{
		st = systick_get_ms();
		if (st >= last_nxtstate_time + 10) 
		{
			/* polling buttons (and battery) */
			ecrobot_poll_nxtstate();
			last_nxtstate_time = st;
		}
		
		/* initialize ECRobot used devices
		 * inside of init function, low level 
		 * initializations are done only first time.
		 */
		ecrobot_device_initialize();
		if (gDevice_status == DEVICE_NO_INIT)
		{
			show_ecrobot_instruction(0);
			gDevice_status = DEVICE_INITIALIZED;
		}
		else if (gDevice_status == BLUETOOTH_CONNECTED &&
			device_status_old != BLUETOOTH_CONNECTED)
		{
			show_ecrobot_instruction(BLUETOOTH_CONNECTED);
		}
		device_status_old = gDevice_status;

		if (ecrobot_get_button_state() == RUN_PRESSED)
		{
   			nxt_motor_set_count(NXT_PORT_A, 0);
   			nxt_motor_set_count(NXT_PORT_B, 0);
			nxt_motor_set_count(NXT_PORT_C, 0);

			/* turn off the LCD before disable int */
			display_clear(1);
			systick_wait_ms(10);
			
			/* start OSEK */
			/* StartOS should be called with disabled int */
#if 0
			disable_int(); 
			gStartOS_flag =1;
   			StartOS(1);
#else /* patch */
			lejos_osek_run();
#endif
    			
   			/* never reached here */
   		}
		else if (ecrobot_get_button_state() == EXIT_PRESSED)
		{
			/* terminate ECRobot used devices */
			ecrobot_device_terminate();
			display_clear(1);

			/* send command to AVR to sleep ARM */
			nxt_avr_power_down();
		}
    }
	/* never reached here */
	return 0;
}
