/*
 * David Muller; Germán Alfaro
 * davehmuller@gmail.com; alfaro.germanevera@gmail.com
 */


#ifndef SEAFET_SEAPHOX_V2_0_SYSTEM_H_
#define SEAFET_SEAPHOX_V2_0_SYSTEM_H_

#include <stdint.h>
#include <stdbool.h>
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <ctype.h>


#include "inc/tm4c123gh6pge.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_hibernate.h"

#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/eeprom.h"
#include "driverlib/gpio.h"
#include "driverlib/hibernate.h"
#include "driverlib/ssi.h"
#include "driverlib/interrupt.h"

#define 	VERSION		"v3.0"		// SeapHOx software version

/* Boolean type */
typedef enum { FALSE = 0, TRUE } BOOL;
typedef enum {IDLE, START, DEPLOYED, COMMAND} deploy_state;
typedef enum {NORMAL=1, VERBOSE} output_mode;

/*
 * Delay lengths for SysCtlDelay().
 */
#define CLOCKSPEED 50000000.0  						//clock is set to run at 50MHZ
#define ONESEC (int)ceil((CLOCKSPEED/3.0))  		//SysCtlDelay takes 3 cycles per loop...so delay = DesiredDelayTimeInSeconds/((1/CLOCKSPEED)*3)
#define MILLISECOND (int)ceil((.001 / ((1.0/CLOCKSPEED)*3.0)))
#define MICROSECOND (int)ceil((.000001 / ((1.0/CLOCKSPEED)*3.0)))

/*
 * Buffer lengths.
 */
#define TIMESTAMPLENGTH 		50
#define INSTRUMENTBUFFSIZE 		400
#define MICROCAT_BUFFER_SIZE 	128
#define OPTODE_BUFFER_SIZE 		128
#define AUX1_BUFFER_SIZE		128
#define AUX2_BUFFER_SIZE		128


#define GDATA_BYTES				512	// Number of bytes to read out with gdata command

#define IS_PRESENT		  1
#define NOT_PRESENT 	  0

/*
 * Constants
 */
#define R_			8.31451			// Univ gas constant
#define F_ 			96487			// Faraday constant
#define dEoINT_dt	-0.0011012		// Temperature coefficient for internal reference [Volts/C]
#define dEoEXT_dt	-0.0010482		// Temeprature coefficient for external reference [Volts/C]
#define LN10		2.302585		// Natural log of 10

// Standard deviation array values
#define SD_AVG		5
#define SD_MEAN		SD_AVG
#define SD_DIFF_SQ	SD_AVG+1
#define SD_VALUES	5

// AD1248 24-bit A/D defines
#define TWOTOTHE23 8388608
#define COUNTSTOVOLTS (float) (2.048 / (TWOTOTHE23 - 1))  //each count returned from the ADC has a weight of (Vref/PGA)/(2^23 -1 ).  We use PGA = 1.
#define PGA_1		0x00
#define PGA_2		0x10
#define PGA_4		0x20
#define PGA_8		0x30
#define PGA_16		0x40
#define PGA_32		0x50
#define PGA_64		0x60
#define PGA_128		0x70

#define SPS_5		0x00
#define SPS_10		0x01
#define SPS_20		0x02
#define SPS_40		0x03
#define SPS_80		0x04
#define SPS_160		0x05
#define SPS_320		0x06
#define SPS_640		0x07
#define SPS_1000	0x08
#define SPS_2000	0x09

/*
 * Definition of a structure containing the controller's parameters
 * These parameters are all modifiable by external user except where noted.
 * Structure is stored in EEPROM during hybernation.
 */
struct systemData
{
	float low_batt_volt;	        // Low battery voltage threshold
	uint32_t sampling_period;	    // pH sampling period
	int32_t sample_average;	    	// Number of pH sensor samples to average
	uint32_t averaging_interval;    // Number of seconds between each average
	uint32_t pumpon_time;		    // Active pump time
	float TCOffset;					// DuraFET temperature calibration variable
	float Eo_ext_25C;
	float Eo_int_25C;
	float default_sal;
	char fileName[80];    			// The name the user would like to give their data output file
	char sensor_name[20];           // Temperature sensor name
	char durafet_SN[30];			// DuraFET sensor serial number
	char capadap_SN[30];			// CAP adapter serial number
	char ISE_SN[30];				// ISE serial number
	char microcat_SN[30];			// Microcat serial number
	char pump_SN[30];				// Pump serial number
	int press_full_scale;			// Pressure sensor full-scale value (psi)
	int Vint_gain;					// pH Vint PGA gain setting
	int Vint_sps;					// pH Vint data rate setting (sps)
	output_mode output;				// Verbose mode during deployment if true
	int test_mode;					// Indicates test deployment
	int state;						// IDLE, DEPLOYED, COMMAND,  NOT USER MODIFIABLE
	uint32_t nextWakeUp;			// Next intended RTC match (wake-up time) NOT USER MODIFIABLE
	unsigned long next_gdata_fptr;	// The file position of the next gdata sample. NOT USER MODIFIABLE
	unsigned int current_sample;	// The current data record to be stored. NOT USER MODIFIABLE
	char user[10];					// User initials
	bool GMT;						// GMT or Local time
	bool sample_aligned;			// Sample aligned to hour
	float AD24_std;					// standard deviation for AD24
};


// Global variables
extern struct systemData sys_data;
extern char MicroCAT_buff[MICROCAT_BUFFER_SIZE];
extern char Optode_buff[OPTODE_BUFFER_SIZE];

// Function Macros
#define pump_on()		ROM_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_3, 0xff);
#define pump_off()		ROM_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_3, 0x00);
#define pressureOn()	ROM_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_5, 0xff);
#define pressureOff()	ROM_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_5, 0x00);
#define console_on()	ROM_GPIOPinWrite(GPIO_PORTL_BASE, GPIO_PIN_0, 0xff);
#define console_off()	ROM_GPIOPinWrite(GPIO_PORTL_BASE, GPIO_PIN_0, 0x00);

// Function prototypes for System.c
void SysTickHandler(void);
unsigned long Timer_10ms(bool reset);
void retrieveSysDataVariables();
int isNameInSavedDataString(char* name);
void saveSysDataVariableName();
float batt_volt();
float batt_volt_iso();
float controller_temp();
float pressure(void);
int writeDeploymentInformationHeader(const time_t currentTime, const time_t firstSample);
void get_sample(void);
void error_store(const char *error_buff);
float DuraFET_temp(float V_therm, float TCOffset);
float calc_pHext(float Eext, float TC, float salt);
float calc_pHint(float Eint, float TC);
void ph_calib(void);

#endif /* SEAFET_SEAPHOX_V2_0_SYSTEM_H_ */
