unit MainUnit; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls; type TMainForm = class(TForm) ScrollBox1: TScrollBox; ControlPanel: TPanel; Label1: TLabel; RangeCombo: TComboBox; CalLabel: TLabel; CalEdit: TComboBox; VoltPanel: TPanel; CountPanel: TPanel; SpacerBevel: TBevel; ADPollTime: TTimer; GoButton: TButton; StopButton: TButton; procedure FormCreate(Sender: TObject); procedure RangeComboChange(Sender: TObject); procedure ADPollTimeTimer(Sender: TObject); procedure GoButtonClick(Sender: TObject); procedure StopButtonClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var MainForm: TMainForm; implementation {$R *.DFM} uses AIOUSB, DetectUnit; type TUSBAI16128Config = packed record ChannelRange: array[$0..$F] of Byte; CalibMode: Byte; TrigMode: Byte; StartStopCh: Byte; Oversample: Byte; StartStopChEx: Byte; //MUX start and end channel extension register. end; var DeviceIndex: LongWord; Config: TUSBAI16128Config; VoltLabel: array of TLabel; CountGauge: array of TProgressBar; Channels: Integer; procedure TMainForm.FormCreate(Sender: TObject); var Status, PID: LongWord; DetectForm: TDetectForm; Hz: Double; I: Integer; ConfigBufSize: LongWord; begin DeviceIndex := diOnly; //If you only have the one board, QueryDeviceInfo() with diOnly will succeed //with the right PID. If you have more than one board, or haven't plugged it //in, it will fail, and this code will pop up the detector form so the user //can pick a board or cancel. Status := QueryDeviceInfo(DeviceIndex, @PID, nil, nil, nil, nil); if (Status <> ERROR_SUCCESS) or not (((PID >= $804A) and (PID <= $805D)) or ((PID >= $814A) and (PID <= $815D))) then begin DetectForm := TDetectForm.Create(Self); if DetectForm.ShowModal = mrOK then begin DeviceIndex := DetectForm.DeviceIndex; DetectForm.Free; QueryDeviceInfo(DeviceIndex, @PID, nil, nil, nil, nil); end else begin DetectForm.Free; Application.Terminate; Exit; end; end; case PID of $804A..$804E, $814A..$814E: Channels := 32; $804F..$8053, $814F..$8153: Channels := 64; $8054..$8058, $8154..$8158: Channels := 96; $8059..$805D, $8159..$815D: Channels := 128; end; SetLength(VoltLabel, Channels); SetLength(CountGauge, Channels); SpacerBevel.Height := 17 * Channels + 2; for I := 0 to Channels-1 do begin VoltLabel[I] := TLabel.Create(Self); with VoltLabel[I] do begin AutoSize := False; Alignment := taCenter; Layout := tlCenter; Align := alTop; Top := 18 * I; Height := 17; Caption := 'Ch ' + IntToStr(I); Parent := VoltPanel; end; CountGauge[I] := TProgressBar.Create(Self); with CountGauge[I] do begin Smooth := True; Color := clLime; //ForeColor := clBtnText; //BackColor := clBtnFace; Align := alTop; Top := 18 * I; Height := 17; Parent := CountPanel; end; end; if ADC_QueryCal(DeviceIndex) <> ERROR_SUCCESS then begin //this board doesn't have calibration CalLabel.Visible := False; CalEdit.Visible := False; end; //Stop the counter, in case it was running. Hz := 0; CTR_StartOutputFreq(DeviceIndex, 0, @Hz); //Set the combo box to the first A/D range, then call RangeComboChange() to //set all the channels to that range. RangeCombo.ItemIndex := 0; RangeComboChange(nil); Config.CalibMode := 0; //Take actual data, not internal calibration sources. Config.TrigMode := $05; //Scan selected channels each counter rising edge. //Config.Oversample := 0; //No oversample. Config.Oversample := 14; //+14 oversample. ConfigBufSize := SizeOf(Config); ADC_SetConfig(DeviceIndex, @Config, ConfigBufSize); end; procedure TMainForm.RangeComboChange(Sender: TObject); var I: Integer; RangeCode: Byte; begin //The ranges in the combo box are listed in order, so that the index is equal //to the range code. RangeCode := RangeCombo.ItemIndex; //Config.ChannelRange[0] controls channels $00 through $07; //Config.ChannelRange[1] controls channels $08 through $0F; etc. //For simplicity, we set 'em all to the same range. for I := $0 to $F do Config.ChannelRange[I] := RangeCode ; for I := 0 to Channels - 1 do begin if (Config.ChannelRange[I div 8] and 1) = 0 then CountGauge[I].Min := 0 else CountGauge[I].Min := -1000 ; CountGauge[I].Max := 1000; if (Config.ChannelRange[I div 8] and 2) = 0 then begin CountGauge[I].Min := CountGauge[I].Min * 2; CountGauge[I].Max := CountGauge[I].Max * 2; end; if (Config.ChannelRange[I div 8] and 4) = 0 then begin CountGauge[I].Min := CountGauge[I].Min * 5; CountGauge[I].Max := CountGauge[I].Max * 5; end; CountGauge[I].Position := I; end; end; procedure TMainForm.GoButtonClick(Sender: TObject); var Status: LongWord; StartChannel, EndChannel: Byte; ConfigBufSize: LongWord; begin StartChannel := 0; EndChannel := Channels - 1; Config.StartStopCH := (EndChannel shl 4) or (StartChannel and $F); Config.StartStopChEx := (EndChannel and $F0) or (StartChannel shr 4); ConfigBufSize := SizeOf(Config); ADC_SetConfig(DeviceIndex, @Config, ConfigBufSize); if CalEdit.Visible then begin Status := ADC_SetCal(DeviceIndex, PChar(CalEdit.Text)); if Status <> ERROR_SUCCESS then begin Application.MessageBox(PChar('Calibration Error ' + IntToStr(Status)), 'Cal Error', MB_ICONEXCLAMATION); Exit; end; end; CalEdit.Enabled := False; RangeCombo.Enabled := False; GoButton.Enabled := False; StopButton.Enabled := True; ADPollTime.Enabled := True; end; procedure TMainForm.StopButtonClick(Sender: TObject); begin ADPollTime.Enabled := False; CalEdit.Enabled := True; RangeCombo.Enabled := True; GoButton.Enabled := True; StopButton.Enabled := False; end; procedure TMainForm.ADPollTimeTimer(Sender: TObject); var Status: LongWord; Volts: array of Double; Channel: Integer; begin SetLength(Volts, Channels); Status := ADC_GetScanV(DeviceIndex, @Volts[0]); if Status <> ERROR_SUCCESS then begin StopButton.Click; Application.MessageBox(PChar('Error ' + IntToStr(Status) + ' from ADC_GetScanV.'), 'ADC_GetScanV Error', MB_ICONEXCLAMATION); Exit; end; for Channel := 0 to Channels - 1 do begin CountGauge[Channel].Position := Round(Volts[Channel] * 1000); VoltLabel[Channel].Caption := Format('Ch %d: %.4f V', [ Channel, Volts[Channel] ]); end; end; end.