// Диапазон массы для сканирования unit MI1201_Range; interface uses Windows, Classes, SysUtils, MCADUser, MITypes; type tPComplexArray=^ComplexArray; tCounter=integer; tChannel=byte; tFlag=(fDataAllocated, fRangeValid, fNoMemory, fStopMeasure, fSinglePass, fError, fPointProcessed, fCumulativeMeasure, fMicroVoltsToVolts ); tFlags=set of tFlag; tError=(ecOK, ecNoMemory, ecUnexpectedError); tSetRangeResult=(rOK, rMin, rMax, rStep, rCantSetup); tMeasureType=(mStop, mSinglePass, mRepeatedlyWithDataReplace, mRepeatedlyWithDataAccumulation, mResume); tStoreType=(stReplace, stAccumulate); const cDoNotMeasureFlags=[fNoMemory, fStopMeasure, fError]; cDoMeasureFlags=[fDataAllocated, fRangeValid]; type tMassData=record MaxIndex,Index:integer; Pass:uint; MinCnt,CurCnt,MaxCnt:uint; Step:word; StepSign:shortint; StepMultiplicator:shortint; end; tSpecterDateTime=record StartDateTime,EndDateTime:TDateTime; end; tRange = class(TOBject) private prFlags:tFlags; prMeasureType:tMeasureType; prDateTime:tSpecterDateTime; prChannels:tChannel; procedure CumulativeDataStore(const Signals:array of tSignal); // Накопительное измерение - суммирование сигнала с учетом времени интегрировани procedure DataStore(const Signals:array of tSignal); // Простое измерение - замена данных на данные нового замера procedure DataFill(var ca:ComplexArray); procedure DataStoreFill; procedure IncPass; function IntegrationTimeGet:uint; function MeasureAvailable:boolean; procedure BIndexSet(Index:integer); procedure BCounterSet(Counter:uint); protected prData:ComplexArray; prMass:tMassData; prError:tError; procedure ErrorSet(e:tError); function CheckDataPoint(var dp:ComplexArray):boolean; function DataAllocate:boolean; procedure DataDeallocate; procedure DataClear; procedure ChangeCounter; function CounterStepGet:tCounter; procedure MeasureTypeSet(MeasureType:tMeasureType); function MeasureTypeGet:tMeasureType; function DeltaDateTimeGet:tDateTime; procedure StepMultiplicatorSet(SMult:shortint); property ErrorCode:tError read prError write ErrorSet; public constructor Create(Channels:byte); destructor Destroy; override; procedure Start; procedure Stop; procedure Resume; function SetRange(MinCounter,MaxCounter:uint; Step:integer):tSetRangeResult; function GetCounterForIndex(Index:uint; var Counter:uint):boolean; function Index2Counter(Index:uint):uint; function Counter2Index(Counter:uint):uint; function Clear:boolean; property Error:tError read prError; property Channels:tChannel read prChannels; property CounterMin:uint read prMass.MinCnt; property CounterMax:uint read prMass.MaxCnt; property CounterStep:integer read CounterStepGet; property IndexMax:integer read prMass.MaxIndex; function IndexValid(i:integer):boolean; function ChannelValid(cl:byte):boolean; property MeasureType:tMeasureType read MeasureTypeGet write MeasureTypeSet; property StepMultiplicator:shortint read prMass.StepMultiplicator write StepMultiplicatorSet; property BIndex:integer read prMass.Index write BIndexSet; property BCounter:uint read prMass.CurCnt write BCounterSet; property BPass:uint read prMass.Pass; property StartDateTime:tDateTime read prDateTime.StartDateTime; property EndDateTime:tDateTime read prDateTime.EndDateTime; property DeltaDateTime:tDateTime read DeltaDateTimeGEt; property IntegrationTime:uint read IntegrationTimeGet; procedure Store(const Signals:array of tSignal; StoreType:tStoreType); function DataArrayRows:uint; function DataArrayCols:uint; function DataArrayGet(var Data:ComplexArray):boolean; function DataColumnGet(Col:byte; var Data:ComplexArray):boolean; function DataBPointGet(Col:byte; Row:integer; var p:tMass):boolean; end; implementation Uses MCAD_MiscFuncs; constructor tRange.Create; begin Inherited Create; prChannels:=Channels; prData.cols:=0; prData.rows:=0; prData.hReal:=NIL; prData.hImag:=NIL; prMass.MinCnt:=0; prMass.MaxCnt:=0; prMass.CurCnt:=0; prMass.Step:=0; prMass.StepSign:=1; prMass.StepMultiplicator:=1; prMass.Index:=0; prMass.MaxIndex:=0; prMass.Pass:=0; prFlags:=[]; prMeasureType:=mSinglePass; prDateTime.StartDateTime:=0.; prDateTime.EndDateTime:=0.; end; destructor tRange.Destroy; begin DataDeallocate; Inherited Destroy; end; // Накопительное измерение - //суммирование сигнала с учетом времени интегрировани procedure tRange.CumulativeDataStore; var i:tChannel; t1,t2,tt:double; tc1,tc2:extended; begin t1:=prData.hReal[Channels,prMass.Index]; t2:=Signals[Low(Signals)].Time; tt:=t1+t2; tc1:=t1/tt; tc2:=t2/tt; for i:=Low(i) to Pred(Channels) do begin prData.hReal[Ord(i),prMass.Index]:= prData.hReal[Ord(i),prMass.Index]*tc1+ +Signals[i].Signal*tc2; end; prData.hReal[Channels,prMass.Index]:=tt; DataStoreFill; end; // Простое измерение - замена данных на данные нового замера procedure tRange.DataStore; var i:tChannel; begin for i:=Low(i) to Pred(Channels) do begin prData.hReal[Ord(i),prMass.Index]:=Signals[i].Signal; end; prData.hReal[Channels,prMass.Index]:=Signals[i].Time; DataStoreFill; end; // Заполнение нулей при скачках через точки procedure tRange.DataFill(var ca:ComplexArray); var j,n0,n1:integer; begin if ABS(StepMultiplicator)>1 then begin j:=BIndex-StepMultiplicator; if CounterStep<0 then begin if j>IndexMax then j:=IndexMax; n0:=Succ(BIndex); n1:=j; end else begin if j<0 then j:=0; n0:=j; n1:=Pred(BIndex); end; // Копирование точки замера for j:=n0 to n1 do begin ArrayFillPoint(ca,BIndex,j); end; end; end; procedure tRange.DataStoreFill; begin DataFill(prData); end; procedure tRange.IncPass; begin if (prMass.Pass>=1) and (fSinglePass in prFlags) then begin end else begin Inc(prMass.Pass); end; end; procedure tRange.ChangeCounter; begin if (prMass.Step<>0) then begin if (fPointProcessed in prFlags) then begin Inc(prMass.Index,prMass.StepMultiplicator*prMass.StepSign); Exclude(prFlags,fPointProcessed); if prMass.Index>prMass.MaxIndex then begin prMass.Index:=0; IncPass; end else if prMass.Index<0 then begin prMass.Index:=prMass.MaxIndex; IncPass; end; end; prMass.CurCnt:=Index2Counter(prMass.Index); end; end; procedure tRange.BIndexSet(Index:integer); begin if (0<=Index) and (Index<=IndexMax) then begin prMass.Index:=Index; end; end; function tRange.DataAllocate; var c,r:uint; begin c:=DataArrayCols; r:=Succ(prMass.MaxIndex); if (c=prData.cols) and (r=prData.rows) then begin DataClear; Result:=TRUE; end else begin DataDeallocate; if r>0 then begin Result:=ArrayAllocate(prData, r, c, TRUE,FALSE); if Result then begin DataClear; Exclude(prFlags,fNoMemory); Include(prFlags,fDataAllocated); end else begin Include(prFlags,fNoMemory); ErrorCode:=ecNoMemory; end; end else begin Result:=FALSE; end; end; end; procedure tRange.DataDeallocate; begin if prData.hReal<>NIL then begin Exclude(prFlags,fDataAllocated); ArrayDeallocate(prData); end; end; function tRange.SetRange; var x:integer; CMax,CMin:cardinal; begin if (MinCounter=CounterMin) and (MaxCounter=CounterMax) and (Step=CounterStep) then begin Result:=rOK; end else begin { CMax:=prMsSp.CounterMax; CMin:=prMsSp.CounterMin;} Result:=rOK; if (MinCounterCMax) then Result:=rMin; if (MinCounterCMax) then Result:=rMax; if Result=rOK then begin if MinCounter<=MaxCounter then begin prMass.MinCnt:=MinCounter; prMass.MaxCnt:=MaxCounter; end else begin prMass.MinCnt:=MaxCounter; prMass.MaxCnt:=MinCounter; end; prMass.Step:=Abs(Step); if Step>=0 then prMass.StepSign:=1 else prMass.StepSign:=-1; if Step<>0 then begin x:=Abs(MaxCounter-MinCounter); prMass.MaxIndex:=x div prMass.Step end else begin prMass.MaxIndex:=0; end; Include(prFlags,fRangeValid); DataAllocate; end; end; end; procedure tRange.ErrorSet(e:tError); begin if e=ecOK then begin prError:=ecOK; Exclude(prFlags,fError); end else if prError=ecOK then begin prError:=e; Include(prFlags,fError); end; end; procedure tRange.DataClear; begin ArrayClear(prData); prMass.Index:=prMass.MaxIndex; end; function tRange.Clear; begin DataClear; end; function tRange.CheckDataPoint(var dp:ComplexArray):boolean; begin Result:=(dp.hReal<>NIL) and (dp.Rows>=Channels) and (dp.Cols>=1); end; procedure tRange.MeasureTypeSet; begin case MeasureType of mStop: begin // Stop; end; mResume: begin // Resume; end; mSinglePass: begin // if (MeasureType=prMeasureType) then Exit; // Stop; Clear; Include(prFlags,fSinglePass); Exclude(prFlags,fCumulativeMeasure); // Start; end; mRepeatedlyWithDataReplace: begin if (MeasureType=prMeasureType) then Exit; // Stop; Clear; Exclude(prFlags,fSinglePass); Exclude(prFlags,fCumulativeMeasure); // Start; end; mRepeatedlyWithDataAccumulation: begin if (MeasureType=prMeasureType) then Exit; // Stop; Clear; Exclude(prFlags,fSinglePass); Include(prFlags,fCumulativeMeasure); // Start; end; else begin MeasureType:=mStop; // Stop; end; end; prMeasureType:=MeasureType; end; function tRange.MeasureTypeGet; begin Result:=prMeasureType; end; function tRange.DataArrayRows:uint; begin Result:=Succ(prMass.MaxIndex); end; function tRange.DataArrayCols:uint; begin Result:=Channels; end; function tRange.DataArrayGet; begin Result:=ArrayCopy(prData,Data); end; function tRange.DataColumnGet; begin Result:=ArrayCopyColumn(Col, prData, 0, Data); end; function tRange.DataBPointGet; begin Result:=IndexValid(Row) and ChannelValid(Col); if Result then begin p:=prData.hReal[Col,Row]; end else begin p:=prData.hReal[Col,Row]; end; end; function tRange.GetCounterForIndex; begin Result:=(0<=Index) and (Index<=prMass.MaxIndex); if not Result Then Exit; Counter:=Index2Counter(Index); end; function tRange.Index2Counter; begin if (Index<=0) then Result:=prMass.MinCnt else if (Index>=IndexMax) then Result:=prMass.MaxCnt else Result:=prMass.MinCnt+Index*prMass.Step; end; function tRange.Counter2Index(Counter:uint):uint; begin if (Counter<=prMass.MinCnt) then Result:=0 else if (Counter>=prMass.MaxCnt) then Result:=IndexMax else Result:=((Counter-prMass.MinCnt)+(prMass.Step div 2)) div prMass.Step; end; procedure tRange.StepMultiplicatorSet; begin prMass.StepMultiplicator:=SMult; end; procedure tRange.Start; begin prMass.Pass:=1; if prMass.StepSign>=0 then prMass.Index:=0 else prMass.Index:=prMass.MaxIndex; Exclude(prFlags,fPointProcessed); prDateTime.StartDateTime:=Now(); prDateTime.EndDateTime:=prDateTime.StartDateTime; Resume; end; procedure tMsThread.Stop; begin Include(prFlags,fStopMeasure); prDateTime.EndDateTime:=Now(); end; procedure tMsThread.Resume; begin Exclude(prFlags,fStopMeasure); end; procedure tMsThread.JumpTo; begin Ready.WaitForever:=True; prMsSp.exJumpTo(Counter); Ready.WaitForever:=False; end; procedure tMsThread.ValveSetOpen; begin try if not prMsSp.exSwitchIsON(fValvesControl) then prMsSp.exSwitchTurnON(fValvesControl); prMsSp.exSourceSet(Valve); except CheckHardwareError; end; end; function tMsThread.ValveGetOpen; begin try Result:=prMsSp.exSource; except CheckHardwareError; end; end; function tMsThread.DeviceSet; begin Result:=False; if Device in [IonizationVoltage..SEM_Voltage] then begin try if (prMsSp.DeviceUMin(Device)<=Value) and (Value<=prMsSp.DeviceUMax(Device)) then begin prMsSp.exDeviceUSet(Device,Value); CheckHardwareError; Result:=(ErrorCode=ecOK); end; except CheckHardwareError; end; end; end; function tMsThread.DeviceGet; begin Result:=Low(Result); if Device in [IonizationVoltage..SEM_Voltage] then begin try Result:=prMsSp.DeviceU(Device); except CheckHardwareError; end; end; end; function tMsThread.Mass2Counter(m:tMass):uint; begin Result:=prMsSp.Mass2Counter(m); end; function tMsThread.Counter2Mass(c:uint):tMass; begin Result:=prMsSp.Counter2Mass(c); end; function tMsThread.IntegrationTimeGet; begin Result:=prMsSp.IntegrationTime; end; procedure tMsThread.Abort; begin prMsSp.SetErrorCode(word(ecAbort)); Ready.MakeOwner; Ready.WaitForever:=False; CheckHardwareError; Ready.SetEventAnyway; end; function tMsThread.CounterLowGet; begin Result:=prMsSp.CounterMin; end; function tMsThread.CounterHighGet; begin Result:=prMsSp.CounterMax; end; function tMsThread.CounterStepGet; begin Result:=prMass.Step*prMass.StepSign; end; function tMsThread.EqupmentFlagsGet; begin prMsSp.exEmergencyFlagsGet(Result); end; function tMsThread.MeasureAvailable:boolean; begin Result:=(prFlags*cDoNotMeasureFlags=[]) and (prFlags*cDoMeasureFlags=cDoMeasureFlags); end; procedure tMsThread.AutoTuningSet(x:boolean); begin if AutoTuningGet<>x then begin if (Wait=wrSignaled) then begin prMsSp.ctrlRoll.exAutoTuning(x); SetReady; end; end; end; function tMsThread.AutoTuningGet:boolean; begin Result:=prMsSp.ctrlRoll.AutoTuning; end; function tMsThread.DeltaDateTimeGet:tDateTime; begin Result:=EndDateTime-StartDateTime; end; procedure tMsThread.BCounterSet(Counter:uint); begin BIndex:=Counter2Index(Counter); end; procedure tMsThread.BMassSet(Mass:tMass); begin BIndex:=Mass2Index(Mass); end; function tMsThread.BMassGet:tMass; begin Result:=Index2Mass(BIndex); end; function tMsThread.IndexValid; begin Result:=(0<=i) and (i<=IndexMax); end; function tMsThread.ChannelValid; begin Result:=(Ord(Low(tChannel))<=cl) and (cl<=Ord(High(tChannel))); end; (*procedure tMsThread.BackDataSet(BData:tPComplexArray); begin prBackData:=BData; BackDataCopy; end; procedure tMsThread.BackDataCopy; begin if not Assigned(prBackData) then Exit; try if not GetDataArray(prBackData^) then prBackData:=Nil; except prBackData:=Nil; end; end; procedure tMsThread.BackDataCopyPoint; begin if not Assigned(prBackData) then Exit; try ArraysCopyPoint(prData,prBackData^,prMass.Index,prMass.Index); DataFill(prBackData^); except BackData:=Nil; end; end; *) end.