unit MainUnit;

interface

uses
  WinAPI.Windows, WinAPI.Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls, StdCtrls, ExtCtrls,
  AIOAIO,
  DACFrames;

type
  TMainForm = class(TForm)
    GroupBox1: TGroupBox;
    DeviceCombo: TComboBox;
    DACFrame0: TDACFrame;
    DACFrame1: TDACFrame;
    DACFrame2: TDACFrame;
    DACFrame3: TDACFrame;
    BlurbMemo: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure DeviceComboChange(Sender: TObject);
    procedure DACFrameRangeComboChange(Sender: TObject);
    procedure DACFrameCountsEditChange(Sender: TObject);
    procedure DACFrame0CountsTrackChange(Sender: TObject);
  protected
    ProgrammaticChange: Integer;
    iBoard: TBoardIndex;
    DACFrame: array[0..3] of TDACFrame;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.DFM}

procedure TMainForm.FormCreate(Sender: TObject);
var
  I: Integer;
  Status, DeviceStrSize: LongWord;
  DeviceStr: AnsiString;

begin
  DACFrame[0] := DACFrame0;
  DACFrame[1] := DACFrame1;
  DACFrame[2] := DACFrame2;
  DACFrame[3] := DACFrame3;

  for I := 0 to High(DACFrame) do begin
    //Set tags on the controls to track which DAC.
    DACFrame[I].RangeCombo.Tag := I;
    DACFrame[I].CountsEdit.Tag := I;
    DACFrame[I].CountsTrack.Tag := I;
  end;

  for I := 0 to BRD_GetHighestBoardIndex do begin
    DeviceStrSize := MAX_PATH;
    DeviceStr := StringOfChar(AnsiChar(#0), DeviceStrSize);
    Status := BRD_GetName(I, DeviceStrSize, TPAnsiChar(DeviceStr), @DeviceStrSize);
    if Status <> ERROR_SUCCESS then begin
      DeviceStr := '<Error ' + AnsiString(IntToStr(Status)) + ' getting name>';
    end
    else begin
      SetLength(DeviceStr, DeviceStrSize);
    end;
    DeviceStr := DeviceStr + ' @ ' + AnsiString(IntToStr(I));
    DeviceCombo.Items.Add(String(DeviceStr));
  end;

  if DeviceCombo.Items.Count <> 0 then begin
    DeviceCombo.ItemIndex := 0;
    DeviceCombo.OnChange(DeviceCombo);
  end;
end;

procedure TMainForm.DeviceComboChange(Sender: TObject);
var
  iDAC: Integer;

begin
  iBoard := DeviceCombo.ItemIndex;

  DAC_SetRange(iBoard, ciAll, rcBipolar10);
  DAC_OutputV(iBoard, ciAll, 0);

  Inc(ProgrammaticChange);

  for iDAC := 0 to 3 do begin
    DACFrame[iDAC].RangeCombo.ItemIndex := rcRangeCode3;
    DACFrame[iDAC].RangeCombo.OnChange(DACFrame[iDAC].RangeCombo);
  end;

  Dec(ProgrammaticChange);
end;

procedure TMainForm.DACFrameRangeComboChange(Sender: TObject);
var
  iDAC, iRange: Integer;

begin
  iDAC := (Sender as TComboBox).Tag;
  iRange := DACFrame[iDAC].RangeCombo.ItemIndex;

  if ProgrammaticChange = 0 then
    DAC_SetRange(iBoard, iDAC, iRange)
  ;

  case iRange of
    rcRangeCode0: DACFrame[iDAC].CountsEdit.Text := '0000'; //0-5V
    rcRangeCode1: DACFrame[iDAC].CountsEdit.Text := '0000'; //0-10V
    rcRangeCode2: DACFrame[iDAC].CountsEdit.Text := '8000'; //±5V
    rcRangeCode3: DACFrame[iDAC].CountsEdit.Text := '8000'; //±10V
    rcRangeCode4: DACFrame[iDAC].CountsEdit.Text := '8000'; //±2½V
  end;
end;

procedure TMainForm.DACFrameCountsEditChange(Sender: TObject);
var
  iDAC: Integer;
  Counts: Word;

begin
  iDAC := (Sender as TEdit).Tag;
  Counts := StrToInt('$' + DACFrame[iDAC].CountsEdit.Text);

  if ProgrammaticChange = 0 then
    DAC_Output(iBoard, iDAC, Counts)
  ;

  Inc(ProgrammaticChange);
    DACFrame[iDAC].CountsTrack.Position := $FFFF - Counts;
  Dec(ProgrammaticChange);
end;

procedure TMainForm.DACFrame0CountsTrackChange(Sender: TObject);
var
  iDAC, iRange: Integer;
  Counts: Word;
  Volts: Double;
  dev: Integer;
begin
  iDAC := (Sender as TTrackBar).Tag;
  Counts := $FFFF - DACFrame[iDAC].CountsTrack.Position;
  iRange := DACFrame[iDAC].RangeCombo.ItemIndex;

  Volts := 1/$10000 * Counts;
  //Volts is now 0..1.
  if iRange in [rcRangeCode2, rcRangeCode3, rcRangeCode4] then Volts := Volts * 2 - 1;
  //Volts is instead ±1 for a bipolar range.
  case iRange of
    rcRangeCode0, rcRangeCode2: Volts := Volts * 5;
    rcRangeCode1, rcRangeCode3: Volts := Volts * 10;
    rcRangeCode4: Volts := Volts * 2.5;
  end;

  // if card is M.2-/mPCIe-ADIODF16-16FDS Family, double the volts — DACs are differential
  AIOAIO.BRD_GetDeviceID(iBoard, @dev);
  dev := dev and $FFFF;
  case dev of
    $C0C0,$C0C1,$C0C2,$C0C3,$C050,$C051,$C052: Volts := Volts * 2;
  end;


  DACFrame[iDAC].VoltsLabel.Caption := FloatToStrF(Volts, ffFixed, 15, 4) + ' V';

  if ProgrammaticChange = 0 then
    DACFrame[iDAC].CountsEdit.Text := IntToHex(Counts, 4)
  ;
end;

end.
