unit MainUnit;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls,
  AIOAIO;

type
  TMainForm = class(TForm)
    Label1: TLabel;
    GroupBox1: TGroupBox;
    DeviceCombo: TComboBox;
    Panel1: TPanel;
    Panel2: TPanel;
    DirCheck0: TCheckBox;
    DirCheck1: TCheckBox;
    Label2: TLabel;
    Label3: TLabel;
    DIOPanel0: TPanel;
    DIOPanel1: TPanel;
    PollTime: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure DeviceComboChange(Sender: TObject);
    procedure DIOPanelClick(Sender: TObject);
    procedure DirCheckClick(Sender: TObject);
    procedure PollTimeTimer(Sender: TObject);
  protected
    DirCheck: array[0..1] of TCheckBox;
    DIOPanel: array[0..1] of TPanel;
    iBoard: TBoardIndex;
    DIOData: TUInt32;
    bForceUpdate: Boolean;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.DFM}

const
  DIODataOffset = $44;
  DIOControlOffset = $48;

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

begin
  DeviceCombo.Align := alTop;
  DirCheck0.Align := alLeft;
  DirCheck1.Align := alRight;

  DirCheck[0] := DirCheck0;
  DirCheck[1] := DirCheck1;
  DIOPanel[0] := DIOPanel0;
  DIOPanel[1] := DIOPanel1;

  DeviceCombo.Items.Clear;
  for I := 0 to BRD_GetHighestBoardIndex do begin
    DeviceStrSize := MAX_PATH;
    DeviceStr := StringOfChar(#0, DeviceStrSize);
    Status := BRD_GetName(I, DeviceStrSize, TPAnsiChar(DeviceStr), @DeviceStrSize);
    if Status <> ERROR_SUCCESS then
      DeviceStr := '<Error ' + IntToStr(Status) + ' from BRD_GetName>'
    else
      SetLength(DeviceStr, DeviceStrSize)
    ;
    DeviceCombo.Items.Add('[' + IntToStr(I) + '] ' + DeviceStr);
  end;
  if DeviceCombo.Items.Count <> 0 then begin
    DeviceCombo.ItemIndex := 0;
    DeviceCombo.OnChange(DeviceCombo);
  end;
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
  //`@
end;

procedure TMainForm.DeviceComboChange(Sender: TObject);
var
  iBit: Integer;
  DIOControl: TUInt32;

begin
  iBoard := DeviceCombo.ItemIndex;

  //Read back the direction control register, and set the direction checkboxes accordingly.
  DIOControl := PIO_In32(iBoard, DIOControlOffset);
  for iBit := 0 to 1 do
    DirCheck[iBit].OnClick := nil //Clear the click handlers, so they don't go off during this.
  ;
  for iBit := 0 to 1 do
    DirCheck[iBit].Checked := (DIOControl and (1 shl iBit)) <> 0
  ;
  for iBit := 0 to 1 do
    DirCheck[iBit].OnClick := DirCheckClick //Put the click handlers back.
  ;

  //Set the timer to read the DIO data.
  bForceUpdate := True;
  PollTime.Enabled := True;
end;

procedure TMainForm.DirCheckClick(Sender: TObject);
var
  iBit: Integer;
  DIOControl: TUInt32;

begin
  DIOControl := 0;
  for iBit := 0 to 1 do
    if DirCheck[iBit].Checked then
      DIOControl := DIOControl or (1 shl iBit)
  ;

  PIO_Out32(iBoard, DIOControlOffset, DIOControl);
end;

procedure TMainForm.PollTimeTimer(Sender: TObject);
var
  iBit: Integer;
  oDIOData, Changes: TUInt32;

begin
  oDIOData := DIOData;
  DIOData := PIO_In32(iBoard, DIODataOffset);
  Changes := DIOData xor oDIOData;

  if bForceUpdate then begin
    Changes := $FFFFFFFF;
    bForceUpdate := False;
  end;

  for iBit := 0 to 1 do
    if (Changes and (1 shl iBit)) <> 0 then begin
      if (DIOData and (1 shl iBit)) <> 0 then begin
        DIOPanel[iBit].Caption := 'Digital I/O #' + IntToStr(iBit) + ' Is High';
        DIOPanel[iBit].Color := $00FF00;
        DIOPanel[iBit].Font.Color := $000000;
      end
      else begin                                                                
        DIOPanel[iBit].Caption := 'Digital I/O #' + IntToStr(iBit) + ' Is Low';
        DIOPanel[iBit].Color := $000000;
        DIOPanel[iBit].Font.Color := $FFFFFF;
      end;
    end
  ;
end;

procedure TMainForm.DIOPanelClick(Sender: TObject);
var
  iBit: Integer;

begin
  iBit := (Sender as TPanel).Tag;

  //Toggle that bit.
  DIOData := DIOData xor (1 shl iBit);

  PIO_Out32(iBoard, DIODataOffset, DIOData);

  bForceUpdate := True;
  PollTime.OnTimer(PollTime);
end;

end.
