{ Функции MathCAD } {--------------------------------------------------------------------------- The control program for mass-spectrometer MI1201-AGM (c) Copyright Aleksandrov O.E., 2001 Molecular Physics department, USTU, Ekaterinsburg, K-2, 620002, RUSSIA phone 75-47-15 E-mail: aleks@dpt.ustu.ru Программа управления масс-спектрометром МИ1201-АГМ (c) Собственность Александрова О.Е., 2001 620002, Екатеринбург, К-2, УГТУ, Кафедра молекулярной физики тел. 75-47-15 E-mail: aleks@dpt.ustu.ru ----------------------------------------------------------------------------} unit MCAD_MI1201; interface // НИКАКОГО ИНТЕРФЕЙСА - все регистрируется вызовом специальной функции MathCAD implementation Uses Windows, SysUtils, McadUserTypes, McadUserEx, MCAD_MI1201_Interface, c_Mi1201, MITypes, MCAD_MI1201_Range, MCAD_MI1201_Thread, MCAD_MI1201_Thread_Types, MCAD_MI1201_Types, MCAD_MiscFuncs, MCAD_MI1201_Errors, MCAD_MI1201_RangeCheck; const cMaxIntegrationTime=High(word)-10; {миллисекунд} const GetInfoInfo:FUNCTIONINFO=( lpstrName:'msInfo'; lpstrParameters:'n'; lpstrDescription:'Возвращает сведения о состоянии приборапри n=: 0 - код ошибки; 1 - калибровка массы; 2 - диапазон.'; lpfnMyCFunction:NIL; returnType:COMPLEX_ARRAY; nArgs:1; argType:(COMPLEX_SCALAR,0,0,0,0,0,0,0,0,0) ); GetBDateInfo:FUNCTIONINFO=( lpstrName:'msGetBDate'; lpstrParameters:'n'; lpstrDescription:'Возвращает дату фонового измерения. n=0:(начало, конец); n=1:(начало); n=2:(конец) .'; lpfnMyCFunction:NIL; returnType:COMPLEX_ARRAY; nArgs:1; argType:(COMPLEX_SCALAR,0,0,0,0,0,0,0,0,0) ); GetDataInfo:FUNCTIONINFO=( lpstrName:'msGetData'; lpstrParameters:'n, M_min, M_max'; lpstrDescription:'Возвращает данные измерения для канала n=0..8 или всех каналов (n<>0..8) на момент вызова.'; lpfnMyCFunction:NIL; returnType:COMPLEX_ARRAY; nArgs:3; argType:(COMPLEX_SCALAR,COMPLEX_SCALAR,COMPLEX_SCALAR,0,0,0,0,0,0,0) ); GetBPointInfo:FUNCTIONINFO=( lpstrName:'msB'; lpstrParameters:'n,i'; lpstrDescription:'Возвращает данные фонового измерения для канала n=0..8 точку с индексом i на момент вызова.'; lpfnMyCFunction:NIL; returnType:COMPLEX_SCALAR; nArgs:2; argType:(COMPLEX_SCALAR,COMPLEX_SCALAR,0,0,0,0,0,0,0,0) ); { BDataInfo:FUNCTIONINFO=( lpstrName:'msBData'; lpstrParameters:'A, n'; lpstrDescription:'Возвращает данные фонового измерения для всех каналов на момент вызова в массив А.'; lpfnMyCFunction:NIL; returnType:COMPLEX_ARRAY; nArgs:2; argType:(COMPLEX_ARRAY, COMPLEX_SCALAR,0,0,0,0,0,0,0,0) );} GetColumnInfo:FUNCTIONINFO=( lpstrName:'msGetBColumn'; lpstrParameters:'N'; lpstrDescription:'Возвращает данные фонового измерения для канала N на момент вызова.'; lpfnMyCFunction:NIL; returnType:COMPLEX_ARRAY; nArgs:1; argType:(COMPLEX_SCALAR,0,0,0,0,0,0,0,0,0) ); SetParameterInfo:FUNCTIONINFO=( lpstrName:'msParameter'; lpstrParameters:'N, X'; lpstrDescription:'Устанавливает для параметра номер N значение X. '+ 'Возвращает установленное значение.'; lpfnMyCFunction:NIL; returnType:COMPLEX_SCALAR; nArgs:2; argType:(COMPLEX_SCALAR,COMPLEX_SCALAR,0,0,0,0,0,0,0,0) ); InterfaceControlInfo:FUNCTIONINFO=( lpstrName:'msControl'; lpstrParameters:'N, X'; lpstrDescription:'Управление интерфейсом. Устанавливает для параметра номер N значение X. '+ 'Возвращает установленное значение.'; lpfnMyCFunction:NIL; returnType:COMPLEX_SCALAR; nArgs:2; argType:(COMPLEX_SCALAR,COMPLEX_SCALAR,0,0,0,0,0,0,0,0) ); ValveControlInfo:FUNCTIONINFO=( lpstrName:'msValve'; lpstrParameters:'Клапан,Время'; lpstrDescription:'Открывает и закрывает вентили напуска "Клапан"=3-9 на время "Время", иначе все закрывается.'; lpfnMyCFunction:NIL; returnType:COMPLEX_ARRAY; nArgs:2; argType:(COMPLEX_SCALAR,COMPLEX_SCALAR,0,0,0,0,0,0,0,0) ); RangesInfo:FUNCTIONINFO=( lpstrName:'msRanges'; lpstrParameters:'RangesArray'; lpstrDescription:'Устанавливает диапазоны измерения шкалы масс и параметры измерения.'; lpfnMyCFunction:NIL; returnType:COMPLEX_SCALAR; nArgs:1; argType:(COMPLEX_ARRAY,0,0,0,0,0,0,0,0,0) ); SetCalibrationInfo:FUNCTIONINFO=( lpstrName:'msMassCalibration'; lpstrParameters:'M0,K'; lpstrDescription:'устанавливает соответствие счетчик(N)-масса(M) по формуле M=M0+K*(N*N).'; lpfnMyCFunction:NIL; returnType:COMPLEX_ARRAY; nArgs:2; argType:(COMPLEX_SCALAR,COMPLEX_SCALAR,0,0,0,0,0,0,0,0) ); SetIMChCalibrationInfo:FUNCTIONINFO=( lpstrName:'msIMChCalibration'; lpstrParameters:'M0,K'; lpstrDescription:'устанавливает соответствие счетчик(N)-индикатор массовых чисел(M) по формуле M=M0+K*(N*N).'; lpfnMyCFunction:NIL; returnType:COMPLEX_ARRAY; nArgs:2; argType:(COMPLEX_SCALAR,COMPLEX_SCALAR,0,0,0,0,0,0,0,0) ); Counter2MassInfo:FUNCTIONINFO=( lpstrName:'msCounter2Mass'; lpstrParameters:'C'; lpstrDescription:'возвращает массу, соответствующую значению счетчика C.'; lpfnMyCFunction:NIL; returnType:COMPLEX_SCALAR; nArgs:1; argType:(COMPLEX_SCALAR,0,0,0,0,0,0,0,0,0) ); Mass2CounterInfo:FUNCTIONINFO=( lpstrName:'msMass2Counter'; lpstrParameters:'M'; lpstrDescription:'возвращает значение счетчика, соответствующее массе M.'; lpfnMyCFunction:NIL; returnType:COMPLEX_SCALAR; nArgs:1; argType:(COMPLEX_SCALAR,0,0,0,0,0,0,0,0,0) ); GetDataByMassInfo:FUNCTIONINFO=( lpstrName:'msGetData'; lpstrParameters:'M'; lpstrDescription:'возвращает для массы M соответствующие значения сигналов со всех каналов.'; lpfnMyCFunction:NIL; returnType:COMPLEX_ARRAY; nArgs:1; argType:(COMPLEX_SCALAR,0,0,0,0,0,0,0,0,0) ); { GetBDataXInfo:FUNCTIONINFO=( lpstrName:'msBDataX'; lpstrParameters:'A'; lpstrDescription:'устанавливает массив для получения данных фонового измерения.'; lpfnMyCFunction:NIL; returnType:COMPLEX_SCALAR; nArgs:1; argType:(COMPLEX_ARRAY,0,0,0,0,0,0,0,0,0) );} // Установка диапазонов масс function Ranges(var FuncResult:COMPLEXSCALAR; const Ranges:COMPLEXARRAY ):LRESULT; cdecl; var i,n:integer; r:tRange; b:MCAD_MI1201_Range.tFlags; begin Result:=TryInit; if Result<>0 then Exit; if Ranges.cols=0 then Exit; if Ranges.rows<2 then begin Result:=MakeErrorResult(ecINVALID_DIMENSION,1); Exit; end; for i:=0 to Pred(Ranges.cols) do begin if Ranges.rows>3 then begin Result:=CheckS_IMmP(Ranges.hReal[i,3],0,High(word),1); if Result<>0 then Exit; end; if Ranges.rows>4 then begin b:=cRangeFlags; Result:=CheckS_IMmP(Ranges.hReal[i,4],0,Byte(b),1); if Result<>0 then Exit; end; end; MsThread.Stop; MsThread.Ranges.Clear; n:=0; for i:=0 to Pred(Ranges.cols) do begin try r:=MsThread.Ranges.New; r.Description:='MathCAD'; r.Min:=Ranges.hReal[i,0]; r.Max:=Ranges.hReal[i,1]; if Ranges.rows>2 then begin r.Step:=Ranges.hReal[i,2]; end; if Ranges.rows>3 then begin if (Ranges.hReal[i,3]=0) then r.IntegrationTime:=0 else r.IntegrationTime:=Trunc(Ranges.hReal[i,3]); end; if Ranges.rows>4 then begin Byte(b):=Trunc(Ranges.hReal[i,4]); r.Enabled:=not (fInactiveRange in b); r.ClearOnStart:=(fClearRange in b); r.UseExistingPoints:=(fUseExistingPoints in b); if (fGlobalAccumulation in b) then r.Accumulation:=rsUseGlobal else if (fAccumulation in b) then r.Accumulation:=rsYes else r.Accumulation:=rsNo; end; Inc(n); except Result:=MakeErrorResult(ecUnknownError,1); Exit; end; end; // MsTread.Resume; FuncResult.Real:=n; end; // Получение информации по состоянию прибора function GetInfo(var FuncResult:COMPLEXARRAY; const InfoType:COMPLEXSCALAR ):LRESULT; cdecl; var lParNumber:tParameter; c:tController; ec:word; r:tRange; i:integer; begin Result:=CheckCS_RIMP(InfoType,Ord(High(lParNumber)),1); if Result<>0 then Exit; {Result:=}TryInit; lParNumber:=tParameter(ABS(Trunc(InfoType.real))); case lParNumber of pErrorCode:begin // Код ошибки и где возникла Result:=Ord(xMathcadArrayAllocate(FuncResult,3,1,TRUE,FALSE)); end; pRanges:begin // Диапазон Result:=Ord(xMathcadArrayAllocate(FuncResult,5,MsThread.Ranges.Count,TRUE,FALSE)); end; pBDateTime, // Дата начала и конца измерения pMassCalibration, // Калибровка шкалы масс pIMChCalibration // Калибровка ИНДИКАТОРА шкалы масс :begin Result:=Ord(xMathcadArrayAllocate(FuncResult,2,1,TRUE,FALSE)); end; pValve // Открытый клапан(ы) :begin Result:=Ord(xMathcadArrayAllocate(FuncResult,4,1,TRUE,FALSE)); end; pDateTime, // Дата время системного таймера pIntegrationTime, // Время интегрирования pMagnetFieldStabilization: // Автостабилизация магн. поля begin Result:=Ord(xMathcadArrayAllocate(FuncResult,1,1,TRUE,FALSE)); end; pIndex,pMass,pCounter: begin // Текущий индекс фонового измерени Result:=Ord(xMathcadArrayAllocate(FuncResult,3,1,TRUE,FALSE)); end; pEqupmentFlags: begin // Флаги ОШИБКА, ПЕРЕГРУЗКА и КАТОД_СГОРЕЛ Result:=Ord(xMathcadArrayAllocate(FuncResult,3,1,TRUE,FALSE)); end; else begin Result:=Ord(ecINVALID_PARAMETER_VALUE); end; end; if Result<>0 then Exit; case lParNumber of pErrorCode:begin // Код ошибки и где возникла ec:=MsThread.HardwareError; FuncResult.hReal[0,0]:=ec; if ec<>0 then begin c:=MsThread.DriverErrorGetFirstCtrlWith; if c<>None then begin FuncResult.hReal[0,1]:=Succ(Ord(c)); FuncResult.hReal[0,2]:=MsThread.DriverErrorCodeFromSubCtrl(c); end; end; end; pMassCalibration:begin // Калибровка шкалы масс MsThread.CalibrationGet(FuncResult.hReal[0,1],FuncResult.hReal[0,0]); end; pIMChCalibration:begin // Калибровка ИНДИКАТОРА шкалы масс MsThread.IMChCalibrationGet(FuncResult.hReal[0,1],FuncResult.hReal[0,0]); end; pRanges:begin // Диапазоны try for i:=0 to Pred(MsThread.Ranges.Count) do begin r:=MsThread.Ranges[i]; FuncResult.hReal[i,0]:=r.Min; FuncResult.hReal[i,1]:=r.Max; FuncResult.hReal[i,2]:=r.Step; FuncResult.hReal[i,3]:=r.IntegrationTime; FuncResult.hReal[i,3]:=Byte(r.Flags); end; except Result:=Ord(ecUnknownError); end; end; pBDateTime:begin // Дата начала и конца измерения FuncResult.hReal[0,0]:=MsThread.StartDateTime; FuncResult.hReal[0,1]:=MsThread.EndDateTime; end; pValve:begin // Открытый клапан(ы) FuncResult.hReal[0,0]:=Source2ValveNum(MsThread.Valve); FuncResult.hReal[0,1]:=MsThread.ValveAutoCloseTime; FuncResult.hReal[0,2]:=MsThread.ValveOpenedTime; FuncResult.hReal[0,3]:=MsThread.ValveAutoCloseTimeLeft; end; pIndex,pMass,pCounter:begin // Текущий индекс фонового измерени FuncResult.hReal[0,0]:=MsThread.Mass; FuncResult.hReal[0,1]:=MsThread.Counter; FuncResult.hReal[0,2]:=MsThread.RangeActiveIndex; // FuncResult.hReal[0,3]:=gMsThread.BMass; end; pDateTime:begin // Дата время системного таймера FuncResult.hReal[0,0]:=Now(); end; pIntegrationTime:begin // Время интегрирования FuncResult.hReal[0,0]:=MsThread.IntegrationTime; end; pEqupmentFlags: begin // Флаги ОШИБКА, ПЕРЕГРУЗКА и КАТОД_СГОРЕЛ FuncResult.hReal[0,0]:=Ord(efFlagsUnavailable in MsThread.EqupmentFlags); FuncResult.hReal[0,1]:=Ord(efOverload in MsThread.EqupmentFlags); FuncResult.hReal[0,2]:=Ord(efCatodBurnOUT in MsThread.EqupmentFlags); end; pMagnetFieldStabilization: begin // Автостабилизация магн. поля FuncResult.hReal[0,0]:=Ord(MsThread.AutoTuning); end; else begin Result:=Ord(ecINVALID_PARAMETER_VALUE); end; end; if Result<>0 then begin MathcadArrayFree(FuncResult); end; // SetReady; end; // Получение даты фонового измерени function GetBDate(var FuncResult:COMPLEXARRAY; const DateType:COMPLEXSCALAR ):LRESULT; cdecl; var lDateType:word; begin Result:=TryInit; if Result<>0 then Exit; Result:=CheckCS_RIMP(DateType,2,1); if Result<>0 then Exit; lDateType:=Trunc(DateType.real); case lDateType of 0:begin // Начало и конец Result:=Ord(xMathcadArrayAllocate(FuncResult,2,1,TRUE,FALSE)); end; 1,2:begin // Начало или конец Result:=Ord(xMathcadArrayAllocate(FuncResult,1,1,TRUE,FALSE)); end; else begin Result:=Ord(ecINVALID_PARAMETER_VALUE); end; end; if Result<>0 then Exit; case lDateType of 0:begin // Начало и конец FuncResult.hReal[0,0]:=MsThread.StartDateTime; FuncResult.hReal[0,1]:=MsThread.EndDateTime; end; 1:begin // Начало FuncResult.hReal[0,0]:=MsThread.StartDateTime; end; 2:begin // Конец FuncResult.hReal[0,0]:=MsThread.EndDateTime; end; else begin MathcadArrayFree(FuncResult); Result:=Ord(ecINVALID_PARAMETER_VALUE); end; end; end; // 1) Получение данных фонового измерения ВСЕХ КАНАЛОВ // 2) Получение данных фонового измерения ОДНОГО КАНАЛА (*function GetBData(var FuncResult:COMPLEXARRAY; const n:COMPLEXSCALAR ):LRESULT; cdecl; var lN:integer; begin Result:=TryInit; if Result<>0 then Exit; // Result:=CheckCS_RIM(n,Pred(gMsThread.DataArrayCols),1); if Result<>0 then Exit; lN:=Trunc(n.Real); if lN<0 then begin { Result:=Ord(xMathcadArrayAllocate(FuncResult, gMsThread.DataArrayRows,gMsThread.DataArrayCols, TRUE,FALSE));} end else begin // Result:=Ord(xMathcadArrayAllocate(FuncResult,gMsThread.DataArrayRows,1,TRUE,FALSE)); end; if Result<>0 then Exit; if lN<0 then begin // if not gMsThread.DataArrayGet(FuncResult) then begin Result:=Ord(ecINVALID_PARAMETER_VALUE); // end; end else begin // if not gMsThread.DataColumnGet(lN,FuncResult) then begin Result:=Ord(ecINVALID_PARAMETER_VALUE); // end; end; FuncResult.hImag:=NIL; if (Result<>0) then MathcadArrayFree(FuncResult); end; *) // 1) Получение данных измерения КАНАЛОВ // 2) Получение данных измерения ОДНОГО КАНАЛА function GetData(var FuncResult:COMPLEXARRAY; const n:COMPLEXSCALAR; const Min:COMPLEXSCALAR; const Max:COMPLEXSCALAR ):LRESULT; cdecl; var ss:tSeriesSet; i,cols,rows:integer; StopONNoData:boolean; begin // Result:=TryInit; // if Result<>0 then Exit; ss:=[Low(tSeries)..High(tSeries)]; Result:=CheckCS_RIMm(n,-Byte(ss),Byte(ss),1); if Result<>0 then Exit; Result:=CheckCS_RMm(Min,0,10000,2); if Result<>0 then Exit; Result:=CheckCS_RMm(Max,0,10000,3); if Result<>0 then Exit; if Min.Real>Max.Real then begin Result:=MakeErrorResult(ecINVALID_PARAMETER_VALUE,1); Exit; end; StopONNoData:=n.Real<0; Byte(ss):=Trunc(Abs(n.Real)); if ss=[] then ss:=[Low(tSeries)..High(tSeries)]; rows:=MsThread.DataRangePointsCount(ss,Min.Real,Max.Real); cols:=Succ(MsThread.DataValidSeriesCount(ss)); if rows=0 then begin if StopONNoData then begin Result:=Ord(ecNoData); Exit; end else begin Result:=Ord(xMathcadArrayAllocate(FuncResult, 1, cols, TRUE,FALSE)); if Result<>0 then Exit; for i:=0 to Pred(cols) do begin FuncResult.hReal[i,0]:=0; end; end; end; Result:=Ord(xMathcadArrayAllocate(FuncResult, rows, cols, TRUE,FALSE)); if Result<>0 then Exit; if not MsThread.DataArrayGet(FuncResult,ss,Min.Real,Max.Real) then begin Result:=Ord(ecUnknownError); end; FuncResult.hImag:=NIL; if (Result<>0) then MathcadArrayFree(FuncResult); end; // Чтение данных с масс-спектрометра (ОДНА ТОЧКА НАПРЯМУЮ) function GetDataByMass(var FuncResult:COMPLEXARRAY; const Mass:COMPLEXSCALAR ):LRESULT; cdecl; const cMaxValue=High(cardinal) div 2; begin Result:=TryInit; if Result<>0 then Exit; Result:=CheckCS_RIMP(Mass,cMaxValue,1); if Result<>0 then Exit; Result:=CheckCS_RIMP(Mass,cMaxValue,2); if not MathcadArrayAllocate(FuncResult,9,1,TRUE,FALSE) then begin Result:=Ord(ecINSUFFICIENT_MEMORY); end else if not MsThread.DataPointGet(Mass.Real,FuncResult) then begin MathcadArrayFree(FuncResult); if CheckHardwareError then Result:=Ord(GlobalErrorCode) else begin Result:=Ord(ecINVALID_PARAMETER_VALUE); end; end; end; // Установка калибровки массы function SetCalibration(var FuncResult:COMPLEXARRAY; const Coeff,Mass0:COMPLEXSCALAR ):LRESULT; cdecl; begin Result:=TryInit; if Result<>0 then Exit; Result:=CheckCS_RP(Coeff,1); if Result<>0 then Exit; Result:=CheckCS_RP(Mass0,2); if not MathcadArrayAllocate(FuncResult,2,1,TRUE,FALSE) then Result:=Ord(ecINSUFFICIENT_MEMORY); if Result<>0 then Exit; if MsThread.CalibrationSet(Mass0.real, Coeff.real) then begin MsThread.CalibrationGet(FuncResult.hReal[0,1], FuncResult.hReal[0,0]); end else begin if CheckHardwareError then Result:=Ord(GlobalErrorCode) else Result:=Ord(ecINVALID_PARAMETER_VALUE); MathcadArrayFree(FuncResult); end; end; // Установка калибровки ИНДИКАТОРА массы function SetIMChCalibration( var FuncResult:COMPLEXARRAY; const Coeff,Mass0:COMPLEXSCALAR ):LRESULT; cdecl; begin Result:=TryInit; if Result<>0 then Exit; Result:=CheckCS_R(Coeff,1); if Result<>0 then Exit; Result:=CheckCS_R(Mass0,2); if Result<>0 then Exit; if not MathcadArrayAllocate(FuncResult,2,1,TRUE,FALSE) then Result:=Ord(ecINSUFFICIENT_MEMORY); if Result<>0 then Exit; try if (Mass0.real=0) and (Coeff.real=0) then begin MsThread.IMChCalibrationGet(FuncResult.hReal[0,1], FuncResult.hReal[0,0]); end else if (Mass0.real<0) and (Coeff.real<0) then begin MsThread.IMChCalibrationCalculate; MsThread.IMChCalibrationGet(FuncResult.hReal[0,1], FuncResult.hReal[0,0]); end else if MsThread.IMChCalibrationSet(Mass0.real, Coeff.real) then begin MsThread.IMChCalibrationRefineOrigin; MsThread.IMChCalibrationGet(FuncResult.hReal[0,1], FuncResult.hReal[0,0]); end else begin Result:=Ord(ecINVALID_PARAMETER_VALUE); MathcadArrayFree(FuncResult); end; except Result:=Ord(ecUnknownError); MathcadArrayFree(FuncResult); end; end; (*// Установка диапазона масс function SetRange(var FuncResult:COMPLEXARRAY; const MinCounter,MaxCounter,Step:COMPLEXSCALAR ):LRESULT; cdecl; var Min,Max:cardinal; S:integer; const cMaxValue=High(integer); begin Result:=TryInit; if Result<>0 then Exit; Result:=CheckCS_RIMP(MinCounter,cMaxValue,1); if Result<>0 then Exit; Result:=CheckCS_RIMP(MaxCounter,cMaxValue,2); if Result<>0 then Exit; Result:=CheckCS_RIM(Step,cMaxValue,3); if Result<>0 then Exit; if not MathcadArrayAllocate(FuncResult,4,1,TRUE,FALSE) then Result:=Ord(ecINSUFFICIENT_MEMORY); if Result<>0 then Exit; Min:=Trunc(MinCounter.real); Max:=Trunc(MaxCounter.real); S:=Trunc(Step.real); // case gMsThread.BCounterRangeSet(Min,Max,S) of // rOK:begin // FuncResult.hReal[0,0]:=Min; // FuncResult.hReal[0,1]:=Max; // FuncResult.hReal[0,2]:=S; // FuncResult.hReal[0,3]:=gMsThread.BIndexMax; // end; // rMin: Result:=MakeErrorResult(ecINVALID_PARAMETER_VALUE, 1); // rMax: Result:=MakeErrorResult(ecINVALID_PARAMETER_VALUE, 2); // rStep: Result:=MakeErrorResult(ecINVALID_PARAMETER_VALUE, 3); // rCantSetup: Result:=Ord(ecTIMEOUT); // else Result:=Ord(ecINVALID_PARAMETER_VALUE); // end; if Result<>0 then MathcadArrayFree(FuncResult); end; *) // Установка значений параметров масс-спектрометра function SetParameter(var FuncResult:COMPLEXSCALAR; const ParNumber:COMPLEXSCALAR; const ParValue:COMPLEXSCALAR ):LRESULT; cdecl; var lParValue:integer; lParNumber:tParameter; lDevice:c_MI1201.tDevice; const cMaxValue=High(integer); begin // Result:=TryInit; Result:=CheckCS_RIMm(ParNumber,-Ord(High(tParameter)),Ord(High(tParameter)),1); if Result<>0 then Exit; lParNumber:=tParameter(ABS(Trunc(ParNumber.real))); Result:=CheckCS_RM(ParValue,cMaxValue,2); if Result<>0 then Exit; lParValue:=Trunc(ParValue.real); if lParNumber=pErrorCode then begin if lParValue=0 then begin try MsThread.ResetError; FuncResult.Real:=MsThread.HardwareError; except SetUnhandledErrorCode; Result:=MakeErrorResult(ecUnknownError,1); end; end; Exit; end; Result:=TryInit; if Result<>0 then Exit; Result:=Ord(Wait); if Result<>0 then Exit; FuncResult.Imag:=0; case lParNumber of pErrorCode:begin FuncResult.Real:=Ord(MsThread.Error); end; pIntegrationTime: begin if (lParValue<=0) or(ABS(lParValue)>cMaxIntegrationTime) then begin Result:=MakeErrorResult(ecINVALID_PARAMETER_VALUE,2); end else begin try MsThread.IntegrationTime:=lParValue; FuncResult.Real:=MsThread.IntegrationTime; except SetUnhandledErrorCode; end; end; end; pClearData:begin try MsThread.Clear; FuncResult.Real:=1; except SetUnhandledErrorCode; Result:=MakeErrorResult(ecUnknownError,1); end; end; (* pMeasureType: begin if (lParValue<0) or (lParValue>Ord(High(tMeasureType))) then begin Result:=MakeErrorResult(ecINVALID_PARAMETER_VALUE,1); end else begin try MsThread.MeasureType:=tMeasureType(lParValue); FuncResult.Real:=Ord(MsThread.MeasureType); except SetUnhandledErrorCode; Result:=MakeErrorResult(ecUnknownError,1); end; end; end;*) pMassStep: begin try MsThread.MassStep:=lParValue; FuncResult.Real:=MsThread.MassStep; except SetUnhandledErrorCode; Result:=Ord(ecUnknownError); end; end; pStepMultiplicator: begin try MsThread.StepMultiplicator:=lParValue; FuncResult.Real:=MsThread.StepMultiplicator; except SetUnhandledErrorCode; Result:=Ord(ecUnknownError); end; end; pStartStop:begin try if (lParValue and 1)=0 then begin MsThread.Stop; end else begin if (lParValue and 2)<>0 then begin MsThread.Switches:=MsThread.Switches+[mstUseRanges]; end else begin MsThread.Switches:=MsThread.Switches-[mstUseRanges]; end; MsThread.Resume; end; FuncResult.Real:=Ord(MsThread.MeasureState); except SetUnhandledErrorCode; Result:=Ord(ecUnknownError); end; end; pIonizationVoltage, pEmissionCurrent, pExtractingVoltage, pFocusingVoltage, pCorrectionX, pCorrectionZ, pSEM_Voltage: begin lDevice:=Parameter2Device(lParNumber); try MsThread.Device[lDevice]:=lParValue; FuncResult.Real:=MsThread.Device[lDevice]; except Result:=MakeErrorResult(ecINVALID_PARAMETER_VALUE,2); end; end; pMagnetFieldStabilization: begin // Автостабилизация магн. поля try MsThread.AutoTuning:=(lParValue<>0); FuncResult.Real:=Ord(MsThread.AutoTuning); except SetUnhandledErrorCode; Result:=Ord(ecUnknownError); end; end; pMass: begin // Текущая масса try if lParValue=0 then begin end else if lParValue>0 then begin MsThread.Mass:=ParValue.real; end else begin MsThread.MassX:=Abs(ParValue.real); end; FuncResult.Real:=MsThread.Mass; except SetUnhandledErrorCode; Result:=Ord(ecUnknownError); end; end; pCounter: begin // Текущий счетчик try if lParValue=0 then begin end else if lParValue>0 then begin MsThread.Counter:=lParValue; end else begin MsThread.CounterX:=lParValue; end; except SetUnhandledErrorCode; Result:=Ord(ecUnknownError); end; FuncResult.Real:=MsThread.Counter; end; pIMChCalibration: begin // Калибровка (вычисление) индикатора массовых чисел if lParValue>0 then begin try MsThread.IMChCalibrationCalculate; FuncResult.Real:=1; except SetUnhandledErrorCode; Result:=Ord(ecUnknownError); end; end else begin FuncResult.Real:=MsThread.Counter; end; end; else begin Result:=MakeErrorResult(ecINVALID_PARAMETER_NUMBER,1); end; end; if Result=0 then Result:=Ord(GlobalErrorCode); SetReady; end; // Открытие-закрытие вентилей function ValvesControl(var FuncResult:COMPLEXARRAY; const Valve:COMPLEXSCALAR; const Time:COMPLEXSCALAR ):LRESULT; cdecl; var v:integer; s:tSource; t:integer; begin Result:=TryInit; if Result<>0 then Exit; Result:=CheckCS_RIMm(Valve,-High(word),High(word),1); if Result<>0 then Exit; Result:=CheckCS_RIMm(Time,Low(integer),High(integer),2); if Result<>0 then Exit; if not MathcadArrayAllocate(FuncResult,4,1,TRUE,FALSE) then Result:=Ord(ecINSUFFICIENT_MEMORY); if Result<>0 then Exit; v:=Trunc(Valve.real); t:=Trunc(Time.real); try s:=ValveNum2Source(Abs(v)); if v>=0 then MsThread.Valve:=s; if t>=0 then MsThread.ValveAutoCloseTimes[s]:=t; if CheckHardwareError then begin Result:=Ord(GlobalErrorCode); end else begin FuncResult.hReal[0,0]:=Source2ValveNum(MsThread.Valve); FuncResult.hReal[0,1]:=MsThread.ValveAutoCloseTime; FuncResult.hReal[0,2]:=MsThread.ValveOpenedTime; FuncResult.hReal[0,3]:=MsThread.ValveAutoCloseTimeLeft; end; except SetUnhandledErrorCode; Result:=MakeErrorResult(ecUnknownError,1); end; end; // Преобразование счетчик-масса function Counter2Mass(var FuncResult:COMPLEXSCALAR; const Counter:COMPLEXSCALAR ):LRESULT; cdecl; const cMaxValue=High(integer); begin // Result:=TryInit; // if Result<>0 then Exit; Result:=CheckCS_RIMP(Counter,cMaxValue,1); if Result<>0 then Exit; try FuncResult.real:=MsThread.Counter2Mass(Trunc(Counter.real)); except SetUnhandledErrorCode; Result:=MakeErrorResult(ecUnknownError, 1); end; end; // Преобразование масса-счетчик function Mass2Counter(var FuncResult:COMPLEXSCALAR; const Mass:COMPLEXSCALAR ):LRESULT; cdecl; const cMaxValue=High(integer); begin // Result:=TryInit; // if Result<>0 then Exit; Result:=CheckCS_RP(Mass,1); if Result<>0 then Exit; try FuncResult.real:=MsThread.Mass2Counter(Mass.real); except Result:=MakeErrorResult(ecINVALID_PARAMETER_VALUE, 1); end; end; // Установка параметров интерфейса масс-спектрометра function InterfaceControl( var FuncResult:COMPLEXSCALAR; const ParNumber:COMPLEXSCALAR; const ParValue:COMPLEXSCALAR ):LRESULT; cdecl; var lParValue:integer; lParNumber:tParameter; const cMaxValue=High(integer); begin Result:=CheckCS_RIMm(ParNumber,-Ord(High(tParameter)),Ord(High(tParameter)),1); if Result<>0 then Exit; Result:=CheckCS_RIM(ParValue,cMaxValue,2); if Result<>0 then Exit; lParNumber:=tParameter(ABS(Trunc(ParNumber.real))); lParValue:=Trunc(ParValue.real); case lParNumber of // Управление интерфейсом pInterface: begin if lParValue>0 then begin FuncResult.real:=1.0; Result:=Ord(LoadInterface); end else begin FuncResult.real:=0.0; Result:=Ord(UnloadVisualInterface); end; end; // Управление переключателями pSwitches: begin if lParValue>0 then begin MsThread.Switches:=tMSSwitches(lParValue)*cSwitchesMask; end; FuncResult.real:=Cardinal(MsThread.Switches); end; pSwitchesON: begin if lParValue>0 then begin MsThread.Switches:=MsThread.Switches+tMSSwitches(lParValue)*cSwitchesMask; end; FuncResult.real:=Cardinal(MsThread.Switches); end; pSwitchesOFF: begin if lParValue>0 then begin MsThread.Switches:=MsThread.Switches-tMSSwitches(lParValue)*cSwitchesMask; end; FuncResult.real:=Cardinal(MsThread.Switches); end; pSwitchesGet: begin if lParValue<>0 then FuncResult.real:=Cardinal(MsThread.Switches*(tMSSwitches(lParValue)*cSwitchesMask)) else FuncResult.real:=Cardinal(MsThread.Switches); end; pErrorCode: begin if lParValue=0 then begin try MsThread.ResetError; FuncResult.Real:=Ord(MsThread.Error); except SetUnhandledErrorCode; Result:=MakeErrorResult(ecUnknownError,1); end; end else begin try FuncResult.Real:=Ord(MsThread.Error); except end; end; end; else begin Result:=MakeErrorResult(ecINVALID_PARAMETER_NUMBER,1); end; end; end; // регистрирует функции в MathCAD-е procedure RegisterFunctions; begin InterfaceControlInfo.lpfnMyCFunction:=@InterfaceControl; CreateUserFunction(SysInit.hInstance, InterfaceControlInfo); SetParameterInfo.lpfnMyCFunction:=@SetParameter; CreateUserFunction(SysInit.hInstance, SetParameterInfo); Counter2MassInfo.lpfnMyCFunction:=@Counter2Mass; CreateUserFunction(SysInit.hInstance, Counter2MassInfo); Mass2CounterInfo.lpfnMyCFunction:=@Mass2Counter; CreateUserFunction(SysInit.hInstance, Mass2CounterInfo); ValveControlInfo.lpfnMyCFunction:=@ValvesControl; CreateUserFunction(SysInit.hInstance, ValveControlInfo); GetDataInfo.lpfnMyCFunction:=@GetData; CreateUserFunction(SysInit.hInstance, GetDataInfo); RangesInfo.lpfnMyCFunction:=@Ranges; CreateUserFunction(SysInit.hInstance, RangesInfo); SetCalibrationInfo.lpfnMyCFunction:=@SetCalibration; CreateUserFunction(SysInit.hInstance, SetCalibrationInfo); SetIMChCalibrationInfo.lpfnMyCFunction:=@SetIMChCalibration; CreateUserFunction(SysInit.hInstance, SetIMChCalibrationInfo); GetInfoInfo.lpfnMyCFunction:=@GetInfo; CreateUserFunction(SysInit.hInstance, GetInfoInfo); (* SetRangeInfo.lpfnMyCFunction:=@SetRange; CreateUserFunction(SysInit.hInstance, SetRangeInfo); GetDataByMassInfo.lpfnMyCFunction:=@GetDataByMass; CreateUserFunction(SysInit.hInstance, GetDataByMassInfo); GetBPointInfo.lpfnMyCFunction:=@GetBPoint; CreateUserFunction(SysInit.hInstance, GetBPointInfo); GetBDateInfo.lpfnMyCFunction:=@GetBDate; CreateUserFunction(SysInit.hInstance, GetBDateInfo); GetColumnInfo.lpfnMyCFunction:=@GetBData; CreateUserFunction(SysInit.hInstance, GetColumnInfo); GetBMassForIndexInfo.lpfnMyCFunction:=@BIndex2Mass; CreateUserFunction(SysInit.hInstance, GetBMassForIndexInfo); GetBCounterForIndexInfo.lpfnMyCFunction:=@BIndex2Counter; CreateUserFunction(SysInit.hInstance, GetBCounterForIndexInfo); GetBIndex2MassInfo.lpfnMyCFunction:=@BIndex2Mass; CreateUserFunction(SysInit.hInstance, GetBIndex2MassInfo); GetBIndex2CounterInfo.lpfnMyCFunction:=@BIndex2Counter; CreateUserFunction(SysInit.hInstance, GetBIndex2CounterInfo); *) end; initialization CreateErrorTable; RegisterFunctions; end.