汎用共通関数

  • 表示値計算
  • 通信結果管理.c
  • 通信結果管理.h
  • C言語_フォーマッター
#include "010.h"

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#include "gtypes.h"

#define DM_COM_MOD_NONE ((GInt64)0x7FFFFFFFFFFFFFFF)

enum {
	_M_,  // メートル法
	_Y_,  // ヤードポンド法
};

typedef struct CalcValue {
	GInt64 uwValue;      // 値
	GInt64 uwValueMult;  // 値に対する縮率
} CalcValue;

/// @brief 表示値計算用テーブル
/// @param RawValue				入力値
/// @param stResolution			分解脳
/// @param dOffset				オフセット
/// @param stCoefficient		単位変換係数
/// @param dCoefficientOffset	単位変換係数オフセット
/// @param dMod					MOD
/// @param ubDigitMetricInt		メートル法 整数桁
/// @param ubDigitMetricDec		メートル法 小数桁
/// @param stMinMetric			メートル法 最小値
/// @param stMaxMetric			メートル法 最大値
/// @param ubDigitYardInt		ヤードポンド法 整数桁0
/// @param ubDigitYardDec		ヤードポンド法 小数桁
/// @param stMinYard			ヤードポンド法 最小値
/// @param stMaxYard			ヤードポンド法 最大値
typedef struct test {
	GInt64 RawValue;            // 入力値
	CalcValue stResolution;     // 分解脳
	GInt64 dOffset;             // オフセット
	CalcValue stCoefficient;    // 単位変換係数
	GInt64 dCoefficientOffset;  // 単位変換係数オフセット
	GInt64 dMod;                // MOD
	GInt32 ubDigitMetricInt;    // メートル法 整数桁
	GInt32 ubDigitMetricDec;    // メートル法 小数桁
	CalcValue stMinMetric;      // メートル法 最小値
	CalcValue stMaxMetric;      // メートル法 最大値
	GInt32 ubDigitYardInt;      // ヤードポンド法 整数桁
	GInt32 ubDigitYardDec;      // ヤードポンド法 小数桁
	CalcValue stMinYard;        // ヤードポンド法 最小値
	CalcValue stMaxYard;        // ヤードポンド法 最大値
} test;

char* getMode(int type);

static const test pTableList[] = {
    {0x127B4, {5, 10}, 0, {2642, 10000}, 0, DM_COM_MOD_NONE, 5, 1, {0, 10}, {999999, 10}, 4, 2, {0, 100}, {999999, 100}},
    {0x126FE, {50, 100}, -3050, {2642, 10000}, 3200, DM_COM_MOD_NONE, 5, 1, {0, 10}, {999999, 10}, 4, 2, {0, 100}, {999999, 100}},
    {0x00, {1, 1}, -40, {18, 10}, 32, DM_COM_MOD_NONE, 3, 0, {-40, 1}, {210, 1}, 3, 0, {-40, 1}, {410, 1}},
    {0xFA, {1, 1}, -40, {18, 10}, 32, DM_COM_MOD_NONE, 3, 0, {-40, 1}, {210, 1}, 3, 0, {-40, 1}, {410, 1}},
    {0x01, {5, 10}, -305, {18, 10}, 320, DM_COM_MOD_NONE, 2, 1, {-300, 10}, {500, 10}, 2, 1, {-220, 10}, {1220, 10}},
    {0xA1, {5, 10}, -305, {18, 10}, 320, DM_COM_MOD_NONE, 2, 1, {-300, 10}, {500, 10}, 2, 1, {-220, 10}, {1220, 10}},
    {35, {50, 100}, 0, {1, 1}, 0, DM_COM_MOD_NONE, 5, 1, {0, 10}, {999999, 10}, 5, 1, {0, 10}, {999999, 10}},
    {-35, {5, 10}, 0, {1, 1}, 0, DM_COM_MOD_NONE, 5, 1, {-999999, 10}, {999999, 10}, 5, 1, {-999999, 10}, {999999, 10}},
    // {0x00000000, {1, 1000}, 500, {1, 1}, 0, DM_COM_MOD_NONE, 2, 3, {500, 1000}, {99999, 1000}, 2, 3, {500, 1000}, {99999, 1000}},
    // {0x000184AB, {1, 1000}, 500, {1, 1}, 0, DM_COM_MOD_NONE, 2, 3, {500, 1000}, {99999, 1000}, 2, 3, {500, 1000}, {99999, 1000}},
    {0x3780, {78125, 10000000}, -2000000000, {1, 1}, 0, DM_COM_MOD_NONE, 2, 1, {-890, 10}, {890, 1000}, 2, 1, {-890, 10}, {890, 10}},
    {0x9080, {78125, 10000000}, -2000000000, {1, 1}, 0, DM_COM_MOD_NONE, 2, 1, {-890, 10}, {890, 1000}, 2, 1, {-890, 10}, {890, 10}},
    {0x9059, {78125, 10000000}, -2000000000, {1, 1}, 0, DM_COM_MOD_NONE, 2, 1, {-890, 10}, {890, 1000}, 2, 1, {-890, 10}, {890, 10}},
    {0x9059, {78125, 10000000}, -2000000000, {1, 1}, 0, DM_COM_MOD_NONE, 2, 1, {-890, 10}, {890, 1000}, 2, 1, {-890, 10}, {890, 10}},
    // {0xFF, {5, 10}, 0, {1, 1}, 0, DM_COM_MOD_NONE, 5, 1, {0, 10}, {999999, 10}, 5, 1, {0, 10}, {999999, 10}},
    // {0xFF, {50, 100}, 0, {1, 1}, 0, DM_COM_MOD_NONE, 5, 1, {0, 10}, {999999, 10}, 5, 1, {0, 10}, {999999, 10}},
    // {0xFF, {5, 100}, 0, {1, 1}, 0, DM_COM_MOD_NONE, 5, 1, {0, 10}, {999999, 10}, 5, 1, {0, 10}, {999999, 10}},
};

static const GInt64 pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};

GInt32 type = _Y_;
GInt64 g_ValueScaled[sizeof(pTableList) / sizeof(pTableList[0])];

int main(void) {
	// type = _M_;
	// 生値→表示値変換
	printf("-------------- %s --------------\n", getMode(type));
	GUInt32 i;

	for (i = 0; i < sizeof(pTableList) / sizeof(pTableList[0]); i++) {
		const test* pTbl = &pTableList[i];

		GInt32 uwDispInt; /* 表示用の整数部 */
		GInt32 uwDispDec; /* 表示用の小数部 */

		GInt8 ubdispInt;  /* 表示整数桁数 */
		GInt8 ubdispDec;  /* 表示小数桁数 */
		GInt64 dMinValue; /* 表示可能最小値(内部スケール変換後) */
		GInt64 dMaxValue; /* 表示可能最大値(内部スケール変換後) */

		GInt64 calcValue; /* 計算結果(内部スケール値) */
		GInt64 decScale;  /* 内部スケール倍率 */
		GInt64 powValue;  /* 小数部抽出用の倍率(10,100,1000...) */

		if (type == _Y_) {
			/* 表示桁数設定 */
			ubdispInt = pTbl->ubDigitYardInt;
			ubdispDec = pTbl->ubDigitYardDec;

		} else {
			/* 表示桁数設定 */
			ubdispInt = pTbl->ubDigitMetricInt;
			ubdispDec = pTbl->ubDigitMetricDec;
		}

		/* 出力: No.番号 */
		printf("No.%03u => ", i + 1);

		/* 表示小数桁数に対応する10の累乗値を取得 */
		powValue = pow10[ubdispDec];

		if (type == _Y_) {
			/* ヤードポンド法の内部スケール値を設定 */
			decScale = pTbl->stResolution.uwValueMult * pTbl->stCoefficient.uwValueMult / powValue;

			/* ((RawValue × 分解能) + stOffset) × 単位変換係数 + 単位変換係数オフセット を計算 */
			calcValue = ((pTbl->RawValue * pTbl->stResolution.uwValue) + pTbl->dOffset) * pTbl->stCoefficient.uwValue + (pTbl->dCoefficientOffset * pTbl->stCoefficient.uwValueMult);
			printf("%10ld = ((%6ld * %ld) + %ld) * %ld + (%ld * %ld) ", calcValue, pTbl->RawValue, pTbl->stResolution.uwValue, pTbl->dOffset, pTbl->stCoefficient.uwValue, pTbl->dCoefficientOffset, pTbl->stCoefficient.uwValueMult);

			/* 最大値・最小値を内部スケール値へ変換 */
			dMinValue = pTbl->stMinYard.uwValue * decScale;
			dMaxValue = pTbl->stMaxYard.uwValue * decScale;
			// dMinValue = pTbl->stMinYard.uwValue;
			// dMaxValue = pTbl->stMaxYard.uwValue;
		} else {
			/* メートル法の内部スケール値を設定 */
			decScale = pTbl->stResolution.uwValueMult / powValue;

			/* (RawValue × 分解能) + stOffset を内部スケールで計算 */
			calcValue = (pTbl->RawValue * pTbl->stResolution.uwValue) + pTbl->dOffset;
			printf("%10ld = (%6ld * %ld) + (%ld)) ", calcValue, pTbl->RawValue, pTbl->stResolution.uwValue, pTbl->dOffset);

			/* 最大値・最小値を内部スケール値へ変換 */
			dMinValue = pTbl->stMinMetric.uwValue * decScale;
			dMaxValue = pTbl->stMaxMetric.uwValue * decScale;
			// dMinValue = pTbl->stMinMetric.uwValue;
			// dMaxValue = pTbl->stMaxMetric.uwValue;
		}

		if (decScale <= 0) {
			return 0;
		}

		/* 不要な桁切り捨て */
		// calcValue = (calcValue / decScale) * decScale;
		calcValue = calcValue / decScale;

		/* 表示値に対するMOD値を内部スケールへ変換 */
		if (pTbl->dMod != DM_COM_MOD_NONE) {
			// calcValue = calcValue % (pTbl->dMod * (decScale * powValue));
			calcValue = calcValue % pTbl->dMod;
		}

		/* 下限丸め込み */
		if (calcValue < dMinValue) {
			calcValue = dMinValue;
		}

		/* 上限丸め込み */
		if (calcValue > dMaxValue) {
			calcValue = dMaxValue;
		}

		/* 整数部を取得 */
		// uwDispInt = (GInt32)(calcValue / (decScale * powValue));
		uwDispInt = (GInt32)(calcValue / powValue);

		/* 小数部を取り出して表示桁数へ変換 */
		// uwDispDec = llabs((GInt32)(calcValue % (decScale * powValue) / decScale));
		uwDispDec = llabs((GInt32)(calcValue % powValue));

		/* 出力: 表示用値 */
		printf("Ret = %ld, ", calcValue);
		printf(" << 表示値 = %d.%0*d >> ", uwDispInt, ubdispDec, uwDispDec);
		printf("Scale = %ld, ", decScale);
		printf("powValue = %ld, ", powValue);
		printf("MIN = %ld, ", dMinValue);
		printf("MAX = %ld, ", dMaxValue);
		// printf("\n          ");
		printf("Int = %d, ", ubdispInt);
		printf("Dec = %d, ", ubdispDec);
		printf("\n");

		/* 表示値→生値変換で使用するため保存 */
		g_ValueScaled[i] = calcValue;
	}

	// 表示値→生値変換
	printf("-----------------------------\n");

	for (i = 0; i < sizeof(pTableList) / sizeof(pTableList[0]); i++) {
		const test* pTbl = &pTableList[i]; /* 対象テーブル */
		GInt64 displayValueScaled;         /* 表示値(内部スケール値) */
		GInt64 rawValue;                   /* 算出した生値 */
		GInt64 decScale;                   /* 内部スケール倍率 */
		GInt64 powValue;                   /* 小数部抽出用の倍率(10,100,1000...) */
		GInt8 ubdispDec;                   /* 表示小数桁数 */

		/* 生値→表示値変換で算出した表示値を取得 */
		displayValueScaled = g_ValueScaled[i];

		printf("No.%03u => ", i + 1);
		printf("表示値(整数スケール)= %6lld, ", (long long)displayValueScaled);

		if (type == _Y_) {
			/* 表示桁数設定 */
			ubdispDec = pTbl->ubDigitYardDec;
		} else {
			/* 表示桁数設定 */
			ubdispDec = pTbl->ubDigitMetricDec;
		}
		/* 表示小数桁数に対応する10の累乗値を取得 */
		powValue = pow10[ubdispDec];

		if (type == _Y_) {
			/* ヤードポンド法の内部スケール値を設定 */
			decScale = pTbl->stResolution.uwValueMult * pTbl->stCoefficient.uwValueMult / powValue;
			displayValueScaled *= decScale;

			/* 保存した表示値(内部スケール値)を使用 */
			rawValue = (((displayValueScaled - (pTbl->dCoefficientOffset * pTbl->stCoefficient.uwValueMult)) / pTbl->stCoefficient.uwValue) - pTbl->dOffset) / pTbl->stResolution.uwValue;

		} else {
			/* メートル法の内部スケール値を設定 */
			decScale = pTbl->stResolution.uwValueMult / powValue;
			displayValueScaled *= decScale;

			/* 保存した表示値(内部スケール値)を使用 */
			rawValue = (displayValueScaled - pTbl->dOffset) / pTbl->stResolution.uwValue;
		}
		printf("変換後 = %6lld /=/ %6lld = 元データ, ", (long long)rawValue, (long long)pTbl->RawValue);
		printf("powValue = %2ld, ", powValue);
		printf("decScale = %ld, \n", decScale);
	}
	return 0;
}

char* getMode(int type) {
	switch (type) {
		case _M_:
			return "メートル法";
			break;

		case _Y_:
			return "ヤード・ポンド法";
			break;

		default:
			break;
	}
	return "UNKNOWN";
}

/******************************************************************************
 * Includes
 ******************************************************************************/
#include "011.h"

#include "guillity.h"

/******************************************************************************
 * Local Functions
 ******************************************************************************/
static GInt32 IsSaveTypeValid(SaveType_t type) { return (type > SAVE_TYPE_NONE) && (type < SAVE_TYPE_NUM); }

/******************************************************************************
 * Global Functions
 ******************************************************************************/

/********************************************
 * @brief 通信状態を初期化
 * @param[out] pState 通信状態
 ********************************************/
void SaveState_Init(SaveState_t* pState) {
	GInt32 index;

	if (pState == NULL) {
		return;
	}

	for (index = 0; index < SAVE_TYPE_NUM; index++) {
		pState->active[index] = INACTIVE;
		pState->result[index] = SAVE_RESULT_NONE;
	}
}

/********************************************
 * @brief 使用する通信種別を有効化
 * @param[out] pState 通信状態
 * @param[in] type 通信種別
 ********************************************/
void SaveState_EnableType(SaveState_t* pState, SaveType_t type) {
	if ((pState == NULL) || !IsSaveTypeValid(type)) {
		return;
	}

	pState->active[type] = ACTIVE;
	pState->result[type] = SAVE_RESULT_NONE;
}

/********************************************
 * @brief 使用しない通信種別を無効化
 * @param[out] pState 通信状態
 * @param[in] type 通信種別
 ********************************************/
void SaveState_DisableType(SaveState_t* pState, SaveType_t type) {
	if ((pState == NULL) || !IsSaveTypeValid(type)) {
		return;
	}

	pState->active[type] = INACTIVE;
	pState->result[type] = SAVE_RESULT_NONE;
}

/********************************************
 * @brief 通信結果を設定
 * @param[out] pState 通信状態
 * @param[in] type 通信種別
 * @param[in] result 通信結果
 ********************************************/
GInt32 SaveState_SetResult(SaveState_t* pState, SaveType_t type, SaveResult_t result) {
	if ((pState == NULL) || !IsSaveTypeValid(type)) {
		return SAVE_RESULT_NONE;
	}

	if (pState->active[type] == INACTIVE) {
		return SAVE_RESULT_NONE;
	}

	pState->result[type] = result;
	return pState->result[type];
}

/********************************************
 * @brief 通信結果を集約し判定
 * @param[in] pState 通信状態
 * @retval STATE_SAVE_RESULT_FAILURE
 *         1つ以上失敗あり
 * @retval STATE_SAVE_RESULT_ALL_SUCCESS
 *         使用した通信が全て成功
 * @retval STATE_SAVE_RESULT_NONE
 *         判定保留
 ********************************************/
StateSaveResult_t GetSaveStateResult(const SaveState_t* pState) {
	GInt32 useCount = 0;
	GInt32 index;

	if (pState == NULL) {
		return STATE_SAVE_RESULT_NONE;
	}

	for (index = SAVE_TYPE_SYNC; index < SAVE_TYPE_NUM; index++) {
		if (pState->active[index] == INACTIVE) {
			continue;
		}

		useCount++;

		if (pState->result[index] == SAVE_RESULT_FAILURE) {
			return STATE_SAVE_RESULT_FAILURE;
		}

		if (pState->result[index] == SAVE_RESULT_NONE) {
			return STATE_SAVE_RESULT_NONE;
		}
	}

	if (useCount > 0) {
		return STATE_SAVE_RESULT_ALL_SUCCESS;
	}

	return STATE_SAVE_RESULT_NONE;
}
#ifndef _011_H_
#define _011_H_

#include <stddef.h>

#include "gtypes.h"

#ifdef __cplusplus
extern "C" {
#endif

/* 通信種別 */
typedef enum {
	SAVE_TYPE_NONE = 0,  // なし
	SAVE_TYPE_SYNC,      // 定期通信
	SAVE_TYPE_ASYNC,     // 不定期通信
	SAVE_TYPE_STORAGE,   // ストレージ
	SAVE_TYPE_NUM,       // 通信種別数
} SaveType_t;

/* 通信結果(個別) */
typedef enum {
	SAVE_RESULT_NONE = 0,  // なし:通信結果(個別)
	SAVE_RESULT_SUCCESS,   // 成功:通信結果(個別)
	SAVE_RESULT_FAILURE,   // 失敗:通信結果(個別)
} SaveResult_t;

/* 通信結果(全体) */
typedef enum {
	STATE_SAVE_RESULT_NONE = 0,     // なし:通信結果(全体)
	STATE_SAVE_RESULT_ALL_SUCCESS,  // 成功:通信結果(全体)
	STATE_SAVE_RESULT_FAILURE,      // 失敗:通信結果(全体)
} StateSaveResult_t;

/* 使用有無 */
enum {
	INACTIVE = 0,  // 非アクティブ
	ACTIVE,        // アクティブ
};

/* 通信状態管理 */
typedef struct {
	SaveResult_t result[SAVE_TYPE_NUM];  // 通信結果(個別)
	GUInt8 active[SAVE_TYPE_NUM];        // 使用有無(個別)
} SaveState_t;

void SaveState_Init(SaveState_t* pState);
void SaveState_EnableType(SaveState_t* pState, SaveType_t type);
void SaveState_DisableType(SaveState_t* pState, SaveType_t type);
GInt32 SaveState_SetResult(SaveState_t* pState, SaveType_t type, SaveResult_t result);
StateSaveResult_t GetSaveStateResult(const SaveState_t* pState);

#ifdef __cplusplus
}
#endif

#endif
タイトルとURLをコピーしました