{ Контроллер ПНЧ 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; { мс - задержка на срабатывание реле } cStartWaitMaxTimeout=100; { мс - макс. время ожидания запуска счета } 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, fCtrlIsReady); 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; { время интегрирования, которое было установлено при последнем запуске } LazyWaitTimeInterval: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); virtual; { Текст сообщения об ошибке (без ввода/вывода в порты)} 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 exJustReadAllChannelsX(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; {Время ожидания запуска счета} function StartWaitTimeout:word; { Вспомогательные функции определния наличия питания, см. exIsPowerON} function PortsNumber:word; virtual; function exReadSafePorts(var PortsValues:tPortValuesArray; Count:word):boolean; virtual; end; IMPLEMENTATION USES {DriverPortsIO,} Windows, MI1201ioctl, {$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; prTmpData.IntegrationTime:=0; prTmpData.Flags:=[]; prTmpData.TimeInterval.Start(1); prTmpData.LazyWaitTimeInterval:=cLazyWaitTimeIntervalMax; prBusPtr:=@Bus; prData.Ports:=Ports; prData.Flags:=[]; 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; 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; if x<=cLazyWaitTimeIntervalMax then prTmpData.LazyWaitTimeInterval:=cLazyWaitTimeIntervalMax else prTmpData.LazyWaitTimeInterval:=cLazyWaitTimeIntervalMin; 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); Exclude(prTmpData.Flags, fCtrlIsReady); 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; var xResult:boolean; begin xResult:=fCtrlIsReady in prTmpData.Flags; CheckExInitDone; if NoError and not xResult then begin xResult:=((prBusPtr^.exInByte(prData.Ports.rwReady_SuspendCount) and cCVF_ReadyMask) = cCNF_CountComplete); if prBusPtr^.Error then begin SetErrorCode(tErrorCode(ecFailReadReady)); end; if xResult then Include(prTmpData.Flags, fCtrlIsReady); end; exReady:=xResult; end; procedure tCtrl.exRead; begin exReadAllChannels(prData.ChlsCntData); OperationTimeReset(0); end; procedure tCtrl.exReadAllChannels; begin CheckExInitDone; exWaitReady; exJustReadAllChannels(x); end; procedure tCtrl.exJustReadAllChannelsX; 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.exJustReadAllChannels; type tChannelInputData=record case byte of 0:(l:tSignalData); 1:(w1,w2:word); end; tChnls=1..9; tCmd0=packed record ReadW1:tGENPORT_MULTIFUNCTION_IO_READ_BUFFER_INPUT; ReadW2:tGENPORT_MULTIFUNCTION_IO_READ_BUFFER_INPUT; end; tCmdArr=packed record Count:ULONG; // число операций в буфере Chnls:array[tChnls] of tCmd0; end; tResultData0=packed record ReadW1:tGENPORT_MULTIFUNCTION_IO_READ_BUFFER_OUTPUT; ReadW2:tGENPORT_MULTIFUNCTION_IO_READ_BUFFER_OUTPUT; end; tResultData=packed record Header:tGENPORT_MULTIFUNCTION_IO_OUTPUT_HEADER; Chnls:array[tChnls] of tResultData0; end; const Cmd:tCmdArr=( Count:0; ); var ResultData:tResultData; i:tChannel; d:tChannelInputData; begin if NoError then begin with Cmd do begin if Count=0 then begin Count:=18; Chnls[Low(i)].ReadW1.Header.OpCode.ULong:=Ord(mfocReadBuffer); Chnls[Low(i)].ReadW1.Port.Number:=0; Chnls[Low(i)].ReadW1.Port.PortType:=Ord(PORT_UCHAR); Chnls[Low(i)].ReadW1.Count:=2; Chnls[Low(i)].ReadW2:=Chnls[Low(i)].ReadW1; for i:=Low(i) to High(i) do begin Chnls[i]:=Chnls[Low(i)]; {1) чтение слова 1 } Chnls[i].ReadW1.Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwData.DblPort[i].rwLo); {2) чтение слова 2 } Chnls[i].ReadW2.Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwData.DblPort[i].rwHi); end; end; end; if prBusPtr^.exMultifunctionIO(Cmd, SizeOf(Cmd), ResultData, SizeOf(ResultData))=0 then begin for i:=Low(i) to High(i) do begin if i in prData.Channels then begin d.w1:=not ResultData.Chnls[i].ReadW1.Data.UShort[0]; d.w2:=not ResultData.Chnls[i].ReadW2.Data.UShort[0]; { Dec(d.w1);}{ ??? может это лишнее? } x[i]:=d.l; end else begin x[i]:=0; end; end; end else 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; type tCmd=packed record Count:ULONG; // число операций в буфере WriteCtlWord:array[tControlPortsNumber] of tGENPORT_MULTIFUNCTION_IO_WRITE_BUFFER_INPUT; WriteInitCounter:array[tDataPortsNumber] of tGENPORT_MULTIFUNCTION_IO_WRITE_BUFFER_INPUT; end; tResultData=packed record Header:tGENPORT_MULTIFUNCTION_IO_OUTPUT_HEADER; end; var {Cmd:tCmd;} ResultData:tResultData; const Cmd:tCmd=( Count:0; ); begin if NoError then begin Exclude(prTmpData.Flags, fCtrlIsReady); with Cmd do begin if Count=0 then begin Count:=Succ(High(tControlPortsNumber)-Low(tControlPortsNumber)) +Succ(High(tDataPortsNumber)-Low(tDataPortsNumber)); {1) запись управляющего слова таймера } WriteCtlWord[Low(tControlPortsNumber)].Header.OpCode.ULong:=Ord(mfocWriteBuffer); WriteCtlWord[Low(tControlPortsNumber)].Port.PortType:=Ord(PORT_UCHAR); WriteCtlWord[Low(tControlPortsNumber)].Count:=3; WriteCtlWord[Low(tControlPortsNumber)].Data.ULong[0]:=$3474B4; { управляющие слово таймеров для счетчика ионов} {2) инициализация счетчика таймера } WriteInitCounter[Low(tDataPortsNumber)].Header.OpCode.ULong:=Ord(mfocWriteBuffer); WriteInitCounter[Low(tDataPortsNumber)].Port.PortType:=Ord(PORT_UCHAR); WriteInitCounter[Low(tDataPortsNumber)].Count:=2; WriteInitCounter[Low(tDataPortsNumber)].Data.ULong[0]:=$FFFF; { байты для записи в счетчики при инициализации } for i:=Low(tControlPortsNumber) to High(tControlPortsNumber) do begin WriteCtlWord[i]:=WriteCtlWord[Low(tControlPortsNumber)]; WriteCtlWord[i].Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.owCtrl.Port[i]); end; for i:=Low(tDataPortsNumber) to High(tDataPortsNumber) do begin WriteInitCounter[i]:=WriteInitCounter[Low(tDataPortsNumber)]; WriteInitCounter[i].Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwData.Port[i]); end; end; end; if prBusPtr^.exMultifunctionIO(Cmd, SizeOf(Cmd), ResultData, SizeOf(ResultData))=0 then begin Include(prTmpData.Flags, fResetChannelsDone); Exclude(prTmpData.Flags, fResetParametersDone); end else begin SetErrorCode(tErrorCode(ecFailResetChannel)); end; end; end; (*procedure tCtrl.exResetCounters; var i:byte; type tCmd=packed record Count:ULONG; // число операций в буфере WriteCtlWord:array[tControlPortsNumber] of tGENPORT_MULTIFUNCTION_IO_WRITE_BUFFER_INPUT; WriteInitCounter:array[tDataPortsNumber] of tGENPORT_MULTIFUNCTION_IO_WRITE_BUFFER_INPUT; end; tResultData=packed record Header:tGENPORT_MULTIFUNCTION_IO_OUTPUT_HEADER; end; var Cmd:tCmd; ResultData:tResultData; begin if NoError then begin Exclude(prTmpData.Flags, fCtrlIsReady); with Cmd do begin Count:=Succ(High(tControlPortsNumber)-Low(tControlPortsNumber)) +Succ(High(tDataPortsNumber)-Low(tDataPortsNumber)); {1) запись управляющего слова таймера } WriteCtlWord[Low(tControlPortsNumber)].Header.OpCode.ULong:=Ord(mfocWriteBuffer); WriteCtlWord[Low(tControlPortsNumber)].Port.PortType:=Ord(PORT_UCHAR); WriteCtlWord[Low(tControlPortsNumber)].Count:=3; WriteCtlWord[Low(tControlPortsNumber)].Data.ULong[0]:=$3474B4; { управляющие слово таймеров для счетчика ионов} {2) инициализация счетчика таймера } WriteInitCounter[Low(tDataPortsNumber)].Header.OpCode.ULong:=Ord(mfocWriteBuffer); WriteInitCounter[Low(tDataPortsNumber)].Port.PortType:=Ord(PORT_UCHAR); WriteInitCounter[Low(tDataPortsNumber)].Count:=2; WriteInitCounter[Low(tDataPortsNumber)].Data.ULong[0]:=$FFFF; { байты для записи в счетчики при инициализации } end; for i:=Low(tControlPortsNumber) to High(tControlPortsNumber) do begin with Cmd do begin WriteCtlWord[i]:=WriteCtlWord[Low(tControlPortsNumber)]; WriteCtlWord[i].Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.owCtrl.Port[i]); end; end; for i:=Low(tDataPortsNumber) to High(tDataPortsNumber) do begin with Cmd do begin WriteInitCounter[i]:=WriteInitCounter[Low(tDataPortsNumber)]; WriteInitCounter[i].Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwData.Port[i]); end; end; if prBusPtr^.exMultifunctionIO(Cmd, SizeOf(Cmd), ResultData, SizeOf(ResultData))=0 then begin Include(prTmpData.Flags, fResetChannelsDone); Exclude(prTmpData.Flags, fResetParametersDone); end else begin SetErrorCode(tErrorCode(ecFailResetChannel)); end; end; 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 Exclude(prTmpData.Flags, fCtrlIsReady); 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; type tCmd=packed record Count:ULONG; // число операций в буфере WriteTimerCtrl:tGENPORT_MULTIFUNCTION_IO_WRITE_INPUT; WriteTimeout:tGENPORT_MULTIFUNCTION_IO_WRITE_BUFFER_INPUT; end; tResultData=packed record Header:tGENPORT_MULTIFUNCTION_IO_OUTPUT_HEADER; end; var ResultData:tResultData; const Cmd:tCmd=( Count:0; WriteTimerCtrl:( Header:(OpCode:(ULong:Ord(mfocWrite))); Port:(Number:0; PortType:Ord(PORT_UCHAR)); Data:(UChar:$32); { управляющие слово таймера для ПНЧ} ); WriteTimeOut:( Header:(OpCode:(ULong:Ord(mfocWriteBuffer))); Port:( Number:0; PortType:Ord(PORT_UCHAR)); Count:2; ); ); begin if NoError then begin Exclude(prTmpData.Flags, fCtrlIsReady); with Cmd do begin if Count=0 then begin Count:=2; {1) запись управляющего слова таймера } WriteTimerCtrl.Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.owTimerControl); {2) запись времени интегрирования таймера} WriteTimeOut.Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwTimerChannel0); end; WriteTimeOut.Data.ULong[0]:=prData.IntegrationTime; end; if prBusPtr^.exMultifunctionIO(Cmd, SizeOf(Cmd), ResultData, SizeOf(ResultData))=0 then begin prTmpData.IntegrationTime:=Cmd.WriteTimeOut.Data.ULong[0]; end else begin SetErrorCode(tErrorCode(ecFailResetTimer)); end; end; end; (* procedure tCtrl.exResetTimer; var IntTime:word; begin if NoError then begin Exclude(prTmpData.Flags, fCtrlIsReady); 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 Exclude(prTmpData.Flags, fCtrlIsReady); 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 Exclude(prTmpData.Flags, fCtrlIsReady); 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; if fCtrlIsReady in prTmpData.Flags then Exit; t0:=OperationTime; OperationTimeSet(t); if prBusPtr^.exLazyWaitNTE(prData.Ports.rwReady_SuspendCount, cCVF_ReadyMask, cCNF_CountComplete, t,cLazyWaitTimeIntervalMin)<>0 then begin SetErrorCode(tErrorCode(ecWaitReadyTimeOut)); exWaitTime:=FALSE; end else begin Include(prTmpData.Flags, fCtrlIsReady); OperationTimeReset(t0); end; end else begin exWaitTime:=FALSE; end; end; procedure tCtrl.DelayWait; var t:longint; begin If not exReady then begin t:=IntelliTimeOut(prTmpData.IntegrationTime,0); Dec(t,cLazyWaitTimeIntervalMin); if t>0 then begin prBusPtr^.Delay(t); 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^.exLazyWaitNTE(prData.Ports.rwReady_SuspendCount, cCVF_ReadyMask, cCNF_CountComplete, t, prTmpData.LazyWaitTimeInterval)<>0 then begin SetErrorCode(tErrorCode(ecWaitReadyTimeOut)); exLazyWaitTime:=FALSE; end else begin Include(prTmpData.Flags, fCtrlIsReady); 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; function tCtrl.StartWaitTimeout:word; begin if cStartWaitMaxTimeout>prTmpData.IntegrationTime then begin StartWaitTimeout:=prTmpData.IntegrationTime; end else begin StartWaitTimeout:=cStartWaitMaxTimeout; end; end; procedure tCtrl.exStartCount; type tStartCmd=packed record Count:ULONG; // число операций в буфере WaitReady:tGENPORT_MULTIFUNCTION_IO_WAIT_INPUT; Write1:tGENPORT_MULTIFUNCTION_IO_WRITE_INPUT; WriteBuff1:tGENPORT_MULTIFUNCTION_IO_WRITE_BUFFER_INPUT; WriteAndWait1:tGENPORT_MULTIFUNCTION_IO_WRITE_AND_WAIT_INPUT; end; tStartResult=packed record Header:tGENPORT_MULTIFUNCTION_IO_OUTPUT_HEADER; WaitReadyResult:tGENPORT_MULTIFUNCTION_IO_WAIT_OUTPUT; WriteAndWaitResult1:tGENPORT_MULTIFUNCTION_IO_WRITE_AND_WAIT_OUTPUT; end; var StartResult:tStartResult; const StartCmd:tStartCmd=( Count:0; { дождаться готовности } WaitReady:( Header:(OpCode:(ULong:Ord(mfocWait))); WaitData:( Port:(PortType:Ord(PORT_UCHAR)); TimeOut:0; // Время ожидания в мс TimeResolution:1; // Интервал опроса порта в мс Mask:cCVF_ReadyMask; // Маска Patt:cCNF_CountComplete;// Образец ControlFlags:0; // Флаги (битовые) управления ожиданием ); ); { установить Gate } Write1:( Header:(OpCode:(ULong:Ord(mfocWrite))); Port:(PortType:Ord(PORT_UCHAR)); Data:(UChar:0); ); { досчитать 2 импульса } WriteBuff1:( Header:(OpCode:(ULong:Ord(mfocWriteBuffer))); Port:(PortType:Ord(PORT_UCHAR)); Count:2; Data:(ULong:(0)); ); { запустить и ждать старта } WriteAndWait1:( Header:(OpCode:(ULong:Ord(mfocWriteAndWait))); Data:( WriteData:( Port:(PortType:Ord(PORT_UCHAR)); Data:(ULong:0); ); WaitData:( Port:(PortType:Ord(PORT_UCHAR)); TimeResolution:0; Mask:cCVF_ReadyMask; Patt:cCVF_CountInProgress; ControlFlags: (1 shl Ord(wcfWaitOnDISPATCH_Level)); ); ); ); ); begin if NoError then begin OperationTimeReSet(2*CurTimeOut); Exclude(prTmpData.Flags, fCtrlIsReady); with StartCmd do begin if Count=0 then begin Count:=4; { дождаться готовности } WaitReady.WaitData.Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwReady_SuspendCount); { установить Gate } Write1.Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwGate_ResetInt); { досчитать 2 импульса } WriteBuff1.Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwReady_SuspendCount); { запустить и ждать старта } WriteAndWait1.Data.WriteData.Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwReset_Start); WriteAndWait1.Data.WaitData.Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwReady_SuspendCount); end; WaitReady.WaitData.TimeOut:=CurTimeout; WriteAndWait1.Data.WaitData.TimeOut:=StartWaitTimeout; end; prTmpData.TimeInterval.Start(prTmpData.IntegrationTime); if ( prBusPtr^.exMultifunctionIO(StartCmd, SizeOf(StartCmd), StartResult, SizeOf(StartResult))<>0) then begin SetErrorCode(tErrorCode(ecFailStart)); end else if not StartResult.WaitReadyResult.Event then begin SetErrorCode(tErrorCode(ecWaitReadyTimeOut)); end else begin MarkTime; OperationTimeReSet(prTmpData.IntegrationTime+CurTimeOut); if not StartResult.WriteAndWaitResult1.Event then begin if (prTmpData.IntegrationTime>1000) then SetErrorCode(tErrorCode(ecFailStart)); end; end; end; end; (*procedure tCtrl.exStartCount; type tStartCmd=packed record Count:ULONG; // число операций в буфере Write1:tGENPORT_MULTIFUNCTION_IO_WRITE_INPUT; WriteBuff1:tGENPORT_MULTIFUNCTION_IO_WRITE_BUFFER_INPUT; WriteAndWait1:tGENPORT_MULTIFUNCTION_IO_WRITE_AND_WAIT_INPUT; end; tStartResult=packed record Header:tGENPORT_MULTIFUNCTION_IO_OUTPUT_HEADER; WriteAndWaitResult1:tGENPORT_MULTIFUNCTION_IO_WRITE_AND_WAIT_OUTPUT; end; var StartCmd:tStartCmd; StartResult:tStartResult; begin if NoError then begin OperationTimeReSet(2*CurTimeOut); Exclude(prTmpData.Flags, fCtrlIsReady); with StartCmd do begin Count:=3; { установить Gate } Write1.Header.OpCode.ULong:=Ord(mfocWrite); Write1.Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwGate_ResetInt); Write1.Port.PortType:=Ord(PORT_UCHAR); Write1.Data.UChar:=0; { досчитать 2 импульса } WriteBuff1.Header.OpCode.ULong:=Ord(mfocWriteBuffer); WriteBuff1.Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwReady_SuspendCount); WriteBuff1.Port.PortType:=Ord(PORT_UCHAR); WriteBuff1.Count:=2; WriteBuff1.Data.ULong[0]:=0; { запустить и ждать старта } WriteAndWait1.Header.OpCode.ULong:=Ord(mfocWriteAndWait); WriteAndWait1.Data.WriteData.Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwReset_Start); WriteAndWait1.Data.WriteData.Port.PortType:=Ord(PORT_UCHAR); WriteAndWait1.Data.WriteData.Data.ULong:=0; WriteAndWait1.Data.WaitData.Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwReady_SuspendCount); WriteAndWait1.Data.WaitData.Port.PortType:=Ord(PORT_UCHAR); WriteAndWait1.Data.WaitData.TimeOut:=StartWaitTimeout; WriteAndWait1.Data.WaitData.TimeResolution:=0; WriteAndWait1.Data.WaitData.Mask:=cCVF_ReadyMask; WriteAndWait1.Data.WaitData.Patt:=cCVF_CountInProgress; WriteAndWait1.Data.WaitData.ControlFlags:= (1 shl Ord(wcfWaitOnDISPATCH_Level)); end; MarkTime; prTmpData.TimeInterval.Start(prTmpData.IntegrationTime); if ( prBusPtr^.exMultifunctionIO(StartCmd, SizeOf(StartCmd), StartResult, SizeOf(StartResult))<>0) then begin SetErrorCode(tErrorCode(ecFailStart)); end else if not StartResult.WriteAndWaitResult1.Event then begin if (prTmpData.IntegrationTime>1000) then SetErrorCode(tErrorCode(ecFailStart)); end; OperationTimeReSet(prTmpData.IntegrationTime+CurTimeOut); end; end;*) (*procedure tCtrl.exStartCount; const cZW:word=0; begin if NoError then begin Exclude(prTmpData.Flags, fCtrlIsReady); 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 ( prBusPtr^.exOutByteAndWait( prData.Ports.rwReset_Start, 0, prData.Ports.rwReady_SuspendCount, cCVF_ReadyMask, cCVF_CountInProgress, StartWaitTimeout )<>0 ) then begin if (prTmpData.IntegrationTime>=300) then SetErrorCode(tErrorCode(ecFailStart)); end else begin OperationTimeReSet(prTmpData.IntegrationTime+CurTimeOut); end; { 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:tSignalData); 1:(w1,w2:word); end; tCmd=packed record Count:ULONG; // число операций в буфере ReadW1:tGENPORT_MULTIFUNCTION_IO_READ_BUFFER_INPUT; ReadW2:tGENPORT_MULTIFUNCTION_IO_READ_BUFFER_INPUT; end; tResultData=packed record Header:tGENPORT_MULTIFUNCTION_IO_OUTPUT_HEADER; ReadW1:tGENPORT_MULTIFUNCTION_IO_READ_BUFFER_OUTPUT; ReadW2:tGENPORT_MULTIFUNCTION_IO_READ_BUFFER_OUTPUT; end; var ResultData:tResultData; const Cmd:tCmd=( Count:2; ReadW1:( Header:(OpCode:(ULong:Ord(mfocReadBuffer))); Port:( Number:0; PortType:Ord(PORT_UCHAR)); Count:2; ); ReadW2:( Header:(OpCode:(ULong:Ord(mfocReadBuffer))); Port:( Number:0; PortType:Ord(PORT_UCHAR) ); Count:2; ); ); // var ChkData:tGENPORT_MULTIFUNCTION_IO_OPERATION_CHECK_OUTPUT_BUFFER; var d:tChannelInputData; begin with Cmd do begin {1) чтение слова 1 } ReadW1.Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwData.DblPort[x].rwLo); {2) чтение слова 2 } ReadW2.Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwData.DblPort[x].rwHi); end; // DriverPortsIO.CheckMultifunctionIO(Cmd, SizeOf(Cmd), ChkData); if prBusPtr^.exMultifunctionIO(Cmd, SizeOf(Cmd), ResultData, SizeOf(ResultData))=0 then begin d.w1:=not ResultData.ReadW1.Data.UShort[0]; d.w2:=not ResultData.ReadW2.Data.UShort[0]; end else begin Self.SetErrorCode(tErrorCode(ecFailReadChannel)); end; { Dec(d.w1);}{ ??? может это лишнее? } exReadChannel:=d.l; end; (* function tCtrl.exReadChannel(x:tChannel):tSignalData; type tChannelInputData=record case byte of 0:(l:tSignalData); 1:(w1,w2:word); end; tCmd=packed record Count:ULONG; // число операций в буфере ReadW1:tGENPORT_MULTIFUNCTION_IO_READ_BUFFER_INPUT; ReadW2:tGENPORT_MULTIFUNCTION_IO_READ_BUFFER_INPUT; end; tResultData=packed record Header:tGENPORT_MULTIFUNCTION_IO_OUTPUT_HEADER; ReadW1:tGENPORT_MULTIFUNCTION_IO_READ_BUFFER_OUTPUT; ReadW2:tGENPORT_MULTIFUNCTION_IO_READ_BUFFER_OUTPUT; end; var Cmd:tCmd; ResultData:tResultData; // var ChkData:tGENPORT_MULTIFUNCTION_IO_OPERATION_CHECK_OUTPUT_BUFFER; var d:tChannelInputData; begin with Cmd do begin Count:=2; {1) чтение слова 1 } ReadW1.Header.OpCode.ULong:=Ord(mfocReadBuffer); ReadW1.Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwData.DblPort[x].rwLo); ReadW1.Port.PortType:=Ord(PORT_UCHAR); ReadW1.Count:=2; {2) чтение слова 2 } ReadW2.Header.OpCode.ULong:=Ord(mfocReadBuffer); ReadW2.Port.Number:=prBusPtr^.PortShift2Port(prData.Ports.rwData.DblPort[x].rwHi); ReadW2.Port.PortType:=Ord(PORT_UCHAR); ReadW2.Count:=2; end; // DriverPortsIO.CheckMultifunctionIO(Cmd, SizeOf(Cmd), ChkData); if prBusPtr^.exMultifunctionIO(Cmd, SizeOf(Cmd), ResultData, SizeOf(ResultData))=0 then begin d.w1:=not ResultData.ReadW1.Data.UShort[0]; d.w2:=not ResultData.ReadW2.Data.UShort[0]; end else begin Self.SetErrorCode(tErrorCode(ecFailReadChannel)); end; { Dec(d.w1);}{ ??? может это лишнее? } exReadChannel:=d.l; end;*) (* function tCtrl.exReadChannel(x:tChannel):tSignalData; type tChannelInputData=record case byte of 0:(l:tSignalData); 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.