unit Main; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, ExtCtrls, StdCtrls, Registry; type TMainForm = class(TForm) GroupBits: TRadioGroup; GroupRange: TRadioGroup; GroupOutput: TGroupBox; Value: TTrackBar; LOutput: TLabel; Label2: TLabel; GroupChannel: TRadioGroup; StatusBar1: TStatusBar; CardName: TLabel; AddressList: TComboBox; Memo1: TMemo; ExitButton: TButton; Initialize: TButton; Label3: TLabel; ISAPanel: TGroupBox; Label1: TLabel; ISAEdit: TEdit; procedure GroupBitsClick(Sender: TObject); procedure GroupPolarityClick(Sender: TObject); procedure FormActivate(Sender: TObject); procedure UpdateDAC; function ConvertForOutput(V:longword):longword; procedure ValueChange(Sender: TObject); procedure GroupRangeClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure ExitButtonClick(Sender: TObject); procedure InitializeClick(Sender: TObject); procedure AddressListChange(Sender: TObject); private { Private declarations } DriverRegistry:TRegistry; public { Public declarations } end; var MainForm: TMainForm; implementation {$R *.DFM} uses ACCES32; //global variables for internal use const bits:longword=12; Offset:double=5; invert:longint=1; CurVal:word=0; span:double=10.0; //myKey = 'System\CurrentControlSet\Services\NTioPCI\Parameters'; myKey = 'Software\PCIFIND\NTioPCI\Parameters'; maxch:integer=16; var buf: array [0..63] of TPCI_COMMON_CONFIG; Address, Address2: WORD; RunFlag:Boolean; CalibMax: Word; CalibMin: Word; { This function accepts a value of 0-65535 and returns the value scaled for the current DAC settings. } function TMainForm.ConvertForOutput(v:longword):longword; var i:integer; CalV: Real; CalResult: LongWord; begin result:=trunc(v / 65536.0*(1 shl bits)); //scale for 12 or 16 bits. CalV := (((65536 - CalibMax - CalibMin) / 65536) * v + CalibMin); CalResult := Trunc(CalV / 65536 * (1 shl bits)); //Calibrated version thereof //write to hardware here. if (GroupChannel.ItemIndex < maxch) then begin //the last item in the channel list is ALL outport(Address+(GroupChannel.ItemIndex*2),CalResult); inportb(Address+$A); //update DACs, leave card in async mode end else begin //"all channels" is selected, use simul mode inportb(Address+0); //enter simul mode without updating dacs for i:=0 to maxch-1 do outport(Address+(i*2),CalResult); inportb(Address+8); //update DACs, leave card in simul mode end;//else end; function IntToBin(input,bits:longword):string; var temp:string; i:word; f:double; begin //this for loop converts to binary temp:=''; for i:=(bits-1) downto 0 do begin if (input AND (1 shl i))=0 then temp:=temp+'0' else temp:=temp+'1'; end;//for; //this conditional handles the xxxx for justification if bits=12 then temp:='xxxx'+temp; f:=((1 shl (bits+1)-1) AND input) * span / (1 shl bits) - offset; temp:=temp+' '+inttohex(input,bits div 4)+' '+floattostrf(f,ffFixed,6,6); if (MainForm.GroupRange.ItemIndex>5) then result:=temp+' mA' else result:=temp+' Volts'; end; procedure TMainForm.UpdateDAC; begin offset:=0; case GroupRange.ItemIndex of 0:span:=5.0; 1:span:=2.5; 2:span:=10.0; 3:begin offset:=5.0;span:=10.0;end; 4:begin offset:=2.5;span:=5.0;end; 5:begin offset:=10.0;span:=20.0;end; 6:begin offset:=-4.0;span:=16.0;end; end;//case LOutput.Caption:=IntToBin(ConvertForOutput(CurVal),bits); end; procedure TMainForm.GroupBitsClick(Sender: TObject); const old:integer=-1; begin if old<>GroupBits.ItemIndex then begin //only if it is different case GroupBits.ItemIndex of 0:begin bits:=12; value.LineSize:=16; //slider control end; 1:begin bits:=16; value.linesize:=1; //slider control end; end;//case old:=GroupBits.ItemIndex; UpdateDAC; end;//if different end;//EndGroupBits procedure TMainForm.GroupPolarityClick(Sender: TObject); begin end;//end GroupPolarity procedure TMainForm.FormActivate(Sender: TObject); begin if not RunFlag then FocusControl(IsaEdit); // UpdateDAC; memo1.lines.append(''); memo1.lines.append('Please configure the dialog options shown to reflect the card that is installed. '+ 'The card''s output voltage shown onscreen will only be correct if these settings are correct. '+ 'Refer to the card''s manual for specifics about jumper settings and switches.'); Memo1.ScrollBars:=ssVertical; end; procedure TMainForm.ValueChange(Sender: TObject); begin CurVal:=value.position; UpdateDAC; end; procedure TMainForm.GroupRangeClick(Sender: TObject); begin UpdateDAC; end; procedure TMainForm.FormCreate(Sender: TObject); var num, i,n,t: Integer; begin ISAPanel.hide; DriverRegistry:=TRegistry.Create; DriverRegistry.RootKey:=HKEY_LOCAL_MACHINE; num:=0; n:=0; 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; if (DriverRegistry.OpenKey(MyKey, False)) then num := DriverRegistry.ReadInteger('NumDevices'); if (num > 0) then DriverRegistry.ReadBinaryData('PCICommonConfig',buf,num*sizeof(TPCI_COMMON_CONFIG)); for i := 0 to num-1 do begin RunFlag:=True; with Buf[i] do begin case (DeviceID) of $6CB0:begin CardName.Caption:='PCI-DA12-16 Digital-To-Analog Card'; AddressList.Items.Add('PCI-DA12-16:'+IntToHex(BaseAddresses[2] AND $FFF8,4)+':'+IntToHex(BaseAddresses[3] AND $FFF8,4)); n:=n+1; end; $6CB1:begin CardName.Caption:='PCI-DA12-16V Digital-To-Analog Card'; AddressList.Items.Add('PCI-DA12-16V:'+IntToHex(BaseAddresses[2] AND $FFF8,4)+':'+IntToHex(BaseAddresses[3] AND $FFF8,4)); n:=n+1; end; $6CA8:begin CardName.Caption:='PCI-DA12-8 Digital-To-Analog Card'; AddressList.Items.Add('PCI-DA12-8:'+IntToHex(BaseAddresses[2] AND $FFF8,4)+':'+IntToHex(BaseAddresses[3] AND $FFF8,4)); n:=n+1; end; $6CA9:begin CardName.Caption:='PCI-DA12-8V Digital-To-Analog Card'; AddressList.Items.Add('PCI-DA12-8V:'+IntToHex(BaseAddresses[2] AND $FFF8,4)+':'+IntToHex(BaseAddresses[3] AND $FFF8,4)); n:=n+1; end; $6CA0:begin CardName.Caption:='PCI-DA12-6 Digital-To-Analog Card'; AddressList.Items.Add('PCI-DA12-6:'+IntToHex(BaseAddresses[2] AND $FFF8,4)+':'+IntToHex(BaseAddresses[3] AND $FFF8,4)); n:=n+1; end; $6C98:begin CardName.Caption:='PCI-DA12-4 Digital-To-Analog Card'; AddressList.Items.Add('PCI-DA12-4:'+IntToHex(BaseAddresses[2] AND $FFF8,4)+':'+IntToHex(BaseAddresses[3] AND $FFF8,4)); n:=n+1; end; $6C90:begin CardName.Caption:='PCI-DA12-2 Digital-To-Analog Card'; AddressList.Items.Add('PCI-DA12-2:'+IntToHex(BaseAddresses[2] AND $FFF8,4)+':'+IntToHex(BaseAddresses[3] AND $FFF8,4)); n:=n+1; end; end;{case} end;{with} end;{for} if n=0 then begin CardName.Caption:='No PCI DAC Card Found In Registry'; Memo1.Lines.Clear; Memo1.Lines.Append('No PCI DAC Card Found In Registry.'); Memo1.Lines.Append('This may mean no PCI card is installed, or that PCIFind.exe or NTioPCI.SYS (NT only) is not installed, or the PCI card(s) you have installed are not DAC cards. '+ 'If you believe this message is in error, please make sure you have run PCIFind.EXE.'); Memo1.Lines.Append('If you have an ISA DAC card installed, you may continue running the sample ' + 'by entering the card''s Base Address in the edit box above and continuing as normal.'); IsaPanel.Visible := True; AddressList.Visible := False; AddressList.Enabled:=False; RunFlag:=False; end; AddressList.ItemIndex:=0; if RunFlag then begin Address:=StrToInt('$'+copy(AddressList.Items[AddressList.ItemIndex],length(AddressList.Items[AddressList.ItemIndex])-8,4)); Address2:=StrToInt('$'+copy(AddressList.Items[AddressList.ItemIndex],length(AddressList.Items[AddressList.ItemIndex])-3,4)); t:=StrToInt(copy(AddressList.Items[AddressList.ItemIndex],10,1)); case t of 2: begin maxch:=2; CardName.Caption:='PCI-DA12-2 Digital-to-Analog Card' end; 4: begin maxch:=4; CardName.Caption:='PCI-DA12-4 Digital-to-Analog Card' end; 6: begin maxch:=6; CardName.Caption:='PCI-DA12-6 Digital-to-Analog Card' end; 8: begin maxch:=8; CardName.Caption:='PCI-DA12-8 Digital-to-Analog Card' end; else begin maxch:=16; CardName.Caption:='PCI-DA12-16 Digital-to-Analog Card'; end; end; end; DriverRegistry.Free; GroupChannel.Items.Clear; for i:=1 to maxch do GroupChannel.Items.Append('Channel '+inttostr(i-1)); GroupChannel.Items.Append('All Channels'); GroupChannel.ItemIndex:=0; end; procedure TMainForm.ExitButtonClick(Sender: TObject); begin close; end; procedure TMainForm.InitializeClick(Sender: TObject); var code,data:integer; NewTicks: LongWord; begin data:=0; if runflag then begin CalibMin := inportb((Address2+(GroupChannel.ItemIndex*2)+(GroupRange.itemindex)*32)); NewTicks := GetTickCount + 10; repeat Application.ProcessMessages until GetTickCount >= NewTicks; //Pause for 10ms CalibMax := inportb((Address2+(GroupChannel.ItemIndex*2)+(GroupRange.itemindex)*32)+1); if Bits = 12 then begin CalibMax := CalibMax * 16; CalibMin := CalibMin * 16; end; end else begin {$R-} val('$'+ISAEdit.Text,data,code); {$R+} CalibMax := 0; //ISA cards are calibrated by pots, so there's no software CalibMin := 0; //calibration on the max or min end; if ((data>$100) and (code=0)) then begin Address:=data; runflag:=True; end; if runflag then begin inportb(Address+2); //remove simul mode inportb(Address+15); //remove zero latch GroupOutput.visible:=True; GroupOutput.enabled:=True; end; end; procedure TMainForm.AddressListChange(Sender: TObject); var t,i:integer; begin Address:=StrToInt('$'+copy(AddressList.Items[AddressList.ItemIndex],length(AddressList.Items[AddressList.ItemIndex])-3,4)); t:=StrToInt(copy(AddressList.Items[AddressList.ItemIndex],10,1)); case t of 2: begin maxch:=2; CardName.Caption:='PCI-DA12-2 Digital-to-Analog Card' end; 4: begin maxch:=4; CardName.Caption:='PCI-DA12-4 Digital-to-Analog Card' end; 6: begin maxch:=6; CardName.Caption:='PCI-DA12-6 Digital-to-Analog Card' end; 8: begin maxch:=8; CardName.Caption:='PCI-DA12-8 Digital-to-Analog Card' end; else begin maxch:=16; CardName.Caption:='PCI-DA12-16 Digital-to-Analog Card'; end; end; GroupChannel.Items.Clear; for i:=1 to maxch do GroupChannel.Items.Append('Channel '+inttostr(i-1)); GroupChannel.Items.Append('All Channels'); GroupChannel.ItemIndex:=0; end; end.