
/************************************************************************
* Copyright(c) 2023 Levetop Semiconductor Co.,Led. All rights reserved.
* @file    	main.c
* @author  	OS Team
* @version  V1.0.0
* @date     2023-07-27
* @brief 	This file include main function.

*************************************************************************/


#include "tp.h"
#include "pwm.h"
#include "LT768_Lib.h"
#include "lcd.h"
#include "rtc.h"

#include "stdio.h"

#include "LT776_gra.h"

extern unsigned const char BMP_Acorn[];
extern unsigned const char BMP_Acorn1[];

extern UINT32 gSysTick_Counter;
extern void HAL_IncTick(void);
extern void HAL_SDRAM_Init(uint32_t Sys_clk);

extern void Init_SysTick(void);

char *version="V1.0";

// =================================================================
// For FreeRTOS

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "event_groups.h"

#define configSUPPORT_STATIC_ALLOCATION	1
#define configSUPPORT_DYNAMIC_ALLOCATION 	0

#define TASK_STACK_SIZE 	      			512

#define TASK_QUEUE_LENGTH						10
#define TASK_QUEUE_ITEM_SIZE					16

static StaticSemaphore_t 		mutex_0;
static StaticQueue_t 	 		queue_0,queue_1;
static StaticSemaphore_t 		semaphore_0;
static StaticEventGroup_t 		eventgroup_0;


static SemaphoreHandle_t 		mutex_handler;
static QueueHandle_t 			queue_handler;
static SemaphoreHandle_t 		sem_handler;
static EventGroupHandle_t 		event_handler;

// Define for FreeRTOS system Idle task while using STATIC memory 
StaticTask_t idle_buf;
StackType_t idle_stack[TASK_STACK_SIZE];

// For application tasks
static StaticTask_t task0_buf;
static StaticTask_t task1_buf;
static StaticTask_t task2_buf;
static StaticTask_t task3_buf;
static StaticTask_t task4_buf;
static StaticTask_t task5_buf;
static StaticTask_t task6_buf;
static StaticTask_t task7_buf;
static StaticTask_t task8_buf;

static StackType_t task0_stack[TASK_STACK_SIZE];
static StackType_t task1_stack[TASK_STACK_SIZE];
static StackType_t task2_stack[TASK_STACK_SIZE] __attribute__ ((aligned (4)));
static StackType_t task3_stack[TASK_STACK_SIZE] __attribute__ ((aligned (4)));
static StackType_t task4_stack[TASK_STACK_SIZE] __attribute__ ((aligned (4)));
static StackType_t task5_stack[TASK_STACK_SIZE] __attribute__ ((aligned (4)));
static StackType_t task6_stack[TASK_STACK_SIZE] __attribute__ ((aligned (4)));
static StackType_t task7_stack[TASK_STACK_SIZE] __attribute__ ((aligned (4)));
static StackType_t touch_stack[TASK_STACK_SIZE] __attribute__ ((aligned (4)));

// Define the counters used in the application...

uint32_t 	task_0_counter;
uint32_t    task_1_counter;
uint32_t    task_2_counter;
uint32_t    task_3_counter;
uint32_t    task_4_counter;
uint32_t    task_5_counter;
uint32_t    task_6_counter;
uint32_t    task_7_counter;
uint32_t    task_touch_counter;

uint8_t task1_queue[TASK_QUEUE_LENGTH * TASK_QUEUE_ITEM_SIZE];

uint32_t taskID[10]={0,1,2,3,4,5,6,7,8,9};

// Define task prototypes.
void x_application_define(void);

void task_0_entry(void *p_arg);
void task_1_entry(void *p_arg);
void task_2_entry(void *p_arg);
void task_3_and_4_entry(void *p_arg);
void task_5_entry(void *p_arg);
void task_6_and_7_entry(void *p_arg);
void task_touch_entry(void *p_arg);


// ======================================================

void HAL_IncTick(void)
{
	gSysTick_Counter++;
}

static void Printf_Version(void)
{
	printf("/**************************************************/\r\n");
	printf(" LT776 FreeRTOS demo %s\r\n",version);
	printf(" System clock... %dMHz\r\n",g_sys_clk/1000000);
	printf(" IPS clock...... %dMHz\r\n",g_ips_clk/1000000);
	printf(" Panel size..... %dx%d\r\n",LCD_SIZE_X,LCD_SIZE_Y);   
	printf(" Baud rate...... %d\r\n",115200);	
	printf(" Date = %s,Time = %s\r\n",( char *)__DATE__,( char *)__TIME__);
	printf("/**************************************************/\r\n");
}

void PeripheralInit(void)
{		
	INTX_ENABLE();
	HAL_Init();	
	HAL_SDRAM_Init(g_sdram_clk/1000);	
	HAL_CPM_GETCLCK();		
	UART_Debug_Init(UART1, g_ips_clk, 115200);	// UART3
	
	SPI5_STD_Init();	
	LT_ReadParam();

	LT_RtcInit();
	Printf_Version();	
	
	InitBacklight();
	InitBeep();		
	InitLcd();
	Canvas_image_width(LCD_SIZE_X);
	ClearScreen(grYELLOW);		
	
#ifdef LCD1024x600
	CTP_Init();
#else
	InitTouch();
#endif

	DelayMS(50);
	ConfigBacklight(1);
}


// Provide this function for system idle task while defining STATIC
void vApplicationGetIdleTaskMemory(StaticTask_t **pxIdleTaskTCBBuffer,StackType_t **pxIdleTaskStackBuffer, uint32_t *ulIdleTaskStackSize )
{
	*pxIdleTaskTCBBuffer=&idle_buf;
	*pxIdleTaskStackBuffer=&idle_stack[0];
	*ulIdleTaskStackSize=TASK_STACK_SIZE;
}

int main(void)
{	
	PeripheralInit();
	
	x_application_define();
	
	vTaskStartScheduler();
}


void x_application_define(void)
{
	TaskHandle_t task_result; 	

	// Create task resource
	sem_handler  =xSemaphoreCreateBinaryStatic(&semaphore_0);
	mutex_handler=xSemaphoreCreateMutexStatic(&mutex_0);
	event_handler=xEventGroupCreateStatic(&eventgroup_0);	
	queue_handler=xQueueCreateStatic(TASK_QUEUE_LENGTH,TASK_QUEUE_ITEM_SIZE,&task1_queue[0],&queue_0);

	// Create task
	task_result=xTaskCreateStatic(task_0_entry,      "Event send"	,TASK_STACK_SIZE,(void *)0 ,1,task0_stack,&task0_buf);
	task_result=xTaskCreateStatic(task_1_entry,      "MsgBuf send" ,TASK_STACK_SIZE,(void *)1 ,2,task1_stack,&task1_buf);
	task_result=xTaskCreateStatic(task_2_entry,      "MsgBuf rcv"  ,TASK_STACK_SIZE,(void *)2 ,2,task2_stack,&task2_buf);
	task_result=xTaskCreateStatic(task_3_and_4_entry,"Semaphore1"  ,TASK_STACK_SIZE,(void *)3 ,5,task3_stack,&task3_buf);
	task_result=xTaskCreateStatic(task_3_and_4_entry,"Semaphore2"  ,TASK_STACK_SIZE,(void *)4 ,5,task4_stack,&task4_buf);
	task_result=xTaskCreateStatic(task_5_entry,      "Event rcv"   ,TASK_STACK_SIZE,(void *)5 ,6,task5_stack,&task5_buf);
	task_result=xTaskCreateStatic(task_6_and_7_entry,"Mutex1"  		,TASK_STACK_SIZE,(void *)6 ,8,task6_stack,&task6_buf);
	task_result=xTaskCreateStatic(task_6_and_7_entry,"Mutex2"  		,TASK_STACK_SIZE,(void *)7 ,8,task7_stack,&task7_buf);
	task_result=xTaskCreateStatic(task_touch_entry,  "Touch panel" ,TASK_STACK_SIZE,(void *)8,10,touch_stack,&task8_buf);

	//if (task_result!=NULL) Put16BitBMP(10,400,BMP_Acorn,0xFFFF);
}


void task_0_entry(void *p_arg)
{
	EventBits_t status;
	Put16BitBMP(10,20,BMP_Acorn,0xFFFF);
	LT768_TFT_ShowAscii(18,2,24,1,grRED,grYELLOW,(UINT8 *)"Event send");
	
    // This task simply send eventflag.  
    while(1)
    {
        // Increment the task counter.
        if (task_0_counter<9999) task_0_counter++;
        else task_0_counter=0;
		Show16BitDecimal(7,9,task_0_counter,grWHITE,grBLACK);
		// Set event flag 0 to wakeup task 5.
        status = xEventGroupSetBits(event_handler, 0x04);
		if (status != 0x04) break;
		
		// Sleep for 10 ticks.
		vTaskDelay(10);

		if (task_0_counter%2) Put16BitBMP(10,20,BMP_Acorn,0xFFFF);
		else Put16BitBMP(10,20,BMP_Acorn1,0xFFFF);
    }
}


void task_1_entry(void *p_arg)
{
	BaseType_t status;
	uint8_t txMsg[TASK_QUEUE_ITEM_SIZE]="~LeveTop~";
	
	Put16BitBMP(170,20,BMP_Acorn,0xFFFF);
	LT768_TFT_ShowAscii(184,2,24,1,grRED,grYELLOW,(UINT8 *)"Msg send");
    // This task simply sends messages to a queue shared by task 2.
    while(1)
    {
        // Increment the task counter.
        if (task_1_counter<9999) task_1_counter++;
        else task_1_counter=0;
		Show16BitDecimal(27,9,task_1_counter,grWHITE,grBLACK);
		
        // Send message to the queue.
		status =  xQueueSend(queue_handler, &txMsg[0], portMAX_DELAY);
		if (status != pdPASS) break;
		
		vTaskDelay(20);

		if (task_1_counter%2) Put16BitBMP(170,20,BMP_Acorn,0xFFFF);
		else Put16BitBMP(170,20,BMP_Acorn1,0xFFFF);
    }
}

void task_2_entry(void *p_arg)
{
	BaseType_t  status;
	uint8_t rxMsg[TASK_QUEUE_ITEM_SIZE];
	
	Put16BitBMP(170,180,BMP_Acorn,0xFFFF);
	LT768_TFT_ShowAscii(190,162,24,1,grRED,grYELLOW,(UINT8 *)"Msg rcv");
    // This task retrieves messages placed on the queue by task 1.
    while(1)
    {
        // Increment the task counter.
        if (task_2_counter<9999) task_2_counter++;
        else task_2_counter=0;
		Show16BitDecimal(27,19,task_2_counter,grWHITE,grBLACK);
		
        // Retrieve a message from the queue.
		status = xQueueReceive(queue_handler, &rxMsg[0],portMAX_DELAY);
		if (status != pdPASS) break;
		
		if (task_2_counter%2) Put16BitBMP(170,180,BMP_Acorn,0xFFFF);
		else Put16BitBMP(170,180,BMP_Acorn1,0xFFFF);
    }
}

void task_3_and_4_entry(void *p_arg)
{
	BaseType_t status;
	UINT32 id=(UINT32) p_arg;

	Put16BitBMP(330,20,BMP_Acorn,0xFFFF);
	LT768_TFT_ShowAscii(338,2,24,1,grRED,grYELLOW,(UINT8 *)"Semaphore");
    // This function is executed from task 3 and task 4.  As the loop
    // below shows, these function compete for ownership of sem_handler.
	
	xSemaphoreGive(sem_handler);
	vTaskDelay(10);
    while(1)
    {
        // Increment the task counter.
        if (id == 3)
		{
            if (task_3_counter<9999) task_3_counter++;
			else task_3_counter=0;
			Show16BitDecimal(44,9,task_3_counter,grWHITE,grBLACK);
		}
        else
		{
            if (task_4_counter<9999) task_4_counter++;
			else task_4_counter=0;
			Show16BitDecimal(50,9,task_4_counter,grWHITE,grBLACK);
		}

        // Get the semaphore with suspension.
        status = xSemaphoreTake(sem_handler,portMAX_DELAY);	//portMAX_DELAY = WAITING_FOREVER 
		if (status != pdPASS) break;
		
        // Sleep for 10 ticks to hold the semaphore.
        vTaskDelay(20);

        // Release the semaphore.
        status = xSemaphoreGive(sem_handler);
		if (status != pdPASS) break;
		
		vTaskDelay(20);
		
		if (task_3_counter%2) Put16BitBMP(330,20,BMP_Acorn,0xFFFF);
		else Put16BitBMP(330,20,BMP_Acorn1,0xFFFF);
    }
}


void task_5_entry(void *p_arg)
{
	EventBits_t status;
	TaskHandle_t  event;

	Put16BitBMP(10,180,BMP_Acorn,0xFFFF);
	LT768_TFT_ShowAscii(18,162,24,1,grRED,grYELLOW,(UINT8 *)"Event rcv");
	
    // This task simply waits for an event.
    while(1)
    {
        // Increment the task counter.
        if (task_5_counter<9999) task_5_counter++;
		else task_5_counter=0;
		Show16BitDecimal(7,19,task_5_counter,grWHITE,grBLACK);

        // Wait for event flag 0.
        do
		{
			vTaskDelay(10);
			status = xEventGroupGetBits(event_handler);
		} while (status != 0x04);
		
		status = xEventGroupWaitBits(event_handler,0x04,pdTRUE,pdFALSE,portMAX_DELAY);
		if (status != 0x04) break;
		
		if (task_5_counter%2) Put16BitBMP(10,180,BMP_Acorn,0xFFFF);
		else Put16BitBMP(10,180,BMP_Acorn1,0xFFFF);
    }
}


void task_6_and_7_entry(void *p_arg)
{
	BaseType_t status;
	UINT32 id=(UINT32) p_arg;

	Put16BitBMP(330,180,BMP_Acorn,0xFFFF);
	LT768_TFT_ShowAscii(364,162,24,1,grRED,grYELLOW,(UINT8 *)"Mutex");
    // This function is executed from task 6 and task 7.  As the loop
    //   below shows, these function compete for ownership of mutex_Handler.
	
	xSemaphoreGive(mutex_handler);
	vTaskDelay(10);
    while(1)
    {
        // Increment the task counter.
        if (id == 6)
		{
			if (task_6_counter<9999) task_6_counter++;
			else task_6_counter=0;
			Show16BitDecimal(44,19,task_6_counter,grWHITE,grBLACK);
		}
        else
		{
			if (task_7_counter<9999) task_7_counter++;
			else task_7_counter=0;
			Show16BitDecimal(50,19,task_7_counter,grWHITE,grBLACK);
		}

        // Get the mutex with suspension.
        status = xSemaphoreTake(mutex_handler,portMAX_DELAY);	//portMAX_DELAY
		if (status != pdPASS) break;
		
        // Sleep for 10 ticks to hold the mutex.
        vTaskDelay(40);

        // Release the mutex.
        status = xSemaphoreGive(mutex_handler);
		if (status != pdPASS) break;
		
		vTaskDelay(40);
		
		if (task_6_counter%2) Put16BitBMP(330,180,BMP_Acorn,0xFFFF);
		else Put16BitBMP(330,180,BMP_Acorn1,0xFFFF);
    }
}

void task_touch_entry(void *p_arg)
{
	int  tpStatus;

	Put16BitBMP(600,20,BMP_Acorn,0xFFFF);
	LT768_TFT_ShowAscii(596,2,24,1,grRED,grYELLOW,(UINT8 *)"Touch panel");
	
    // This task waits touch panel pressed. 
    while(1)
    {
    	// Increment the task counter.
		if (task_touch_counter<9999) task_touch_counter++;
		else task_touch_counter=0;
    	Show16BitDecimal(81,9,task_touch_counter,grWHITE,grBLACK);

    	tpStatus=FT5216_Scan();
    	if (tpStatus)
    	{
			Show16BitDecimal(70,4,gTpInfo.x[0],grWHITE,grBLACK);
			Show16BitDecimal(70,6,gTpInfo.y[0],grWHITE,grBLACK);
			if ((gTpInfo.x[0]>=600)&&(gTpInfo.x[0]<(600+128))&&(gTpInfo.y[0]>=20)&&(gTpInfo.y[0]<=(20+128)))	
					Put16BitBMP(600,20,BMP_Acorn1,0xFFFF);
			else Put16BitBMP(600,20,BMP_Acorn,0xFFFF);
		}
		else
		{
			Show16BitDecimal(70,4,0,grWHITE,grBLACK);
			Show16BitDecimal(70,6,0,grWHITE,grBLACK);
			Put16BitBMP(600,20,BMP_Acorn,0xFFFF);
		}
    	vTaskDelay(30);
	}
}




