Files
CHJ/user/Compute/AccCompute.c
2026-03-20 21:19:04 +08:00

561 lines
16 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "../main/SystemInclude.h"
//==============================================================================
u8 Total[ACC_MAX],Dis2[20];
u64 flowTotalBuffer;
u32 lastRemaining, AccComputeTimeBase;
u16 totalPulse;
u8 MemoryPointer;
u16 flowAccCumulationRemaining, samplingIntervalForTotal;
/******************************************************************************/
void ReleaseTotalToDisArray(void)
{
Dis2[0] = Total[0] >> 4;
Dis2[1] = Total[0] & 0x0f;
Dis2[2] = Total[1] >> 4;
Dis2[3] = Total[1] & 0x0f;
Dis2[4] = Total[2] >> 4;
Dis2[5] = Total[2] & 0x0f;
Dis2[6] = Total[3] >> 4;
Dis2[7] = Total[3] & 0x0f;
Dis2[8] = Total[4] >> 4;
Dis2[9] = Total[4] & 0x0f;
Dis2[10] = Total[5] >> 4;
Dis2[11] = Total[5] & 0x0f;
Dis2[12] = Total[MIN_BIT] >> 4;
Dis2[13] = Total[MIN_BIT] & 0x0f;
}
/******************************************************************************/
void ReleaseToIntAndDecimalBuf(void)
{
u16 I;
flowTotalBuffer = 0;
for(I=0; I<=ACC_DOT6; I++)
{
flowTotalBuffer *= 10;
flowTotalBuffer += Dis2[I];
}
}
/******************************************************************************/
void ReleaseToIntAndDecimalBufForUart(void)
{
u16 I;
u16 DotStartBit;
flowAccumulationInteger = 0;
flowAccumulationDecimal = 0;
// Update V2006
DotStartBit = ACC_DOT1;
switch(AccComUnit)
{
case ML: DotStartBit = ACC_DOT4; break;
case SL:
if(FR_STD_UNIT == SCCM) DotStartBit = ACC_DOT1;
else DotStartBit = ACC_DOT4;
break;
//case NM3: DotStartBit = ACC_DOT1; break;
//case SCF: DotStartBit = ACC_DOT1; break;
//case PPM: lastUnit = (float)ONE_PPM_TO_STD_ACC; break;
//case KG: DotStartBit = ACC_DOT1; break;
default: ;
}
#ifndef ACC_INT_7BIT
#pragma message("[undefined] ACC_INT_7BIT")
#elif(ACC_INT_7BIT)
I = DotStartBit - 7;
#endif
#ifndef ACC_INT_6BIT
#pragma message("[undefined] ACC_INT_6BIT")
#elif(ACC_INT_6BIT)
I = DotStartBit - 6;
#endif
#ifndef ACC_INT_8BIT
#pragma message("[undefined] ACC_INT_8BIT")
#elif(ACC_INT_8BIT)
I = DotStartBit - 8;
#endif
//----------------------------------------------------------------------------
for(; I<DotStartBit; I++)
{
flowAccumulationInteger *= 10;
flowAccumulationInteger += Dis2[I];
}
for(I=DotStartBit; I<DotStartBit+3; I++)
{
flowAccumulationDecimal *= 10;
flowAccumulationDecimal += Dis2[I];
}
flowAccumulationHex = ( signed long long int)flowAccumulationInteger;
flowAccumulationHex *= (unsigned long long int)1000;
flowAccumulationHex += (unsigned long long int)flowAccumulationDecimal;
//----------------------------------------------------------------------------
#ifndef ENABLE_ACC_DEC_COMPUTE
#pragma message("[undefined] ENABLE_ACC_DEC_COMPUTE")
#elif(ENABLE_ACC_DEC_COMPUTE)
if(Dis2[0] != 0)
{
flowAccumulationInteger *= -1;
flowAccumulationHex *= -1;
}
#endif
}
/******************************************************************************/
void SendToTotalArray(void)
{
Total[0] = Dis2[0];
Total[0] <<= 4;
Total[0] += Dis2[1];
Total[1] = Dis2[2];
Total[1] <<= 4;
Total[1] += Dis2[3];
Total[2] = Dis2[4];
Total[2] <<= 4;
Total[2] += Dis2[5];
Total[3] = Dis2[6];
Total[3] <<= 4;
Total[3] += Dis2[7];
Total[4] = Dis2[8];
Total[4] <<= 4;
Total[4] += Dis2[9];
Total[5] = Dis2[10];
Total[5] <<= 4;
Total[5] += Dis2[11];
Total[CRC_CHK] = CRC8(Total, 6); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Total[MIN_BIT] = Dis2[12];
Total[MIN_BIT] <<= 4;
Total[MIN_BIT] += Dis2[13];
}
/******************************************************************************/
// save ACC FlowRate to memeroy
u16 FRAMWriteTotal(void)
{
// write to first bank and second bank and update EPROMPointer
// input: voltAcc, voltAcc0, EPROMPointer
// output: EPROMPointer
unsigned int blockAddr, I;
u8 temp[7], WriteCounter=0;
FRAMWriteRepeat:
MemoryPointer++;
WriteCounter++;
if (MemoryPointer > REC_DEPTH) MemoryPointer = 0;
if (WriteCounter > REC_DEPTH) return 1;
blockAddr = REC_BASE + MemoryPointer * REC_WIDTH;
WriteMultiByteToFRAM(blockAddr,Total,7);
ReadMultiByteFromFRAM(blockAddr,temp,7);
for(I=0; I < (u16)BLOCK_WIDTH; I++)
{
if(temp[I] != Total[I]) goto FRAMWriteRepeat;
}
blockAddr += BLOCK2_START;
WriteMultiByteToFRAM(blockAddr,Total,7);
ReadMultiByteFromFRAM(blockAddr,temp,7);
for(I=0; I<BLOCK_WIDTH; I++)
{
if(temp[I] != Total[I]) goto FRAMWriteRepeat;
}
blockAddr = REC_PULSE_REMAINING + MemoryPointer * PULSE_REMAINING_WIDTH;
tempDev.DWord[0] = lastRemaining;
tempDev.Byte[PULSE_REMAINING_CRC] = CRC8(tempDev.Byte, PULSE_REMAINING_CRC);
WriteMultiByteToFRAM(blockAddr,tempDev.Byte,PULSE_REMAINING_WIDTH);
//tempDev.DWord[0] = pulseCounter;
//tempDev.Byte[PULSE_COUNTER_CRC] = CRC8(tempDev.Byte, PULSE_COUNTER_CRC);
//WriteMultiByteToFRAM(PULSE_COUNTER,tempDev.Byte, PULSE_COUNTER_WIDTH);
//ReadMultiByteFromFRAM(PULSE_COUNTER,temp, PULSE_COUNTER_WIDTH);
return 0;
}
/******************************************************************************/
// Routines for FRAM <20><><EFBFBD><EFBFBD>ʵʱ<CAB5><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B4A2>¼ <20><><EFBFBD><EFBFBD> <20><>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD>1 <20><><EFBFBD>󷵻<EFBFBD>0
u16 FRAMCheckSaveTotalFlow(u8 Pointer)
{
u8 block1[7], block2[7];
u16 blockAddr, I;
blockAddr = REC_BASE + Pointer * REC_WIDTH;
ReadMultiByteFromFRAM(blockAddr, block1, 7);
blockAddr += BLOCK2_START;
ReadMultiByteFromFRAM(blockAddr, block2, 7);
if(block1[CRC_CHK] != CRC8(block1, 6)) return false;
if(block1[CRC_CHK] != block2[CRC_CHK]) return false;
for(I=0; I<6; I++)
{
if(block1[I] != block2[I]) return false;
block1[I] &= 0x0f;
if(block1[I] > 0x09) return false;
block1[I] &= 0xf0;
if(block1[I] > 0x90) return false;
}
return true;
}
/******************************************************************************/
// Routines for flow calculations
u16 RetrieveLastAccumulationFromFRAM(void)
{
u32 voltPartA, tempPartA;
u16 voltPartB, tempPartB;
unsigned char I, max_g;
unsigned char good_ind[REC_DEPTH+1];
if(ReadFRAMDeviceID()) return 0;
//find EPROMPointer with good data
max_g = 0;
for(I = 0; I <= REC_DEPTH; I++)
{
if(FRAMCheckSaveTotalFlow(I)) { good_ind[max_g] = I; max_g++; }
}
if(max_g == 0) return 0;
// among all the valid data, get the largest one
voltPartA = 0;
voltPartB = 0;
MemoryPointer = 0;
for(I = 0; I < max_g; I++)
{
ReadMultiByteFromFRAM(REC_BASE + (u16)good_ind[I]* REC_WIDTH, Total, 7);
//tempPartA = make32(Total[0],Total[1],Total[2],Total[3]);
//tempPartB = make16(Total[4],Total[5]);
tempL.Byte[3] = Total[0];
tempL.Byte[2] = Total[1];
tempL.Byte[1] = Total[2];
tempL.Byte[0] = Total[3];
tempPartA = tempL.DWord;
tempL.Byte[1] = Total[4];
tempL.Byte[0] = Total[5];
tempPartB = tempL.Word[0];
if(voltPartA > tempPartA) continue;
else if(voltPartA == tempPartA)
{
if(voltPartB > tempPartB) continue;
}
voltPartA = tempPartA;
voltPartB = tempPartB;
MemoryPointer = good_ind[I];
}
ReadMultiByteFromFRAM(REC_BASE + (u16)MemoryPointer* REC_WIDTH, Total, 7);
ReleaseTotalToDisArray();
ReadMultiByteFromFRAM(REC_PULSE_REMAINING+ MemoryPointer * PULSE_REMAINING_WIDTH, tempDev.Byte, PULSE_REMAINING_WIDTH);
if(tempDev.Byte[PULSE_REMAINING_CRC] != CRC8(tempDev.Byte, PULSE_REMAINING_CRC)) lastRemaining = 0;
else lastRemaining = tempDev.DWord[0];
//ReadMultiByteFromFRAM(PULSE_COUNTER, tempDev.Byte, PULSE_COUNTER_WIDTH);
//if(tempDev.Byte[PULSE_COUNTER_CRC] != CRC8(tempDev.Byte, PULSE_COUNTER_CRC)) pulseCounter = 0;
//else pulseCounter = tempDev.DWord[0];
flowAccCumulationRemaining = 0;
//lastRemaining = 0;
Total[MIN_BIT] = 0;
return 1;
}
/******************************************************************************/
// Routines for flow calculations
void RetrieveLastAccumulation(void)
{
u16 I;
u8 temp[HISTORY_WIDTH];
if(RetrieveLastAccumulationFromFRAM()) return;
flowAccCumulationRemaining = 0;
//pulseCounter = 0;
lastRemaining = 0;
//===========================================================================
#ifndef REC_HISTORY_DATA
#pragma message("[undefined] REC_HISTORY_DATA")
#elif(REC_HISTORY_DATA)
if(ReadRecentHistoryData(temp))
{
Total[0] = temp[5];
Total[1] = temp[6];
Total[2] = temp[7];
Total[3] = temp[8];
Total[4] = temp[9];
Total[5] = temp[10];
Total[CRC_CHK] = CRC8(Total, 6);
ReleaseTotalToDisArray();
return;
}
#endif
//===========================================================================
#ifndef REC_DATE_DATA
#pragma message("[undefined] REC_DATE_DATA")
#elif(REC_DATE_DATA)
if(ReadRecentDateAccData(temp))
{
Total[0] = temp[5];
Total[1] = temp[6];
Total[2] = temp[7];
Total[3] = temp[8];
Total[4] = temp[9];
Total[5] = temp[10];
Total[CRC_CHK] = CRC8(Total, 6);
ReleaseTotalToDisArray();
}
#endif
for (I = 0; I < CRC_CHK; I++) Total[I] = 0;
Total[CRC_CHK] = CRC8(Total, CRC_CHK);
ReleaseTotalToDisArray();
}
/******************************************************************************/
void BcdIncOperate(u8 *addendA, u8 *addendB)
{
u16 Symbol = 0;
for(u16 I = 13; ; I--)
{
addendA[I] += addendB[I];
addendA[I] += Symbol;
if(addendA[I] >= 10) { Symbol = 1; addendA[I] -= 10; }
else Symbol = 0;
if(I==0) break;
}
}
/******************************************************************************/
void BcdDecOperate(u8 *minuend, u8 *subtrahend)
{
for(u16 I=13; I>0 ; I--){
if(minuend[I] >= subtrahend[I]) minuend[I] -= subtrahend[I];
else {
minuend[I] += 10;
minuend[I] -= subtrahend[I];
subtrahend[I-1]++;
}
}
}
/******************************************************************************/
// compute acc flowrate
//void ComputeFlowRateToTotal(void)
void ComputeFlowRateToTotal(void)
{
u32 tempInt;
u8 tempF[14];
// V2004
// FRUnitForHour: <20>Ŵ<EFBFBD>1000<30><30>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><><EFBFBD><EFBFBD><EAB6A8>λ<EFBFBD><CEBB>SLPM, NCMH
// [8λ<38><CEBB><EFBFBD><EFBFBD>ģʽ]<5D>ܹ<EFBFBD><DCB9><EFBFBD><EFBFBD><EFBFBD>14λ: 12345678.123456<EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŵ<EFBFBD>1000<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 12345678.1234 4λС<CEBB><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2λ56<35><36><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><E9BCB0><EFBFBD><EFBFBD>
// [8λ<38><CEBB><EFBFBD><EFBFBD>ģʽ]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λΪSLPM<50><4D>NCMHʱ<48><CAB1><EFBFBD><EFBFBD>С<EFBFBD><D0A1>λ 1mL
// [8λ<38><CEBB><EFBFBD><EFBFBD>ģʽ]Flow Unit = SLPM: (((Flow*60)/1000)*1000)/TimeBase
// [8λ<38><CEBB><EFBFBD><EFBFBD>ģʽ]Flow Unit = NCMH: (Flow*1000)/TimeBase
// [6λ<36><CEBB><EFBFBD><EFBFBD>ģʽ]<5D>ܹ<EFBFBD><DCB9><EFBFBD><EFBFBD><EFBFBD>14λ: 123456.78123456<EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŵ<EFBFBD>100000<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 123456.781234 6λС<CEBB><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2λ56<35><36><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><E9BCB0><EFBFBD><EFBFBD>
// if FR_STD_UNIT = SCCM, ACC_UNIT = SL, 12345678.123456 SL
// if FR_STD_UNIT = SLPM, ACC_UNIT = NM3, 12345678.123456 NM3
// if FR_STD_UNIT = NCMH, ACC_UNIT = NM3, 12345678.123456 NM3
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>ͬһ<CDAC><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ŵ<EFBFBD>1000
/****************************************************************************/
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϣ<D0B6>
/****************************************************************************/
// <20><>֤λ<D6A4><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3B2BB><EFBFBD><EFBFBD>
// Step 1: A = Flow / (time <20><><EFBFBD><EFBFBD>)
// Step 2: B = Flow - A * (time <20><><EFBFBD><EFBFBD>)
// Step 3: B *= 1000; A *= 1000; // <20><><EFBFBD><EFBFBD><EFBFBD>Ŵ<EFBFBD>
// Step 4: B += flowAccCumulationRemaining; // <20>ϴμ<CFB4><CEBC><EFBFBD>ʣ<EFBFBD><CAA3>
// Step 5: C = B/(time <20><><EFBFBD><EFBFBD>)
// Step 6: A += C (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)<29><>flowAccCumulationRemaining = B-C*(time <20><><EFBFBD><EFBFBD>)
tmpIA = ConvertTimeBaseAndUnit(flowComUnit, samplingIntervalForTotal);
//------------------------------------------------------------------------------
#ifndef ENABLE_FLOW_GAIN
#pragma message("[undefined] ENABLE_FLOW_GAIN")
#elif(ENABLE_FLOW_GAIN)
if(tmpIA < calibFlowGain) AccComputeTimeBase *= (u32)calibFlowGain;
else tmpIA /= calibFlowGain;
#endif
//------------------------------------------------------------------------------
tempInt = (u32)flowRate/(u32)AccComputeTimeBase;
tmpLB = flowRate - tempInt*AccComputeTimeBase;
tempInt *= (u32)tmpIA;
tmpLB = tmpLB*(u32)tmpIA + flowAccCumulationRemaining;
tmpLA = tmpLB/(u32)AccComputeTimeBase;
tempInt += tmpLA;
flowAccCumulationRemaining = tmpLB - tmpLA*(u32)AccComputeTimeBase;
// ȷ<><C8B7><EFBFBD>ѱ<EFBFBD><D1B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Determine the total flow
if(Total[CRC_CHK] != CRC8(Total, 6)) RetrieveLastAccumulation();
ReleaseTotalToDisArray();
tempF[0] = 0;
tempF[1] = 0;
tempF[2] = 0;
tempF[3] = 0;
//------------------------------------------------------------------------------
#ifndef ENABLE_ACC_GAIN
#pragma message("[undefined] ENABLE_ACC_GAIN")
#elif(ENABLE_ACC_GAIN)
if(currentMode.Bit.CalibMode) ConvertHEXToBCDArray(tempInt, &tempF[4], 10, HIGH_FIRST);
else ConvertHEXToBCDArray(tempInt*102/100), &tempF[4], 10, HIGH_FIRST);
#else
ConvertHEXToBCDArray(tempInt, &tempF[4], 10, HIGH_FIRST);
#endif
//------------------------------------------------------------------------------
// V2004
#ifndef ENABLE_ACC_DEC_COMPUTE
#pragma message("[undefined] ENABLE_ACC_DEC_COMPUTE")
#elif(ENABLE_ACC_DEC_COMPUTE)
u16 Symbol, I;
if(Dis2[0] != 0) BcdIncOperate(Dis2, tempF);
else {
if(CompareAcc(Dis2, tempF)) {
BcdDecOperate(tempF, Dis2);
Dis2[0] = 1;
}
else BcdDecOperate(Dis2, tempF);
}
tempF[0] = 0;
tempF[1] = 0;
tempF[2] = 0;
tempF[3] = 0;
ConvertHEXToBCDArray(alarmAcc, &tempF[4], 10, HIGH_FIRST); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
isAlarmAcc = CompareAcc(Dis2, tempF)
#else
BcdIncOperate(Dis2, tempF);
#endif
//------------------------------------------------------------------------------
SendToTotalArray();
Total[CRC_CHK] = CRC8(Total, 6);
//------------------------------------------------------------------------------
#ifndef ENABLE_ACCPULSE
#pragma message("[undefined] ENABLE_ACCPULSE")
#elif(ENABLE_ACCPULSE)
lastRemaining += (u32)tempInt;
totalPulse = (u16)(lastRemaining / unitPerPulse);
lastRemaining -= (u32)totalPulse * (u32)unitPerPulse;
if(totalPulse > MaxPulseOutput[samplingIntervalForTotal]) totalPulse = MaxPulseOutput[samplingIntervalForTotal];
#endif
//------------------------------------------------------------------------------
#ifndef REC_ACC_PER
#pragma message("[undefined] REC_ACC_PER")
#elif(REC_ACC_PER)
FRAMWriteTotal();
#endif
}
/******************************************************************************/
void ReadACCFRByCom(void)
{
u16 I;
for(I=0; I<12; I++) MBBuf.RxPointer[MBBuf.Index++] = Dis2[I]+0x30;
MBBuf.DataByte = 12;
ModbusVariablePointerDec();
}
/******************************************************************************/
void SetupACCArray(void)
{
u16 I;
lastRemaining = 0;
//pulseCounter = 0;
flowAccCumulationRemaining = 0;
SendToTotalArray();
ReleaseToIntAndDecimalBufForUart();
#ifndef REC_ACC_PER
#pragma message("[undefined] REC_ACC_PER")
#elif(REC_ACC_PER)
for(I=0; I <= REC_DEPTH; I++) FRAMWriteTotal();
#endif
}
/******************************************************************************/
void WriteACCFRByCom(void)
{
MBBuf.DataByte = 12;
if(MBBuf.ByteNumber < 12)
{
MBBuf.ByteNumber = 0;
MBBuf.BusError = ILLEGAL_DATA_VALUE;
return;
}
u8 I, K;
for(I=0; I<12; I++)
{
K = MBBuf.RxPointer[MBBuf.Index++];
if(K == 0x20) Dis2[I] = 0;
else if((K < 0x30) || (K > 0x39))
{
MBBuf.BusError = ILLEGAL_DATA_VALUE;
MBBuf.ByteNumber = 0;
return;
}
else Dis2[I] = K & 0x0f;
}
Dis2[12] = 0;
Dis2[13] = 0;
SetupACCArray();
}
/******************************************************************************/
void ClearACC(void)
{
u8 I;
for(I=0; I<14; I++) Dis2[I] = 0;
SetupACCArray();
}
/******************************************************************************/
u16 CompareAcc(u8 *compaerA, u8 *compaerB)
{
if(compaerA[0] != 0) return 1;
for(u16 I=1; I<14; I++)
{
if(compaerA[I] > compaerB[I]) return 0;
else if(compaerA[I] < compaerB[I]) return 1;
}
return 0;
}