/*
 * main.c [test_stand.c ]
 * Controller for Marine Engineering Air Shock
 * This program provides basic functionality to test the air shock controller and read instrumentation.
 * It will be used to test the air shock and develop control routines.
 * It will take advantage of serial communication to log data using Putty.
 * Many of the features used in this code are based on TI's TM4C123G LaunchPad Workshop
 * This was originally tested without BIOS, then ported to BIOS
 *
 * Written by Dale Tardiff, Innovative Power Solutions Inc.
 * Version 0.1 - Started June 24, 2014
 *
 */

/*=====================================================================================================
 * BIOS Headers
 */
#include <xdc/std.h>
#include <xdc/runtime/System.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <xdc/cfg/global.h>

/*======================================================================================================
 * Tiva-C headers
 */
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/sysctl.h"
#include "driverlib/adc.h"
#include "driverlib/gpio.h"
#include "driverlib/timer.h"
#include "driverlib/i2c.h"
#include "driverlib/interrupt.h"
#include "driverlib/pwm.h"
#include "driverlib/rom.h"
#include "inc/tm4c123gh6pm.h"

/*======================================================================================================
 * Sensor Utilities
 */
#include "utils/uartstdio.h"
#include "sensorlib/i2cm_drv.h"
#include "hw_lis3dsh.h"
#include "lis3dsh.h"

#define BUFFER_SIZE 1025

#define LIS3DSH_I2C_ADDRESS 0x1e // LIS3DSH I2C address

///*
// *  ======== taskFxn ========
// */
//Void taskFxn(UArg a0, UArg a1)
//{
//    System_printf("enter taskFxn()\n");
//
//    Task_sleep(10);
//
//    System_printf("exit taskFxn()\n");
//}

/*
 * Global Variables
 */
tI2CMInstance g_sI2CInst; // I2C master driver structure
tLIS3DSH g_sLIS3DSHInst; // LIS3DSH sensor driver structure
volatile unsigned long g_vui8DataFlag; // Data ready flag
volatile unsigned long g_vui8ErrorFlag; // Error flag

uint32_t ui32ADC0Value[4];
uint32_t count = 0;
uint32_t time = 0;
uint8_t ui8MEMSValue[6];
uint_fast16_t AccelX[BUFFER_SIZE];
uint_fast16_t AccelY[BUFFER_SIZE];
uint_fast16_t AccelZ[BUFFER_SIZE];
uint32_t CPU_Temp[BUFFER_SIZE];
uint32_t Pressure[BUFFER_SIZE];
const int SetPressure = 16;
/*
 *  ======== main ========
 */
Int main()
{ 
	void ApplicationCallback(void *pvCallbackData, uint_fast8_t ui8Status);
	void LIS3DSHI2CIntHandler(void);
	void MEMSIntHandler(uint8_t *pui8data);
	void LIS3DSHI2CWait(char *pcFilename, uint_fast32_t ui32Line);
	void Sys_Init(void);


	Sys_Init();

    Pressure[0] = 0;
    while(Pressure[0] < SetPressure) GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 4);	// hold while cylinder pressure is increased
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0);
    	//enable MEMS interrupt after cylinder at full pressure
	
    BIOS_start();    /* does not return */

	return(0);
}

//	if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_0)) return 0;	// Use SW2 as a STOP
//	else
//	{
//		if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_4))	// Use SW1 to restart data acquisition

/*=======================================================================================================
 * Read Analog/MEMs inputs
 * Adjust Control outputs
 */
void Timer2IntHandler(void)
{
//	int width;

	TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT);
//	GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
	Swi_post(swi_ADC1);

	// adjust A7 pulse width, which controls 4 - 20 mA out
//	width = SetPressure*4000/500;	// Scale 0 - 500 kPa to a width of 4000 which will be close to full scale
//	PWMPulseWidthSet(PWM1_BASE, PWM_OUT_3, width);

	if(count > BUFFER_SIZE)

	{
		Semaphore_post(BufferFull);
//		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0);
		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
		IntMasterDisable();
	}

}
//========================================================================================================

void GPIOBIntHandler(void)
{
	// Clear the GPIO interrupt
	GPIOIntClear(GPIO_PORTB_BASE, GPIO_INT_PIN_3|GPIO_INT_PIN_4);
	GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 4);

}

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

//***********************************************************************
void
MEMSCallback(void *pvCallbackData, uint_fast8_t ui8Status)
{
//	LIS3DSHDataGetFloat(&g_sLIS3DSHInst,
//	                               &AccelX[count],
//	                               &AccelY[count],
//	                               &AccelZ[count]);
	LIS3DSHDataGetRaw(&g_sLIS3DSHInst,
		                               &AccelX[count],
		                               &AccelY[count],
		                               &AccelZ[count]);

}

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

void MEMSIntHandler(uint8_t *pui8data)
{

	// Request read of Accel data
	// This will register an interrupt, which will be serviced when this handler is finished.
	LIS3DSHDataRead(&g_sLIS3DSHInst, MEMSCallback, &g_sLIS3DSHInst);

	if(count++ == BUFFER_SIZE) Semaphore_post(BufferFull);

}

void ADCSeq1IntHandler(void)
{

	ROM_ADCSequenceDataGet(ADC0_BASE, 1, ui32ADC0Value);
	CPU_Temp[count] = ui32ADC0Value[0];
	Pressure[count] = ui32ADC0Value[1];

}

//***********************************************************************
void
ApplicationCallback(void *pvCallbackData, uint_fast8_t ui8Status)
{
	if(ui8Status == I2CM_STATUS_SUCCESS)
	{
		g_vui8DataFlag = 1;
	}
	g_vui8ErrorFlag = ui8Status;
}
//*************************************************************************


//*************************************************************************
//void
//GPIOFIntHandler(void)
//{
//
//}
//*************************************************************************

//*************************************************************************
void
LIS3DSHErrorHandler(char *pcFilename, uint_fast32_t ui32Line)
{
	while(1)
	{
	}
}
//*************************************************************************

//*************************************************************************
void
LIS3DSHI2CWait(char *pcFilename, uint_fast32_t ui32Line)
{
	while((g_vui8DataFlag == 0) && (g_vui8ErrorFlag == 0))
	{
	}
	if(g_vui8ErrorFlag)
	{
		LIS3DSHErrorHandler(pcFilename, ui32Line);
	}
	g_vui8DataFlag = 0;
}
//*************************************************************************

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

/* Duration of execution is determined by BUFFER_SIZE.
	 * Originally, the controller ran and logged data until the buffer is full, then stopped.
	 * With BIOS, need a flag to indicate buffer is full and it is time to transmit the data
	 * This will be an 'idle' task, and the flag will unblock this task
	 */
void
SendData()

{

	int i;

	Semaphore_pend(BufferFull, BIOS_WAIT_FOREVER);
	for(i = 0; i < BUFFER_SIZE; i++)
	{
		UARTprintf("%d, ", CPU_Temp[i]);
		UARTprintf("%d, ", Pressure[i]);
		UARTprintf("%d, ", AccelX[i]);
		UARTprintf("%d, ", AccelY[i]);
		UARTprintf("%d\n", AccelZ[i]);
	}
	UARTprintf("Done!\n");
}
//**************************************************************************


#ifdef DEBUG
void __error__(char *pcFilename, uint32_t ui32Line)
{
	while(1)
	{
		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 2);
	}

}
#endif

