Lazarus

Announcements => Third party => Topic started by: mig-31 on December 03, 2014, 09:52:12 am

Title: FreePascal bindings for National Instrument oscilloscope/digitizer cards
Post by: mig-31 on December 03, 2014, 09:52:12 am
Hello all,
I opened this topic because there is no subforum for Automation and Measurement.

National Instruments provide ANSI C headers for library NI-Scope for working with their oscilloscope/digitazer cards, for example NI PCI-5122 http://sine.ni.com/nips/cds/view/p/lang/cs/nid/13309 (http://sine.ni.com/nips/cds/view/p/lang/cs/nid/13309).

NI-Scope for Windows http://www.ni.com/download/ni-scope-4.1.3/4598/en/ (http://www.ni.com/download/ni-scope-4.1.3/4598/en/)
NI-Scope for Linux http://www.ni.com/download/ni-scope-3.1/1633/en/ (http://www.ni.com/download/ni-scope-3.1/1633/en/)

I discovered C headers (approx. 5 files) and its have macros and some other definitions, which need deeper C knowledge.
From my side i can also propose bindings testing on real harware, because we will have two NI PXI-5122 card this year or at the start of New Year.

I think it will be good to create binding for FreePascal.
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitazer cards
Post by: Laksen on December 03, 2014, 10:15:41 am
Well where are the C headers? Are they just a raw VISA register interface, or maybe an IVI driver interface?

If it's just the VISA(visa.h and visatype.h) headers plus a header for the register table in the specific card then you can find a conversion of the VISA headers here: https://github.com/Laksen/FP-VISA
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitazer cards
Post by: mig-31 on December 03, 2014, 10:38:30 am
It Ivi driver interface.
From my discovering it six C headers files:
ivi.h
IviScope.h
niScope.h
visa.h
visatype.h
vpptype.h

The most problem is how to convert macros:
its do something or not?
remove all of them?
terrible stringification? >:(


If it's just the VISA(visa.h and visatype.h) headers plus a header for the register table in the specific card then you can find a conversion of the VISA headers here: https://github.com/Laksen/FP-VISA

Two of them you have already translated.

Well where are the C headers? Are they just a raw VISA register interface, or maybe an IVI driver interface?
I don't know if I can upload C headers here, due to copyright restrictions?
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitazer cards
Post by: Laksen on December 03, 2014, 11:30:22 am
IviScope sounds like it could be used from IVI-COM. The other headers are probably for a IVI-C interface

If you are on windows you should be able to generate that a header for IVI-COM with importtl. Just run it on the DLL that NI supplies and you should have an autogenerated IVI-COM wrapper right away without the need for the VISA header stuff
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitazer cards
Post by: mig-31 on December 03, 2014, 03:59:30 pm
What is importtl?
I can't find this tool
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitazer cards
Post by: Laksen on December 03, 2014, 04:35:06 pm
It should come with fpc. At least it does in SVN trunk
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitazer cards
Post by: mig-31 on December 03, 2014, 05:01:35 pm
Thanks, I will try it.

Did you convert visa.h and visatypes.h by partly using h2pas utility or just manually?
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitazer cards
Post by: Laksen on December 03, 2014, 05:11:34 pm
I used Chelper (http://wiki.lazarus.freepascal.org/Chelper) and some manual fiddling
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitazer cards
Post by: Paul Breneman on December 03, 2014, 11:36:47 pm
I hope to add information from these messages to this page: http://controlpascal.com/ (http://controlpascal.com/)

The Comedi page (http://controlpascal.com/comedi.htm (http://controlpascal.com/comedi.htm)) has similar material.
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitazer cards
Post by: mig-31 on December 04, 2014, 09:23:35 am
It will be good, but now we only have binding for NI-VISA, not complete NI-Scope. Thanks for @Laksen.
And also comedy drivers are not supported NI oscilloscopes/digitazers. I hope, yet.
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitazer cards
Post by: mig-31 on December 04, 2014, 03:53:37 pm
I have a problem to convert this part form ivi.h, because i don't what it is

#define IVI_VAL_NAN             (*Ivi_GetPtrToSpecialViReal64Value(IVI_VAL_TYPE_NAN))
#define IVI_VAL_PINF            (*Ivi_GetPtrToSpecialViReal64Value(IVI_VAL_TYPE_PINF))
#define IVI_VAL_NINF            (*Ivi_GetPtrToSpecialViReal64Value(IVI_VAL_TYPE_NINF))


It looks like macro to pointer of function
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitazer cards
Post by: marcov on December 04, 2014, 04:05:18 pm

Quote
Ivi_GetPtrToSpecialViReal64Value(IVI_VAL_TYPE_NAN)

run that macro or function, which returns a pointer.

The asterix then dereferences that pointer. (

So  literally it is
Code: [Select]
{$define IVI_VAL_NAN   := (Ivi_GetPtrToSpecialViReal64Value(IVI_VAL_TYPE_NAN)^)}

though while possible, making it a macro doesn't make much sense in Pascal.
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitazer cards
Post by: mig-31 on December 04, 2014, 04:50:35 pm
Thank,
I think so.
Code: [Select]
{$define IVI_VAL_NAN   := (Ivi_GetPtrToSpecialViReal64Value(IVI_VAL_TYPE_NAN)^)}
Ivi_GetPtrToSpecialViReal64Value - function, IVI_VAL_TYPE_NAN -parametr and defined in other header

I check it not used in other parts of header and other headers.

Only for understanding, can we rewrite it using constant variable like
Code: [Select]
var
  IVI_VAL_NAN:Pointer=Ivi_GetPtrToSpecialViReal64Value(IVI_VAL_TYPE_NAN)^;
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitazer cards
Post by: mig-31 on December 08, 2014, 02:02:47 pm
Still I don't know if I can upload here C headers to NI-Scope driver.
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitazer cards
Post by: mig-31 on December 08, 2014, 02:12:39 pm
Hi, all

there are Pascal bindings for NI-Scope 14.0 driver for Win32 (probably works with Win64) and NI-Scope 3.1 fo Linux 32-bit.
Not tested on real hardware.

Simply add niscope.pas to your project to test it with your hardware. You can find information how to work with it in ANSI C examples, which are distributed with NI-Scope driver.
I hope, when I have real hardware, I will upload some basic examples in Pascal. Without real hardware, I think there is no sense to rewrite some ANSI C examples to Pascal.
There is a good guard to make first steps with NI-Scope on National Instruments web http://www.ni.com/white-paper/3382/en/ (http://www.ni.com/white-paper/3382/en/)

Linux version probably works only for linux kernel 2.6.x, which still supported https://www.kernel.org/ (https://www.kernel.org/) and used in RHEL5,6, Scientific Linux 5,6 (supported until 2017) and old distributions like Mandriva 2006 or Suse Linux.

Bindings are in the attachments.

Title: Re: FreePascal bindings for National Instrument oscilloscope/digitizer cards
Post by: mig-31 on December 19, 2014, 01:23:52 pm
Hi,

I found bugs in niscope_win32 bindging and correted it. Please find update in the attachment.

But I how troubles with testing it on NI-PXI5122 card.
Same code works on console application, but crashed in GUI on function CheckError(niScope_AutoSetup(vi),vi); with External:SIGSEGV error.
Now I don't know the way how to solve it.
Thanks for showing the way where is a bug (FPC 2.6.0 Lazarus 1.1 win32).

Console application code:
Code: [Select]
program test;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, niscope, visatype,sysutils
  { you can add units after this };
var
  resourceName:string = 'Dev3';
  vi:ViSession = VI_NULL;
  actualRecordLength:ViInt32;
  actualSampleRate:viReal64;
  data:array of viReal64;
  channel:string='0';
  wfmInfo:niScope_wfmInfo;
  i:word;

procedure CheckError(AErrorCode: ViStatus; Avi: viSession);
var
  errorMessage:string;
begin
  SetLength(errorMessage,MAX_ERROR_DESCRIPTION);
  if (AErrorCode<>VI_SUCCESS) then begin
    niScope_GetErrorMessage(Avi,AErrorCode,Length(errorMessage),@errorMessage[1]);
    writeln(errorMessage);
    if Avi<>VI_NULL then begin
       niScope_close(Avi);
    end;
    Halt;
  end;
 end;
begin
  //Init Session
  CheckError(niScope_init(@resourceName[1],NISCOPE_VAL_FALSE,NISCOPE_VAL_FALSE,@vi),vi);
  writeln('Pointer value:' ,vi);
  //auto setup measurement
  CheckError(niScope_AutoSetup(vi),vi);
  showMessage(vi);
  //read the actual record length and sample rate setuped by autosetup
  CheckError(niScope_ActualRecordLength(vi,@actualRecordLength),vi);
  CheckError(niScope_SampleRate(vi,@actualSampleRate),vi);
  writeln('Record lenght: ',actualRecordLength,'. Sample Rate: ',actualSampleRate);
  //set buffer length(array) and read data
  SetLength(data,actualRecordLength);
  CheckError(niScope_Read(vi,@channel[1],5.0,ActualRecordLength,@data[1],@wfmInfo),vi);
  //shows first 1000 samples
  writeln('Pointer value:' ,vi);
  for i:=1 to 10 do writeln('sample[',i,'] = ',data[i]:4:2);
  //close Session
  if vi<>VI_NULL then niScope_close(vi)
end.

GUI application onButtonClick code

Code: [Select]
procedure TForm1.StartBtnClick(Sender: TObject);
var
  resourceName:string;
  vi:ViSession;
  actualRecordLength:ViInt32;
  actualSampleRate:viReal64;
  data:array of viReal64;
  channel:string;
  wfmInfo:niScope_wfmInfo;
  procedure CheckError(AErrorCode: ViStatus; Avi: viSession);
var
  errorMessage:string;
begin
  SetLength(errorMessage,MAX_ERROR_DESCRIPTION);
  if (AErrorCode<>VI_SUCCESS) then begin
    niScope_GetErrorMessage(Avi,AErrorCode,Length(errorMessage),@errorMessage[1]);
    ShowMessage(errorMessage);
    if Avi<>VI_NULL then begin
       niScope_close(Avi);
    end;
    Halt;
  end;
 end;
begin
  //Setup hardware
  vi:=VI_NULL;
  resourceName:='Dev3';
  channel:='0';
  //Init Session
  CheckError(niScope_init(Pchar(@resourceName[1]),NISCOPE_VAL_FALSE,NISCOPE_VAL_FALSE,@vi),vi);
  //auto setup measurement
  CheckError(niScope_AutoSetup(vi),vi);

  CheckError(niScope_ActualRecordLength(vi,@actualRecordLength),vi);
   //read the actual record length and sample rate setuped by autosetup
  CheckError(niScope_ActualRecordLength(vi,@actualRecordLength),vi);
  CheckError(niScope_SampleRate(vi,@actualSampleRate),vi);
  //DataMemo.Append('Record lenght: '+IntToStr(actualRecordLength));
  //DataMemo.Append('Sample Rate: '+FloatToStrF(actualSampleRate,ffFixed,6,2));

  //set buffer length(array) and read data
  if  actualRecordLength >1 then begin
    SetLength(data,actualRecordLength);
    niScope_Read(vi,@channel[1],5.0,ActualRecordLength,@data[1],@wfmInfo);
    //shows first 1000 samples
    //for i:=1 to 1000 do DataMemo.Append('Sample['+IntToStr(i)+'] = '+FloatToStrF(data[i],ffFixed,4,2));
  end;

  //close Session
  if vi<>VI_NULL then niScope_close(vi)
end;                   
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitizer cards
Post by: mig-31 on January 12, 2015, 05:37:03 pm
Problem solved!

Thank guys, who found my stupid mistake with cdecl and stdcall convetion error! :)
There is first small worked example with autosetuped card.
To your own project simply add niscope and visatype to USES.
Code: [Select]
program test;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, niscope, visatype,sysutils
  { you can add units after this };
var
  resourceName:string='Dev3';
  vi:ViSession=VI_NULL;
  wfmNum:ViInt32;
  actualRecordLength:dword;
  actualSampleRate:viReal64;
  data:array of viReal64;
  channel:string = '0';
  wfmInfo:array of niScope_wfmInfo;
  i:longint;
procedure CheckError(AErrorCode: ViStatus; Avi: viSession);
var
  errorMessage:string;
  bufferSize:ViStatus;
begin
  SetLength(errorMessage,MAX_ERROR_DESCRIPTION);
  if (AErrorCode<>VI_SUCCESS) then begin
    //should call twice because we don't know errorMessage length
    //get string length
    bufferSize:=niScope_GetErrorMessage(Avi,AErrorCode,0,@errorMessage[1]);
   //get Error message
    SetLength(errorMessage,bufferSize);
    niScope_GetErrorMessage(Avi,AErrorCode,Length(errorMessage),@errorMessage[1]);
    writeln(errorMessage);
    if Avi<>VI_NULL then begin
       niScope_close(Avi);
    end;
    Halt;
  end;
 end;
begin
  //Init Session
  CheckError(niScope_init(PChar(@resourceName[1]),NISCOPE_VAL_FALSE,NISCOPE_VAL_FALSE,@vi),vi);
  writeln('Vi handler value (should be 1):' ,vi);
  //auto setup measurement
  CheckError(niScope_AutoSetup(vi),vi);
  //read the actual record length and number of waveforms
  //setuped by autosetup
  CheckError(niScope_ActualRecordLength(vi,@actualRecordLength),vi);
  CheckError(niScope_SampleRate(vi,@actualSampleRate),vi);
  CheckError(niScope_ActualNumWfms(vi,PChar(@channel[1]),@wfmNum),vi);

  //set buffer for data (lenght of data array)
  SetLength(data,actualRecordLength*wfmNum);
  SetLength(wfmInfo,wfmNum);

  CheckError(niScope_Read(vi,PChar(@channel[1]),5.0,actualRecordLength,@data[0],@wfmInfo[0]),vi);
  //shows first 10 samples
  writeln('----first ten samples of record------------------');
  for i:=Low(data) to Low(data)+9 do writeln('sample[',i,'] = ',data[i]:4:2);
  //show Info
  writeln('---------------------------------------------------');
  writeln('Record lenght: ',actualRecordLength);
  writeln('Sample rate: ',actualSampleRate);
  writeln('Number of waveforms: ',wfmNum);
  //show Info from wfmInfo record
  writeln('Actual samples: ',wfmInfo[0].actualSamples);
  writeln('X Increament: ',wfmInfo[0].xIncrement);
  writeln('Gain: ',wfmInfo[0].Gain);
  //close Session
  if vi<>VI_NULL then niScope_close(vi)
end.                         
Find corrected bindings in the attachment
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitizer cards
Post by: mig-31 on January 27, 2015, 11:34:09 am
There is next example based on binary acquisition example from NI-Scope driver.
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitizer cards
Post by: mig-31 on March 18, 2015, 01:54:11 pm
Hi,

there is corrected (bugs in visatype.pas missing of some pointers definitions) NI-Scope pascal bindings for NI-Scope 3.1 for Linux(to correct installation of NI-Scope install NIDAQmx 8.0.2 for Linux after NI-Scope).

Tested under Scientific Linux 6.4 on National Instruments PXI system:
1. NI PXIe-1078 chassic.
2. NI PXIe-8101 controller.
3. 2x NI PXI-5122 (NI-Scope 3.1 for Linux driver needed).

Autosetup code example

Code: [Select]
program test;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, niscope, visatype,sysutils
  { you can add units after this };
var
  resourceName:string='Dev1';
  vi:ViSession=VI_NULL;
  wfmNum:ViInt32;
  actualRecordLength:dword;
  actualSampleRate:viReal64;
  data:array of viReal64;
  channel:string = '0';
  wfmInfo:array of niScope_wfmInfo;
  i:longint;
procedure CheckError(AErrorCode: ViStatus; Avi: viSession);
var
  errorMessage:string='';
  bufferSize:ViStatus;
begin
  SetLength(errorMessage,MAX_ERROR_DESCRIPTION);
  if (AErrorCode<>VI_SUCCESS) then begin
    //due on unkown string length niScope_GetErrorMessage should call twice
    //get buffer size
    bufferSize:=niScope_GetError(Avi,@AErrorCode,0,@errorMessage[1]);
    //read error message
    SetLength(errorMessage,bufferSize);
    niScope_GetError(Avi,@AErrorCode,Length(errorMessage),@errorMessage[1]);
    writeln(errorMessage);
    if Avi<>VI_NULL then begin
       niScope_close(Avi);
    end;
    Halt;
  end;
 end;
begin
  //Init Session
  CheckError(niScope_init(PChar(@resourceName[1]),NISCOPE_VAL_FALSE,NISCOPE_VAL_FALSE,@vi),vi);
  writeln('Vi handler value (should be 1):' ,vi);
  //auto setup measurement
  CheckError(niScope_AutoSetup(vi),vi);
  //read the actual record length and number of waveforms
  //setuped by autosetup
  CheckError(niScope_ActualRecordLength(vi,@actualRecordLength),vi);
  CheckError(niScope_SampleRate(vi,@actualSampleRate),vi);
  CheckError(niScope_ActualNumWfms(vi,PChar(@channel[1]),@wfmNum),vi);

  //set buffer for data (lenght of data array)
  SetLength(data,actualRecordLength*wfmNum);
  SetLength(wfmInfo,wfmNum);

  CheckError(niScope_Read(vi,PChar(@channel[1]),5.0,actualRecordLength,@data[0],@wfmInfo[0]),vi);
  //shows first 10 samples
  writeln('----first ten samples of record------------------');
  for i:=Low(data) to Low(data)+9 do writeln('sample[',i,'] = ',data[i]:4:2);
  //show Info
  writeln('---------------------------------------------------');
  writeln('Record lenght: ',actualRecordLength);
  writeln('Sample rate: ',actualSampleRate);
  writeln('Number of waveforms: ',wfmNum);
  //show Info from wfmInfo record
  writeln('Actual samples: ',wfmInfo[0].actualSamples);
  writeln('X Increament: ',wfmInfo[0].xIncrement);
  writeln('Gain: ',wfmInfo[0].Gain);
  //close Session
  if vi<>VI_NULL then niScope_close(vi)
end.

Binary acquisition example

Code: [Select]
program binaryacq;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes,niscope,visatype
  { you can add units after this };
 var
   error:ViStatus = VI_SUCCESS;
   vi:ViSession;
   //Variables setuped hardware
   resourceName:string = 'Dev1';
   channelName:string = '0,1';  //nastavit merici kanal
   verticalRange:ViReal64 = 10;//rozsah -5 - 5 V
   verticalOffset:ViReal64 = 0.0;
   minSampleRate:ViReal64 = 2e5;
   minRecordLength:ViInt32 = 1000;
   binaryDataType:ViInt32;
   numWaveform:ViInt32;
   actualRecordLength:ViInt32;
   //Default values
   triggerType:ViInt32 = 0; //Immediate trigger
   triggerCoupling:ViInt32 = NISCOPE_VAL_DC;
   triggerSlope:ViInt32 = NISCOPE_VAL_POSITIVE;
   triggerLevel:ViReal64 = 0.0;
   triggerHoldoff:ViReal64 = 0.0;
   triggerDelay:ViReal64 = 0.0;
   triggerSource:string = '0';//nastavit kanal pro trigger
   refPosition:ViReal64 = 50.0;
   timeout:ViReal64 = 5.0;
   stop:ViInt32;
   i,j:ViInt32;

   wfmInfo:array of niScope_wfmInfo;
   scaledWfm:array of ViReal64;
   //NI-5122 is 14-bit digitizer
   binaryWfm:array of ViInt16;
procedure CheckError(AErrorCode: ViStatus; Avi: viSession);
var
  errorMessage:string='';
  bufferSize:ViStatus;
begin
  SetLength(errorMessage,MAX_ERROR_DESCRIPTION);
  if (AErrorCode<>VI_SUCCESS) then begin
    //due on unkown string length niScope_GetErrorMessage should call twice
    //get buffer size
    bufferSize:=niScope_GetError(Avi,@AErrorCode,0,@errorMessage[1]);
    //read error message
    SetLength(errorMessage,bufferSize);
    niScope_GetError(Avi,@AErrorCode,Length(errorMessage),@errorMessage[1]);
    writeln(errorMessage);
    if Avi<>VI_NULL then begin
       niScope_close(Avi);
    end;
    Halt;
  end;
 end;
begin
   //Open the NI_SCOPE instrument handler
   CheckError(niScope_init(Pchar(@resourceName[1]),NISCOPE_VAL_FALSE,NISCOPE_VAL_FALSE,@vi),vi);

   //Configure the vertical parameters
   CheckError(niScope_ConfigureVertical(vi,PChar(@channelName[1]),verticalRange,verticalOffset,NISCOPE_VAL_DC,1.0,NISCOPE_VAL_TRUE),vi);
   //Configure the horizontal parameters
   //one record

   CheckError(niScope_ConfigureHorizontalTiming(vi,minSampleRate,minRecordLength,refPosition,1,VI_TRUE),vi);
   //Configure the trigger

   if triggerType<>0  //Edge
     then CheckError(niScope_ConfigureTriggerEdge(vi,PChar(@triggerSource[1]),triggerLevel,triggerSlope,triggerCoupling,triggerHoldoff,triggerDelay),vi)
     else CheckError(niScope_ConfigureTriggerImmediate(vi),vi);

   //Get number of waveforms
   CheckError(niScope_ActualNumWfms(vi,PChar(@channelName[1]),@numWaveform),vi);

   //Get record length
   CheckError(niScope_ActualRecordLength(vi,@ActualRecordLength),vi);
   writeln('Record length: ',ActualRecordLength);

   //Set buffer for data and waveform Info
   SetLength(binaryWfm,ActualRecordLength*numWaveform);
   SetLength(scaledWfm,ActualRecordLength*numWaveform);
   SetLength(wfmInfo,numWaveform);

   //signal acquisition  1 record
   stop:=NISCOPE_VAL_FALSE;
   while stop<>NISCOPE_VAL_TRUE do begin
     CheckError(niScope_InitiateAcquisition(vi),vi);
     CheckError(niScope_FetchBinary16(vi,PChar(@channelName[1]),timeout,actualRecordLength,@binaryWfm[0],@wfmInfo[0]),vi);
     stop:=NISCOPE_VAL_TRUE;
   end;
   niScope_Close(vi);
   //calculate scaled data from binary data
   for i:=0 to NumWaveform-1 do
     for j:=0 to ActualRecordLength-1 do scaledWfm[j+(i*ActualRecordLength-1)]:=binaryWfm[j+(i*ActualRecordLength-1)]*wfmInfo[i].Gain+wfmInfo[i].offset;

   for i:=0 to NumWaveform-1 do begin
     writeln('   Waveform channel   ',i+1);
     writeln('   First 10 samples ');
     writeln('----------------------');
     for j:=0 to 10 do writeln('value[',j,'] = ',scaledWfm[j+(i*ActualRecordLength-1)]:4:2);
     writeln('----------------------');
  end;
   writeln('program stoped');
end.                                       
Title: Re: FreePascal bindings for National Instrument oscilloscope/digitizer cards
Post by: mig-31 on April 08, 2015, 04:14:24 pm
Hi, guys

I have created the wiki page for NI-Scope Pascal bindings http://wiki.freepascal.org/NI-Scope_examples (http://wiki.freepascal.org/NI-Scope_examples).

I hope it would be usefull for others.

I invite you to check, improve, correct and add information.

Thanks.
TinyPortal © 2005-2018