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; DiffCheck: TCheckBox; 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; AIMUXChEx: Byte; //AIMUX start and end address bit extension register. end; var DeviceIndex: LongWord; Config: TUSBAI16128Config; VoltLabel: array of TLabel; CountGauge: array of TProgressBar; const Channels = 64; 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 >= $8045) and (PID <= $8049)) or ((PID >= $8145) and (PID <= $8149))) then begin DetectForm := TDetectForm.Create(Self); if DetectForm.ShowModal = mrOK then begin DeviceIndex := DetectForm.DeviceIndex; DetectForm.Free; end else begin DetectForm.Free; Application.Terminate; Exit; end; 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; NewHeight: Integer; begin //The ranges in the combo box are listed in order, so that the index is equal //to the range code. RangeCode := RangeCombo.ItemIndex; if DiffCheck.Checked then RangeCode := RangeCode or $08; //Config.ChannelRange[0] controls channels $00 through $03; //Config.ChannelRange[1] controls channels $04 through $07; 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 and $F] and 1) = 0 then CountGauge[I].Min := 0 else CountGauge[I].Min := -1000 ; CountGauge[I].Max := 1000; if (Config.ChannelRange[I and $F] and 2) = 0 then begin CountGauge[I].Min := CountGauge[I].Min * 2; CountGauge[I].Max := CountGauge[I].Max * 2; end; if (Config.ChannelRange[I and $F] 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; if DiffCheck.Checked then NewHeight := 1 else NewHeight := 17; for I := Channels div 2 to Channels - 1 do begin VoltLabel[I].Height := NewHeight; CountGauge[I].Height := NewHeight; end; end; procedure TMainForm.GoButtonClick(Sender: TObject); var Status: LongWord; StartChannel, EndChannel: Byte; ConfigBufSize: LongWord; begin StartChannel := 0; if DiffCheck.Checked then EndChannel := (Channels div 2) - 1 else EndChannel := Channels - 1 ; Config.StartStopCH := (EndChannel shl 4) or (StartChannel and $F); Config.AIMUXChEx := (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; DiffCheck.Enabled := False; 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; DiffCheck.Enabled := True; end; procedure TMainForm.ADPollTimeTimer(Sender: TObject); var Status: LongWord; Volts: array of Double; Channel, ChannelsUsed: 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; if DiffCheck.Checked then ChannelsUsed := Channels div 2 else ChannelsUsed := Channels ; for Channel := 0 to ChannelsUsed - 1 do begin CountGauge[Channel].Position := Round(Volts[Channel] * 1000); VoltLabel[Channel].Caption := Format('Ch %d: %.4f V', [ Channel, Volts[Channel] ]); end; end; end.