/* ------------------------------------------------------------------------------------------------ */
/* FILE :		Demo_4_LPC1766STK_ATOLLIC.c															*/
/*																									*/
/* CONTENTS :																						*/
/*				Demo for the Olimex LPC1766-STK evaluation board									*/
/*				Operation of the joystick shown on the LCD and serial port							*/
/*				Both UARTs (RS232_0 & RS232_1) ports are used										*/
/*				Serial port settings:																*/
/*							Baud Rate: 115200														*/
/*							Data bits:      8														*/
/*							Stop bits:		1														*/
/*							Parity:      none														*/
/*							Flow Ctrl:   none														*/
/*																									*/
/*																									*/
/* Copyright (c) 2012-2014, Code-Time Technologies Inc. All rights reserved.						*/
/*																									*/
/* Code-Time Technologies retains all right, title, and interest in and to this work				*/
/*																									*/
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS							*/
/* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF										*/
/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL							*/
/* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR								*/
/* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,							*/
/* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR							*/
/* OTHER DEALINGS IN THE SOFTWARE.																	*/
/*																									*/
/*																									*/
/*	$Revision: 1.2 $																				*/
/*	$Date: 2012/06/17 18:41:36 $																	*/
/*																									*/
/* ------------------------------------------------------------------------------------------------ */

#if OS_DEMO != 4
	#error "Wrong OS_DEMO value" 
#endif

#include <stdio.h>
#include <ctype.h>
#include <Abassi.h>

/* ------------------------------------------------ */

#include "lpc17xx_gpio.h"
#include "lpc17xx_libcfg.h"
#include "lpc17xx_pinsel.h"
#include "lpc17xx_uart.h"

#include "drv_glcd_cnfg.h"
#include "drv_glcd.h"
#include "glcd_ll.h"

#define BAUDRATE	   115200						/* Serial port baud rate						*/
#define SYS_FREQ	100000000						/* Processor clock frequency					*/

#define BG_COLOR	0x00000FFF						/* Background RGB color							*/
#define FG_COLOR	0x00000000						/* Foreground RGB color							*/

extern FontType_t Terminal_9_12_6;

UART_CFG_Type		UARTConfigStruct;
PINSEL_CFG_Type		PinCfg;

#define LCD_LINE(x, txt) do {																		\
							int ISRstate;															\
							ISRstate = OSdint();													\
							GLCD_SetWindow(0, ((x)*12)+3, GLCD_HORIZONTAL_SIZE-1, (((x)+1)*12)+3);	\
							GLCD_TextSetPos(0,0);													\
							GLCD_print("\f %s\r", txt);												\
							OSeint(ISRstate);														\
						} while(0)

/* ------------------------------------------------ */

#define JOY_CENTER	(0x0005)						/* Center is P0[4]								*/
#define JOY_LEFT	(0x0207)						/* Left   is P2[7]								*/
#define JOY_RIGHT	(0x0208)						/* Right  is P2[8]								*/
#define JOY_UP		(0x0200)						/* Up     is P2[0]								*/
#define JOY_DOWN	(0x0201)						/* Down   is P2[1]								*/

/* ------------------------------------------------ */

int Debounce[6];									/* Used to debounce the joystick				*/

MBX_t *MbxUpDown;									/* Mailbox for the UP/DOWN task					*/
SEM_t *SemCenter;									/* Semaphore for CENTER task					*/
TSK_t *TaskCenter;									/* Task handling the joystick center activated	*/
TSK_t *TaskLeftRight;								/* Task handling the joystick R/L activated		*/
TSK_t *TaskTick;									/* Task operated one every RTOS tick			*/
TSK_t *TaskUpDown;									/* Task handling the joystick UP/DOWN activated	*/

/* ------------------------------------------------ */

void FctCenter(void);								/* Functon attached to TaskCenter				*/
void FctLeftRight(void);							/* Functon attached to TaskLeftRight			*/
void FctTick(void);									/* Functon attached to TaskTick					*/
void FctUpDown(void);								/* Functon attached to TaskUpDOwn				*/
void JoyStickHandler(void);							/* Joystick interrupt handler					*/

/* ------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------ */

int main(void)
{
int  ii;											/* General purpose								*/
int  Prio = 0;										/* SysTick interrupt priority					*/
int *TimerBase;										/* SysTick register base address				*/

/* ------------------------------------------------ */
/* 	Processor clock set-up							*/

	SystemInit();

/* ------------------------------------------------ */
/* 	RTOS set-up										*/

	OSstart();

/* ------------------------------------------------ */
/* UART0 set-up										*/

	PinCfg.Funcnum   = 1;
	PinCfg.OpenDrain = 0;
	PinCfg.Pinmode   = 0;
	PinCfg.Pinnum    = 2;
	PinCfg.Portnum   = 0;
	PINSEL_ConfigPin(&PinCfg);
	PinCfg.Pinnum    = 3;
	PINSEL_ConfigPin(&PinCfg);

	UART_ConfigStructInit(&UARTConfigStruct);
	UARTConfigStruct.Baud_rate = BAUDRATE;
	UART_Init((LPC_UART_TypeDef *)LPC_UART0, &UARTConfigStruct);
	UART_TxCmd((LPC_UART_TypeDef *)LPC_UART0, ENABLE);


/* ------------------------------------------------ */
/* UART1 set-up										*/

	PinCfg.Funcnum   = 1;
	PinCfg.OpenDrain = 0;
	PinCfg.Pinmode   = 0;
	PinCfg.Pinnum    = 15;
	PinCfg.Portnum   = 0;
	PINSEL_ConfigPin(&PinCfg);
	PinCfg.Pinnum    = 16;
	PINSEL_ConfigPin(&PinCfg);

	UART_ConfigStructInit(&UARTConfigStruct);
	UARTConfigStruct.Baud_rate = BAUDRATE;
	UART_Init((LPC_UART_TypeDef *)LPC_UART1, &UARTConfigStruct);
	UART_TxCmd((LPC_UART_TypeDef *)LPC_UART1, ENABLE);

	setvbuf(stdin,  NULL, _IONBF, 0);
	setvbuf(stdout, NULL, _IONBF, 0);

/* ------------------------------------------------ */
/* LCD set-up										*/

	GLCD_PowerUpInit(NULL);
	GLCD_Backlight(BACKLIGHT_ON);
	Dly100us((void*)3000);

	GLCD_SetFont(&Terminal_9_12_6, FG_COLOR, BG_COLOR);
	for (ii=0 ; ii<10 ; ii++) {
		LCD_LINE(ii, " ");
	}
	GLCD_SetWindow(0,0,GLCD_HORIZONTAL_SIZE-1, GLCD_VERTICAL_SIZE-1);
	GLCD_TextSetPos(0,0);
	GLCD_SetWindow(0, 120, GLCD_HORIZONTAL_SIZE-1, 131);
	GLCD_TextSetPos(0,0);
	GLCD_print("\f \r");
	GLCD_SetWindow(0, 0, GLCD_HORIZONTAL_SIZE-1, 12);
	GLCD_TextSetPos(0,0);
	GLCD_print("\f \r");

/* ------------------------------------------------ */
/* SysTick Set-up									*/

	TimerBase = (int *)0xE000E000;
	((volatile int *)0xE000Ed20)[0] = (((volatile int *)0xE000Ed20)[0] & 0x1FFFFFFF)
	                                |   ((Prio & 7) << 29);
	OSisrInstall(-1, TIMtick);						/* Install the OS timer tick function			*/
	TimerBase[5] = ((((SYS_FREQ)/100000) * OS_TIMER_US)/10)-1;
	TimerBase[4] = 0x7;								/* internal clock / int & enable				*/

/* ------------------------------------------------ */
/* Application set-up								*/

	TaskCenter    = TSKcreate("Center", 1, TC_TSK_STACK, &FctCenter,    1);
	TaskUpDown    = TSKcreate("UpDown", 1, TC_TSK_STACK, &FctUpDown,    1);
	TaskLeftRight = TSKcreate("LftRgh", 1, TC_TSK_STACK, &FctLeftRight, 1);
	TaskTick      = TSKcreate("Tick  ", 1, TC_TSK_STACK, &FctTick,      1);

	MbxUpDown     = MBXopen("UpDown", 3);			/* Create the mailbox used by FctUpDown()		*/

	SemCenter     = SEMopen("Center");				/* Create the semaphore used by FctCenter()		*/

/* ------------------------------------------------ */
/* GPIO set-up										*/

	OSisrInstall(21, JoyStickHandler);				/* Install the joystick interrupt function		*/

	FIO_ByteSetDir(JOY_CENTER>>8, (JOY_CENTER & 0x18)>>4, 1<<(JOY_CENTER & 0x07), 0);
	FIO_ByteSetDir(JOY_RIGHT >>8, (JOY_LEFT   & 0x18)>>4, 1<<(JOY_LEFT   & 0x07), 0);
	FIO_ByteSetDir(JOY_RIGHT >>8, (JOY_RIGHT  & 0x18)>>4, 1<<(JOY_RIGHT  & 0x07), 0);
	FIO_ByteSetDir(JOY_UP    >>8, (JOY_UP     & 0x18)>>4, 1<<(JOY_UP     & 0x07), 0);
	FIO_ByteSetDir(JOY_DOWN  >>8, (JOY_DOWN   & 0x18)>>4, 1<<(JOY_DOWN   & 0x07), 0);

	GPIO_IntCmd(0, 0x00000020, 1);
	GPIO_IntCmd(2, 0x00000183, 1);

	NVIC_EnableIRQ(EINT3_IRQn);

/* ------------------------------------------------ */

	puts("\n\n");									/* Welcome banner								*/
	puts("\n      Abassi Demo 4");
	puts("\n   Olimex LPC1766-STK\n");
	puts("\n    Use the joy stick\n\n");

	LCD_LINE(1, "    Abassi Demo 4");
	LCD_LINE(3, "  Use the joy stick");

/* ------------------------------------------------ */
/* Interrupts ON, the application runs				*/

	memset(&Debounce[0], sizeof(Debounce),0);

	OSeint(1);										/* And here we go								*/

	for (;;) {
		TSKselfSusp();								/* And Adam & Eve is done, it self suspends		*/
	}
}

/* ------------------------------------------------------------------------------------------------ */
/*																									*/
/* Idle Task																						*/
/*																									*/
/* ------------------------------------------------------------------------------------------------ */

void IdleTask(void)
{
	for(;;);										/* Idle is a do nothing task					*/
}

/* ------------------------------------------------------------------------------------------------ */
/*																									*/
/* Task functions																					*/
/*																									*/
/* ------------------------------------------------------------------------------------------------ */

void FctCenter(void)
{
 #if defined(OS_NEWLIB_REENT)						/* In case the reentrance is set on per task	*/
  #if ((OS_NEWLIB_REENT) > 0)
	setvbuf(stdin,  NULL, _IONBF, 0);
	setvbuf(stdout, NULL, _IONBF, 0);
  #endif
 #endif
	for (;;) {
		SEMwaitBin(SemCenter, -1);					/* Get blocked waiting for the joystick center	*/
													/* to be activated								*/
		printf("    Center\r");
		LCD_LINE(7, "      Center    ");
	}
}


/* ------------------------------------------------------------------------------------------------ */

void FctLeftRight(void)
{
int events;

 #if defined(OS_NEWLIB_REENT)						/* In case the reentrance is set on per task	*/
  #if ((OS_NEWLIB_REENT) > 0)
	setvbuf(stdin,  NULL, _IONBF, 0);
	setvbuf(stdout, NULL, _IONBF, 0);
  #endif
 #endif

	for (;;) {
		EVTwait(0xFFFF, 0xFFFF, -1);				/* Wait for the event flags to be set by ISR	*/
		events = EVTget();
		if ((0x01 & events) != 0) {					/* Flag bit #0 is for right position			*/
			printf("    Right \r");
			LCD_LINE(7, "       Right    ");
		}
		if ((0x10 & events) != 0) {					/* Flag bit #4 is for right position			*/
			printf("    Left  \r");
			LCD_LINE(7, "       Left    ");
		}
	}
}

/* ------------------------------------------------------------------------------------------------ */

void FctUpDown(void)
{
intptr_t Msg;

 #if defined(OS_NEWLIB_REENT)						/* In case the reentrance is set on per task	*/
  #if ((OS_NEWLIB_REENT) > 0)
	setvbuf(stdin,  NULL, _IONBF, 0);
	setvbuf(stdout, NULL, _IONBF, 0);
  #endif
 #endif

	for (;;) {
		MBXget(MbxUpDown, &Msg, -1);

		if ((int)Msg == 1) {						/* Message #1 is for up position				*/
			printf("    Up    \r");
			LCD_LINE(7, "        Up    ");
		}
		if ((int)Msg == 2) {						/* Message #2 is for down position				*/
			printf("    Down  \r");
			LCD_LINE(7, "       Down    ");
		}
	}
}

/* ------------------------------------------------------------------------------------------------ */

void FctTick(void)
{
int   ii;
const char Running[] = "|/-\\";

 #if defined(OS_NEWLIB_REENT)						/* In case the reentrance is set on per task	*/
  #if ((OS_NEWLIB_REENT) > 0)
	setvbuf(stdin,  NULL, _IONBF, 0);
	setvbuf(stdout, NULL, _IONBF, 0);
  #endif
 #endif

	ii = 0;
	for (;;) {
		EVTwait(0xFFFF, 0xFFFF, -1);				/* Wait for any event flag to be set by the		*/
													/* RTOS tierm callback							*/
		putchar(Running[ii++]);
		putchar('\r');
		ii &= 3;
	}
}

/* ------------------------------------------------------------------------------------------------ */
/*																									*/
/* Joystick interrupt handler function																*/
/* 																									*/
/* ------------------------------------------------------------------------------------------------ */

void JoyStickHandler(void)
{
int ii;

	ii = 5;

	if (GPIO_GetIntStatus(JOY_DOWN>>8, (JOY_DOWN&0x1F), 1)) {
		ii = 0;
	}
	if (GPIO_GetIntStatus(JOY_UP>>8, (JOY_UP&0x1F), 1)) {
		ii = 1;
	}
	if (GPIO_GetIntStatus(JOY_CENTER>>8, (JOY_CENTER&0x1F), 1)) {
		ii = 2;
	}
	if (GPIO_GetIntStatus(JOY_RIGHT>>8, (JOY_RIGHT&0x1F), 1)) {
		ii = 3;
	}
	if (GPIO_GetIntStatus(JOY_LEFT>>8, (JOY_LEFT&0x1F), 1)) {
		ii = 4;
	}

	if (Debounce[ii] == 0) {						/* Is this pin currently being debounced		*/
		Debounce[ii] = OS_TICK_PER_SEC/50;			/* 20 ms debounce time							*/
		switch(ii) {								/* Trigger the corresponding task unless the	*/
		case 0:										/* pin is currently in debounce					*/
			MBXput(MbxUpDown, 2, 0);				/* Down position								*/
			break;
		case 1:										/* Up position									*/
			MBXput(MbxUpDown, 1, 0);
			break;
		case 2:										/* Center position								*/
			SEMpost(SemCenter);
			break;
		case 3:										/* Right position								*/
			EVTset(TaskLeftRight, 0x01);
			break;
		case 4:										/* Left position								*/
			EVTset(TaskLeftRight, 0x10);
			break;
		default:
			break;
		}
	}

	GPIO_ClearInt(0,0x00000020);
	GPIO_ClearInt(2,0x00000183);

	return;
}

/* ------------------------------------------------------------------------------------------------ */
/*																									*/
/* Timer call back function																			*/
/* 																									*/
/* ------------------------------------------------------------------------------------------------ */

void TIMcallBack(void)
{
int ii;
static int CBcnt=0;


	if (++CBcnt > (OS_TICK_PER_SEC/10)) {			/* Trigger FctTick()once every 0.1 s			*/
		CBcnt=0;
		EVTset(TaskTick, 1);
	}


	for (ii=0 ; ii<5 ; ii++) {						/* Debouncing: Need to wait for the pin to go	*/
		if (Debounce[ii] != 0) {					/* back to a high level for long enough			*/
			Debounce[ii]--;
		}
	}

	return;
}

/* ------------------------------------------------------------------------------------------------ */
/*																									*/
/* UART functions needed by the Peripheral library to access the UART								*/
/*																									*/
/* ------------------------------------------------------------------------------------------------ */

#if !defined(_write_r)
_ssize_t _write_r (struct _reent *rreenn, int fd, const void *vbuf, size_t len)
{
const char *buf;
int   size;

	size = len;
	buf  = vbuf;
	while (size > 0) {
		if (*buf == '\n') {
			while (!(LPC_UART0->LSR & UART_LSR_THRE));
			UART_SendByte((LPC_UART_TypeDef *)LPC_UART0, '\r');
			while (!(LPC_UART1->LSR & UART_LSR_THRE));
			UART_SendByte((LPC_UART_TypeDef *)LPC_UART1, '\r');
		}
		while (!(LPC_UART0->LSR & UART_LSR_THRE));
		UART_SendByte((LPC_UART_TypeDef *)LPC_UART0, *buf);
		while (!(LPC_UART1->LSR & UART_LSR_THRE));
		UART_SendByte((LPC_UART_TypeDef *)LPC_UART1, *buf);
		buf++;
		size--;
	}

	return(len);
}
#endif

/* ------------------------------------------------------------------------------------------------ */

#if !defined(_read_r)
_ssize_t  _read_r(struct _reent *rreenn, int fd, void *vbuf, size_t size)
{
int   len;
char *buf;

	buf = vbuf;
	len = 1;
	while ((!(LPC_UART0->LSR & UART_LSR_RDR))
	&&     (!(LPC_UART1->LSR & UART_LSR_RDR)));
	if (LPC_UART0->LSR & UART_LSR_RDR) {
		*buf = UART_ReceiveByte((LPC_UART_TypeDef *)LPC_UART0);
	}
	else {
		*buf = UART_ReceiveByte((LPC_UART_TypeDef *)LPC_UART1);
	}

	return(len);
}
#endif

/* ------------------------------------------------------------------------------------------------ */

int __putchar(int ccc)
{

	if (ccc == '\n') {
		while (!(LPC_UART0->LSR & UART_LSR_THRE));
		UART_SendByte((LPC_UART_TypeDef *)LPC_UART0, '\r');
		while (!(LPC_UART1->LSR & UART_LSR_THRE));
		UART_SendByte((LPC_UART_TypeDef *)LPC_UART1, '\r');
	}
	while (!(LPC_UART0->LSR & UART_LSR_THRE));
	UART_SendByte((LPC_UART_TypeDef *)LPC_UART0, ccc);
	while (!(LPC_UART1->LSR & UART_LSR_THRE));
	UART_SendByte((LPC_UART_TypeDef *)LPC_UART1, ccc);

	return(ccc);
}


/* ------------------------------------------------------------------------------------------------ */

int GetKey(void)
{
int RetVal;

	RetVal = 0;
	if ((LPC_UART0->LSR & UART_LSR_RDR)) {
		RetVal = UART_ReceiveByte((LPC_UART_TypeDef *)LPC_UART0);
	}
	else if ((LPC_UART1->LSR & UART_LSR_RDR)) {
		RetVal = UART_ReceiveByte((LPC_UART_TypeDef *)LPC_UART1);
	}

	return(RetVal);
	
}

/* EOF */
