/**
******************************************************************************
* File Name : temp.c
* Description : This file provides code for the measument of voltage
and current.
******************************************************************************
* @attention
*
*
© Copyright (c) 2019 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "temp.h"
#include "adc.h"
#include "asutil.h"
#include "device_param.h"
#include "delay.h"
#include
/* Private typedef -----------------------------------------------------------*/
typedef struct
{
s16 Value;
s16 AdValue;
// PARAMETER Information
s16 HighParam; // Temperature parameter referenced only in AD[4](Unify-Temp)
s16 HighCParam;
s16 LowParam;
s16 LowCParam;
s16 FailParam;
s16 FailCParam;
u8 Enabled; // Enabled/Disabled
u8 Failed; // Fail/Noraml
u8 State; // Normal, High(Wet), Low, NotUsed (0/1/2/3)
u8 Changed; // notchanged, NormToHigh, HighToNorm, NormToLow, LowToNorm, NotUsed->Used, Used->NotUsed, Normal->Failed, Failed->Normal
} TAnalogrec, *PAnalogrec;
typedef struct
{
s16 temp;
u16 vref;
u16 vbat;
u16 reserved;
} TCPUStatus, *PCPUStatus;
/* Private define ------------------------------------------------------------*/
#define TEMP_TASK_TIME 50 // 100ms TASK
#define AD_TEMP_CH_MAX 10
#define TEMP_CH_MAX 8
#define T1_TEMP_ID 0
#define T2_TEMP_ID 1
#define T3_TEMP_ID 2
#define T4_TEMP_ID 3
#define T5_TEMP_ID 4
#define T6_TEMP_ID 5
#define T7_TEMP_ID 6
#define T8_TEMP_ID 7
#define CPU_TEMP_ID 8
#define CPU_VREF_ID 9
#define CPU_VBAT_ID 10
#define TEMP_BUF_MAX 10
// Temperature alarm flag define
#define cFahr 0x00
#define cCent 0x01
#define cHighOccur 0x01 // Normal -> High(Wet)
#define cLowOccur 0x02 // Normal -> Low
#define cNotUsed 0x03 // Disabled
#define cNotChanged 0x00 // No change
#define cNormToHigh 0x11 // Normal -> High(Wet)
#define cHighToNorm 0x12 // High(Wet) -> Normal
#define cNormToLow 0x13 // Normal -> Low
#define cLowToNorm 0x14 // Low -> Normal
#define cNotToUsed 0x15 // NotUsed->Used
#define cUsedToNot 0x16 // Used->NotUsed
#define cFailToNorm 0x17 // Fail->Normal
#define cNormToFail 0x18 // Normal->Fail
#define cNormalOpen 0
#define cNormalClose 1
#define cNORMAL 0
#define cINITVALUE 0xff
#define cOCCUR 1
#define cUNKNOWN 2
#define cDISABLE 3
#define cCANCEL 0
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
// CPU Status
TCPUStatus CPUStatus, disCPUStatus;
// ADC Buffer
u16 AdData[AD_TEMP_CH_MAX][TEMP_BUF_MAX];
u16 AdCh = 0;
// Temperature Buffer
TAnalogrec TD[TEMP_CH_MAX];
TAnalogrec DisTD[TEMP_CH_MAX];
u8 TempUnit, BakTempUnit;
void InitAD(u8 ch);
void ADC_Data_Process(void);
s16 GetTemperature(u8 ch);
/*
*********************************************************************************************************
* App_TaskAdc Init
*
* Description : ADC TASK INIT
*
*********************************************************************************************************
*/
void AdcInit(void)
{
// ADC initialization
// ADC Clock frequency: 115.200 kHz
// ADC Voltage Reference: Vref Pin
// ADC High Speed Mode: On
memset(AdData, 0x00, sizeof(AdData));
memset(TD , 0x00, sizeof(TAnalogrec) * TEMP_CH_MAX);
ADC_Param_Load();
TempUnit = cCent;
for (int i = 0; i < TEMP_CH_MAX; i++)
InitAD(i);
}
/*
*********************************************************************************************************
* App_TaskAdc
*
* Description : ADC TASK
*
*********************************************************************************************************
*/
void AppTaskTempAdc(void)
{
AdcInit();
for (;;)
{
ADC_Data_Process();
ADC_Process();
delay_os_ms(TEMP_TASK_TIME);
}
}
/*
*********************************************************************************************************
* Function for App_TaskAdc
*
* Description : ADC TASK
*
*********************************************************************************************************
*/
void InitAD(u8 ch)
{
for (int i = 0; i < 20; i++)
{
TD[ch].Value = GetTemperature(ch);
}
TD[ch].Enabled = true;
TD[ch].Failed = false;
TD[ch].State = cNORMAL;
TD[ch].Changed = cNotChanged;
}
void ADC_Data_Process(void)
{
u32 sum;
double temp;
for (int i = 0; i < AD_TEMP_CH_MAX; i++)
{
sum = AvgAdc1DmaValue(i);
AdData[i][AdCh] = (u16)((sum * ADC_VBASE) / 0xFFF);
if (i == CPU_TEMP_ID)
{
temp = AdData[i][AdCh];
temp = ((temp - V25)/ AVG_SLOPE) + 25.0 + 80.0;
AdData[i][AdCh] = (u16)(temp * 10);
}
}
AdCh++;
AdCh %= TEMP_BUF_MAX;
// BMCU B'D Temp
sum = 0;
for (int i = 0; i < TEMP_BUF_MAX; i++)
sum += AdData[CPU_TEMP_ID][i];
CPUStatus.temp = sum / TEMP_BUF_MAX;
// BMCU B'D Vref
sum = 0;
for (int i = 0; i < TEMP_BUF_MAX; i++)
sum += AdData[CPU_VREF_ID][i];
CPUStatus.vref = sum / TEMP_BUF_MAX;
// BMCU B'D Vbat
sum = 0;
for (int i = 0; i < TEMP_BUF_MAX; i++)
sum += AdData[CPU_VBAT_ID][i];
CPUStatus.vbat = sum / (TEMP_BUF_MAX / 2);
}
s16 CalcTemperatureST32(u16 volt)
{
s16 cvolt;
double imsi;
double xx[6];
double flt;
cvolt = volt;
imsi = (double)cvolt / 1000;
xx[5] = imsi * imsi * imsi * imsi * imsi;
xx[4] = imsi * imsi * imsi * imsi;
xx[3] = imsi * imsi * imsi;
xx[2] = imsi * imsi;
xx[1] = imsi;
flt = (135.6 * xx[5]) -
(578.9 * xx[4]) +
(960.5 * xx[3]) -
(761.3 * xx[2]) +
(354.7 * xx[1]) -
46.39;
return(s16)(flt * 10);
}
s16 GetTemperature(u8 ch)
{
s32 tsum = 0;
for (int i = 0; i < TEMP_BUF_MAX; i++)
{
tsum += CalcTemperatureST32(AdData[ch][i]);
}
return (s16)(tsum / TEMP_BUF_MAX);
}
void ADC_Param_Load(void)
{
for (int i = 0; i < TEMP_CH_MAX; i++)
{
TD[i].HighParam = device_param.safety.temperature.OT_Chg_Warning;
TD[i].HighCParam = device_param.safety.temperature.OT_Chg_Recovery;
TD[i].LowParam = device_param.safety.temperature.LT_Chg_Warning;
TD[i].LowCParam = device_param.safety.temperature.LT_Chg_Recovery;
TD[i].FailParam = device_param.safety.temperature.Open_Thermistor;
TD[i].FailCParam = device_param.safety.temperature.Recovery_Thermistor;
}
}
u8 Check_Analog(u8 ch)
{
s16 aValue, ret, aHighOccur, aHighCancel, aLowOccur, aLowCancel;
switch (ch)
{
case T1_TEMP_ID:
case T2_TEMP_ID:
case T3_TEMP_ID:
case T4_TEMP_ID:
case T5_TEMP_ID:
case T6_TEMP_ID:
case T7_TEMP_ID:
case T8_TEMP_ID:
aValue = TD[ch].Value;
aHighOccur = TD[ch].HighParam;
aHighCancel = TD[ch].HighCParam;
aLowOccur = TD[ch].LowParam;
aLowCancel = TD[ch].LowCParam;
break;
default:
return 0;
}
ret = cNotChanged; // Nothing
switch(TD[ch].State) // Past state
{
case cHighOccur: // Past: High(Wet)
if (aValue < aHighCancel) ret = cHighToNorm; // HIGH CANCEL
break;
case cLowOccur: // Past: Low
if (aValue > aLowCancel) ret = cLowToNorm; // LOW CANCEL
break;
default:
if (aValue >= aHighOccur) ret = cHighOccur; // HIGH OCCUR
else if (aValue <= aLowOccur) ret = cLowOccur; // LOW OCCUR
break;
}
return(ret);
}
void Analog_Process(u8 ch) // Read temperature/humidity and evaluate alarms
{
TD[ch].Value = GetTemperature(ch);
if(TD[ch].Enabled == true)
{
// Check sensor fail on low temperature range
if (TD[ch].Failed != true)
{
if ((TD[ch].Value < TD[ch].FailParam) || (TD[ch].Value > 1250))
{
TD[ch].State = cNORMAL;
TD[ch].Changed = cNormToFail;
TD[ch].Failed = true;
}
}
else
{
if ((TD[ch].Value > TD[ch].FailCParam) && (TD[ch].Value < 1200))
{
TD[ch].State = cNORMAL;
TD[ch].Changed = cFailToNorm;
TD[ch].Failed = false;
}
}
// Check temperature alarm
if (TD[ch].Failed == false)
{
switch (Check_Analog(ch))
{
case cHighOccur: // HIGH OCCUR
TD[ch].State = cHighOccur;
TD[ch].Changed = cNormToHigh;
break;
case cHighToNorm: // HIGH CANCEL
TD[ch].State = cNORMAL;
TD[ch].Changed = cHighToNorm;
break;
case cLowOccur: // LOW OCCUR
TD[ch].State = cLowOccur;
TD[ch].Changed = cNormToLow;
break;
case cLowToNorm: // LOW CANCEL
TD[ch].State = cNORMAL;
TD[ch].Changed = cLowToNorm;
break;
}
}
}
else
TD[ch].State = cNotUsed;
}
u16 ADState(u8 ch)
{
u16 ret = AD_DISABLE;
if (TD[ch].Enabled == true)
{
if (TD[ch].Failed == true)
{
ret = AD_FAIL;
}
else
{
switch (TD[ch].State)
{
case cHighOccur:
ret = AD_HIGH;
break;
case cLowOccur:
ret = AD_LOW;
break;
case cNORMAL :
ret = AD_NORMAL;
break;
default :
ret = AD_NORMAL;
break;
}
}
}
return ret;
}
s16 TEMP_GRADE_CONVERTOR(s16 aTempValue, u8 aGrade)
{
s16 Tf, Tc;
if (aGrade == 'F')
{
Tc = aTempValue;
Tf = (18 * Tc)/10 + 320; // Celsius to Fahrenheit
return(Tf);
}
else
{
Tf = aTempValue;
Tc = (Tf - 320)/18;
return(Tc);
}
/*
// Celsius to Fahrenheit: Tf = 9/5 * Tc + 32
// Fahrenheit to Celsius: Tc = (Tf - 32) * 5/9
*/
}
s16 ADValue(u8 ch)
{
s16 result = 0;
switch (ch)
{
case T1_TEMP_ID :
case T2_TEMP_ID :
case T3_TEMP_ID :
case T4_TEMP_ID :
case T5_TEMP_ID :
case T6_TEMP_ID :
case T7_TEMP_ID :
case T8_TEMP_ID :
if (TempUnit == cCent) result = TD[ch].Value;
else result = TEMP_GRADE_CONVERTOR(TD[ch].Value,'F');
break;
}
return result;
}
float ADValueF(u8 ch)
{
float result = 0.0;
switch (ch)
{
case T1_TEMP_ID :
case T2_TEMP_ID :
case T3_TEMP_ID :
case T4_TEMP_ID :
case T5_TEMP_ID :
case T6_TEMP_ID :
case T7_TEMP_ID :
case T8_TEMP_ID :
result = (float)TD[ch].Value / 10;
break;
}
return result;
}
void TEMPERATURE_Process(u8 ch)
{
u8 aAlarm;
aAlarm = TD[ch].State;
switch (TD[ch].Changed)
{
case cHighToNorm :
aAlarm = cNORMAL;
// ADD_RUN_HISTORY(true,osENVIR,Temp1,(char *)Temp2,mg1,35);
break;
case cLowToNorm :
aAlarm = cNORMAL;
// ADD_RUN_HISTORY(true,osENVIR,Temp1,(char *)Temp2,mg1,35);
break;
case cNormToHigh :
aAlarm = cHighOccur;
// ADD_RUN_HISTORY(true,osENVIR,Temp1,(char *)Temp2,mg1,36);
break;
case cNormToLow :
aAlarm = cLowOccur;
// ADD_RUN_HISTORY(true,osENVIR,Temp1,(char *)Temp2,mg1,37);
break;
case cNormToFail :
aAlarm = cNORMAL;
// ADD_RUN_HISTORY(true,osENVIR,Temp1,(char *)Temp2,mg1,38);
break;
case cFailToNorm :
aAlarm = cNORMAL;
// ADD_RUN_HISTORY(true,osENVIR,Temp1,(char *)Temp2,mg1,35);
break;
}
if (TD[ch].Enabled != true)
aAlarm = cNORMAL;
TD[ch].State = aAlarm;
}
void Analog_Event_Process(u8 ch)
{
switch (ch)
{
case T1_TEMP_ID:
case T2_TEMP_ID:
case T3_TEMP_ID:
case T4_TEMP_ID:
case T5_TEMP_ID:
case T6_TEMP_ID:
case T7_TEMP_ID:
case T8_TEMP_ID:
TEMPERATURE_Process(ch);
break;
}
}
void CalcAvgTemperature(void)
{
u32 sum;
TMinMax min, max;
sum = 0;
max.value = 0;
max.num = 0;
min.value = 0;
min.num = 0;
int j = 0;
for (int i = 0; i < (TEMP_CH_MAX - 2); i++)
{
if (TD[i].Failed == false)
{
if (j == 0)
{
max.value = ADValue(i);
max.num = i;
min.value = ADValue(i);
min.num = i;
}
if (max.value < ADValue(i))
{
max.value = ADValue(i);
max.num = i;
}
if (min.value > ADValue(i))
{
min.value = ADValue(i);
min.num = i;
}
sum += ADValue(i);
j++;
}
}
if (j == 0)
device_value.Temp.avg.avg = 0;
else
device_value.Temp.avg.avg = sum / j;
device_value.Temp.avg.Max.value = max.value;
device_value.Temp.avg.Max.num = max.num;
device_value.Temp.avg.Min.value = min.value;
device_value.Temp.avg.Min.num = min.value;
device_value.Temp.avg.diff = max.value - min.value;
}
void ADC_Get_Process(u8 ch)
{
TD[ch].Changed = cNotChanged; // Initialize Changed_Member
Analog_Process(ch);
Analog_Event_Process(ch);
}
void ADC_Process(void)
{
for (int i = 0; i < (TEMP_CH_MAX - 2); i++)
{
ADC_Get_Process(i);
device_value.Temp.temperature[i] = ADValue(i);
}
CalcAvgTemperature();
}
s16 GetCpuTemp(void)
{
return (s16)(CPUStatus.temp - 800);
}
#ifdef CONSOLE_DEBUG
void ODisplayAdcStatus(u8 p)
{
u16 i, x, y;
float aParam;
u8 aRedFont;
static int tcount = 0;
// TEMP DISPLAY
if (p || (tcount == 0))
{
tcount = 10;
for (i = 0; i < (TEMP_CH_MAX); i++)
{
if (p || (memcmp(&TD[i], &DisTD[i], sizeof(TAnalogrec)) != 0))
{
x = 27 + ((i / 2)* 10);
y = 18 + ((i % 2)* 2);
if ((TD[i].Enabled == true) & ((TD[i].State != cNORMAL) | (TD[i].Failed == true)))
aRedFont = DISPLAY_RED;
else
aRedFont = DISPLAY_GREEN;
if (TD[i].Failed == true)
{
aParam = (float)ADValue(i) / 10;
FloatColorOutIntXY(aRedFont, x, y, aParam, 5, 1);
if (p || (TD[i].Failed != DisTD[i].Failed))
ColorOutXY(aRedFont, x + 1, y + 1, (u8 *)"FAIL");
}
else
{
aParam = (float)ADValue(i) / 10;
FloatColorOutIntXY(aRedFont, x, y, aParam, 5, 1);
if (p || (TD[i].State != DisTD[i].State)||(TD[i].Failed != DisTD[i].Failed))
{
switch (TD[i].State)
{
case cHighOccur: ColorOutXY(aRedFont, x + 1, y + 1, (u8 *)"HIGH");
break;
case cLowOccur: ColorOutXY(aRedFont, x + 1, y + 1, (u8 *)"LOW ");
break;
case cNORMAL : ColorOutXY(aRedFont, x + 1, y + 1, (u8 *)"NORM");
break;
default : ColorOutXY(aRedFont, x + 1, y + 1, (u8 *)"????");
break;
}
}
}
memcpy(&DisTD[i], &TD[i], sizeof(TAnalogrec));
}
}
// Temp Status
if (p || (disCPUStatus.temp != CPUStatus.temp))
{
aParam = (float)(CPUStatus.temp - 800) / 10;
FloatNormalOutIntXY( 72, 21, aParam, 5, 1);
disCPUStatus.temp = CPUStatus.temp;
}
// // Temp Status
// if (p || (dis_device_value.Temp.avg.avg != device_value.Temp.avg.avg))
// {
// aParam = (float)device_value.Temp.avg.avg / 10;
// FloatNormalOutIntXY( 72, 21, aParam, 5, 1);
// dis_device_value.Temp.avg.avg = device_value.Temp.avg.avg;
// }
// // Vref Status
// if (p || (disCPUStatus.vref != CPUStatus.vref)) {
// aParam = (float)CPUStatus.vref / 1000;
// FloatNormalOutIntXY( 71, 20, aParam, 5, 3);
// disCPUStatus.vref = CPUStatus.vref;
// }
// // Vbat Status
// if (p || (disCPUStatus.vbat != CPUStatus.vbat)) {
// aParam = (float)CPUStatus.vbat / 1000;
// FloatNormalOutIntXY( 71, 21, aParam, 5, 3);
// disCPUStatus.vbat = CPUStatus.vbat;
// }
// Vbat Status
// if (p || (disCPUStatus.vbat != CPUStatus.vbat))
// {
// aParam = (float)CPUStatus.vbat / 1000;
// FloatNormalOutIntXY( 72, 21, aParam, 5, 3);
// disCPUStatus.vbat = CPUStatus.vbat;
// }
}
tcount--;
}
#endif // #ifdef CONSOLE_DEBUG
/* KT Requirement: Temperature sensor open/fault detection */
u8 IsTempSensorFailed(void)
{
for (int i = 0; i < (DEVICE_MAX_TEMP - 2); i++)
{
s16 temp = device_value.Temp.temperature[i];
// <= -35 deg C (Open/Broken) or >= 110 deg C (Short/Abnormal)
if ((temp <= -350) || (temp >= 1100) || (ADState(i) == AD_FAIL))
{
return true;
}
}
return false;
}