//----------------------------------------------------
/**
	\file	init.c

	\brief	Inicializace zarizeni
			<<< ALL >>>
			
	\author	ConTeK s.r.o., Pavel Bazika
	\version	01.01
	\date	12.01.2007
*/
//----------------------------------------------------

#include <hwsubmdl.h>
#include <hwmodel.h>
#include <hwboard.h>
#include <sync.h>
#include <timeticks.h>
#include <paramstore.h>
#include <verinfo.h>
#include <uctp.h>
#include <ctktime.h>

#include "realtick.h"
#include "fasttick.h"
#include "slowtick.h"
#include "maintick.h"
#include "pccomm.h"
#include "appsets.h"
#include "appiodef.h"
#include "gvariables.h"

#ifdef MSVC
//  #include "vld.h"
//  #include "sim.h"
#endif

#ifdef DBGMONITOR
  #include "appdebug.h"
#endif


//-----------------------------------------------------
/**
	\ brief	Inicializace parametru verze
*/
//-----------------------------------------------------

static void FillVersionInfo(void)
{
	gParam.State.Version.ProtocolVersion = VERINFO_PROTOCOL_VERSION;
	gParam.State.Version.ProjectIdent = VerInfoGetProjectIdent();
	gParam.State.Version.HWVersion = VerInfoGetHWVersion();
	gParam.State.Version.HWRevision= VerInfoGetHWRevision();
	gParam.State.Version.SWVersion = VerInfoGetSWVersion();
	gParam.State.Version.SWRevision= VerInfoGetSWRevision();
	gParam.State.Version.DataVersion= VerInfoGetDataVersion();
	gParam.State.Version.NvDataVersion= VerInfoGetNvDataVersion();
	gParam.State.Version.PstDataVersion= VerInfoGetPstDataVersion();

	ctktm_t tim;
	memset(&tim, 0, sizeof(tim));
	uint16_t date = VerInfoGetRevisionDate();
	tim.tm_mday = VerInfoGetRevisionDay(date);
	tim.tm_mon = VerInfoGetRevisionMonth(date) - 1;
	tim.tm_year = VerInfoGetRevisionYear(date) - 1900;
	gParam.State.Version.RevisionDate = mktime(&tim);
}


//-----------------------------------------------------
/**
	\brief	Kontrola Conf verze a propojky
*/
//-----------------------------------------------------

static bool_t pmCheckConfVersion(const PARAMSTORE_CTX * const _ctx, const uint16_t _version)
{
	return !GetJumper(0);
}


//-----------------------------------------------------
/**
	\brief	Kontrola Pst verze a propojky
*/
//-----------------------------------------------------

static bool_t pmCheckPstVersion(const PARAMSTORE_CTX * const _ctx, const uint16_t _version)
{
	return ((_ctx->GetPstVersion(_ctx) == _version) && !GetJumper(0));
}


//-----------------------------------------------------
/**
	\brief	Inicializace datove zakladny, nacteni parametru, trvale ukladanych parametru...
*/
//-----------------------------------------------------

static bool_t InitParams(void)
{
	static const ticks_t LOAD_FLASH_TIMER = 50;
	bool_t status = TRUE;

	//! Nahrani vychozich dat z programflash do RAM (ctrl unit)
	memcpy_pconst(&gParam, &cdftParam, sizeof(gParam));

	DatadefInitialize( &gCtxCtrl );

	//! Aby se spravne nainicializoval ParamStoreInitialize...
	status &= NvMemInitialize(
					&confMem,
					MEM_TYPE_FRAM,
					1024,
					0,
					32,
					32);

	//! Ukladat se budou pouze konfiguracni data do FRAM, nikoliv persistentni
	status &= ParamStoreInitialize(&gParCtxCtrl,
					    &confMem,
						piParamConfxxx,
						piParamConfxxx
#ifdef USEHW_FRAM
						,
						&gFram.Parent,
						500,
						gPstBuf,
						&gParam.Pst,
						sizeof(gParam.Pst)
#endif //USEHW_FRAM
						);


#ifdef USEHW_FRAM
	pstRegisterCheckVersion(&gParCtxCtrl, &pmCheckPstVersion);
#endif //USEHW_FRAM

	//! registrace kontrolnich funkci verze - kvuli testu propojky
	confRegisterCheckVersion(&gParCtxCtrl, &pmCheckConfVersion);

	_FastUnlock();

	//! nacteni parametru
	bool_t led = FALSE;
	ticks_t timer = tmTicks();

	while (!pstReady(&gParCtxCtrl))
	{
		ParamStoreTick(&gParCtxCtrl);
		if (tmElapsed(timer))
		{
			timer = tmTimeout(LOAD_FLASH_TIMER);
			SetLedEx(0, led = !led);
		}
	}

	SetLedEx(0, FALSE);

	_FastLock();


#ifdef USEHW_FRAM
	PST_ERROR pstErr = pstGetError(&gParCtxCtrl);
	status &= (pstErr == PSERR_NONE) || (pstErr == PSERR_SET_DEFAULT);
	assert_C(status);
	if (!status)
	{
		return FALSE;
	}
#endif //USEHW_FRAM

	PARAM_ERROR parErr = confGetError(&gParCtxCtrl);
	status &= (parErr == PERR_NONE);
	assert_C(status);

	if (!status)
	{
		SetLedEx(0, 1);
		return FALSE;
	}

	//! Nahrani parametru verze
	FillVersionInfo();

	//! Zacneme periodicky ukladat stav stroje
#ifdef USEHW_FRAM
	pstStart(&gParCtxCtrl);
#endif //USEHW_FRAM
	return TRUE;
}

//-----------------------------------------------------
/**
	\brief	Inicializace termoclanku
*/
//-----------------------------------------------------

static bool_t InitThermocouple(void)
{
	bool_t ret = FALSE;

	ThermocoupleInit (  &gThermocouple );
	ThermoUpdateConstant( &gThermocouple, gParam.Pst.Conf.Temp.AmpfGain,
		gParam.Pst.Conf.Temp.mVoltOnC, gParam.Pst.Conf.Temp.AmpfOffset,
		gParam.Pst.Conf.Temp.FilterConstant, gParam.Pst.Conf.Temp.ThermoSens25,
		gParam.Pst.Conf.Temp.A0, gParam.Pst.Conf.Temp.A1, gParam.Pst.Conf.Temp.A2,
		gParam.Pst.Conf.Temp.A3, gParam.Pst.Conf.Temp.A4, gParam.Pst.Conf.Temp.A5,
		gParam.Pst.Conf.Temp.A6, gParam.Pst.Conf.Temp.A7, gParam.Pst.Conf.Temp.A8, 
		gParam.Pst.Conf.Temp.A9);	

	return ret;
}


//-----------------------------------------------------
/**
	\brief	Inicializace
*/
//-----------------------------------------------------

bool_t Initialize(void)
{
	//! Inicializace FastLock
	FastLockInitialize();

	//! Zakazani preruseni
	_FastLock();
	wdtDisable();

	//! Inicializace HW modelu, submodelu a desky
	HWModelInitialize();
	HWSubMdlInitialize();

#if defined(MSVC)
	HWBoardInitialize(&gFram, _T("fram.bin"));
#else
	HWBoardInitialize(&gFram, &gTwi);
#endif
	//! Inicializace filtru
	memset(gDInpFilter, 0, sizeof(gDInpFilter));

	//! Inicializace IO
	IOInitialize(gDInpVal, gDInpX, gDInpFilter, gDOutpVal, gDOutpX, gAInpVal, NULL, gAOutpVal);

	IOBoardInitialize(&gIOBoardCtx);

	IORegisterDevice(&gIOBoardCtx.Device, 0, 0, 0, 0);

	//! Inicializace TimeTicks a HW
	TimeTicksInitialize();
#ifdef MSVC
	TimeTicksHWInitialize(10);
#else
	TimeTicksHWInitializeus(500);
#endif
	//! inicializace datove zakladny a globalnich parametru
	InitParams();


	//! Nastaveni doby trvani ticku
#ifdef MSVC
	SetFastTickSpeed(10); //100ms
	SetSlowTickSpeed(20); //200ms
#else
	SetFastTickSpeed(2); //1ms
	SetSlowTickSpeed(20); //10ms
#endif

	//! Registrace tiku
	RegisterFastTick(FastTick);
	RegisterSlowTick(SlowTick);
	RegisterMain(MainTick);

	//! inicializace komunikace
	PcCommInitialize();

#ifdef MSVC
	//! inicializace dat simulatoru
//	SimInitialize();
#endif //MSVC

#ifdef DBGMONITOR
	//! Inicializace ladicich vypisu
	AppDebugInitialize();
#endif //DBGMONITOR

	//! povoleni vstupu a vystupu
	IOEnable();

	//! Inicializace termoclanku
	InitThermocouple();
	LambdaInit( &gLambda );
	PhotoInit( &gPhoto );


	//! nastaveni watch dog timeru na periodou 5s
	wdtReset();
	wdtEnable(WDTO_5S);

	//! povoleni preruseni
	_FastUnlock();

	return TRUE;
}
