/* ------------------------------------------------------------------------------------------------ */
/* FILE :		Demo_4_EKLM3S1968_ATOLLIC.c															*/
/*																									*/
/* CONTENTS :																						*/
/*				Demo for the Stellaris EKLM3S1968 evaluation board									*/
/*				Operation of the joystick shown on the oLED Display & Serial port					*/
/*				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.3 $																				*/
/*	$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 "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/lm3s1968.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "driverlib/uart.h"
#include "drivers/rit128x96x4.h"

#define BAUDRATE	115200							/* Serial port baud rate						*/

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

MBX_t *MbxUpDown;									/* Mailbox used by TaskUpDown					*/

SEM_t *SemLeft;										/* Semaphore used by TaskLeft					*/

TSK_t *TaskLeft;									/* Task handling the Left button operations		*/
TSK_t *TaskRight;									/* Task handling the Right button operations	*/
TSK_t *TaskTick;									/* Task handling tick operations				*/
TSK_t *TaskUpDown;									/* Task handling the Up and Down buttons		*/

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

void FctLeft(void);									/* Function used for TaskLeft					*/
void FctRight(void);								/* Function used for TaskRight					*/
void FctTick(void);									/* Function used for TaskTick					*/
void FctUpDown(void);								/* Function used for TaskUpDown					*/
void JoyStick(void);								/* Buttons interrupt handler					*/

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

int main(void)
{
int  Prio = 0;										/* Priority of the timer tick interrupt			*/
int *TimerBase;										/* SysTick timer registers base address			*/


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

	SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_8MHZ);

/* ------------------------------------------------ */
/* 	Start the RTOS									*/

	OSstart();

/* ------------------------------------------------ */
/* 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] = (((SysCtlClockGet()/100000) * OS_TIMER_US)/10)-1;
	TimerBase[4] = 0x7;								/* internal clock / int & enable				*/


/* ------------------------------------------------ */
/* UART set-up										*/

	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

	GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
	UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
	                    (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

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

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

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);

    GPIOPinTypeGPIOInput(GPIO_PORTG_BASE, GPIO_PIN_3);
    GPIOPinTypeGPIOInput(GPIO_PORTG_BASE, GPIO_PIN_4);
    GPIOPinTypeGPIOInput(GPIO_PORTG_BASE, GPIO_PIN_5);
    GPIOPinTypeGPIOInput(GPIO_PORTG_BASE, GPIO_PIN_6);

    GPIOPadConfigSet(GPIO_PORTG_BASE, GPIO_PIN_3, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    GPIOPadConfigSet(GPIO_PORTG_BASE, GPIO_PIN_4, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    GPIOPadConfigSet(GPIO_PORTG_BASE, GPIO_PIN_5, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    GPIOPadConfigSet(GPIO_PORTG_BASE, GPIO_PIN_6, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

    GPIOIntTypeSet(GPIO_PORTG_BASE, GPIO_PIN_3, GPIO_FALLING_EDGE);
    GPIOIntTypeSet(GPIO_PORTG_BASE, GPIO_PIN_4, GPIO_FALLING_EDGE);
    GPIOIntTypeSet(GPIO_PORTG_BASE, GPIO_PIN_5, GPIO_FALLING_EDGE);
    GPIOIntTypeSet(GPIO_PORTG_BASE, GPIO_PIN_6, GPIO_FALLING_EDGE);

    GPIOPinIntEnable(GPIO_PORTG_BASE, GPIO_PIN_3);
    GPIOPinIntEnable(GPIO_PORTG_BASE, GPIO_PIN_4);
    GPIOPinIntEnable(GPIO_PORTG_BASE, GPIO_PIN_5);
    GPIOPinIntEnable(GPIO_PORTG_BASE, GPIO_PIN_6);


/* ------------------------------------------------ */
/* OLED set-up										*/

	puts("\n\n");									/* Welcome banner								*/
	puts("\n      Abassi Demo 4");
	puts("\n     TI EKK-LM3S1968 \n");
	puts("\n     Use the buttons\n\n");

	RIT128x96x4Init(1000000);
	RIT128x96x4StringDraw("    Abassi Demo     ", 0, 16, 15);
	RIT128x96x4StringDraw("  Use the buttons   ", 0, 32, 15);

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

	TaskLeft   = TSKcreate("Center", 1, TC_TSK_STACK, &FctLeft,   1);
	TaskUpDown = TSKcreate("UpDown", 1, TC_TSK_STACK, &FctUpDown, 1);
	TaskRight  = TSKcreate("LftRgh", 1, TC_TSK_STACK, &FctRight,  1);
	TaskTick   = TSKcreate("Tick  ", 1, TC_TSK_STACK, &FctTick,   1);

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

	SemLeft    = SEMopen("Left");					/* Create the semaphore used by FctLeft()		*/

	OSisrInstall(31, &JoyStick);					/* Install the joystick interrupt handler		*/

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

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

	IntEnable(INT_GPIOG);

	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 FctLeft(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(SemLeft, -1);					/* ISr psot the semaphore: Left button pressed	*/

		printf("    Left   \r");

		RIT128x96x4StringDraw("        Left        ", 0, 64, 15);
	}
}


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

void FctRight(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 ISR to set an event flag			*/
		events = EVTget();
		if ((0x01 & events) != 0) {					/* Event flag bit 0 is right button				*/
			printf("    Right \r");

			RIT128x96x4StringDraw("        Right       ", 0, 64, 15);
		}
	}
}

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

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);				/* Wait for the ISR to put something in mailbox	*/

		if ((int)Msg == 1) {						/* Message == 1 is up button					*/
			printf("    Up    \r");

			RIT128x96x4StringDraw("         Up         ", 0, 64, 15);
		}

		if ((int)Msg == 2) {						/* Message == 2 is down button					*/
			printf("    Down  \r");

			RIT128x96x4StringDraw("        Down        ", 0, 64, 15);
		}
	}
}

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

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 the ISR to set an event flag		*/

		putchar(Running[ii++]);
		putchar('\r');

		ii &= 3;
	}
}

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

void JoyStick(void)
{


	if (GPIOPinIntStatus(GPIO_PORTG_BASE, GPIO_PIN_3)) {	/* Up button depressed					*/
	    GPIOPinIntClear(GPIO_PORTG_BASE, GPIO_PIN_3);		/* Acknowledge the interrupt			*/
		MBXput(MbxUpDown, 1, 0);							/* Send msg == 1 to TaskUpDown			*/
	}
	if (GPIOPinIntStatus(GPIO_PORTG_BASE, GPIO_PIN_4)) {	/* Downb button depressed				*/
	    GPIOPinIntClear(GPIO_PORTG_BASE, GPIO_PIN_4);		/* Acknowledge the interrupt			*/
		MBXput(MbxUpDown, 2, 0);							/* Send msg == 2 to TaskUpDown			*/
	}
	if (GPIOPinIntStatus(GPIO_PORTG_BASE, GPIO_PIN_5)) {	/* Left button depressed				*/
	    GPIOPinIntClear(GPIO_PORTG_BASE, GPIO_PIN_5);		/* Acknowledge the interrupt			*/
		SEMpost(SemLeft);									/* Post TaskLeft semaphore				*/
	}
	if (GPIOPinIntStatus(GPIO_PORTG_BASE, GPIO_PIN_6)) {	/* Right button depressed				*/
	    GPIOPinIntClear(GPIO_PORTG_BASE, GPIO_PIN_6);		/* Acknowledge the interrupt			*/
		EVTset(TaskRight, 0x01);							/* Set event flag bit 0 of TaskRight	*/
	}

	return;
}

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

void TIMcallBack(void)
{
static int CBcnt = 0;								/* Used to determine when to awake TaskTick		*/


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

	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') {
			UARTCharPut(UART0_BASE, '\r');
		}
		UARTCharPut(UART0_BASE, *buf);
		buf++;
		size--;
	}

	return(len);
}
#endif

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

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

	buf = vbuf;
	for (; !(UARTCharsAvail(UART0_BASE)) ; );
	*buf = UARTCharGetNonBlocking(UART0_BASE);

	return(1);
}
#endif

/* EOF */
