{ Эмулятор "железа" масс-спектрометра (аналоговая часть прибора, далее HE) . Предназначен для: 1) объединения и согласования сигналов поступающих на электронные блоки управления эмулятора МИ-1201АГМ. 2) эмуляции "физики" процесса измерения. Эмуляторы электронных блоков ответственны за установление соответствующих значений параметров в HE. Эмуляторы электронных блоков должны использовать значения параметров из HE при необходимости. } unit MI1201AGM_Hardware_Emulator; interface Uses TimeInterval_Emulator, Peak_Emulator, MassScale_Emulator; const cDataSignature='Hardware emulator data. '^M^L; cPressureScale=1000000; cRegistrySubPath='Hardware'; type tDataSignature=array[1..Length(cDataSignature)] of char; tNapuskCoeff=double; tPressure=double; tHardwareSignal=(esCatodOK, esBPGI_ON, esHighVoltage_ON, esOverload, esBeam_Off); tHardwareSignals=set of tHardwareSignal; tMotor=(mCorrZ, mCorrY, mFocusU, mExtrU, mEmisI, mIonizU); tMotorSignalScale=0..1000; tMotorSignalScales=array[tMotor] of tMotorSignalScale; tBlock=(bBPGI, b10kV, bVEU, bValveControl); tBlocks=set of tBlock; tValve=(vNone,vProba1,vProba2,vEtalon1,vEtalon2,vEtalon3,vEtalon4, vPumping); tValves=set of tValve; tMi1201HardwareEmulatorError=( erOK ); tMi1201HardwareEmulatorDataError=( deMass, dePressureHi, deNapuskCoeff ); tMi1201HardwareEmulatorDataErrors=set of tMi1201HardwareEmulatorDataError; tVoltmeterPoint=( vpIMCh, {0000 - напряжение ИМЧ } vpAcceleration, { 0001 - ускоряющее напряжение } vpMagnetI, { 0010 - ток электромагнита } vpMultiplicator, { 0011 - напряжение умножителя } vpAntiDinatron, { 0100 - напряжение антидинатрона } vpBasePNC, { 0101 - напряжение опоры ПНЧ } vpUPT1, { 0110 - напряжение УПТ 1 } vpUPT2, { 0110 - напряжение УПТ 2 } vpUPT3, { 0110 - напряжение УПТ 3 } vpUPT4, { 0110 - напряжение УПТ 4 } vpUPT5, { 0110 - напряжение УПТ 5 } vpUPT6, { 0110 - напряжение УПТ 6 } vpUPT7, { 0110 - напряжение УПТ 7 } vpUPT8, { 0110 - напряжение УПТ 8 } vpUPTU, { 0110 - напряжение УПТ-У } vpLens { 1111 - напряжение линзы } ); tUPT=vpUPT1..vpUPTU; tVoltages=array[tVoltmeterPoint] of double; {V} tUPTData=record BaseMass:tMass; Shifts:array[tUPT] of tMass; Sensitivities:array[tUPT] of real; end; tValveData=record StablePressure:tPressure; NapuskCoeff:tNapuskCoeff; end; tValvesData=array[tValve] of tValveData; tPNCRele=(rbZeroOnBase, rbInputIsEMU, rbInvertSignal); tPNCReleSet=set of tPNCRele; tData=record Signature:tDataSignature; Mass:tMass; Pressure:tPressure; PressureLo,PressureHi:tPressure; NapuskCoeff:double; NapuskStartTime:tTime_ms; Voltages:tVoltages; UPT:tUPTData; HardwareSignals:tHardwareSignals; IonSourceScales:tMotorSignalScales; Blocks:tBlocks; Valve:tValve; ValvesData:tValvesData; Valves:byte; VEU:word; PNCRele:tPNCReleSet; end; tMi1201HardwareEmulator=class(TObject) private prError:tMi1201HardwareEmulatorError; prDataErrors:tMi1201HardwareEmulatorDataErrors; prData:tData; prDefaultMassAndSignal:tMassScaleAndSignal; prMassAndSignal:tMassScaleAndSignal; procedure SetDefaultData; procedure SignalsUpdate; procedure SetMassAndSignal(AMassAndSignal:tMassScaleAndSignal); function GetMassAndSignal:tMassScaleAndSignal; procedure SetMass(m:tMass); function GetMass:tMass; function GetSignal:tSignal; procedure SetupHardwareSignals; procedure HardwareSignalSetState(s:tHardwareSignal; state:boolean); public constructor Create; destructor Destroy; override; procedure ReInit; // Ошибки эмулятора оборудования property Error:tMi1201HardwareEmulatorError read prError; // Генератор сигнала (спектра) без связи с текущими параметрами прибора property MassAndSignal:tMassScaleAndSignal read GetMassAndSignal write SetMassAndSignal; // Значение массы property Mass:tMass read GetMass write SetMass; // Значение сигнала, с учетом параметров property Signal:tSignal read GetSignal; function SetData(var D:tData):boolean; procedure GetData(var D:tData); function SaveData(var F:File):boolean; function RestData(var F:File):boolean; // Установка сигналов оборудования function HardwareSignals:tHardwareSignals; procedure HardwareSignalSet(s:tHardwareSignal); procedure HardwareSignalClear(s:tHardwareSignal); function CheckData(var d:tData):boolean; function CheckSelfData:boolean; function IonSourceScaleGet(m:tMotor):tMotorSignalScale; procedure IonSourceScaleSet(m:tMotor; s:tMotorSignalScale); function IonCounterSignal:tSignal; function Voltage(c:tVoltmeterPoint):double; function BlockON(b:tBlock):boolean; procedure BlockSetState(b:tBlock; state:boolean); procedure BlocksSet(b:tBlocks); function BlocksGet:byte; function Valve:tValve; procedure ValveOpen(v:tValve); procedure ValvesSet(vs:byte); function ValvesGet:byte; function VEU:word; procedure VEUSet(v:word); function PNCRele:byte; procedure PNCReleSet(b:tPNCReleSet); function UPTSignal(p:tUPT):tSignal; procedure PressureSet(P:tPressure; Coeff:tNapuskCoeff); function Pressure:tPressure; end; implementation Uses Emulator_Registry; procedure tMi1201HardwareEmulator.SetMassAndSignal(AMassAndSignal:tMassScaleAndSignal); begin end; function tMi1201HardwareEmulator.GetMassAndSignal:tMassScaleAndSignal; begin Result:=prMassAndSignal; If not Assigned(Result) then begin Result:=prDefaultMassAndSignal; end; end; function tMi1201HardwareEmulator.GetSignal:tSignal; begin Result:=0; end; function tMi1201HardwareEmulator.UPTSignal(p:tUPT):tSignal; begin Result:=0; end; function tMi1201HardwareEmulator.IonCounterSignal:tSignal; begin IonCounterSignal:=1; end; function tMi1201HardwareEmulator.PNCRele:byte; begin PNCRele:=Byte(prData.PNCRele); end; procedure tMi1201HardwareEmulator.PNCReleSet(b:tPNCReleSet); begin prData.PNCRele:=b; end; procedure tMi1201HardwareEmulator.SetupHardwareSignals; begin HardwareSignalSetState(esBPGI_ON, bBPGI in prData.Blocks); HardwareSignalSetState(esHighVoltage_ON, b10kV in prData.Blocks); end; procedure tMi1201HardwareEmulator.BlocksSet(b:tBlocks); begin prData.Blocks:=b; SetupHardwareSignals; end; procedure tMi1201HardwareEmulator.BlockSetState(b:tBlock; state:boolean); begin if state then Include(prData.Blocks,b) else Exclude(prData.Blocks,b); SetupHardwareSignals; end; function tMi1201HardwareEmulator.BlockON(b:tBlock):boolean; begin BlockON:=b in prData.Blocks; end; function tMi1201HardwareEmulator.BlocksGet:byte; begin BlocksGet:=byte(prData.Blocks); end; function tMi1201HardwareEmulator.VEU:word; begin VEU:=prData.VEU; end; procedure tMi1201HardwareEmulator.VEUSet(v:word); begin prData.VEU:=v; end; function tMi1201HardwareEmulator.Valve:tValve; begin Valve:=prData.Valve; end; procedure tMi1201HardwareEmulator.ValveOpen(v:tValve); begin if prData.Valve<>v then begin PressureSet(prData.ValvesData[v].StablePressure,prData.ValvesData[v].NapuskCoeff); prData.Valves:=(prData.Valves and ($FF-7)) or byte(v); end; end; procedure tMi1201HardwareEmulator.ValvesSet(vs:byte); begin if prData.Valves<>vs then begin prData.Valves:=vs; ValveOpen(tValve(vs and 7)); end; end; function tMi1201HardwareEmulator.ValvesGet:byte; begin ValvesGet:=prData.Valves; end; procedure tMi1201HardwareEmulator.IonSourceScaleSet(m:tMotor; s:tMotorSignalScale); begin prData.IonSourceScales[m]:=s; end; function tMi1201HardwareEmulator.IonSourceScaleGet(m:tMotor):tMotorSignalScale; begin IonSourceScaleGet:=prData.IonSourceScales[m]; end; function tMi1201HardwareEmulator.Voltage(c:tVoltmeterPoint):double; begin Voltage:=prData.Voltages[c]; end; function tMi1201HardwareEmulator.HardwareSignals:tHardwareSignals; begin HardwareSignals:=prData.HardwareSignals; end; procedure tMi1201HardwareEmulator.HardwareSignalSet(s:tHardwareSignal); begin Include(prData.HardwareSignals,s); end; procedure tMi1201HardwareEmulator.HardwareSignalClear(s:tHardwareSignal); begin Exclude(prData.HardwareSignals,s); end; procedure tMi1201HardwareEmulator.HardwareSignalSetState(s:tHardwareSignal; state:boolean); begin if state then HardwareSignalSet(s) else HardwareSignalClear(s); end; function tMi1201HardwareEmulator.SetData(var D:tData):boolean; begin if CheckData(D) then begin prData:=D; SetData:=TRUE; end else begin SetData:=FALSE; end; end; procedure tMi1201HardwareEmulator.GetData(var D:tData); begin D:=prData; end; function tMi1201HardwareEmulator.SaveData(var F:File):boolean; var pos:cardinal; c:integer; begin pos:=FilePos(f); prData.Signature:=cDataSignature; BlockWrite(f,prData,SizeOF(prData),c); if c<>SizeOF(prData) then begin Seek(F,pos); SaveData:=False; end else begin SaveData:=TRUE; end; end; function tMi1201HardwareEmulator.RestData(var F:File):boolean; var pos:integer; c:integer; d:tData; begin pos:=FilePos(f); if (FileSize(f)-pos)>=SizeOF(prData) then begin BlockRead(f,d,SizeOF(d),c); if c<>SizeOF(prData) then begin Seek(F,pos); RestData:=False; SetDefaultData; end else if SetData(d) then begin RestData:=TRUE; end else begin Seek(F,pos); RestData:=False; SetDefaultData; end; end else begin RestData:=False; SetDefaultData; end; end; function tMi1201HardwareEmulator.CheckData(var d:tData):boolean; begin CheckData:=TRUE; prDataErrors:=[]; if d.Mass>cMassScale*1000 then begin d.Mass:=cMassScale*1000; Include(prDataErrors,deMass); end; if d.NapuskCoeff<0 then begin d.NapuskCoeff:=0; Include(prDataErrors,deNapuskCoeff); end; if d.PressureHi>1000 then begin d.PressureHi:=1000; Include(prDataErrors,dePressureHi); end; end; function tMi1201HardwareEmulator.CheckSelfData:boolean; begin CheckSelfData:=CheckData(prData); end; procedure tMi1201HardwareEmulator.PressureSet; begin prData.NapuskStartTime:=GetTickCount; prData.Pressure:=Pressure; prData.PressureHi:=Abs(P); prData.NapuskCoeff:=Abs(Coeff); end; function tMi1201HardwareEmulator.Pressure; var dP:double; begin if prData.NapuskCoeff=0 then begin Pressure:=prData.Pressure; end else begin dP:=prData.Pressure-prData.PressureHi; Pressure:=dP*exp(-prData.NapuskCoeff*TickSpend(prData.NapuskStartTime))+prData.PressureHi; end; end; constructor tMi1201HardwareEmulator.Create; var aData:tData; begin Inherited; SetDefaultData; if EmulatorRegistry.OpenRead(cRegistrySubPath) then begin try EmulatorRegistry.ReadBinaryData('Data',aData,SizeOf(aData)); if CheckData(aData) then begin prData:=aData; end; except end; EmulatorRegistry.CloseKey; end; Reinit; end; destructor tMi1201HardwareEmulator.Destroy; begin if EmulatorRegistry.OpenWrite(cRegistrySubPath) then begin try EmulatorRegistry.WriteBinaryData('Data',prData,SizeOf(prData)); except end; EmulatorRegistry.CloseKey; end; Inherited; end; procedure tMi1201HardwareEmulator.ReInit; begin end; procedure tMi1201HardwareEmulator.SetDefaultData; var m:tMotor; v:tValve; begin prDataErrors:=[]; prError:=erOK; prData.Mass:=1; prData.PressureHi:=1E-10; prData.Pressure:=prData.PressureHi; prData.NapuskCoeff:=0; prData.UPT.BaseMass:=252*cMassScale; prData.UPT.Shifts[vpUPT1]:=0; prData.UPT.Sensitivities[vpUPT1]:=1; prData.UPT.Shifts[vpUPT2]:=14*cMassScale; prData.UPT.Sensitivities[vpUPT2]:=100; prData.UPT.Shifts[vpUPT3]:=prData.UPT.Shifts[vpUPT2]+1*cMassScale; prData.UPT.Sensitivities[vpUPT3]:=50; prData.UPT.Shifts[vpUPT4]:=prData.UPT.Shifts[vpUPT3]+1*cMassScale; prData.UPT.Sensitivities[vpUPT4]:=100; prData.UPT.Shifts[vpUPT5]:=prData.UPT.Shifts[vpUPT4]+2*cMassScale; prData.UPT.Sensitivities[vpUPT5]:=1; prData.UPT.Shifts[vpUPT6]:=prData.UPT.Shifts[vpUPT1]; prData.UPT.Sensitivities[vpUPT6]:=0; prData.UPT.Shifts[vpUPT7]:=prData.UPT.Shifts[vpUPT1]; prData.UPT.Sensitivities[vpUPT7]:=0; prData.UPT.Shifts[vpUPT8]:=prData.UPT.Shifts[vpUPT1]; prData.UPT.Sensitivities[vpUPT8]:=0; prData.UPT.Shifts[vpUPTU]:=prData.UPT.Shifts[vpUPT4]+1*cMassScale; prData.UPT.Sensitivities[vpUPTU]:=1E5; prData.HardwareSignals:=[esCatodOK, esBPGI_ON, esBeam_Off]; for m:=Low(m) to High(m) do begin prData.IonSourceScales[m]:=1; end; prData.Blocks:=[]; prData.Valve:=vNone; prData.Valves:=0; prData.VEU:=0; for v:=Low(v) to High(v) do begin with prData.ValvesData[v] do begin StablePressure:=5E-6; NapuskCoeff:=1; end; end; prData.ValvesData[vNone].NapuskCoeff:=0; prData.ValvesData[vPumping].StablePressure:=5E-6; prData.PNCRele:=[rbZeroOnBase, rbInputIsEMU]; end; procedure tMi1201HardwareEmulator.SetMass(m:tMass); begin if prData.Mass<>m then begin prData.Mass:=m; SignalsUpdate; end; end; procedure tMi1201HardwareEmulator.SignalsUpdate; var u:tUpt; m:tMass; begin for u:=Low(u) to High(u) do begin if prData.UPT.Sensitivities[u]=0 then begin prData.Voltages[u]:=0; end else begin m:=Mass; prData.Voltages[u]:=MassAndSignal.Signal(m+prData.UPT.Shifts[u])*prData.UPT.Sensitivities[u]; end; end; end; function tMi1201HardwareEmulator.GetMass:tMass; begin Result:=prData.Mass; end; end.