unit PAI1216u; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons, Registry, ACCES32, ExtCtrls; type TForm1 = class(TForm) Label1: TLabel; Label3: TLabel; Label2: TLabel; Label4: TLabel; Label5: TLabel; Label6: TLabel; Label7: TLabel; Label8: TLabel; Label9: TLabel; Label10: TLabel; Label11: TLabel; Label12: TLabel; Label13: TLabel; Label14: TLabel; Label15: TLabel; Label16: TLabel; Label17: TLabel; Label18: TLabel; Label19: TLabel; ExitBtn: TBitBtn; CardCombo: TComboBox; GroupBox1: TGroupBox; Memo1: TMemo; Edit0: TEdit; Edit1: TEdit; Edit2: TEdit; Edit3: TEdit; Edit7: TEdit; Edit6: TEdit; Edit5: TEdit; Edit4: TEdit; Edit12: TEdit; Edit11: TEdit; Edit10: TEdit; Edit9: TEdit; Edit8: TEdit; Edit15: TEdit; Edit14: TEdit; Edit13: TEdit; ChannelsCombo: TComboBox; GetDataBtn: TBitBtn; Edit16: TEdit; Edit17: TEdit; Edit18: TEdit; Edit19: TEdit; Edit23: TEdit; Edit22: TEdit; Edit21: TEdit; Edit20: TEdit; Edit24: TEdit; Edit25: TEdit; Edit26: TEdit; Edit27: TEdit; Edit31: TEdit; Edit30: TEdit; Edit29: TEdit; Edit28: TEdit; Label20: TLabel; Label21: TLabel; Label22: TLabel; Label23: TLabel; Label24: TLabel; Label25: TLabel; Label26: TLabel; Label27: TLabel; Timer1: TTimer; procedure ExitBtnClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure GetDataBtnClick(Sender: TObject); procedure Timer1Timer(Sender: TObject); private { Private declarations } public { Public declarations } procedure GetCardInfo; procedure NoFifo(Base: DWORD); procedure Fifo(Base: DWORD); procedure SetChannel(BASE: DWORD; channel: BYTE); procedure SetFifoChannels(BASE: DWORD); procedure StartConversion(BASE: DWORD); function WaitForEOC(BASE: DWORD): WORD; function RetrieveADConversion(BASE: DWORD): SmallInt; procedure EnableFifoCounter(BASE: DWORD); procedure CheckFifo(BASE: DWORD); procedure DisableCounters(BASE: DWORD); procedure ResetFifos(BASE: DWORD); end; var Form1: TForm1; DriverRegistry: TRegistry; buf: array [0..63] of TPCI_COMMON_CONFIG; RunFlag, TimedOut: Boolean; WhichCard: array [0..63] of Byte; WhichAddress: array [0..63] of DWORD; Cards: array [0..1] of string; VoltsDisplay: array [0..15] of TEdit; CountsDisplay: array [0..15] of TEdit; Testing: Boolean; const MyKey = 'Software\PCIFIND\NTioPCI\Parameters'; implementation {$R *.DFM} procedure CtrMode(addr: word; cntr, mode: byte); begin OutPortB(addr+3, (cntr shl 6) or $30 or (mode shl 1)); end; //--------------------------------------------------------------------------- procedure CtrLoad(addr: word; c, val: word); begin OutPortB(addr+c, val and $00FF); OutPortB(addr+c, (val shr 8) and $00FF); end; //--------------------------------------------------------------------------- procedure TForm1.ExitBtnClick(Sender: TObject); begin Close; end; procedure TForm1.GetCardInfo; var num,i,n: Integer; begin n := 0; DriverRegistry := TRegistry.Create; DriverRegistry.RootKey := HKEY_LOCAL_MACHINE; DriverRegistry.OpenKey(MyKey, True); try num := DriverRegistry.ReadInteger('NumDevices'); except on ERegistryException do num := 0; end; if (num > 0) then DriverRegistry.ReadBinaryData('PCICommonConfig',buf,(sizeof(TPCI_COMMON_CONFIG)*num)); for i := 0 to num - 1 do with buf[i] do begin RunFlag := True; if (VendorID = $494F) and ((DeviceID = $ACA8) or (DeviceID = $ACA9)) then begin WhichAddress[n] := BaseAddresses[2] and $FFF8; if DeviceID = $ACA8 then WhichCard[n] := 0 else WhichCard[n] := 1; CardCombo.Items.Add('Card ' + IntToHex(n+1,2) + ' ' + Cards[WhichCard[n]] + ' Base Address: ' + IntToHex(BaseAddresses[2] and $FFF8, 4)); Inc(n); end; end; if (n = 0) then begin Memo1.Lines.Clear; Memo1.Lines.Append('No PCI Cards found!'); Memo1.Lines.Append('This may mean the card is not installed, or that the installed card is ISA.'); Memo1.Lines.Append('If you have an ISA card installed, you may continue running the sample ' + 'by entering the card''s Base Address in the edit box above and continuing as normal.'); if (num > 0) then begin Memo1.Lines.Append('NOTE: A PCI card was found, but it is not the ' + Cards[0] + ' card.'); end; Memo1.Lines.Append('Make sure you have run PCIFind.exe.'); Label3.hide; CardCombo.hide; RunFlag := False; end; if (RunFlag) then CardCombo.ItemIndex := 0; DriverRegistry.Free; end; procedure TForm1.FormCreate(Sender: TObject); begin Cards[0] := 'PCI-AI12-16'; Cards[1] := 'PCI-AI12-16A'; GetCardInfo; ChannelsCombo.ItemIndex := 0; VoltsDisplay[0] := Edit0; VoltsDisplay[1] := Edit1; VoltsDisplay[2] := Edit2; VoltsDisplay[3] := Edit3; VoltsDisplay[4] := Edit4; VoltsDisplay[5] := Edit5; VoltsDisplay[6] := Edit6; VoltsDisplay[7] := Edit7; VoltsDisplay[8] := Edit8; VoltsDisplay[9] := Edit9; VoltsDisplay[10] := Edit10; VoltsDisplay[11] := Edit11; VoltsDisplay[12] := Edit12; VoltsDisplay[13] := Edit13; VoltsDisplay[14] := Edit14; VoltsDisplay[15] := Edit15; CountsDisplay[0] := Edit16; CountsDisplay[1] := Edit17; CountsDisplay[2] := Edit18; CountsDisplay[3] := Edit19; CountsDisplay[4] := Edit20; CountsDisplay[5] := Edit21; CountsDisplay[6] := Edit22; CountsDisplay[7] := Edit23; CountsDisplay[8] := Edit24; CountsDisplay[9] := Edit25; CountsDisplay[10] := Edit26; CountsDisplay[11] := Edit27; CountsDisplay[12] := Edit28; CountsDisplay[13] := Edit29; CountsDisplay[14] := Edit30; CountsDisplay[15] := Edit31; if (InPortB($61) = $AA55) then begin Application.MessageBox('ACCESNT.SYS not detected. Please copy ACCESNT.SYS into [NT]/system32/drivers and re-run this sample.', 'Warning', IDOK); end; end; procedure TForm1.GetDataBtnClick(Sender: TObject); begin if not RunFlag then Memo1.Lines.Append('Cannot run without card!') else if Testing then begin Testing := false; Timer1.Enabled := false; GetDataBtn.Caption := 'Get Data'; end else begin Testing := true; Timer1.Enabled := true; GetDataBtn.Caption := 'Stop Data'; end; end; //--------------------------------------------------------------------------- procedure TForm1.Fifo(BASE: DWORD); var chan, numchan: byte; Value: word; counts: smallint; volts: double; begin if ChannelsCombo.ItemIndex = 0 then numchan := 8 else numchan := 16; ResetFifos(BASE); SetFifoChannels(BASE); CtrMode(BASE+8, 1, 2); CtrLoad(BASE+8, 1, $2); CtrMode(BASE+8, 2, 2); CtrLoad(BASE+8, 2, $FF); EnableFifoCounter(BASE);//conversions started once counters are enabled CheckFifo(BASE); //check fifo bit to see if it's half full DisableCounters(BASE);//stop conversions while((InPortB(BASE+4) and $02) = $02) do//bit goes low when fifo is empty begin Value := InPort(BASE); counts := Value and $FFF; if (counts > $7FF) then counts := counts or $F000; chan := Value shr 12; volts := 20.0 * (counts / 4095.0);//convert to volts: counts*max volt span/max counts if (chan >= numchan) then begin VoltsDisplay[chan].Text := ''; CountsDisplay[chan].Text := ''; end else begin VoltsDisplay[chan].Text := FloatToStrF(volts, ffFixed, 0, 3); CountsDisplay[chan].Text := IntToStr(counts); end; end; end; //--------------------------------------------------------------------------- procedure TForm1.NoFifo(BASE: DWORD); var chan, numchan: BYTE; counts: smallint; volts: real; Ticks: DWORD; begin DisableCounters(BASE); if ChannelsCombo.ItemIndex = 0 then numchan := 8 else numchan := 16; for chan := 0 to 15 do begin if chan >= numchan then begin VoltsDisplay[chan].Text := ''; CountsDisplay[chan].Text := ''; end else begin SetChannel(BASE, chan); // write channel, range, SE or diff Ticks := GetTickCount; while Ticks + 2 > GetTickCount do; // allow for settle time StartConversion(BASE); // start conversion if (WaitForEOC(BASE) = 0) then //WAITFOREOC returns zero if it times out begin Memo1.Lines.Append('Channel ' + IntToStr(chan) + ' A/D Timed Out'); VoltsDisplay[chan].Text := ''; CountsDisplay[chan].Text := ''; end else begin counts := RetrieveADConversion(BASE); volts := 20.0 * (counts / 4095.0); //convert to volts: counts*max volt span/max counts VoltsDisplay[chan].Text := FloatToStr(volts); CountsDisplay[chan].Text := IntToStr(counts); end; end; end; end; //--------------------------------------------------------------------------- procedure TForm1.SetChannel(BASE: DWORD; channel: BYTE); var Value: Byte; begin Value := (channel shl 4); //channel selected in upper nibble at base+2 // and single-ended, range +/-10V OutPortB(BASE+2, Value); end; //--------------------------------------------------------------------------- procedure TForm1.SetFifoChannels(BASE: DWORD); begin OutPort(BASE+2, $0000); OutPort(BASE+2, $1010); OutPort(BASE+2, $2020); OutPort(BASE+2, $3030); OutPort(BASE+2, $4040); OutPort(BASE+2, $5050); OutPort(BASE+2, $6060); OutPort(BASE+2, $7070); OutPort(BASE+2, $8080); OutPort(BASE+2, $9090); OutPort(BASE+2, $A0A0); OutPort(BASE+2, $B0B0); OutPort(BASE+2, $C0C0); OutPort(BASE+2, $D0D0); OutPort(BASE+2, $E0E0); OutPort(BASE+2, $F0F0); InPortB(BASE+2); end; //--------------------------------------------------------------------------- procedure TForm1.EnableFifoCounter(BASE: DWORD); begin OutPortB(BASE+4, 1); // enable conversion on counter end; procedure TForm1.CheckFifo(BASE: DWORD); begin while((InPortB(BASE+4) and $04) = $04) do;//bit goes low when fifo half full end; //--------------------------------------------------------------------------- procedure TForm1.DisableCounters(BASE: DWORD); begin OutPortB(BASE+4, 0); end; //--------------------------------------------------------------------------- procedure TForm1.ResetFifos(BASE: DWORD); var i: Integer; begin OutPortB(BASE+4, $48);//0x40 resets channel fifo, 0x08 resets data fifo for i := 0 to 1023 do InPortB(BASE); InPortB(BASE+6); end; //--------------------------------------------------------------------------- procedure TForm1.StartConversion(BASE: DWORD); begin OutPortB(BASE, 0); //write anything to base+0 to start conversion end; function TForm1.WaitForEOC(BASE: DWORD): WORD; var timeout: WORD; begin timeout := $FFFF; while((InPortB(BASE+4) and $80) = 0) and (timeout > 0) do Dec(timeout); Result := timeout; //0==error end; //--------------------------------------------------------------------------- function TForm1.RetrieveADConversion(BASE: DWORD): SmallInt; var data: SmallInt; begin data := (InPort(BASE) and $0FFF); //mask upper nibble if (data and $800) > 0 then data := data or $F000; // effectively sign-extend Result := data; end; //--------------------------------------------------------------------------- procedure TForm1.Timer1Timer(Sender: TObject); begin if WhichCard[CardCombo.ItemIndex] = 1 then Fifo(WhichAddress[CardCombo.ItemIndex]) else NoFifo(WhichAddress[CardCombo.ItemIndex]) end; end.