unit Sample1u; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons, Registry, ACCES32, ExtCtrls; type TSampleForm = class(TForm) TitleLabel: TLabel; CardSelectLabel: TLabel; ChannelLabel0: TLabel; ChannelLabel1: TLabel; ChannelLabel2: TLabel; ChannelLabel3: TLabel; ChannelLabel7: TLabel; ChannelLabel4: TLabel; ChannelLabel5: TLabel; ChannelLabel6: TLabel; ChannelLabel8: TLabel; ChannelLabel9: TLabel; ChannelLabel10: TLabel; ChannelLabel11: TLabel; ChannelLabel12: TLabel; ChannelLabel13: TLabel; ChannelLabel14: TLabel; ChannelLabel15: TLabel; ChannelSelectLabel: TLabel; ExitBtn: TBitBtn; CardCombo: TComboBox; StatusGroupBox: TGroupBox; StatusMemo: TMemo; VoltsEdit0: TEdit; VoltsEdit1: TEdit; VoltsEdit2: TEdit; VoltsEdit3: TEdit; VoltsEdit7: TEdit; VoltsEdit6: TEdit; VoltsEdit5: TEdit; VoltsEdit4: TEdit; VoltsEdit12: TEdit; VoltsEdit11: TEdit; VoltsEdit10: TEdit; VoltsEdit9: TEdit; VoltsEdit8: TEdit; VoltsEdit15: TEdit; VoltsEdit14: TEdit; VoltsEdit13: TEdit; ChannelsCombo: TComboBox; GetDataBtn: TBitBtn; CountsEdit0: TEdit; CountsEdit1: TEdit; CountsEdit2: TEdit; CountsEdit3: TEdit; CountsEdit7: TEdit; CountsEdit6: TEdit; CountsEdit5: TEdit; CountsEdit4: TEdit; CountsEdit8: TEdit; CountsEdit9: TEdit; CountsEdit10: TEdit; CountsEdit11: TEdit; CountsEdit15: TEdit; CountsEdit14: TEdit; CountsEdit13: TEdit; CountsEdit12: TEdit; Counts1Label: TLabel; Volts1Label: TLabel; Counts4Label: TLabel; Volts4Label: TLabel; Counts3Label: TLabel; Volts3Label: TLabel; Counts2Label: TLabel; Volts2Label: TLabel; TestTimer: TTimer; procedure ExitBtnClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure GetDataBtnClick(Sender: TObject); procedure TestTimerTimer(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 SampleForm: TSampleForm; 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..2] of string; VoltsDisplay: array [0..15] of TEdit; CountsDisplay: array [0..15] of TEdit; Testing: Boolean; const MyKey = 'System\CurrentControlSet\Services\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 TSampleForm.ExitBtnClick(Sender: TObject); begin Close; end; procedure TSampleForm.GetCardInfo; var num,i,n: Integer; begin n := 0; DriverRegistry := TRegistry.Create; DriverRegistry.RootKey := HKEY_LOCAL_MACHINE; DriverRegistry.OpenKey(MyKey, True); num := DriverRegistry.ReadInteger('NumDevices'); 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 = $ECA9) or (DeviceID = $ECAA)) then begin WhichAddress[n] := BaseAddresses[2] and $FFF8; if DeviceID = $ECA9 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 StatusMemo.Lines.Clear; StatusMemo.Lines.Append('No Cards found!'); StatusMemo.Lines.Append('This may mean the card is not installed.'); if (num > 0) then begin StatusMemo.Lines.Append('NOTE: A card was found, but it is not the ' + Cards[0] + ' card.'); end; StatusMemo.Lines.Append('Make sure you have run PCIFind.exe.'); RunFlag := False; end; if (RunFlag) then CardCombo.ItemIndex := 0; DriverRegistry.Free; end; procedure TSampleForm.FormCreate(Sender: TObject); begin Cards[0] := 'PCI-A12-16'; Cards[1] := 'PCI-A12-16A'; GetCardInfo; ChannelsCombo.ItemIndex := 0; VoltsDisplay[0] := VoltsEdit0; VoltsDisplay[1] := VoltsEdit1; VoltsDisplay[2] := VoltsEdit2; VoltsDisplay[3] := VoltsEdit3; VoltsDisplay[4] := VoltsEdit4; VoltsDisplay[5] := VoltsEdit5; VoltsDisplay[6] := VoltsEdit6; VoltsDisplay[7] := VoltsEdit7; VoltsDisplay[8] := VoltsEdit8; VoltsDisplay[9] := VoltsEdit9; VoltsDisplay[10] := VoltsEdit10; VoltsDisplay[11] := VoltsEdit11; VoltsDisplay[12] := VoltsEdit12; VoltsDisplay[13] := VoltsEdit13; VoltsDisplay[14] := VoltsEdit14; VoltsDisplay[15] := VoltsEdit15; CountsDisplay[0] := CountsEdit0; CountsDisplay[1] := CountsEdit1; CountsDisplay[2] := CountsEdit2; CountsDisplay[3] := CountsEdit3; CountsDisplay[4] := CountsEdit4; CountsDisplay[5] := CountsEdit5; CountsDisplay[6] := CountsEdit6; CountsDisplay[7] := CountsEdit7; CountsDisplay[8] := CountsEdit8; CountsDisplay[9] := CountsEdit9; CountsDisplay[10] := CountsEdit10; CountsDisplay[11] := CountsEdit11; CountsDisplay[12] := CountsEdit12; CountsDisplay[13] := CountsEdit13; CountsDisplay[14] := CountsEdit14; CountsDisplay[15] := CountsEdit15; 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 TSampleForm.GetDataBtnClick(Sender: TObject); begin if not RunFlag then StatusMemo.Lines.Append('Cannot run without card!') else if Testing then begin Testing := false; TestTimer.Enabled := false; GetDataBtn.Caption := 'Get Data'; end else begin Testing := true; TestTimer.Enabled := true; GetDataBtn.Caption := 'Stop Data'; end; end; //--------------------------------------------------------------------------- procedure TSampleForm.Fifo(BASE: DWORD); var chan, numchan: byte; Value: word; counts: word; 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 TSampleForm.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 StatusMemo.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 TSampleForm.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 TSampleForm.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 TSampleForm.EnableFifoCounter(BASE: DWORD); begin OutPortB(BASE+4, 1); // enable conversion on counter end; procedure TSampleForm.CheckFifo(BASE: DWORD); begin while((InPortB(BASE+4) and $04) = $04) do;//bit goes low when fifo half full end; //--------------------------------------------------------------------------- procedure TSampleForm.DisableCounters(BASE: DWORD); begin OutPortB(BASE+4, 0); end; //--------------------------------------------------------------------------- procedure TSampleForm.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 TSampleForm.StartConversion(BASE: DWORD); begin OutPortB(BASE, 0); //write anything to base+0 to start conversion end; function TSampleForm.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 TSampleForm.RetrieveADConversion(BASE: DWORD): SmallInt; var data: word; 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 TSampleForm.TestTimerTimer(Sender: TObject); begin if WhichCard[CardCombo.ItemIndex] <> 0 then Fifo(WhichAddress[CardCombo.ItemIndex]) else NoFifo(WhichAddress[CardCombo.ItemIndex]) end; end.