/*
 * David Muller; Germán Alfaro
 * davehmuller@gmail.com; alfaro.germanevera@gmail.com
 */


#ifndef SYSTEM_H_
#define SYSTEM_H_

#include "SeapHOx.h"


//NAMEOF takes a variable and returns the string representation of the variable's name
#define NAMEOF(variable) #variable

/*
 * 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 INSTRUMENTBUFFSIZE 		400
#define MICROCAT_BUFFER_SIZE 	128
#define OPTODE_BUFFER_SIZE 		128
#define AUX1_BUFFER_SIZE		128
#define AUX2_BUFFER_SIZE		128

#define IS_PRESENT		  1
#define NOT_PRESENT 	  0



// This is an obsolete variable. 
#define LOW_VOLTAGE_PERIOD 21600   //when the SeapHOX is in a low voltage situation

/*
 * Conversions:  Preserved from "SeapHOX_Controller_V1.0"
 */
 

// Constants used for pH calcluations.
#define R_			8.31451						// Universal 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]



 // I think it would be best if we turned these into functions. YT 04092014
 
 // Calculates temperature from Durafet's thermistor. V_therm is the voltage from thermistor, measured using isolated 24-bit ADC.
 // TCOffset is an user input, to correct thermistor to be more accurate. Could make this a sys_data variable...
 float getDurafettemp(float V_therm, float TCOffset)
 {
	// Thermistor coefficients
	float c0 = 340.9819863;
	float c1 = -9.10257E-05
	float c2 = -95.08806667;
	float c3 = 0.965370274;
	// Declare variables
	float Rtherm;
	float TC; 
	// Calculate TC
	Rtherm = 20000/(3.3 / V_therm - 1);
	TC = c0 + c1*Rtherm + c2*(log10(Rtherm)) + c3*(pow(log10(Rtherm), 3));
	// Apply offset to TC; TCOffset is an user input.
	TC = TC + TCOffset;
	return TC;
 }
 
 // Function to calculate pH using internal reference.
 
 // Eint refers to the voltage from the internal reference, measured using the isolated 24-bit ADC.
 // TC should be calculated using fucntion getDurafettemp.
 float calc_pHint(float Eint, float TC)
 {
	float TK; 		// Temperature in Kelvin
	float S_T; 		// Nernest Slope
	float Eoint;  	// Calibration coefficient corrected to in situ temperature.
	
	TK = TC + 273.15;
	S_T = (R_ * TK) / F_ * ln(10);  
	
	Eoint = sys_data.Eo_int_25C + dEoINT_dt * (TC - 25); 
	pHint = (Eint - Eoint) / S_T;
 
	return pHint
 }
 
 // Calculate pH using external reference.
 // Eext referes to voltage from external reference, measured using isolated 24-bit ADC.
 // TC should be calculated using fucntion getDurafettemp.
 // Salt refers to salinity, extracted from SBE 37.
float clac_pHext(float Eext, float TC, float salt)
{
	float TK;				// Temperature in Kelvin
	float S_T;				// Nernst Slope
	float Eoext;			// Calibration coefficient corrected to in situ temperature
	float Z; 				// Ionic Strength; Dickson 2007
	float SO4_tot; 			// Total sulfate concentration; Dickson 2007
	float mCl; 				// Molality of Chloride; Dickson 2007;
	float K_HSO4; 			// Bisulfate acidity constant; Dickson 1990.
	float DHconst;			// Debye-Huckel; Khoo et al. 1997
	float log10gamma_HCl;	// log10 of mean activity coefficient of HCl in seawater
	float beta_SO4;			// ??
	float pHext_free;		// pH on free scale calculated from external reference
	float pHext_tot;		// pH on total scale calculated from external reference
	
	// Start calculations
	TK = TC + 273.15;
	S_T = (R_ * TK) / F_ * ln(10);  
	Eoext = sys_data.Eo_ext_25C + dEoEXT_dt * (TC - 25); 
	Z = 19.924 * salt / (1000 - 1.005 * salt); // Ionic strength
	SO4_tot = (0.14 / 96.062) * (salt / 1.80655); // molality sulfate from conservative relationship.
	mCl = 0.99889 / 35.453 * salt / 1.80655; // moallity chloride from conservative relationship.
	K_HSO4 =  exp(-4276.1/(TK)+141.328-23.093*log(TK)+(-13856/(TK)+324.57-47.986*log(TK))*sqrt(Z)+(35474/(TK)-771.54+114.723*log(TK))*Z-2698/(TK)*pow(sqrt(Z), 3)+1776/(TK)*pow(Z, 2)+log(1-0.001005*salt)); 
	DHconst = 0.00000343 * (pow(TC, 2)) + 0.00067524 * TC + 0.49172143; //Debye-Huckel
	log10gamma_HCl = 2*(-DHconst * sqrt(Z) / (1 + 1.394 * sqrt(Z)) + (0.08885 - 0.000111 * TC) * Z);
	
	pHext_free =  -((E0ext-Eext) - S_T * (log10(mCl) + log10gamma_HCl)) / S_T;
	pHext_tot = pHext_free - log10(1 + SO4_tot / KHSO4); // pH from external reference electrode on total scale.
	return pHext_tot;
	
}

// I RENAMED THESE MACROS!! YT 4/9/2014
// These macros are simple 
#define CALC_TC_BOARD(X)		(float) ((X * 1000 - 480) / 15.6)			// Calculate temperature from TC chip on board; X is voltage from ADC
#define CALC_BATT1_VOLT(X)		(float) (X * 11 + 0.2)						// Calculate main battery voltage. 11 is for the voltage divider, and 0.2 is for diode drop.
#define CALC_PRESSURE_VOLT(X) 	(float) (X * 32 / 10)						// Calculate pressure voltage. Correct for V-divider 
#define CALC_ISOBATT_VOLT(X)      (float) (X * 11)							// Calcualte isolated battery voltage. 11 corrects for the voltage divider.

/*
 * Definition of a structure containing the controller's parameters
 * These parameters are all modifiable by external user except where noted.
 */
 
 // I RENAMED A COUPLE VARIABLES!!! Eo_ext_25C and Eo_int_25C
struct systemData
{
	char savedDataString[256];              // in EEPROM, if one of the following variables has been saved, savedDataString will save that variable's name so we know that variable has been given a value NOT USER MODIFIABLE
	float low_batt_volt;	                // Low battery voltage threshold
	uint32_t sampling_period;	        	// pH sampling period
	int32_t sampling_average;	            // Number of samples to average
	uint32_t averaging_interval;       		// Number of seconds between each average
	uint32_t pumpon_time;		        	// Active pump time
//	int32_t output_mode;
	float Eo_ext_25C; 						// Calibration Coefficient for external reference, at 25C
	float Eo_int_25C;                       // Calibration Coefficient for internal reference, at 25C
	float sal_cal;                          // Salinity at the time of calibration
	char fileName[80];    					// The name the user would like to give their data output file
	int isSuspended;						// Is the controller in suspend mode? NOT USER MODIFIABLE
	char lastSample[INSTRUMENTBUFFSIZE];    // The instrument buffer from the last sample. NOT USER MODIFIABLE
	uint32_t nextWakeUp;					// our next intended RTC match (wake-up time) NOT USER MODIFIABLE
	int test_mode;							// For test deployment
	char sensor_name[20];                	// Sensor Package name (SP001, SF002, etc).
	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

};



/*
 * Holds the microCat and Optode responses along with the total bytes in our instrument buffer.
 */
struct pollingBuffers
{
	char microBuffer[MICROCAT_BUFFER_SIZE];		// MicroCAT buffer
	char optodeBuffer[OPTODE_BUFFER_SIZE];		// Optode buffer
	char AUX1_Buffer[AUX1_BUFFER_SIZE];			// AUX1 buffer
	char AUX2_Buffer[AUX2_BUFFER_SIZE];			// AUX2 buffer

	int microIndex;
	int optodeIndex;
	int AUX1_Index;
	int AUX2_Index;

	unsigned int totalBytes;	//keep track of the number of bytes written in to our instrument buffer
};



/*
 * Our global variables.
 */
extern struct pollingBuffers poll_Buffers;
extern struct systemData sys_data;
extern char instrument_buffer[INSTRUMENTBUFFSIZE];     //5/1/13  instrument_buffer compiles all of our measurements in one place. To be written to SD card
extern char deploymentHeader[INSTRUMENTBUFFSIZE];      //6/16/13 save the sys_data parameters to the top of the data output file (a "deployment information header" for the data output file).

/*
 * Function prototypes for System.c
 */
void SysTickHandler(void);
unsigned long Timer_10ms(bool reset);
void retrieveSysDataVariables();
int isNameInSavedDataString(char* name);
void saveSysDataVariableName();
void pumpOn();
void pumpOff();
void pressureOn();
void pressureOff();
void takeSample(deploymentStates deploymentState);
void takeSample_test();





#endif /* SYSTEM_H_ */
