/*=============================================================================================================
 * Sys Init.c - initialisation routines for Air Shock Controller with BIOS
 * These routines are to run prior to starting BIOS
 * Written by Dale Tardiff, Innovative Power Solutions Inc
 * Version 0.1 - started July 2, 2014
 * ============================================================================================================
 */


#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 "inc/tm4c123gh6pm.h"
#include "utils/uartstdio.h"
#include "sensorlib/i2cm_drv.h"
#include "driverlib/rom.h"

#include "hw_lis3dsh.h"
#include "lis3dsh.h"

#define SAMPLESPERSECOND 100
#define LIS3DSH_I2C_ADDRESS 0x1e // LIS3DSH I2C address

extern tI2CMInstance g_sI2CInst; // I2C master driver structure
extern tLIS3DSH g_sLIS3DSHInst; // LIS3DSH sensor driver structure

void Sys_Init(void)
{


//	uint32_t ui32Period;
	uint8_t id;
	uint8_t ui8Mask;


	extern void PortFunctionInit(void);
	void ApplicationCallback(void *pvCallbackData, uint_fast8_t ui8Status);
	void LIS3DSHI2CWait(char *pcFilename, uint_fast32_t ui32Line);

//	void LIS3DSHErrorHandler(char *pcFilename, uint_fast32_t ui32Line);

	SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);

	PortFunctionInit(); //Defined in GPIO Pin Assignments.c, which is generated by the TI Tiva-C Pinmux utility
	GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0);	// turn off compressor relay - in case previous run left it on.

	// ensure configuration proceeds without interrupts
	IntMasterDisable();

	// Timer code removed as it is configured using SYS/BIOS
	/* Timer0 will be configured to a frequency of "SAMPLEPERSECOND".
	 * This will drive a timer interrupt.
	 * Every timer interrupt various peripherals will be read
	 * This requires configuring the timer to trigger the ADC interrupt.
	 */

//	TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC); // Configure Timer0 as Periodic
//	ui32Period = (SysCtlClockGet() / SAMPLESPERSECOND) / 2;		// Calculate timer period for desired timer frequency
//	TimerLoadSet(TIMER0_BASE, TIMER_A, ui32Period -1);
//	IntEnable(INT_TIMER0A);							// Enable timer and ADC interrupts
//	TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
////	IntPrioritySet(INT_TIMER0A, 0);

//	TimerEnable(TIMER0_BASE, TIMER_A);


	/* THe ADC will be configured to sample all analog inputs
	 * This is driven by TIMER0 to get the required samples per second.
	 * The ADC Channels are:
	 * CH0: J24 - Cylinder pressure
	 * CH1: J25 - Cylinder position
	 * CH2: Accel X - not implemented
	 * CH3: Accel Y - not implemented
	 * CH4: Accel Z - not implemented
	 * CH5: J4 - Spare
	 * CPU temperature is measured at the start of the sequence
	 */

	TimerControlTrigger(TIMER2_BASE, TIMER_A, true);	// Allows TIMER to trigger ADC
	ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_TIMER, 2);
	ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_TS);	//CPU Temp
	ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH1|ADC_CTL_IE|ADC_CTL_END);
//	ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH3);
//	ADCSequenceStepConfigure(ADC0_BASE,1,3,ADC_CTL_CH4|ADC_CTL_IE|ADC_CTL_END);
	ADCSequenceEnable(ADC0_BASE, 1);
//	IntEnable(INT_ADC0SS1);
//	IntPrioritySet(INT_ADC0SS1, 1);
//	ADCIntEnable(ADC0_BASE, 1);

	/* Configure output PA7 for PWM
	 * This will be used to drive the 4 - 20 mA converter
	 */

	PWMGenConfigure(PWM1_BASE, PWM_GEN_1, PWM_GEN_MODE_DOWN|PWM_GEN_MODE_NO_SYNC);	//PA7
	PWMGenPeriodSet(PWM1_BASE, PWM_GEN_1, 16000);				// 2.5 kHz
	PWMGenEnable(PWM1_BASE, PWM_GEN_1);
	PWMOutputState(PWM1_BASE, PWM_OUT_3_BIT, true);

	/* Configure I2C communication
	 * This is used by the MEMs module
	 * I2C3 is defined in GPIO Pin Assignments as active
	 * The MEMS will be configured to to use INT1 to indicate data ready.
	 * This is sent to GPIO A6
	 */

	I2CMInit(&g_sI2CInst, I2C3_BASE, INT_I2C3, 0xFF, 0xFF, ROM_SysCtlClockGet()); //I2C3 using sys clock, fast transfer
	SysCtlDelay(SysCtlClockGet() / 3);		// 1000 ms delay


	GPIOIntTypeSet(GPIO_PORTA_BASE, GPIO_INT_PIN_6, GPIO_RISING_EDGE); // Using rising edge trigger for MEMs interrupt
	GPIOIntEnable(GPIO_PORTA_BASE, GPIO_INT_PIN_6);


	/* The UART is configured
	 * The UART will be used to transmit all data to a PC
	 * Configuration is 115200 baud, 8 bit word, 1 stop bit, no parity
	 */

//	UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
	UARTStdioConfig(0, 115200, SysCtlClockGet()); //need UARTStdioConfig to use UARTPrintf function
//	UARTFIFOEnable(UART0_BASE);

	UARTprintf("Hello\n");

	// Remaining I2C operations are interrupt driven
	// Therefore, Master interrupt is enabled.
	// GPIO Port A will be enabled later to allow the MEMs to be initialized

	IntMasterEnable();

	LIS3DSHInit(&g_sLIS3DSHInst, &g_sI2CInst, LIS3DSH_I2C_ADDRESS,ApplicationCallback, &g_sLIS3DSHInst);
	//	SysCtlDelay(SysCtlClockGet() / 3);
	LIS3DSHI2CWait(__FILE__, __LINE__);


	/*
	 * LIS3DSH Configuration parameters
	 * ApplicationCallback sets g_vui8DataFlag when
	 * I2C transaction completes
	 */

	ui8Mask = 0xff;

	// Set fullscale range
	LIS3DSHReadModifyWrite(&g_sLIS3DSHInst, LIS3DSH_CTRL_REG5, ~ui8Mask,
			(LIS3DSH_CTRL_REG5_FSCALE_4G),
			ApplicationCallback, &g_sLIS3DSHInst);
	LIS3DSHI2CWait(__FILE__, __LINE__);

	// CTRL_REG3 sets interrupt parameters
	// Configuration is: DataReady signal to INT1, INT is active high, pulsed, and INT1 is enabled.
	LIS3DSHReadModifyWrite(&g_sLIS3DSHInst, LIS3DSH_CTRL_REG3, ~ui8Mask,
			(LIS3DSH_CTRL_REG3_DR_EN_CON|LIS3DSH_CTRL_REG3_IEA|LIS3DSH_CTRL_REG3_IEL|LIS3DSH_CTRL_REG3_INT1_EN),
			ApplicationCallback, &g_sLIS3DSHInst);
	LIS3DSHI2CWait(__FILE__, __LINE__);

	// CTRL_REG4 seems to need to be last - it won't update if modified before 3 and 5
	// CTRL_REG4 sets the output data rate, and enables all 3 axes (X, Y, Z)
	LIS3DSHReadModifyWrite(&g_sLIS3DSHInst, LIS3DSH_CTRL_REG4, ~ui8Mask,
			(LIS3DSH_CTRL_REG4_ODR_100HZ|LIS3DSH_CTRL_REG4_XEN|LIS3DSH_CTRL_REG4_YEN|LIS3DSH_CTRL_REG4_ZEN),
			ApplicationCallback, &g_sLIS3DSHInst);
	LIS3DSHI2CWait(__FILE__, __LINE__);

	/* Test I2C to MEMS by reading WHO AM I register
	 *
	 */
	LIS3DSHRead(&g_sLIS3DSHInst, LIS3DSH_WHO_AM_I, &id, 1, ApplicationCallback, &g_sLIS3DSHInst);
	LIS3DSHI2CWait(__FILE__, __LINE__);

	UARTprintf("ID = %d\n", id);

//	UARTprintf("Pressure?");
//	UARTgets(RawPressure, 6);

}


