/*
 * Settings.h
 *
 *  Created on: 12 мая 2015 г.
 *      Author: esaulenko
 */

#ifndef COMMON_SETTINGS_H_
#define COMMON_SETTINGS_H_

#include "CommonTypes.h"
#include "source/SourcePath.h"

#ifdef SRC_TYPES
#include SRC_TYPES
#endif

class CSettings
{
public:
// глобальная структура с настройками
	struct TSettings
	{
		#define SETTING(...)									// не используется
		#define SETTING_CAN(name, attrib, type, ...)			type name;
		#define SETTING_RSRV(...)								// не используется
		#define SETTING_NAME(...)								// не используется
			#include SRC_SETTINGS
	} __attribute__((packed));
	#undef SETTING
	#undef SETTING_RSRV
	#undef SETTING_ALIAS
	#undef SETTING_CAN
	#undef SETTING_NAME

// объявляем номера настроек. этот enum может расти только вниз!
	enum TSettingsID : uint16_t
	{
		#define SETTING(name, ...)		name,
		#define SETTING_RSRV(name)		name,
		#define SETTING_ALIAS(name)		name,
		#include "SettingsTable.h"		// настройки ядра

		CanSettingsStart = 0x600,		// отсюда начинаются настройки CAN-прошивки (ПРИЧЕМ, самой 0x600 не может быть!!! т.к. это enum)

		#define SETTING(name, ...)		// не используется
		#define SETTING_RSRV(name)		name,
		#define SETTING_CAN(name,...)	name,
		#define SETTING_NAME(...)		// не используется
		#include SRC_SETTINGS			// собственные настройки CAN-прошивки

		LastVal = 0x7FF				// последний параметр
	};
	#undef SETTING
	#undef SETTING_RSRV
	#undef SETTING_ALIAS
	#undef SETTING_CAN
	#undef SETTING_NAME


// значения по умолчанию
	enum DefaultValues {
		minTimeZone = -9,		// значение <-9> из-за ограничения при ручной установке пояса с брелока
		defTimeZone = 0,
		maxTimeZone = 12,
		defClockSyncMode = 2,
		maxClockSyncMode = 2,
		defTimeZoneSyncMode = 2,
		maxTimeZoneSyncMode = 2,

		defLightsAutoStartMode = 2,
		maxLightsAutoStartMode = 2,
		defIlluminationMode = 0,
		maxIlluminationMode = 3,

		defLockByDriveMode = 0,
		maxLockByDriveMode = 3,
		defUnlockByParkMode = 0,
		maxUnlockByParkMode = 2,

		defArmReturnTimeIndex = 0,
		minPlafondAlarmDelay = 1,
		defPlafondAlarmDelay = 20,//60,
		maxPlafondAlarmDelay = 120,
		minDoorsLampDeciseconds = 0,
		defDoorsLampDeciseconds = 30,
		maxDoorsLampDeciseconds = 100,
		minTrunkLampDeciseconds = 0,
		defTrunkLampDeciseconds = 30,
		maxTrunkLampDeciseconds = 100,

		minAlarmDoorsDeciseconds = 0,
		defAlarmDoorsDeciseconds = 5,		// 0.5сек по умолчанию
		maxAlarmDoorsDeciseconds = 50,		// 5сек максимум
		minAlarmTrunkDeciseconds = 0,
		defAlarmTrunkDeciseconds = 5,		// 0.5сек по умолчанию
		maxAlarmTrunkDeciseconds = 100,		// 10сек максимум
		minKillEngineDeciseconds = 10,		// 1.0сек минимум
		defKillEngineDeciseconds = 0x80,	// по умолчанию, выключено
		maxKillEngineDeciseconds = 127,		// 12.7сек максимум

		defTurboTimerIndex = 0,
		minReadyMinutes = 1,
		defReadyMinutes = 2,
		maxReadyMinutes = 8,
		minSupportMinutes = 10,
		defSupportMinutes = 20,
		maxSupportMinutes = 60,
		defPitStopTimeIndex = 1,
		minPreHeaterMinutes = 1,
		defPreHeaterMinutes = 10,
		maxPreHeaterMinutes = 60,
		defSetReadyMode = 0,
		maxSetReadyMode = 2,
		minManualAttempts = 1,
		defManualAttempts = 1,
		maxManualAttempts = 3,
		defClrReadyMode = 0,
		maxClrReadyMode = 1,
		defPrestartSSB = 0,
		maxPrestartSSB = 3,
		defStopSSB = 0,
		maxStopSSB = 3,
		minCrankDelaySeconds = 1,
		defCrankDelaySeconds = 3,
		maxCrankDelaySeconds = 20,
		minAutoStartBatteryLevel = 108,
		defAutoStartBatteryLevel = 110|0x80,	// выключено по-умолчанию
		maxAutoStartBatteryLevel = 126,
		minAutoStartTemperature = -30,
		defAutoStartTemperature = 0-128,		// выключена по-умолчанию
		maxAutoStartTemperature = 60,
		defDailyRunCountIndex = 0,
		defAutomaticsPeriodIndex = 0,
		defAutomaticsLimitIndex = 0,
		minEngineStartPercent = 40/2,
		defEngineStartPercent = 70/2,
		maxEngineStartPercent = 100/2,
		minEngineRunPercent = 30/2,
		defEngineRunPercent = 60/2,
		maxEngineRunPercent = 80/2,
		minTurboTimerPercent = 150/2,
		defTurboTimerPercent = 300/2,
		maxTurboTimerPercent = 350/2,

		minExternalHeatersTemperature = -20,
		defExternalHeatersTemperature = 0-128,	// выключена по-умолчанию
		maxExternalHeatersTemperature = 20,

		maxExternalTemperatureSensorType = 1,

		defEmergencyBraking = 2,
		maxEmergencyBraking = 2,

		maxShockSensTable = 1,

		minWaitAnswerTimeout = 5,
		defWaitAnswerTimeout = 20,
		maxWaitAnswerTimeout = 60,
		minCallEndTimeout = 5,
		defCallEndTimeout = 10,
		maxCallEndTimeout = 60,
		minTripEndTimeout = 5,
		defTripEndTimeout = 15,
		maxTripEndTimeout = 60,
		minLowBatteryVoltage = 110,
		defLowBatteryVoltage = 118,
		maxLowBatteryVoltage = 125,
	};

private:

// заголовок таблицы настроек
	struct THeader
	{
		uint16_t	ID		:11;	// идентификатор. Erase=0x000; Core=[0x001..0x5FF]; CanFw=[0x601..0x7FE]; LastVal=0x7FF
		uint16_t	Kind	: 5;	// тип данных, см. SettingKind
		uint8_t		Fixed	: 1;
		uint8_t		Len		: 7;	// длина с учётом заголовка
//		uint8_t		Data[0];

		bool operator == (const THeader & Header) const		// fixed не проверяется!
//		{	return (ID == Header.ID) && (Kind == Header.Kind) && (Len == Header.Len);	}
//		{	return (*(uint16_t*)this == *(uint16_t*)&Header) && (Len == Header.Len);	}
		{	return (*(uint16_t*)this == *(uint16_t*)&Header);	}	// и длина не проверяется!
	} __attribute__ ((packed));	// sizeof() = 3

	enum {
		minRecordSize	= sizeof(THeader)+1,
		maxRecordSize	= sizeof(THeader)+124		// 127 = 3+124 - самый максимум, т.к. Len = 7 бит.
	};

	// список допустимых типов данных.
	// важно! при добавлении новых необходимо расширять список!
	enum SettingKind	// 0..31
	{
		kind_bit_t,
		kind_uint8_t,
		kind_uint16_t,
		kind_uint32_t,
		kind_int8_t,
		kind_int16_t,
		kind_int32_t,
		kind_array_t,
		kind_TInputPinSettings = kind_array_t,
		kind_TInputSettings = kind_array_t,
		kind_TSequence = kind_array_t,
		kind_TCanOutMask = kind_array_t,
		kind_uint64_t = kind_array_t,
		kind_TKeyAES = kind_array_t,
		kind_TVehicleID = kind_array_t,
		kind_TStartTimerSetting = kind_array_t,
		kind_TImmoKey = kind_array_t,
		kind_TPhoneNumber = kind_array_t,
		kind_TModemAPN = kind_array_t,
		kind_TModemLogin = kind_array_t,
		kind_TModemPassword = kind_array_t,
		kind_TTagRSSI = kind_array_t,

		kind_SettingName = 0x1F		// спецзначение - указатель на описание настройки в CAN-прошивке
	};

	enum SettingAttr
	{
		NotFixed = 0,
		Fixed = 1,
	};

// Подбор ближайшего множителя к указанным милисекундам: MUL = ((2^p - 1)*2^5) + m*2^p = 2^(p+5) - 2^5 + m*2^p = (m + 2^5)*2^p - 2^5
	static constexpr uint8_t qMS(int ms, int p = 0)
	{	return ms < ((127<<p)-64)/2 ? p*32+((2*ms+64-(63<<p))>>(p+1)) : p < 7 ? qMS(ms, p+1) : 0xFF; }


public:

	// таблица с настройками CAN-прошивки
	struct TCANSettingsTable
	{
	#define SETTING(name, attr, type, ...)	\
		THeader hdr_ ## name;	type name;
	#define SETTING_CAN(name, attr, type, ...)	\
		THeader hdr_ ## name;	type name;

	#define SETTING_RSRV(...)								// не используется
	#define SETTING_NAME(name,string)	\
		THeader hdr_ ## name ## Str;	const char * p ## name ## Str;

			#include SRC_SETTINGS

	#undef SETTING
	#undef SETTING_RSRV
	#undef SETTING_ALIAS
	#undef SETTING_CAN
	#undef SETTING_NAME

		uint16_t last_val;
	} __attribute__ ((packed));

// таблица с настройками CAN-прошивки
	static const TCANSettingsTable CanSettingsTable;

// таблица с названиями полей CAN-прошивки
	static const char * const CanSettingsName[];

};

#endif // COMMON_SETTINGS_H_
