#include "NyLPC_flash.h"
#include "NyLPC_httpService.h"
#include "cConfiglationStorage.h"

/**
 * Onchip flashを使ったコンフィギュレーション保存システムです。
 */




#define IP2Int(a0,a1,a2,a3) ((0xff000000&(a0<<24))|(0x00ff0000&(a1<<16))|(0x0000ff00&(a2<<8))|(0x000000ff&(a3)))
/**
 * コンフィギュレーションの保存セクタ
 */
#define MIMIC_CONFIGLATION_FLASH_SECTOR 29
#define MIMIC_CONFIGLATION_FLASH_SECTOR_ADDR 0x00078000

/**
 * コンフィギュレーション値はホストオーダーで保存する。
 */
const struct TMimicConfigulation factory_default=
{
	0xffffffff,
	0x02010203,0x0405ffff,
	IP2Int(192,168,0,39),
	IP2Int(255,255,255,0),
	IP2Int(192,168,0,254),
	80,
	0x0000FFFF
};

static NyLPC_TBool setUserConfigulation(void);
static NyLPC_TBool hasUserConfigulation(void);

/**
 * ユーザコンフィギュレーションを更新する。
 * この関数をコールするときは、割込/FreeRTOSを一時停止すること。
 */
NyLPC_TBool cConfiglationStorage_updateConfigulation(const struct TMimicConfigulation* i_congfiglation)
{
	NyLPC_TcOnchipFlashWriter_t s;
	NyLPC_cOnchipFlashWriter_initialize(&s);
	//イレース
	if(!NyLPC_cOnchipFlashWriter_elase(&s,MIMIC_CONFIGLATION_FLASH_SECTOR,MIMIC_CONFIGLATION_FLASH_SECTOR)){
		NyLPC_OnErrorGoto(Error);
	}
	//コンフィギュレーションを書き込む。
	if(!NyLPC_cOnchipFlashWriter_writeSector(&s,MIMIC_CONFIGLATION_FLASH_SECTOR,0x00000000,i_congfiglation,sizeof(struct TMimicConfigulation))){
		NyLPC_OnErrorGoto(Error);
	}
	//ユーザコンフィギュレーションをONにする。
	if(setUserConfigulation()){
		NyLPC_OnErrorGoto(Error);
	}
	NyLPC_cOnchipFlashWriter_finalize(&s);
	return NyLPC_TBool_TRUE;
Error:
	NyLPC_cOnchipFlashWriter_finalize(&s);
	return NyLPC_TBool_FALSE;
}
/**
 * コンフィギュレーション値を返す。
 */
const struct TMimicConfigulation* cConfiglationStorage_loadMiMicConfigulation(void)
{
	if(hasUserConfigulation()){
		//userコンフィギュレーション読むよ
		return (const struct TMimicConfigulation*)(MIMIC_CONFIGLATION_FLASH_SECTOR_ADDR);
	}else{
		//Userコンフィギュレーションない
		return &factory_default;
	}
}




/**
 * ユーザコンフィギュレーションが存在すると、true.
 */
static NyLPC_TBool hasUserConfigulation(void)
{
	volatile const NyLPC_TUInt32* fast_boot=&(factory_default.fast_boot);
	return (*fast_boot)!=0xffffffff;
}
/**
 * コンフィギュレーションモードを、ユーザコンフィギュレーションにセットする。
 */
static NyLPC_TBool setUserConfigulation(void)
{
	const NyLPC_TUInt32* volatile fast_boot=&(factory_default.fast_boot);
	NyLPC_TUInt32 data=0xFFFFFFFE;
	NyLPC_TcOnchipFlashWriter_t s;

	if(*fast_boot==0xffffffff){
		//フラグ値のアドレスが4バイトアライメントにあるFlashメモリか確認する。
		if(((NyLPC_TUInt32)fast_boot)%4==0 && (!NyLPC_cOnchipFlashWriter_isOnchipFlash(fast_boot))){
			//書き込み
			NyLPC_cOnchipFlashWriter_initialize(&s);
			NyLPC_cOnchipFlashWriter_write(&s,fast_boot,&data,4);
			NyLPC_cOnchipFlashWriter_finalize(&s);
		}else{
			//しくじった
			return NyLPC_TBool_FALSE;
		}
	}
	return NyLPC_TBool_TRUE;
}

