/* THIS SAMPLE CODE IS PROVIDED AS IS AND IS SUBJECT TO ALTERATIONS. FUJITSU */

/* MICROELECTRONICS ACCEPTS NO RESPONSIBILITY OR LIABILITY FOR ANY ERRORS OR */

/* ELIGIBILITY FOR ANY PURPOSES.                                             */

/*                 (C) Fujitsu Microelectronics Europe GmbH                  */

/*------------------------------------------------------------------------
  taskutility.C
  - 
-------------------------------------------------------------------------*/

/*************************@INCLUDE_START************************/
#include "mb96348hs.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

static void vUART0Task( void *pvParameters );

/**************************@INCLUDE_END*************************/

/*********************@GLOBAL_VARIABLES_START*******************/
const char	ASCII[] = "0123456789ABCDEF";

xTaskHandle UART_TaskHandle;

static xQueueHandle xQueue;
void InitUart0( void )
{
	/* Initialize UART asynchronous mode */
	BGR0 = configCLKP1_CLOCK_HZ / 9600; /* 9600 Baud @ CLKP1 - 56 MHz */

	SCR0 = 0x17;						/* 8N1 */
	SMR0 = 0x0d;						/* enable SOT3, Reset, normal mode */
	SSR0 = 0x02;						/* LSB first, enable receive interrupts */

	PIER08_IE2 = 1; /* enable input */
	DDR08_D2 = 0;	/* switch P08_2 to input */
	DDR08_D3 = 1;	/* switch P08_3 to output */
}

void Putch0( char ch )	/* sends a char */
{
	while( SSR0_TDRE == 0 );

	/* wait for transmit buffer empty 	*/
	TDR0 = ch;	/* put ch into buffer			*/
}

char Getch0( void ) /* waits for and returns incomming char 	*/
{
	volatile unsigned	ch;

	while( SSR0_RDRF == 0 );

	/* wait for data received  	*/
	if( SSR0_ORE )		/* overrun error 		*/
	{
		ch = RDR0;		/* reset error flags 		*/
		return ( char ) ( -1 );
	}
	else
	{
		return( RDR0 ); /* return char 			*/
	}
}

void Puts0( const char *Name1 ) /* Puts a String to UART */
{
	volatile portSHORT	i, len;
	len = strlen( Name1 );

	for( i = 0; i < len; i++ )	/* go through string */
	{
		if( Name1[i] == 10 )
		{
			Putch0( 13 );
		}

		Putch0( Name1[i] );					/* send it out                           */
	}
}

void Puthex0( unsigned long n, unsigned char digits )
{
	unsigned portCHAR	digit = 0, div = 0, i;

	div = ( 4 * (digits - 1) );				/* init shift divisor */
	for( i = 0; i < digits; i++ )
	{
		digit = ( (n >> div) & 0xF );		/* get hex-digit value */
		Putch0( digit + ((digit < 0xA) ? '0' : 'A' - 0xA) );
		div -= 4;		/* next digit shift */
	}
}

void Putdec0( unsigned long x, int digits )
{
	portSHORT	i;
	portCHAR	buf[10], sign = 1;

	if( digits < 0 )
	{					/* should be print of zero? */
		digits *= ( -1 );
		sign = 1;
	}

	buf[digits] = '\0'; /* end sign of string */

	for( i = digits; i > 0; i-- )
	{
		buf[i - 1] = ASCII[x % 10];
		x = x / 10;
	}

	if( sign )
	{
		for( i = 0; buf[i] == '0'; i++ )
		{				/* no print of zero */
			if( i < digits - 1 )
			{
				buf[i] = ' ';
			}
		}
	}

	Puts0( buf );		/* send string */
}

void vUtilityStartTraceTask( unsigned portBASE_TYPE uxPriority )
{
	xQueue = xQueueCreate( 5, sizeof( char ) );

	if( xQueue != NULL )
	{
		portENTER_CRITICAL();
		InitUart0();
		portENTER_CRITICAL();
		xTaskCreate( vUART0Task, (signed portCHAR *) "UART1", configMINIMAL_STACK_SIZE * 3, ( void * ) NULL, uxPriority, &UART_TaskHandle );
	}
}

static void vUART0Task( void *pvParameters )
{
	static portCHAR	buff[ 800 ] = { 0 };
	unsigned portLONG	trace_len;
	signed portLONG		i, j, l = 0;

	unsigned portCHAR	ch;
	( void ) pvParameters;

	SSR0_RIE = 1;

	Puts0( "\n -------------MB96348 FreeRTOS DEMO Task List and Trace Utility----------- \n" );

	for( ;; )
	{
		Puts0( "\n\rPress any of the following keys for the corresponding functionality: " );

		Puts0( "\n\r1: To call vTaskList() and display current task status " );

		Puts0( "\n\r2: To call vTaskStartTrace() and to display trace results once the trace ends" );

		/* Block on the semaphore.  The UART interrupt will use the semaphore to
		wake this task when required. */
		xQueueReceive( xQueue, &ch, portMAX_DELAY );

		switch( ch )
		{
			case '1':
				vTaskList( (signed char *) buff );
				Puts0( "\n\rThe current task list is as follows...." );
				Puts0( "\n\r----------------------------------------------" );
				Puts0( "\n\rName          State  Priority  Stack   Number" );
				Puts0( "\n\r----------------------------------------------" );
				Puts0( buff );
				Puts0( "\r----------------------------------------------" );
				break;

			case '2':
				vTaskStartTrace( (signed char *) buff, sizeof( buff ) );
				Puts0( "\n\rThe trace started!!" );
				vTaskDelay( (portTickType) 500 );
				trace_len = ulTaskEndTrace();
				Puts0( "\n\rThe trace ended!!" );
				Puts0( "\n\rThe trace is as follows...." );
				Puts0( "\n\r--------------------------------------------------------" );
				Puts0( "\n\r  Tick     | Task Number  |     Tick     | Task Number  |" );
				Puts0( "\n\r--------------------------------------------------------\n\r" );

				for( i = 0; i < trace_len; i += 4 )
				{
					for( j = i + 3; j >= i; j-- )
					{
						Puthex0( buff[j], 2 );
					}

					Puts0( "   |   " );
					l++;
					if( l == 4 )
					{
						Puts0( "\n" );
						l = 0;
					}
				}

				Puts0( "\r--------------------------------------------------------" );
				break;

			default:
				break;
		}

		Puts0( "\n" );
	}
}

__interrupt void UART0_TraceRxISR( void )
{
unsigned portCHAR ch;
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

	ch = RDR0;
	xQueueSendFromISR( xQueue, &ch, &xHigherPriorityTaskWoken );
}
