unit Device_template;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Buttons, ExtCtrls, Placemnt, CommInt, HexGrid, ComCtrls, SendThread,
  Mask, ToolEdit, ComboDigEdit, MainForm;

type
  TObjAction = procedure of object;

  TfrmDevice = class(TForm)
    pnDevice: TPanel;
    Panel3: TPanel;
    sbRead: TSpeedButton;
    sbProgr: TSpeedButton;
    sbVerify: TSpeedButton;
    sbBlankCheck: TSpeedButton;
    sbStop: TSpeedButton;
    ProgressBar: TProgressBar;
    Panel8: TPanel;
    edBufFrom: TComboDigEdit;
    Label1: TLabel;
    Label7: TLabel;
    edChipFrom: TComboDigEdit;
    edChipTo: TComboDigEdit;
    Label13: TLabel;
    Panel1: TPanel;
    Label16: TLabel;
    procedure sbReadClick(Sender: TObject);
    procedure sbProgrClick(Sender: TObject);
    procedure sbVerifyClick(Sender: TObject);
    procedure sbBlankCheckClick(Sender: TObject);
    procedure sbStopClick(Sender: TObject);
  private

  protected
    FSendThread:TSendThread;
    FRead:   TObjAction;
    FProgr:  TObjAction;
    FVerify: TObjAction;
    FBlankCheck: TObjAction;
    FStop: TObjAction;

    FProgressBarPos:LongInt;
    FProgressBarMax:LongInt;

    procedure UpdateGrid;
    procedure RefreshGrid;
    procedure UpdateProgress;
    procedure BottonsEnable;
    procedure BottonsDisable;
    procedure CheckSendThread;


  public
    frmMain:TfrmMain;
    Grid:THexGrid;
    Grid_EE:THexGrid;
    CommPort:TComm;
    DeviceEnabled:boolean;
    BufOffSet:Longint;
    CurBufAdr:Longint;
    ChipLoAdr:Longint;
    ChipHiAdr:Longint;
    CodeWordSize:Byte;
    EEWordSize:Byte;
    { Public declarations }
    procedure DoRead;virtual;abstract;
    procedure DoProgr;virtual;abstract;
    procedure DoVerify;virtual;abstract;
    procedure DoBlankCheck;virtual;abstract;
    procedure DoStop;virtual;abstract;
    procedure CloseDevForm;
    procedure SetTimeouts;
    procedure PurgePort;

    constructor Create(AOwner: TComponent); override;
  end;

var
  frmDevice: TfrmDevice;

implementation

uses  RUtilites;


{$R *.DFM}
Constructor TfrmDevice.Create(AOwner: TComponent);
begin
  inherited;
  frmMain:=TfrmMain(AOwner);
  CommPort:=frmMain.CommPort;
  if not CommPort.Enabled then CommPort.Open;
  Grid:=frmMain.HexGrid_Code;
  edBufFrom.value:=Grid.BegAddr;
  frmMain.PageControl1.Pages[0].Caption:='Code memory';
  frmMain.PageControl.ActivePage:=frmMain.tsDevice;
  FSendThread:=Nil;
  DeviceEnabled:=false;
  pnDevice.parent:=frmMain.pnDevice;
  CodeWordSize:=1;
  EEWordSize:=1;
end;

procedure TfrmDevice.UpdateGrid;
var Count:Longint;

begin
  Count:=0;
  if edChipFrom.value>edChipTo.value then
  begin
    edChipFrom.SetFocus;
    MessageDlg('Lower Addr > Higher Addr',mtError,[mbOK],0);
    Abort;
  end;

  // Не допустить выход величины BufFrom ниже величины BegAddr

  if edBufFrom.value<LongInt(Grid.BegAddr) then
  begin
    edBufFrom.SetFocus;
    MessageDlg('Buffer From < Grid Lower Addr',mtError,[mbOK],0);
    Abort;
  end;


  // Вычислить смещение указателя начала буфера относительно


  // Если указатель BufFrom лежит ниже BegAddr таблицы то
  // изменить начальный адресс таблицы
  if edBufFrom.value<Longint(Grid.BegAddr) then
    Grid.BegAddr:=edBufFrom.value;
  if CodeWordSize=1 then
    Count:=(edBufFrom.value-Longint(Grid.BegAddr))+(edChipTo.value-edChipFrom.value+1);
  if CodeWordSize=2 then
    Count:=((edBufFrom.value-Longint(Grid.BegAddr))+(edChipTo.value-edChipFrom.value+1))*2;


  if Count>$FFFFFF then
  begin
    edChipTo.SetFocus;
    MessageDlg('Required data buffer too large!',mtError,[mbOK],0);
    Abort;
  end;

  if Count>Grid.DataCount then
    Grid.DataCount:=Count;
  BufOffSet:= edBufFrom.value-Longint(Grid.BegAddr);
  ChipLoAdr:= edChipFrom.Value;
  ChipHiAdr:= edChipTo.Value;
  frmMain.UpdateStatusBar;
  FProgressBarMax:=edChipTo.value-edChipFrom.value;
  FProgressBarPos:=0;
  UpdateProgress;
end;

procedure TfrmDevice.RefreshGrid;
begin
  Grid.Invalidate;
  if Grid_EE <> Nil then Grid_EE.Invalidate;
end;

procedure TfrmDevice.UpdateProgress;
begin
  ProgressBar.Max:=FProgressBarMax;
  ProgressBar.Position:=FProgressBarPos;
end;

procedure TfrmDevice.BottonsEnable;
var i:word;
begin
  for i:=0 to Self.ComponentCount-1 do
    if Components[i] is  TSpeedButton then
      if  TSpeedButton(Components[i]).tag=1 then
         TSpeedButton(Components[i]).Enabled:=true;
end;

procedure TfrmDevice.BottonsDisable;
var i:word;
begin
  for i:=0 to Self.ComponentCount-1 do
    if Components[i] is  TSpeedButton then
      if  TSpeedButton(Components[i]).tag=1 then
         TSpeedButton(Components[i]).Enabled:=false;
end;

procedure TfrmDevice.CheckSendThread;
begin
  if FSendThread<>nil then
  begin
    Abort
  end
  else
  begin
    FSendThread:=TSendThread.Create(true,CommPort);
  end;
end;


procedure TfrmDevice.CloseDevForm;
begin
  frmMain.FDeviceForm:=Nil;
//  TfrmMain(Self.Owner).FDeviceForm:=Nil;
  CommPort.Close;
  if FSendThread<>Nil then FSendThread.Terminate;
  frmMain.LoFirstOrder:=false;
  frmMain.UpdateStatusBar;
  Free;
end;

procedure TfrmDevice.sbReadClick(Sender: TObject);
begin
  DoRead;
end;

procedure TfrmDevice.sbProgrClick(Sender: TObject);
begin
  DoProgr;
end;

procedure TfrmDevice.sbVerifyClick(Sender: TObject);
begin
  DoVerify;
end;

procedure TfrmDevice.sbBlankCheckClick(Sender: TObject);
begin
  DoBlankCheck;
end;

procedure TfrmDevice.sbStopClick(Sender: TObject);
begin
  DoStop;
end;


Procedure TfrmDevice.SetTimeouts;
begin
  FSendThread.TimeOuts(10, // Интервал ожидания приема первого байта (мс)
                        1, // Множитель интервала между приемом байт (мс)
                        1, // Константа интервала между приемом байт (мс)
                        0, // Множитель интервала между выводом байт (мс)
                        10 // Константа интервала между выводом байт (мс)
                        );
end;

Procedure TfrmDevice.PurgePort;
begin
  PurgeComm(CommPort.Handle, PURGE_RXABORT +
                             PURGE_RXCLEAR +
                             PURGE_TXABORT +
                             PURGE_TXCLEAR);

end;


end.
