{ Контроллер ПНЧ 5.105.154 (преобразователь напряжение-частота) АК-9 } {--------------------------------------------------------------------------- The control units for mass-spectrometer MI1201-AGM (c) Copyright Aleksandrov O.E., 1998 Модуль управления масс-спектрометром МИ1201-АГМ (c) Собственность Александрова О.Е., 1998 Molecular Physics department 620002, Екатеринбург, К-2 USTU, Ekaterinsburg, K-2, 620002 УГТУ, RUSSIA Кафедра молекулярной физики phone 75-48-39 тел. 75-48-39 E-mail aleks@dpt.ustu.ru ----------------------------------------------------------------------------} Unit c_CVF; {$X+} INTERFACE USES c_Ctrl, c_Ctrl1, c_Bus, MITypes, MiscFunc; type tRegimeSwitchs=(frsBaseIsZero, frsInputIsEMU, frsDoNotInvertSignal); tRegime=set of tRegimeSwitchs; const { Шина опоры: 0V; На вход ПНЧ подан сигнал с ЭМУ; Сигнал не инвертируется. } cWorkRegime=[frsBaseIsZero, frsInputIsEMU, frsDoNotInvertSignal]; cCalibrationRegime0=[frsBaseIsZero, frsDoNotInvertSignal]; cCalibrationRegime1=[frsDoNotInvertSignal]; cDefaultRegime=cWorkRegime;{ Шина опоры: 0V; На вход ПНЧ подан сигнал с ЭМУ; Сигнал не инвертируется. } cFirstChannel =1; { номер первого канала } cLastChannel =9; { номер последнего канала } cWorkingChannels=[1..5, 9]; { рабочие каналы для МИ1201-АГМ } cSEMChannel =9; { канал ВЭУ } cSEMChannels =[9]; { каналы ВЭУ } cEMUChannels =cWorkingChannels-cSEMChannels; { каналы ЭМУ } cDefaultChannels=cWorkingChannels; cDefaultIntegrationTime=100; { мс } cDefaultTimeOut=2000; { мс } cDefaultDelayTime=300; { мс - задержка на срабатывание реле } type { Коды ошибок } tErrorCodes=({$I C_ErrCds.Inc}, ecFailResetController, ecFailResetChannel, ecFailResetTimer, ecFailResetRegime, ecFailInit, ecFailReadReady, ecFailStart, ecWaitReadyTimeOut, {11} ecFailReadChannel, ecFailCalibrate0, ecBadControllerState); tFlag=(fFastStart, fCalibrationValid); tFlags=set of tFlag; tTmpFlag=(fInitialResetDone,fResetCtrlDone, fResetChannelsDone, fResetRegimeDone, fResetParametersDone); tTmpFlags=set of tTmpFlag; tChannel=1..9; tChannelName=(cnPNC1,cnPNC2,cnPNC3,cnPNC4,cnPNC5,cnPNC6, cnReserved7,cnReserved8, cnSEM); tChannels=set of tChannel; tChannelNames=set of tChannelName; type tCalibrationData=record K:tMkVolts; U0:tMkVolts; Kx:double; U0x:double; end; tChannelsCalibrationData=array[tChannel] of tCalibrationData; tChannelsCountersData=array[tChannel] of tSignalData; { Запись управляющих слов } tControlPortsNumber=1..6; tControlPorts=record case byte of 1:(owLo123, owHi123, owLo456, owHi456, owLo789, owHi789:word); 2:(Port:array[tControlPortsNumber] of word); end; tDataPort=record rwLo, rwHi:word; end; { Чтение данных } tDataPortsNumber=1..18; tDblDataPortsNumber=1..9; tDataPorts=record case byte of 1:(rwLo1, rwHi1, rwLo2, rwHi2, rwLo3, rwHi3, rwLo4, rwHi4, rwLo5, rwHi5, rwLo6, rwHi6, rwLo7, rwHi7, rwLo8, rwHi8, rwLo9, rwHi9:word); 2:(Port:array[1..18] of word); 3:(DblPort:array[1..9] of tDataPort); end; tPort=( { Управление контроллером } prwReset_Start, prwGate_ResetInt, powRegime, prwReady_SuspendCount, { Управление таймером } powTimerControl, prwTimerChannel1, prwTimerChannel0 { Запись управляющих слов } ); tPortsArray=array[Ord(Low(tPort))..Ord(High(tPort))+36] of Byte; const cUnreadablePorts=[prwReset_Start, prwGate_ResetInt, powTimerControl]; type tPorts=record case byte of 0:({ Управление контроллером } rwReset_Start, rwGate_ResetInt, owRegime, rwReady_SuspendCount, { Управление таймером } owTimerControl, rwTimerChannel1, rwTimerChannel0:word; { Запись управляющих слов } owCtrl:tControlPorts; { Чтение данных } rwData:tDataPorts); 1:(Ports:array[tPort] of Word); end; tData=record Flags:tFlags; Ports:tPorts; Regime:tRegime; IntegrationTime:word; { время интегрирования, которое будет установлено при следующем запуске } Channels:tChannels; ActiveChannelsCount:word; ChlsClbData:tChannelsCalibrationData; ChlsCntData:tChannelsCountersData; RegimeDelayTime:word; PortsData:tPortsArray; end; tTmpCtrlData=record Flags:tTmpFlags; TimeInterval:tTimeInterval; IntegrationTime:word; { время интегрирования, которое было установлено при последнем запуске } end; tCtrl=object(c_Ctrl1.tCtrl) function Name:tName; virtual; { НЕисполняемые функции (без ввода/вывода в порты)} { Инициализация (без ввода/вывода в порты)} constructor InitDefault(var Bus:c_Bus.tCtrl); constructor Init(var Bus:c_Bus.tCtrl; Ports:tPorts); destructor Done; { Установка параметров (без ввода/вывода в порты)} procedure Regime(x:tRegime); procedure IntegrationTime(x:word); procedure RegimeDelayTime(x:word); function CurRegimeDelayTime:word; procedure SetActiveChannels(x:tChannels); procedure FastMode(x:boolean); { Чтение текущих значений счетчиков (последнее измерение, без ввода/вывода в порты)} function Channel(x:tChannel):tSignalData; { счетчик без преобразований } function ChannelU(x:tChannel):tMkVolts; { напряжение [мкВ]. Требует калибровки } function ChannelV(x:tChannel):double; { напряжение [В]. Требует калибровки } function ChannelsV(AChannels:tChannels; var AArrayOfDouble; ASize:byte):byte; { Чтение текущих значений параметров (без ввода/вывода в порты)} procedure CurActiveChannels(var x:tChannels); procedure CurRegime(var x:tRegime); function CurIntegrationTime:word; function CurFastMode:boolean; { среднее по каналам счетчиков X без преобразования } function CurAverageOverChannels(x:tChannels):tSignalData; function CurAverageOverActiveChannels:tSignalData; procedure SetNoError; virtual; procedure SetErrorCode(ec:tErrorCode); { Текст сообщения об ошибке (без ввода/вывода в порты)} function ErrorMessage(en:tErrorCode):string; virtual; { Сохранение/восстановление состояния контроллера } function DataSize:word; // procedure Save(var DataPtr:pointer); // procedure exRestore(var DataPtr:pointer); function Restore(var DataPtr:pointer):boolean; function Save(var DataPtr:pointer):boolean; { Исполняемые функции (ввод/вывод в порты)} procedure exInit; virtual; procedure exReInit; virtual; procedure exDone; virtual; procedure exCalibrate(U0, U1:tMkVolts); { калибровка счетчиков } procedure exCalibrateEx(U0, U1:tMkVolts; ChannelsSet:TChannels); procedure exCalibrateDefault; { калибровка счетчиков U0=0 мкВ; U1=-9000000 мкВ } function CalibrationValid:boolean; { TRUE - правильная калибровка счетчиков } procedure CalibrationSetInvalid; { принудительное снятие флага правильная калибровка счетчиков - вызывает перекалибровку } procedure exCalibrationRegime0; procedure exCalibrationRegime1; procedure CalibrationDataGet(cl:tChannel; var K,U0:tMkVolts); procedure CalibrationDataSet(cl:tChannel; K,U0:tMkVolts); procedure CalibrationDataGetV(cl:tChannel; var K{,U0}:double); procedure CalibrationDataSetV(cl:tChannel; K{,U0}:double); procedure exGetData; { запуск измерения и чтение данных} procedure exGetDataFromAllChannels(var x:tChannelsCountersData); procedure exStart; { запуск измерения } function exReady:boolean; { проверка готовности к чтению данных } function exWaitReady:boolean; { ожидание готовности к чтению данных } { чтение данных (с ожиданием готовности) во внутренний буфер} procedure exRead; { чтение данных (с ожиданием готовности) в X} procedure exReadAllChannels(var x:tChannelsCountersData); { чтение данных (БЕЗ ожидания готовности) в X} procedure exJustReadAllChannels(var x:tChannelsCountersData); procedure exRegime; { переустановка текущего режима } procedure exRegimeSet(r:tRegime); { установка режима } procedure exResetAll; { полный аппаратный сброс и инициализация } procedure exDetectCtrl(var x:tCtrlAlive); virtual; private prBusPtr:c_Bus.tCtrlPtr; prData:tData; prTmpData:tTmpCtrlData; procedure GetAllCounters(var x:tChannelsCountersData); procedure SetAllCounters(const x:tChannelsCountersData); { СКРЫТЫЕ Исполняемые функции (ввод/вывод в порты)} procedure exInitialReset; function exWaitTime(t:tTiks):boolean; { ожидание готовности к чтению данных } function exWait:boolean; { ожидание готовности к чтению данных } function exLazyWaitTime(t:tTiks):boolean; { ожидание готовности к чтению данных } function exWaitShort:boolean; { ожидание готовности (короткий интервал) } procedure DelayWait; procedure exResetTrigger; procedure exResetRegime; { реальная установка режима } procedure exResetTimer; procedure exResetCounters; procedure exStartCount; function exReadChannel(x:tChannel):tSignalData; {Процедуры сохранения значений в портах} procedure exReadPortsData(var PD:tPortsArray); procedure exSavePortsData; function exIsNotChangedPortsData:boolean; procedure ClearPortsData; function ErrorMessageEx(en:tErrorCode):string; { Вспомогательные функции определния наличия питания, см. exIsPowerON} function PortsNumber:word; virtual; function exReadSafePorts(var PortsValues:tPortValuesArray; Count:word):boolean; virtual; end; IMPLEMENTATION USES {$IFDef LogPortIO} SysUtils, PortsIOLog,{$EndIF Def LogPortIO} xStrings, DataSave; const cCtrlAlive=3; { число портов <>$FF для "живого" контроллера, используется для детектирования наличия } cCVF_ReadyMask=1; cCVF_CountInProgress=1; cCNF_CountComplete=0; cCVFCalibrationCoeff=100; bitRegime_BaseVoltageIsZero= (1 shl 0); { иначе опора -9V} bitRegime_InputSignalDataIsMagnet=(1 shl 1); { иначе на вход подана шина опоры } bitRegime_DoNotInvertSignalData= (1 shl 2); { иначе входной сигнал инвертируется } cDefaultPorts:tPorts=( { Управление контроллером } rwReset_Start: $7C; rwGate_ResetInt: $7D; owRegime: $7E; rwReady_SuspendCount:$7F; { Управление таймером } owTimerControl:$78; rwTimerChannel1:$7A; rwTimerChannel0:$7B; { Запись управляющих слов } owCtrl:( owLo123:$60; owHi123:$64; owLo456:$68; owHi456:$6C; owLo789:$70; owHi789:$74 ); { Чтение данных } rwData:( rwLo1:$63; rwHi1:$67; rwLo2:$62; rwHi2:$66; rwLo3:$61; rwHi3:$65; rwLo4:$6B; rwHi4:$6F; rwLo5:$6A; rwHi5:$6E; rwLo6:$69; rwHi6:$6D; rwLo7:$73; rwHi7:$77; rwLo8:$72; rwHi8:$76; rwLo9:$71; rwHi9:$75 ) ); {------------------------------------------------------------------------} { Инициализация (без ввода/вывода в порты)} constructor tCtrl.Init(var Bus:c_Bus.tCtrl; Ports:tPorts); var i:tChannel; begin Inherited Init; prBusPtr:=@Bus; prData.Ports:=Ports; prData.Flags:=[]; prTmpData.IntegrationTime:=0; prTmpData.Flags:=[]; prTmpData.TimeInterval.Start(1); Regime(cDefaultRegime); IntegrationTime(cDefaultIntegrationTime); SetActiveChannels(cDefaultChannels); TimeOut(cDefaultTimeOut); RegimeDelayTime(cDefaultDelayTime); for i:=tChannel(1) to tChannel(9) do begin prData.ChlsCntData[i]:=0; prData.ChlsClbData[i].K:=0; prData.ChlsClbData[i].U0:=0; prData.ChlsClbData[i].Kx:=1.0; // prData.ChlsClbData[i].U0xx:=0.0; end; ClearPortsData; If (Bus.Error) {and (NoError)} then begin SetErrorCode(tErrorCode(ecBadBus)); end; end; constructor tCtrl.InitDefault(var Bus:c_Bus.tCtrl); begin Init(Bus, cDefaultPorts); end; destructor tCtrl.Done; begin Inherited Done; prData.Flags:=[]; end; function tCtrl.Name; begin Name:='CVF'; end; (*procedure tCtrl.exRestore; begin CheckExInitDone; Inherited exRestore(DataPtr); RestoreData(DataPtr, prData, SizeOf(prData)); if NoError then begin exInitialReset; exResetAll; end; end; *) (*procedure tCtrl.Save; begin exSavePortsData; Inherited Save(DataPtr); StoreData(DataPtr, prData, SizeOf(prData)); end;*) function tCtrl.Restore(var DataPtr:pointer):boolean; begin Restore:=FALSE; if Inherited Restore(DataPtr) then begin if RestoreDataEx(DataPtr, prData, SizeOf(prData)) then begin prTmpData.Flags:=prTmpData.Flags-[fResetCtrlDone, fResetChannelsDone, fResetRegimeDone, fResetParametersDone ]; Restore:=TRUE; end; end; end; function tCtrl.Save(var DataPtr:pointer):boolean; begin if Inherited Save(DataPtr) then Save:=StoreDataEx(DataPtr, prData, SizeOf(prData)) else Save:=FALSE; end; function tCtrl.DataSize:word; begin DataSize:=Inherited DataSize + DataSave.SizeOfData(SizeOf(prData)); end; {------------------------------------------------------------------------} { Установка параметров (без ввода/вывода в порты)} procedure tCtrl.Regime(x:tRegime); begin if prData.Regime<>x then begin prData.Regime:=x; Exclude(prTmpData.Flags, fResetRegimeDone); end; end; procedure tCtrl.IntegrationTime(x:word); begin if prData.IntegrationTime<>x then begin prData.IntegrationTime:=x; Exclude(prTmpData.Flags, fResetParametersDone); end; end; procedure tCtrl.RegimeDelayTime(x:word); begin prData.RegimeDelayTime:=x; end; function tCtrl.CurRegimeDelayTime:word; begin CurRegimeDelayTime:=prData.RegimeDelayTime; end; procedure tCtrl.SetActiveChannels(x:tChannels); var i:tChannel; begin if prData.Channels<>x then begin prData.Channels:=x; prData.ActiveChannelsCount:=0; for i:=1 to 9 do begin if not (i in x) then begin prData.ChlsCntData[i]:=0; end else begin Inc(prData.ActiveChannelsCount); end; end; { Exclude(prData.Flags, fParametersDone);} CalibrationSetInvalid; end; end; procedure tCtrl.FastMode(x:boolean); begin if x then Include(prData.Flags,fFastStart) else Exclude(prData.Flags,fFastStart); end; {------------------------------------------------------------------------} { Чтение текущих значений параметров (без ввода/вывода в порты)} function tCtrl.Channel(x:tChannel):tSignalData; begin Channel:=prData.ChlsCntData[x]; end; function tCtrl.CurAverageOverChannels(x:tChannels):tSignalData; { среднее по каналам счетчиков X без преобразования } var i:tChannel; c, c1:tSignalData; count:word; ac:tChannels; begin c:=0; CurActiveChannels(ac); x:=x*ac; count:=0; for i:=1 to 9 do if (i in x) then Inc(count); if Count>0 then begin c1:=0; for i:=1 to 9 do if (i in x) then begin Inc(c, (prData.ChlsCntData[i] div count)); Inc(c1, (prData.ChlsCntData[i] mod count)); end; c:=c+(c1 div Count); end; CurAverageOverChannels:=c; end; function tCtrl.CurAverageOverActiveChannels:tSignalData; { среднее по каналам счетчиков X без преобразования } begin CurAverageOverActiveChannels:=CurAverageOverChannels(prData.Channels); end; function tCtrl.ChannelU(x:tChannel):tMkVolts; begin ChannelU:=( (prData.ChlsClbData[x].K*prData.ChlsCntData[x]+prData.ChlsClbData[x].U0) + (cCVFCalibrationCoeff div 2)) div cCVFCalibrationCoeff; end; function tCtrl.ChannelV(x:tChannel):double; { напряжение [В]. Требует калибровки } begin ChannelV:=prData.ChlsClbData[x].Kx*prData.ChlsCntData[x]/prTmpData.IntegrationTime {+prData.ChlsClbData[x].U0x}; end; function tCtrl.ChannelsV(AChannels:tChannels; var AArrayOfDouble; ASize:byte):byte; type tAD=array[byte] of double; var max,j:word; c:tChannel; begin if ASize>Succ(Ord(High(tChannel))) then max:=Succ(Ord(High(tChannel))) else max:=ASize; j:=0; for c:=Low(tChannel) to High(tChannel) do if c in AChannels then begin if j0 then begin // Вычисления для фиксированной точки { Вычисление коэффициента мкВольт/(импульс*сек) } prData.ChlsClbData[i].K:= ((dU*cCVFCalibrationCoeff+(dN div 2)) div dN ) * dT; prData.ChlsClbData[i].U0:= (U0*cCVFCalibrationCoeff)-((prData.ChlsClbData[i].K*N0[i]+dT05) div dT); // Вычисления для плавающей точки { Вычисление коэффициента [Вольт/(импульс*сек)] } prData.ChlsClbData[i].Kx:=(dU*dT)/dN/1E6; { Вычисление уровня нуля [Вольт] } { Вычисление уровня 0 не используется - нет смысла, учитывается это в нулевом уровне сигнала prData.ChlsClbData[i].U0x:=U0/1E6-prData.ChlsClbData[i].Kx*N0[i]/dT;} end else begin SetErrorCode(tErrorCode(ecFailCalibrate0)); Break; end; end; end; if NoError then Include(prData.Flags, fCalibrationValid); Regime(OldRegime); exRegime; prBusPtr^.Delay(CurRegimeDelayTime*4); end; OperationTimeReset(0); end; procedure tCtrl.exCalibrateDefault; begin exCalibrate(0, -9000000); end; procedure tCtrl.CalibrationDataGet(cl:tChannel; var K:tMkVolts; var U0:tMkVolts); begin K :=prData.ChlsClbData[cl].K; U0:=prData.ChlsClbData[cl].U0; end; procedure tCtrl.CalibrationDataSet(cl:tChannel; K:tMkVolts; U0:tMkVolts); begin prData.ChlsClbData[cl].K:= K; prData.ChlsClbData[cl].U0:=U0; end; procedure tCtrl.CalibrationDataGetV(cl:tChannel; var K{,U0}:double); begin K :=prData.ChlsClbData[cl].Kx; // U0:=prData.ChlsClbData[cl].U0xx; end; procedure tCtrl.CalibrationDataSetV(cl:tChannel; K{,U0}:double); begin prData.ChlsClbData[cl].Kx:= K; // prData.ChlsClbData[cl].U0xx:=U0; end; procedure tCtrl.exRegime; { установка рабочего режима } begin CheckExInitDone; OperationTimeSet(CurTimeOut); if exWait then begin exResetRegime; end; end; procedure tCtrl.exRegimeSet(r:tRegime); begin Regime(r); exRegime; end; procedure tCtrl.exStart; begin {$IfDef LogPortIO} PortsIOLog.LogStrLn('-----------StartCVF'); {$EndIf Def LogPortIO} OperationTimeReSet(2*CurTimeOut); CheckExInitDone; exResetRegime; exResetTrigger; if (fFastStart in prData.Flags) then begin if not (fResetChannelsDone in prTmpData.Flags) then exResetCounters; if not (fResetParametersDone in prTmpData.Flags) then exResetTimer; end else begin exResetCounters; exResetTimer; end; exWaitShort; exStartCount; end; function tCtrl.exReady:boolean; begin exReady:=FALSE; CheckExInitDone; if NoError then begin exReady:=((prBusPtr^.exInByte(prData.Ports.rwReady_SuspendCount) and cCVF_ReadyMask) = cCNF_CountComplete); if prBusPtr^.Error then begin SetErrorCode(tErrorCode(ecFailReadReady)); end; end; end; procedure tCtrl.exRead; begin exReadAllChannels(prData.ChlsCntData); OperationTimeReset(0); end; procedure tCtrl.exReadAllChannels; begin CheckExInitDone; exWaitReady; exJustReadAllChannels(x); end; procedure tCtrl.exJustReadAllChannels; var i:tChannel; begin if NoError then begin for i:=1 to 9 do begin if i in prData.Channels then begin x[i]:=exReadChannel(i); end else begin x[i]:=0; end; end; if prBusPtr^.Error then begin SetErrorCode(tErrorCode(ecFailReadChannel)); end; end; end; procedure tCtrl.exResetAll; begin CheckExInitDone; exResetTrigger; exWaitShort; exResetCounters; exResetRegime; exResetTimer; exStartCount; exResetTrigger; end; {------------------------------------------------------------------------} procedure tCtrl.SetNoError; begin prBusPtr^.SetErrorCode(0); Inherited SetNoError; end; procedure tCtrl.SetErrorCode(ec:tErrorCode); begin Inherited SetErrorCode(ec); if ec <> 0 then prData.Flags:=[]; end; { Текст сообщения об ошибке (без ввода/вывода в порты)} function tCtrl.ErrorMessageEx(en:tErrorCode):string; begin case tErrorCodes(en) of ecFailResetController: ErrorMessageEx:='Ошибка команды Reset контроллера'; ecFailResetChannel: ErrorMessageEx:='Ошибка команды ResetChannel'; ecFailResetTimer: ErrorMessageEx:='Ошибка команды ResetTimer'; ecFailResetRegime: ErrorMessageEx:='Ошибка команды ResetRegime'; ecFailInit: ErrorMessageEx:='Ошибка инициализации'; ecFailReadReady: ErrorMessageEx:='Ошибка чтения байта состояния ReadReady'; ecFailStart: ErrorMessageEx:='Ошибка запуска счета Start'; ecWaitReadyTimeOut: ErrorMessageEx:='Истекло время ожидания заверщения счета WaitReady'; ecFailReadChannel: ErrorMessageEx:='Ошибка чтения счетчиков (ReadChannel)'; ecBadControllerState: ErrorMessageEx:='Ошибочное состояние контроллера'; else ErrorMessageEx:=Inherited ErrorMessage(en); end; end; function tCtrl.ErrorMessage(en:tErrorCode):string; begin ErrorMessage:=ErrorMessageEx(en)+' (ПНЧ)'; end; {------------------------------------------------------------------------} { * PRIVATE секция } { СКРЫТЫЕ Исполняемые функции (ввод/вывод в порты)} procedure tCtrl.GetAllCounters; begin x:=prData.ChlsCntData; end; procedure tCtrl.SetAllCounters; begin prData.ChlsCntData:=x; end; procedure tCtrl.exResetCounters; var i:byte; const h3474B4:array[1..3] of byte=($34, $74, $B4); hFFFF :array[1..2] of byte=($FF, $FF); begin if NoError then begin for i:=Low(tControlPortsNumber) to High(tControlPortsNumber) do begin prBusPtr^.exOutBytes(prData.Ports.owCtrl.Port[i], h3474B4, SizeOf(h3474B4)); end; for i:=Low(tDataPortsNumber) to High(tDataPortsNumber) do begin prBusPtr^.exOutBytes(prData.Ports.rwData.Port[i], hFFFF, SizeOf(hFFFF)); end; if prBusPtr^.NoError then begin Include(prTmpData.Flags, fResetChannelsDone); Exclude(prTmpData.Flags, fResetParametersDone); end else begin SetErrorCode(tErrorCode(ecFailResetChannel)); end; end; end; procedure tCtrl.exResetTimer; var IntTime:word; begin if NoError then begin prBusPtr^.exOutByte(prData.Ports.owTimerControl, $32); IntTime:=prData.IntegrationTime; prBusPtr^.exOutBytes(prData.Ports.rwTimerChannel0, IntTime, 2); if prBusPtr^.NoError then prTmpData.IntegrationTime:=IntTime; if prBusPtr^.Error then begin SetErrorCode(tErrorCode(ecFailResetTimer)); end; end; end; procedure tCtrl.exResetRegime; begin if (NoError) and not (fResetRegimeDone in prTmpData.Flags) then begin prBusPtr^.exOutByte(prData.Ports.owRegime, Byte(prData.Regime)); if prBusPtr^.Error then begin SetErrorCode(tErrorCode(ecFailResetRegime)); end else begin { задержка на срабатывание реле } OperationTimeSet(CurRegimeDelayTime); prBusPtr^.Delay(CurRegimeDelayTime); Include(prTmpData.Flags, fResetRegimeDone); end; end; end; procedure tCtrl.exResetTrigger; begin if NoError then begin prBusPtr^.exInByte(prData.Ports.rwReset_Start); if prBusPtr^.NoError then begin Include(prTmpData.Flags,fInitialResetDone) end else begin SetErrorCode(tErrorCode(ecFailResetController)); end; end; end; function tCtrl.exWaitTime(t:tTiks):boolean; var t0:tTiks; begin if NoError then begin exWaitTime:=TRUE; t0:=OperationTime; OperationTimeSet(t); if prBusPtr^.exWait(prData.Ports.rwReady_SuspendCount, cCVF_ReadyMask, cCNF_CountComplete, t)<>0 then begin SetErrorCode(tErrorCode(ecWaitReadyTimeOut)); exWaitTime:=FALSE; end else begin OperationTimeReset(t0); end; end else begin exWaitTime:=FALSE; end; end; procedure tCtrl.DelayWait; var t{,t1}:longint; const cDt=10; begin If not exReady then begin t:=IntelliTimeOut(prTmpData.IntegrationTime,0); // t1:=prTmpData.TimeInterval.TimeLeft; Dec(t,cDt); // Dec(t1,cDt); if t>0 then begin prBusPtr^.Delay(t); // prBusPtr^.Delay(t1); end; end; end; function tCtrl.exWait:boolean; begin exWait:=exWaitTime(prTmpData.IntegrationTime+CurTimeOut); end; function tCtrl.exLazyWaitTime(t:tTiks):boolean; begin if not exReady then begin exLazyWaitTime:=TRUE; t:=IntelliTimeOut(t,CurTimeOut); if prBusPtr^.exLazyWait(prData.Ports.rwReady_SuspendCount, cCVF_ReadyMask, cCNF_CountComplete, t, 1)<>0 then begin SetErrorCode(tErrorCode(ecWaitReadyTimeOut)); exLazyWaitTime:=FALSE; end; end else begin exLazyWaitTime:=TRUE; end; end; function tCtrl.exWaitReady:boolean; { ожидание готовности к чтению данных } begin DelayWait; exWaitReady:=exLazyWaitTime(prTmpData.IntegrationTime+CurTimeOut); end; function tCtrl.exWaitShort:boolean; begin exWaitShort:=exWaitTime(CurTimeOut); end; procedure tCtrl.exStartCount; const cZW:word=0; begin if NoError then begin prBusPtr^.exOutByte(prData.Ports.rwGate_ResetInt, 0); prBusPtr^.exOutBytes(prData.Ports.rwReady_SuspendCount, cZW, 2); prBusPtr^.exOutByte(prData.Ports.rwReset_Start, 0); prTmpData.TimeInterval.Start(prTmpData.IntegrationTime); MarkTime; if (prTmpData.IntegrationTime>=300) and (prBusPtr^.exLazyWait(prData.Ports.rwReady_SuspendCount, cCVF_ReadyMask, cCVF_CountInProgress, CurTimeOut,0)<>0) then begin SetErrorCode(tErrorCode(ecFailStart)); end else begin OperationTimeReSet(prTmpData.IntegrationTime+CurTimeOut); end; end; end; function tCtrl.exReadChannel(x:tChannel):tSignalData; type tChannelInputData=record case byte of 0:(l:longint); 1:(w1,w2:word); end; var d:tChannelInputData; begin prBusPtr^.exInBytes(prData.Ports.rwData.DblPort[x].rwLo, d.w1, 2); prBusPtr^.exInBytes(prData.Ports.rwData.DblPort[x].rwHi, d.w2, 2); asm not d.l; end; { Dec(d.w1);}{ ??? может это лишнее? } exReadChannel:=d.l; end; procedure tCtrl.exDetectCtrl(var x:tCtrlAlive); var c:word; begin c:=prBusPtr^.exScanNotFFports(prData.Ports, (SizeOf(prData.Ports) shr 1)); case c of cCtrlAlive:x:=aYes; 0: x:=aNo; else if c>=(cCtrlAlive shr 1) then x:=aMayBeYes else x:=aMayBeNo; end; end; procedure tCtrl.exReadPortsData; var i,j:word; begin ClearPortsDataX(PD); if NoError then begin for i:=Ord(Low(tPort)) to Ord(High(tPort)) do begin if prBusPtr^.NoError then begin if not (tPort(i) in cUnreadablePorts) then PD[i]:=prBusPtr^.exInByte(prData.Ports.Ports[tPort(i)]); end else begin SetErrorCode(Ord(ecFailReadPortsData)); break; end; end; end; if (NoError) then begin j:=Succ(Ord(High(tPort))); for i:=1 to 18 do begin if prBusPtr^.NoError then begin PD[j]:=prBusPtr^.exInByte(prData.Ports.rwData.Port[i]); PD[Succ(j)]:=prBusPtr^.exInByte(prData.Ports.rwData.Port[i]); end else begin SetErrorCode(Ord(ecFailReadPortsData)); break; end; Inc(j,2); end; end; end; procedure tCtrl.exSavePortsData; begin exReadPortsData(prData.PortsData); end; procedure tCtrl.ClearPortsData; begin ClearPortsDataX(prData.PortsData); end; function tCtrl.exIsNotChangedPortsData:boolean; var PD:tPortsArray; begin exReadPortsData(pd); exIsNotChangedPortsData:=Equal(PD,prData.PortsData,SizeOf(PD)); end; procedure tCtrl.exCalibrationRegime0; begin Regime(cCalibrationRegime0); exRegime; prBusPtr^.Delay(CurRegimeDelayTime); end; procedure tCtrl.exCalibrationRegime1; begin Regime(cCalibrationRegime1); exRegime; prBusPtr^.Delay(CurRegimeDelayTime); end; function tCtrl.PortsNumber:word; begin PortsNumber:=Succ(Ord(High(tPort)))+2*2*9 {9 каналов счетчиков по 2 порта на канал по 2 байта с порта}; end; function tCtrl.exReadSafePorts(var PortsValues:tPortValuesArray; Count:word):boolean; var i:tPort; n,j:word; begin exReadSafePorts:=FALSE; if NoError and (Count=PortsNumber) then begin for i:=Low(tPort) to High(tPort) do begin if prBusPtr^.NoError then begin if not (i in cUnreadablePorts) then PortsValues[Ord(i)]:=prBusPtr^.exInByte(prData.Ports.Ports[i]) else PortsValues[Ord(i)]:=$FF; end else begin SetErrorCode(Ord(ecFailReadPortsData)); break; end; end; if (NoError) then begin j:=Succ(Ord(High(tPort))); for n:=1 to 18 do begin if prBusPtr^.NoError then begin prBusPtr^.exInBytes(prData.Ports.rwData.Port[n],PortsValues[j],2); end else begin SetErrorCode(Ord(ecFailReadPortsData)); break; end; Inc(j,2); end; end; if prBusPtr^.Error then SetErrorCode(Ord(ecFailReadPortsData)) else exReadSafePorts:=TRUE; end; end; END.