/** ****************************************************************************** * 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; }