/*
 * TLGB_flash.c
 *
 *  Created on: 24/feb/2015
 *      Author: gozzini.davide
 *
 */

// la memoria occupata dal programma si puo' vedere in View -> Memory Allocation -> FLASH

//==============================================================================
// Include files

#include "string.h"
#include "stdint.h"
#include "stdio.h"

#include "driverlib/rom.h"

#include "TLGB/TLGB_flash.h"

//==============================================================================
// Constants

// creo una definizione dell'indirizzo di partenza allineata a 16k
#define START_RICETTE_TLGB						0xF4000 // 16kB
#define START_SALVA_TLGB     					0xF0000 // 16kB
#define START_PARAMETRI_TLGB   					0xEC000 // 16kB
#define START_ADC_TLGB	     					0xE8000 // 16kB
// #define START_UNUSED_5     					0xE4000 // 16kB
// #define START_UNUSED_6     					0xE0000 // 16kB
// #define START_UNUSED_7     					0xDC000 // 16kB
// #define START_UNUSED_8     					0xD8000 // 16kB
// #define START_UNUSED_9     					0xD4000 // 16kB
// #define START_UNUSED_10    					0xD0000 // 16kB
// #define START_UNUSED_11    					0xCC000 // 16kB
// #define START_UNUSED_12    					0xC8000 // 16kB
// #define START_UNUSED_13    					0xC4000 // 16kB
// #define START_UNUSED_14    					0xC0000 // 16kB
// #define START_UNUSED_15    					0xBC000 // 16kB
// #define START_UNUSED_16    					0xB8000 // 16kB
// #define START_UNUSED_17    					0xB4000 // 16kB
// #define START_UNUSED_18    					0xB0000 // 16kB
// #define START_UNUSED_19    					0xAC000 // 16kB
// #define START_UNUSED_20    					0xA8000 // 16kB
// #define START_UNUSED_21    					0xA4000 // 16kB
// #define START_UNUSED_22    					0xA0000 // 16kB
// #define START_UNUSED_23    					0x9C000 // 16kB
// #define START_UNUSED_24    					0x98000 // 16kB
// #define START_UNUSED_25    					0x94000 // 16kB
// #define START_UNUSED_26    					0x90000 // 16kB

//==============================================================================
// Types

//==============================================================================
// Static global variables

//static const unsigned char gDoubleInfinityByteArray[(int)sizeof(double)] = { 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
//static const unsigned char gDoubleNanByteArray[(int)sizeof(double)] = { 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
//static const unsigned char gDoubleExponentMask[(int)sizeof(double)] = { 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
//static const unsigned char gDoubleMantissaMask[(int)sizeof(double)] = { 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const unsigned char gDoublexFFByteArray[(int)sizeof(double)] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
//static const unsigned char gFloatxFFByteArray[(int)sizeof(float)] = { 0xFF, 0xFF, 0xFF, 0xFF };

//==============================================================================
// Static functions

/*
static double NotANumber(void)
{
    return ByteArrayToDouble(gDoubleNanByteArray);
}

*/

static double ByteArrayToDouble(const unsigned char *byteArray)
{
    volatile double result = 0.;
    int i;

    // NOTE: the following code only works on x86 processors because of Endianess
    for (i = 0; i < sizeof(double); ++i)
    {
        ((volatile unsigned char*) &result)[sizeof(double)-1-i] = byteArray[i];
    }
    return result;
}


static double Hex_FF_Double(void)
{
	return ByteArrayToDouble(gDoublexFFByteArray);
}

/*
static float ByteArrayToFloat(const unsigned char *byteArray)
{
    volatile float result = 0.;
    int i;

    // NOTE: the following code only works on x86 processors because of Endianess
    for (i = 0; i < sizeof(float); ++i)
    {
        ((volatile unsigned char*) &result)[sizeof(float)-1-i] = byteArray[i];
    }
    return result;
}

static float Hex_xFF_Float(void)
{
	return ByteArrayToFloat(gFloatxFFByteArray);
}
*/

//==============================================================================
// Global variables

TFlashRicetta ricetta;
TFlashSalva salva;
TFlashParametri parametri;
TFlashAdc adc;

//==============================================================================
// Global functions

void TLGB_Flash_Init(void)
{
	memset(&ricetta, 0, sizeof(TFlashRicetta));
	memset(&salva, 0, sizeof(TFlashSalva));
	memset(&parametri, 0, sizeof(TFlashParametri));
	memset(&adc, 0, sizeof(TFlashAdc));
	return;
}

void WriteRicette(TFlashRicetta *par)
{
	if(par == NULL)
	{
		return;
	}

	ROM_FlashErase(START_RICETTE_TLGB);
	ROM_FlashProgram((unsigned int *)par, START_RICETTE_TLGB, sizeof(TFlashRicetta));
	return;
}

void ReadRicette(TFlashRicetta *par)
{
	TFlashRicetta *tmp_ptr = NULL;
	unsigned char contatore_programmi = {0};
	unsigned char contatore_stazioni = {0};
	unsigned char contatore_tempi = {0};
	unsigned char contatore_soglie = {0};
	unsigned char contatore_stringhe = {0};

	if(par == NULL)
	{
		return;
	}

	tmp_ptr = (TFlashRicetta *)START_RICETTE_TLGB;

	if(tmp_ptr->titolo[programma_0][0] != 0xFF)
	{
		memcpy(par,tmp_ptr,sizeof(TFlashRicetta));
	}
	else
	{
		// faccio le inizializzazioni
		for(contatore_programmi = 0; contatore_programmi < numero_programmi; contatore_programmi++)
		{
			sprintf(par->titolo[contatore_programmi], "RICETTA %d", contatore_programmi);

			for(contatore_stazioni = 0; contatore_stazioni < numero_stazioni; contatore_stazioni++)
			{
				for(contatore_tempi = 0; contatore_tempi < tempo_numero_totale; contatore_tempi++)
				{
					par->tempi[contatore_programmi][contatore_stazioni][contatore_tempi] = 0;
				}
				for(contatore_soglie = 0; contatore_soglie < soglia_numero_totale; contatore_soglie++)
				{
					par->soglie[contatore_programmi][contatore_stazioni][contatore_soglie] = 0;
				}
				for(contatore_stringhe = 0; contatore_stringhe < stringhe_numero_totale; contatore_stringhe++)
				{
					sprintf(par->stringhe[contatore_programmi][contatore_stazioni][contatore_stringhe], "");
				}
			}
		}
		for(contatore_soglie = 0; contatore_soglie < soglia_numero_totale; contatore_soglie++)
		{
			par->umis[contatore_soglie] = unita_misura_NULL;
			par->decimali[contatore_soglie] = 0;
		}
	}
	return;
}

void WriteSalva(TFlashSalva *par)
{
	if(par == NULL)
	{
		return;
	}

	ROM_FlashErase(START_SALVA_TLGB);
	ROM_FlashProgram((unsigned int *)par, START_SALVA_TLGB, sizeof(TFlashSalva));
	return;
}

void ReadSalva(TFlashSalva *par)
{
	TFlashSalva *tmp_ptr = NULL;
	unsigned char contatore_stazioni = {0};

	if(par == NULL)
	{
		return;
	}

	tmp_ptr = (TFlashSalva *)START_SALVA_TLGB;
	if(tmp_ptr->lingua != EnumLingue_32bit)
	{
		memcpy(par,tmp_ptr,sizeof(TFlashSalva));
	}
	else
	{
		par->lingua = lingua_italiano;
		for(contatore_stazioni = 0; contatore_stazioni < numero_stazioni; contatore_stazioni++)
		{
			par->programma_attivo[contatore_stazioni] = programma_0;
		}
	}
	return;
}

void WriteParametri(TFlashParametri *par)
{
	if(par == NULL)
		return;

	ROM_FlashErase(START_PARAMETRI_TLGB);

	ROM_FlashProgram((unsigned int *)par, START_PARAMETRI_TLGB, sizeof(TFlashParametri));

	return;
}

void ReadParametri(TFlashParametri *par)
{
	TFlashParametri *tmp_ptr = NULL;
	//double NaN = NotANumber();
	double xFF = Hex_FF_Double();
	unsigned char contatore_tempi = {0};
	unsigned char contatore_soglie = {0};
	unsigned char contatore_stazioni = {0};

	if(par == NULL)
	{
		return;
	}

	tmp_ptr = (TFlashParametri *)START_PARAMETRI_TLGB;
	if(tmp_ptr->tempi_generali[GT00] != xFF)
	{
		memcpy(par,tmp_ptr,sizeof(TFlashParametri));
	}
	else
	{
		for(contatore_tempi = 0; contatore_tempi < tempi_generali_numero_totale; contatore_tempi++)
		{
			par->tempi_generali[contatore_tempi] = 0;
		}
		for(contatore_soglie = 0; contatore_soglie < soglie_generali_numero_totale; contatore_soglie++)
		{
			par->soglie_generali[contatore_soglie] = 0;
			par->umis_generali[contatore_soglie] = unita_misura_NULL;
			par->decimali_generali[contatore_soglie] = 0;
		}

		for(contatore_stazioni = 0; contatore_stazioni < numero_stazioni; contatore_stazioni++)
		{
			for(contatore_tempi = 0; contatore_tempi < tempi_stazione_numero_totale; contatore_tempi++)
			{
				par->tempi_stazione[numero_stazioni][contatore_tempi] = 0;
			}
			for(contatore_soglie = 0; contatore_soglie < soglia_stazione_numero_totale; contatore_soglie++)
			{
				par->soglie_stazione[numero_stazioni][contatore_soglie] = 0;
			}
		}
		for(contatore_soglie = 0; contatore_soglie < soglia_stazione_numero_totale; contatore_soglie++)
		{
			par->decimali_stazione[contatore_soglie] = 0;
			par->umis_stazione[contatore_soglie] = unita_misura_NULL;
		}
	}
	return;
}

void WriteAdc(TFlashAdc *par)
{
	if(par == NULL)
	{
		return;
	}

	ROM_FlashErase(START_ADC_TLGB);
	ROM_FlashProgram((unsigned int *)par, START_ADC_TLGB, sizeof(TFlashAdc));
	return;
}

void ReadAdc(TFlashAdc *par)
{
	TFlashAdc *tmp_ptr = NULL;

	if(par == NULL)
	{
		return;
	}

	tmp_ptr = (TFlashAdc *)START_ADC_TLGB;

	if(tmp_ptr->AcquisitionManage.AcquisitionMode != AcquistionModeNone)
	{
		memcpy(par,tmp_ptr,sizeof(TFlashAdc));
	}
	else
	{
		par->AcquisitionManage.AcquisitionMode = Single_ended;
		par->AcquisitionManage.Gain = 1;
		par->AcquisitionManage.GainSel = Gain1;
		par->AcquisitionManage.ChannelNumberSingleEnded = ChannelNum1;
		par->AcquisitionManage.ChannelNumberDifferential = ChannelNum1;

		par->Mode.AVG1 = 0;
		par->Mode.AVG0 = 0;
		par->Mode.FS = 2;
		par->Mode.SINC3 = 0;
		par->Mode.Single = 0;

		par->Configuration.Chop = 1;

		par->Linearizzazione[0].Grandezza[0] = 0;
		par->Linearizzazione[0].Tensione[0] = 0;
		par->Linearizzazione[0].Grandezza[1] = 10;
		par->Linearizzazione[0].Tensione[1] = 10;
		par->Linearizzazione[0].NPuntiAttivi = 2;
		par->umis[0] = unita_misura_NULL;
		par->decimali[0] = 0;

		par->Linearizzazione[1].Grandezza[0] = 0;
		par->Linearizzazione[1].Tensione[0] = 0;
		par->Linearizzazione[1].Grandezza[1] = 10;
		par->Linearizzazione[1].Tensione[1] = 10;
		par->Linearizzazione[1].NPuntiAttivi = 2;
		par->umis[1] = unita_misura_NULL;
		par->decimali[1] = 0;

		par->Linearizzazione[2].Grandezza[0] = 0;
		par->Linearizzazione[2].Tensione[0] = 0;
		par->Linearizzazione[2].Grandezza[1] = 10;
		par->Linearizzazione[2].Tensione[1] = 10;
		par->Linearizzazione[2].NPuntiAttivi = 2;
		par->umis[2] = unita_misura_NULL;
		par->decimali[2] = 0;

		par->Linearizzazione[3].Grandezza[0] = 0;
		par->Linearizzazione[3].Tensione[0] = 0;
		par->Linearizzazione[3].Grandezza[1] = 10;
		par->Linearizzazione[3].Tensione[1] = 10;
		par->Linearizzazione[3].NPuntiAttivi = 2;
		par->umis[3] = unita_misura_NULL;
		par->decimali[3] = 0;
	}
	return;
}
