unit MainForm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ToolWin, ComCtrls, Grids, HexGrid, Buttons, ExtCtrls, jpeg, Menus,
  ActnList, ImgList, Placemnt, MRUList, CommInt, StdCtrls, Mask, ToolEdit,
  ComboDigEdit, CRC;
const
    MainFormCaption = 'Alt-Prog: ';

type
  TActionProc = procedure(Addr:Cardinal) of object;


type
  PDataBuf = ^TDataBuf;
  TDataBuf = record
    Count:Cardinal;
    data:array[0..MaxdataCount] of Byte;
  end;


  TfrmMain = class(TForm)
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    Open1: TMenuItem;
    Save1: TMenuItem;
    Settings1: TMenuItem;
    ActionList: TActionList;
    OpenFile: TAction;
    SaveFile: TAction;
    Exit: TAction;
    Edit: TAction;
    Exit2: TMenuItem;
    N1: TMenuItem;
    ImageList1: TImageList;
    SaveDialog: TSaveDialog;
    OpenDialog: TOpenDialog;
    GridSettings: TAction;
    Gridsettings1: TMenuItem;
    ToolBar1: TToolBar;
    tbEdit: TToolButton;
    tbBIN: TToolButton;
    tbHEX: TToolButton;
    tbDEC: TToolButton;
    StatusBar: TStatusBar;
    FormStorage1: TFormStorage;
    ToolButton2: TToolButton;
    tbASCII: TToolButton;
    tb8: TToolButton;
    tb16: TToolButton;
    ToolButton1: TToolButton;
    MRUManager: TMRUManager;
    CommPort: TComm;
    CommPortSettings: TAction;
    Commportsettings1: TMenuItem;
    Device1: TMenuItem;
    DallasDS2250T1: TMenuItem;
    OpenDallas: TAction;
    OpenPhilips: TAction;
    Panel1: TPanel;
    Splitter1: TSplitter;
    PageControl: TPageControl;
    tsEditing: TTabSheet;
    tsDevice: TTabSheet;
    Panel2: TPanel;
    Label1: TLabel;
    SpeedButton1: TSpeedButton;
    SpeedButton2: TSpeedButton;
    SpeedButton3: TSpeedButton;
    SpeedButton4: TSpeedButton;
    SpeedButton5: TSpeedButton;
    SpeedButton6: TSpeedButton;
    SpeedButton7: TSpeedButton;
    SpeedButton8: TSpeedButton;
    rgRange: TRadioGroup;
    GroupBox1: TGroupBox;
    Label2: TLabel;
    Label3: TLabel;
    pnDevice: TPanel;
    DeviceClose: TAction;
    Deviceclose1: TMenuItem;
    edConstant: TComboDigEdit;
    edBegin: TComboDigEdit;
    edEnd: TComboDigEdit;
    GroupBox2: TGroupBox;
    sbCalculateCRC: TSpeedButton;
    edCount: TComboDigEdit;
    Label4: TLabel;
    DallasDS2250T2: TMenuItem;
    GotoAddr: TAction;
    About1: TMenuItem;
    About: TAction;
    sbUpdateGridRange: TSpeedButton;
    cbCRC: TComboBox;
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    HexGrid_Code: THexGrid;
    TabSheet2: TTabSheet;
    HexGrid_EE: THexGrid;
    UpdateToolBar: TAction;
    OpenAT90S2313: TAction;
    AT90S23131: TMenuItem;
    ToolButton4: TToolButton;
    ToolButton5: TToolButton;
    Search: TAction;
    PopupMenu1: TPopupMenu;
    Goto1: TMenuItem;
    Gridsettings2: TMenuItem;
    Search1: TMenuItem;
    ToolButton3: TToolButton;
    DoGoToAddr: TAction;
    DoSearch: TAction;
    DoSearchNext: TAction;
    edCRC: TEdit;
    CRC1: TCRC;
    Label5: TLabel;
    Label6: TLabel;
    procedure EditExecute(Sender: TObject);
    procedure OpenFileExecute(Sender: TObject);
    procedure SaveFileExecute(Sender: TObject);
    procedure GridSettingsExecute(Sender: TObject);
    procedure tbBINClick(Sender: TObject);
    procedure tbHEXClick(Sender: TObject);
    procedure tbDECClick(Sender: TObject);
    procedure tbASCIIClick(Sender: TObject);
    procedure tb8Click(Sender: TObject);
    procedure tb16Click(Sender: TObject);
    procedure ToolButton1Click(Sender: TObject);
    procedure SaveAsExecute(Sender: TObject);
    procedure MRUManagerClick(Sender: TObject; const RecentName,
      Caption: String; UserData: Integer);
    procedure FormCreate(Sender: TObject);
    procedure ExitExecute(Sender: TObject);
    procedure CommPortSettingsExecute(Sender: TObject);
    procedure OpenDallasExecute(Sender: TObject);
    procedure FormStorage1RestorePlacement(Sender: TObject);
    procedure ClickEditAction(Sender: TObject);
    procedure sbUpdateGridRangeClick(Sender: TObject);
    procedure DeviceCloseExecute(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure edExit(Sender: TObject);
    procedure edKeyPress(Sender: TObject; var Key: Char);
    procedure OpenPhilipsExecute(Sender: TObject);
    procedure GotoAddrExecute(Sender: TObject);
    procedure AboutExecute(Sender: TObject);
    procedure TabSheet2Show(Sender: TObject);
    procedure TabSheet1Show(Sender: TObject);
    procedure UpdateToolBarExecute(Sender: TObject);
    procedure OpenAT90S2313Execute(Sender: TObject);
    procedure SearchExecute(Sender: TObject);
    procedure DoGoToAddrExecute(Sender: TObject);
    procedure Searching(StrtIndex:Integer);
    procedure DoSearchExecute(Sender: TObject);
    procedure DoSearchNextExecute(Sender: TObject);
    procedure sbCalculateCRCClick(Sender: TObject);
  private
    FWorkFileName:String;
    FSaveRequire:boolean;
    FActionProg: TActionProc;
    Constant:word;
    procedure LoadHexFile(FName:String;Grid:THexGrid);
    procedure LoadBinFile(FName:String;Grid:THexGrid);
    procedure SaveHexFile(FName:String;Grid:THexGrid);
    procedure SaveBinFile(FName:String;Grid:THexGrid);
    procedure SaveWorkFile;
    Procedure OpenWorkFile(FName:String);

    procedure ActionFill(Addr:Cardinal);
    procedure ActionAnd(Addr:Cardinal);
    procedure ActionOr(Addr:Cardinal);
    procedure ActionXor(Addr:Cardinal);
    procedure ActionAdd(Addr:Cardinal);
    procedure ActionSub(Addr:Cardinal);
    procedure ActionMul(Addr:Cardinal);
    procedure ActionDiv(Addr:Cardinal);

    procedure DoActionAll;
    procedure DoActionSelection;
    procedure DoActionRange;

    { Private declarations }
  public
    FGotoForm:TForm;
    FSearchForm:TForm;
    FDeviceForm:TForm;
    FEditingForm:TForm;
    HexGrid: THexGrid;      //текущая активная сетка данных
    flLoFirst:boolean;   // Указатель на порядок расположения байт в слове в файле
    procedure UpdateStatusBar;
    procedure UpdateEdits;
  end;

var
  frmMain: TfrmMain;

implementation

uses GridSettings, RUtilites, PortSettings, SendThread,
     About, Device_template, DeviceAT90S2313, DevicePhilips89, DeviceDallas,
  GoToForm, SearchForm;

{$R *.DFM}

procedure TfrmMain.FormCreate(Sender: TObject);
var i:integer;
begin
  Caption:=MainFormCaption+ 'New';
  HexGrid:=HexGrid_Code;
  flLoFirst:=false;
  for i:=0 to High(StandartCRCModels) do
    cbCRC.Items.Add(StandartCRCModels[i].name);
end;

procedure TfrmMain.FormStorage1RestorePlacement(Sender: TObject);
begin
  UpdateToolBarExecute(Self);
  UpdateStatusBar;
  UpdateEdits;
end;


procedure TfrmMain.TabSheet2Show(Sender: TObject);
begin
  HexGrid:=HexGrid_EE;
  UpdateStatusBar;
  UpdateEdits;
  UpdateToolBarExecute(Self);
end;

procedure TfrmMain.TabSheet1Show(Sender: TObject);
begin
  HexGrid:=HexGrid_Code;
  UpdateStatusBar;
  UpdateEdits;
  UpdateToolBarExecute(Self);
end;


procedure TfrmMain.EditExecute(Sender: TObject);
begin
  if goEditing in HexGrid.Options  then
  begin
    HexGrid.Options:=HexGrid.Options-[goAlwaysShowEditor]-[goEditing];
 //   Edit1.Caption:='Edit enable';
  end
  else
  begin
    HexGrid.Options:=HexGrid.Options+[goAlwaysShowEditor]+[goEditing];
 //   Edit1.Caption:='Edit disable';
  end;
  HexGrid.Invalidate;
end;


procedure TfrmMain.GridSettingsExecute(Sender: TObject);
begin
  with TfrmGridsettings.Create(Self) do
  begin
    InitForm(HexGrid);
    Showmodal;
    Free;
  end;
end;

procedure TfrmMain.tbBINClick(Sender: TObject);
begin
  HexGrid.ViewMode:=vmBIN;
end;

procedure TfrmMain.tbHEXClick(Sender: TObject);
begin
  HexGrid.ViewMode:=vmHEX;
end;

procedure TfrmMain.tbDECClick(Sender: TObject);
begin
  HexGrid.ViewMode:=vmDEC;
end;

procedure TfrmMain.tbASCIIClick(Sender: TObject);
begin
  HexGrid.ViewMode:=vmASCII;
end;

procedure TfrmMain.tb8Click(Sender: TObject);
begin
  HexGrid.DataSize:=dsByte
end;

procedure TfrmMain.tb16Click(Sender: TObject);
begin
  HexGrid.DataSize:=dsWord
end;

procedure TfrmMain.ToolButton1Click(Sender: TObject);
var w:Longint;
begin
  w:=HexGrid.ColWidths[0];
  HexGrid.DefaultColWidth:= Trunc((HexGrid.ClientWidth-w-10)/HexGrid.GridColCount);
  HexGrid.ColWidths[0]:=w
end;

procedure TfrmMain.LoadHexFile(FName:String;Grid:THexGrid);
var FHexBuf:TStringList;
    i,j,N,AddrMin,AddrMax,LAddr:Longint;
    Buf:array[0..255] of byte;
    Addr,HiAddr:word;
begin
  FHexBuf:=TStringList.Create;
  try
    FHexBuf.LoadFromFile(FName);
    AddrMin:=MaxLongInt;
    AddrMax:=0;
    HiAddr:=0;
    for i:=0 to FHexBuf.Count-1 do
    begin
      N:=HEXStr_to_Buf(FHexBuf.Strings[i],Addr,HiAddr,Buf);
      if N>0 then
      begin
        LAddr:=Addr+(HiAddr shl 16);
        if AddrMin>LAddr then AddrMin:=LAddr;
        if AddrMax<(LAddr+N-1) then AddrMax:=LAddr+N-1;
      end;
    end;
    if (AddrMax-AddrMin+1)>$1000000 then
       MessageDlg('File longer than 16 777 216 Byte!',mtError,[mbOK],0)
    else
    begin
      Grid.DataCount:=AddrMax-AddrMin+1;
      Grid.BegAddr:=AddrMin;
      HiAddr:=0;
      for i:=0 to FHexBuf.count-1 do
      begin
        N:=HEXStr_to_Buf(FHexBuf.Strings[i],Addr,HiAddr,Buf);
        LAddr:=Addr+(HiAddr shl 16);
        for j:=0 to N-1 do Grid.AData[j+LAddr-AddrMin]:=Buf[j];
      end;
    end;
  finally
    FHexBuf.Free;
  end;
end;


procedure TfrmMain.LoadBinFile(FName:String;Grid:THexGrid);
var FFile:TFileStream;
    Buf:PDataBuf;
begin
   FFile:=TFileStream.Create(FName,fmOpenRead);
   try
     if FFile.Size>$1000000 then
       MessageDlg('File longer than 16 777 216 Byte!',mtError,[mbOK],0)
     else
     begin
       Buf:=AllocMem(FFile.size+SizeOf(Buf.Count));
       try
         FFile.Read(Buf^.data[0],FFile.size);
         Buf^.count:=FFile.size;
         Grid.AssignDataBuf(Buf);
       except
         FreeMem(Buf,FFile.size+SizeOf(Buf.Count)) ;
         Raise;
       end;
     end;
   finally
     FFile.free;
   end;

end;

procedure TfrmMain.SaveHexFile(FName:String;Grid:THexGrid);
var FFile:TFileStream;
    count,OldHiAddr,HiAddr,CurAddr,tmp:Longint;
    Addr:word;
    N:byte;
//    Buf:array[0..255] of byte;
    str:string;
    Pstr:PChar;
begin
  FFile:=TFileStream.Create(FName,fmCreate);
  try
  OldHiAddr:=0;
  count:=0;
  Addr:=Word(Grid.BegAddr);
  while count<Grid.DataCount do
  begin
    CurAddr:=Grid.BegAddr+Cardinal(count);
    HiAddr:=CurAddr shr 16;
    if HiAddr<>OldHiAddr then
    begin
      OldHiAddr:=HiAddr;
      str:=Addr_To_HEXstr(HiAddr);
      Pstr:=PChar(str);
      FFile.Write(Pstr^,Length(str));
    end;
    N:=16;
    tmp:=(((CurAddr shr 16)+1) shl 16)- CurAddr;
    if tmp < N then N:=tmp;
    tmp:=Grid.DataCount-Count;
    if tmp < N then N:=tmp;
    str:=GridBuf_To_HEXStr(N,addr,Count,Grid.DataBufer)+#10;
    Pstr:=PChar(str);
    FFile.Write(Pstr^,Length(str));
    count:=count+N;
    addr:=word(addr+N);
  end; {while}
  str:=':00000001FF';
  Pstr:=PChar(str);
  FFile.Write(Pstr^,Length(str));
  finally
    FFile.Free;
  end;
end;


procedure TfrmMain.SaveBinFile(FName:String;Grid:THexGrid);
var FFile:TFileStream;
begin
   FFile:=TFileStream.Create(FName,fmCreate);
   try
     FFile.Write(PDataBuf(Grid.DataBufer)^.data[0],PDataBuf(Grid.DataBufer)^.count)
   finally
     FFile.free;
   end;
end;

Procedure TfrmMain.OpenWorkFile(FName:String);
begin
 if  LowerCase(ExtractFileExt(FName))='.hex' then
   LoadHexFile(FName,HexGrid)
 else
   LoadBinFile(FName,HexGrid);
 MRUManager.Add(FName,0);
 FWorkFileName:=FName;
 FSaveRequire:=false;
 Caption:=MainFormCaption+ FWorkFileName;
 UpdateStatusBar;
 UpdateEdits;
end;

procedure TfrmMain.OpenFileExecute(Sender: TObject);
begin
  if OpenDialog.Execute then
    OpenWorkFile(OpenDialog.FileName)
end;

procedure TfrmMain.SaveWorkFile;
begin
  if SaveDialog.Execute then
  begin
    if  LowerCase(ExtractFileExt(saveDialog.FileName))='.hex' then
      SaveHexFile(SaveDialog.FileName,HexGrid)
    else
      SaveBinFile(SaveDialog.FileName,HexGrid);
    MRUManager.Add(SaveDialog.FileName,0);
    FWorkFileName:=SaveDialog.FileName;
    FSaveRequire:=false;
    Caption:=MainFormCaption+ FWorkFileName;
  end;
  UpdateStatusBar;
end;

procedure TfrmMain.SaveFileExecute(Sender: TObject);
begin
  saveDialog.FileName:=FWorkFileName;
  SaveWorkFile;
end;

procedure TfrmMain.SaveAsExecute(Sender: TObject);
begin
  saveDialog.FileName:='';
  SaveWorkFile;
end;

procedure TfrmMain.MRUManagerClick(Sender: TObject; const RecentName,
  Caption: String; UserData: Integer);
begin
  OpenWorkFile(RecentName);
end;

procedure TfrmMain.GotoAddrExecute(Sender: TObject);
begin
   if FGoToForm=Nil then
     FGoToForm:=TfrmGoTo.Create(Self);
   TfrmGoTo(FGoToForm).bbGoto.OnClick:=DoGoToAddrExecute;
   FGoToForm.Show;

end;

procedure TfrmMain.DoGoToAddrExecute(Sender: TObject);
var adr:Integer;
    col,row:integer;
begin
  adr:=TfrmGoTo(FGoToForm).edGotoAddr.Value;
  if (adr<Integer(HexGrid.BegAddr)) or
      (adr>Integer(HexGrid.BegAddr+Cardinal(HexGrid.DataCount)-1))  then
  begin
    MessageDlg('Address out of range',mtWarning,[mbAbort],0);
    Abort
  end;
  col:=((adr-LongInt(hexgrid.BegAddr)) mod hexgrid.GridColCount)+1;
  row:=((adr-LongInt(hexgrid.BegAddr)) div hexgrid.GridColCount)+1;
  HexGrid.col:=Col;
  HexGrid.Row:=row;
end;

procedure TfrmMain.SearchExecute(Sender: TObject);
begin
  if FSearchForm=Nil then
    FSearchForm:=TfrmSearch.Create(Self);
  TfrmSearch(FSearchForm).bbFind.OnClick:=DoSearchExecute;
  TfrmSearch(FSearchForm).bbFindNext.OnClick:=DoSearchNextExecute;
  FSearchForm.Show;
end;

procedure TfrmMain.Searching(StrtIndex:Integer);
var vl:Word;
    i:Integer;
    col,row:integer;
    Searched:boolean;
begin
  Searched:=false;
  if HexGrid.DataSize=dsByte then
  begin
    vl:=Byte(TfrmSearch(FSearchForm).edValue.Value);
    if StrtIndex<>0 then StrtIndex:=StrtIndex+1 ;
    for i:=StrtIndex to HexGrid.DataCount-1 do
    begin
      if HexGrid.AData[i]=vl then
      begin
        col:=(i mod hexgrid.GridColCount)+1;
        row:=(i div hexgrid.GridColCount)+1;
        HexGrid.col:=col;
        HexGrid.row:=row;
        Searched:=true;
        Break;
      end
    end;
    if Not Searched then
      MessageDlg('Value not found!',mtWarning,[mbOk],0);
  end
  else
  begin
    vl:=Word(TfrmSearch(FSearchForm).edValue.Value);
    if StrtIndex<>0 then StrtIndex:=(StrtIndex div 2)+1;
    for i:=StrtIndex to (HexGrid.DataCount div 2)-1 do
    begin
      if (HexGrid.AData[i*2]*256+HexGrid.AData[i*2+1])=vl then
      begin
        col:=(i mod hexgrid.GridColCount)+1;
        row:=(i div hexgrid.GridColCount)+1;
        HexGrid.col:=col;
        HexGrid.row:=row;
        Searched:=true;
        Break;
      end
    end;
    if Not Searched then
      MessageDlg('Value not found!',mtWarning,[mbOk],0);
  end;
end;

procedure TfrmMain.DoSearchExecute(Sender: TObject);
begin
  Searching(0)
end;

procedure TfrmMain.DoSearchNextExecute(Sender: TObject);
begin
  Searching(HexGrid.GetDataIndex(HexGrid.Col,HexGrid.Row))
end;

procedure TfrmMain.AboutExecute(Sender: TObject);
begin
  with TfrmAbout.Create(Self) do
  begin
    Showmodal;
    Free;
  end;
end;

procedure TfrmMain.ExitExecute(Sender: TObject);
begin
  Application.Terminate;
end;

procedure TfrmMain.CommPortSettingsExecute(Sender: TObject);
begin
  with  TfrmPortSettings.CreatePortSettings(Self,CommPort) do
  begin
    try
      ShowModal;
    finally
      Free;
      UpdateStatusBar;
    end;
  end;
end;


procedure TfrmMain.UpdateStatusBar;
var str:string;
begin
  with StatusBar do
  begin
    str:=CommPort.DeviceName;
    str:=str+'/'+BaudR[CommPort.BaudRate];
    str:=str+'/'+lParity[CommPort.Parity];
    str:=str+'/'+lStopBits[CommPort.StopBits];
    str:=str+'/'+lDataBits[CommPort.DataBits];
    str:=str+'  Flow control: '+lFlowControl[CommPort.Flowcontrol];
    if CommPort.Enabled then
      str:=str+'. Port open'
    else
      str:=str+'. Port close';
    panels[1].text:=str;

    str:='Size: '+IntToStr(HexGrid.DataCount)+' bytes';
    panels[0].text:=str;
  end;
end;

procedure TfrmMain.UpdateEdits;
begin
  edBegin.value:=HexGrid.BegAddr;
  if HexGrid.DataSize=dsWord then
    edEnd.value:=(HexGrid.DataCount div 2)-1
  else
    edEnd.value:=HexGrid.DataCount-1;
  edExit(edEnd);
  if (FDeviceForm<>Nil) and (HexGrid.name='HexGrid_Code')  then
  begin
    TfrmDevice(FDeviceForm).edBufFrom.Value:=HexGrid.BegAddr;
    TfrmDevice(FDeviceForm).edChipFrom.Value:=0;
    if HexGrid.DataSize=dsWord then
      TfrmDevice(FDeviceForm).edChipTo.value:=(HexGrid.DataCount div 2)-1
    else
      TfrmDevice(FDeviceForm).edChipTo.value:=HexGrid.DataCount-1
  end;
end;

procedure TfrmMain.UpdateToolBarExecute(Sender: TObject);
begin
  case HexGrid.DataSize of
  dsByte: tb8.Down:=true;
  dsWord: tb16.Down:=true;
  end;
  case HexGrid.ViewMode of
  vmHEX: tbHex.Down:=true;
  vmBIN: tbBIN.Down:=true;
  vmDEC: tbDEC.Down:=true;
  vmASCII: tbASCII.Down:=true;
  end;
  if HexGrid.EditorMode then
    tbEdit.Down:=true
  else
    tbEdit.Down:=false;
end;


procedure TfrmMain.ActionFill(Addr:Cardinal);
var F:integer;
begin
    if HexGrid.DataSize=dsWord then
    begin
      F:=Constant;
      HexGrid.AData[Addr]:=Hi(F);
      HexGrid.AData[Addr+1]:=Lo(F);
    end
    else
      HexGrid.AData[Addr]:=Byte(Constant);
end;


procedure TfrmMain.ActionAnd(Addr:Cardinal);
var F:integer;
begin
    if HexGrid.DataSize=dsWord then
    begin
      F:=((HexGrid.AData[Addr] shl 8) or HexGrid.AData[Addr+1]) and Constant;
      HexGrid.AData[Addr]:=Hi(F);
      HexGrid.AData[Addr+1]:=Lo(F);
    end
    else
      HexGrid.AData[Addr]:=HexGrid.AData[Addr] and Byte(Constant);
end;

procedure TfrmMain.ActionOr(Addr:Cardinal);
var F:integer;
begin
    if HexGrid.DataSize=dsWord then
    begin
      F:=((HexGrid.AData[Addr] shl 8) or HexGrid.AData[Addr+1]) or Constant;
      HexGrid.AData[Addr]:=Hi(F);
      HexGrid.AData[Addr+1]:=Lo(F);
    end
    else
      HexGrid.AData[Addr]:=HexGrid.AData[Addr] or Byte(Constant);
end;

procedure TfrmMain.ActionXor(Addr:Cardinal);
var F:integer;
begin
    if HexGrid.DataSize=dsWord then
    begin
      F:=((HexGrid.AData[Addr] shl 8) or HexGrid.AData[Addr+1]) xor Constant;
      HexGrid.AData[Addr]:=Hi(F);
      HexGrid.AData[Addr+1]:=Lo(F);
    end
    else
      HexGrid.AData[Addr]:=HexGrid.AData[Addr] xor Byte(Constant);
end;

procedure TfrmMain.ActionSub(Addr:Cardinal);
var F:integer;
begin
    if HexGrid.DataSize=dsWord then
    begin
      F:=((HexGrid.AData[Addr] shl 8) or HexGrid.AData[Addr+1]) - Constant;
      HexGrid.AData[Addr]:=Hi(F);
      HexGrid.AData[Addr+1]:=Lo(F);
    end
    else
      HexGrid.AData[Addr]:=Byte(HexGrid.AData[Addr]-Byte(Constant));
end;

procedure TfrmMain.ActionAdd(Addr:Cardinal);
var F:integer;
begin
    if HexGrid.DataSize=dsWord then
    begin
      F:=((HexGrid.AData[Addr] shl 8) or HexGrid.AData[Addr+1]) + Constant;
      HexGrid.AData[Addr]:=Hi(F);
      HexGrid.AData[Addr+1]:=Lo(F);
    end
    else
      HexGrid.AData[Addr]:=Byte(HexGrid.AData[Addr]+Byte(Constant));
end;

procedure TfrmMain.ActionMul(Addr:Cardinal);
var F:integer;
begin
    if HexGrid.DataSize=dsWord then
    begin
      F:=((HexGrid.AData[Addr] shl 8) or HexGrid.AData[Addr+1]) * Constant;
      HexGrid.AData[Addr]:=Hi(F);
      HexGrid.AData[Addr+1]:=Lo(F);
    end
    else
      HexGrid.AData[Addr]:=Byte(HexGrid.AData[Addr]*Byte(Constant));
end;

procedure TfrmMain.ActionDiv(Addr:Cardinal);
var F:Integer;
begin
  if Byte(Constant)<>0 then
    if HexGrid.DataSize=dsWord then
    begin
      F:=((HexGrid.AData[Addr] shl 8) or HexGrid.AData[Addr+1]) div Constant;
      HexGrid.AData[Addr]:=Hi(F);
      HexGrid.AData[Addr+1]:=Lo(F);
    end
    else
      HexGrid.AData[Addr]:=Byte(HexGrid.AData[Addr]div Byte(Constant));
end;

procedure TfrmMain.DoActionAll;
var i:cardinal;
begin
  for i:=0 to HexGrid.Datacount-1 do
    if HexGrid.DataSize=dsWord then
      FActionProg(i*2)
    else
      FActionProg(i);
  HexGrid.Invalidate;
end;

procedure TfrmMain.DoActionSelection;
var i,j:cardinal;
begin
  for j:=HexGrid.Selection.Top to HexGrid.Selection.Bottom do
    for i:=HexGrid.Selection.Left to HexGrid.Selection.Right do
      FActionProg(HexGrid.GetDataIndex(i,j));
  HexGrid.Invalidate;
end;

procedure TfrmMain.DoActionRange;
var begaddr,endaddr,i:cardinal;
begin
  begaddr:=edBegin.Value;
  endaddr:=edEnd.Value;
  for i:=begaddr to endaddr do
    if HexGrid.DataSize=dsWord then
      FActionProg(i*2)
    else
      FActionProg(i);
  HexGrid.Invalidate;
end;

procedure TfrmMain.ClickEditAction(Sender: TObject);
begin
  constant:=edConstant.Value;
  case TSpeedButton(Sender).Tag of
  1:FActionProg:=ActionFill;
  2:FActionProg:=ActionAnd;
  3:FActionProg:=ActionOr;
  4:FActionProg:=ActionXor;
  5:FActionProg:=ActionSub;
  6:FActionProg:=ActionAdd;
  7:FActionProg:=ActionMul;
  8:FActionProg:=ActionDiv;
  else
    Abort;
  end;

  case rgRange.ItemIndex of
  0:DoActionAll;
  1:DoActionSelection;
  2:DoActionRange;
  end;
end;

procedure TfrmMain.sbUpdateGridRangeClick(Sender: TObject);
var BegAddr,EndAddr:Longint;
begin
  BegAddr:=edBegin.Value;
  EndAddr:=edEnd.Value;
  HexGrid.DataCount:=EndAddr-BegAddr+1;
  HexGrid.BegAddr:=Cardinal(BegAddr);
  UpdateStatusBar;
end;

procedure TfrmMain.edExit(Sender: TObject);
var edName:string ;
begin
  edName:=TComboDigEdit(Sender).Name;
  if (edName='edBegin') or (edName='edEnd') then
  begin
    If edBegin.value>edEnd.value then
    begin
      MessageDlg('Value Begin > End !',mtError, [mbOk], 0);
      TWinControl(Sender).SetFocus;
    end
    else
    begin
      if edCount.Value<>(edEnd.value-edBegin.value+1) then
        edCount.Value:=edEnd.value-edBegin.value+1;
    end
  end;
  if edName='edCount' then
  begin
    If ((edBegin.Value+edCount.Value-1)>edEnd.MaxValue)
        or (edCount.Value<1) then
    begin
      MessageDlg('Value out of range!',mtError, [mbOk], 0);
      TWinControl(Sender).SetFocus;
    end
    else
    begin
      if edEnd.Value<>(edBegin.value+edCount.value-1) then
        edEnd.Value:=edBegin.value+edCount.value-1;
    end
  end;
end;

procedure TfrmMain.edKeyPress(Sender: TObject; var Key: Char);
begin
  if Key=Chr($0d) then edExit(Sender);
end;

procedure TfrmMain.OpenPhilipsExecute(Sender: TObject);
begin
  if FDeviceForm<>Nil then DeviceCloseExecute(Sender);
  FDeviceForm:=TfrmDevicePhilips89.Create(Self);
end;

procedure TfrmMain.OpenDallasExecute(Sender: TObject);
begin
  if FDeviceForm<>Nil then DeviceCloseExecute(Sender);
  FDeviceForm:=TfrmDeviceDallas.Create(Self);
end;

procedure TfrmMain.OpenAT90S2313Execute(Sender: TObject);
begin
  if FDeviceForm<>Nil then DeviceCloseExecute(Sender);
  FDeviceForm:=TfrmAT90S2313.Create(Self);
end;

procedure TfrmMain.DeviceCloseExecute(Sender: TObject);
begin
  If FDeviceForm<>Nil then
    TfrmDevice(FDeviceForm).CloseDevForm;
  PageControl1.Pages[0].Caption:='Data';
  PageControl1.Pages[1].TabVisible:=false;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  DeviceCloseExecute(Sender);
end;









procedure TfrmMain.sbCalculateCRCClick(Sender: TObject);
var i,j:integer;
    index:integer;
begin
  if cbCRC.Text='' then Abort;
  CRC1.CRC:=StandartCRCModels[cbCRC.Items.IndexOF(cbCRC.Text)];
  CRC1.Cm_Ini;
  case rgRange.ItemIndex of
  0:  CRC1.Cm_Blk(@PDataBuf(HexGrid.DataBufer).data[0],HexGrid.DataCount);

  1:begin   // selection
     for j:=HexGrid.Selection.Top to HexGrid.Selection.Bottom do
       for i:=HexGrid.Selection.Left to HexGrid.Selection.Right do
       begin
         index:=HexGrid.GetDataIndex(i,j);
         if HexGrid.DataSize=dsWord then
         begin
           CRC1.Cm_Nxt(HexGrid.Adata[index]);
           CRC1.Cm_Nxt(HexGrid.Adata[index+1]);
         end
         else
           CRC1.Cm_Nxt(HexGrid.Adata[index]);
       end
    end;
  2:begin   //range
      for i:=edBegin.Value to edEnd.Value do
      begin
        if HexGrid.DataSize=dsWord then
        begin
          CRC1.Cm_Nxt(HexGrid.Adata[i*2]);
          CRC1.Cm_Nxt(HexGrid.Adata[i*2+1]);
        end
        else
          CRC1.Cm_Nxt(HexGrid.Adata[i]);
      end;
    end;
  end;


  edCRC.Text:=Format('%.'+IntToStr(CRC1.CRC.width div 4)+'x',[CRC1.Cm_CRC]);
end;

end.
