unit DeviceDallas;

interface

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

type
  TfrmDeviceDallas = class(TfrmDevice)
    Label2: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label3: TLabel;
    Panel2: TPanel;
    sbReset: TSpeedButton;
    Panel4: TPanel;
    sbWriteMCON: TSpeedButton;
    sbReadMCON: TSpeedButton;
    Label6: TLabel;
    cbPartition: TComboBox;
    Label8: TLabel;
    cbCE2: TCheckBox;
    rgMaxUs: TRadioGroup;
    Panel5: TPanel;
    sbUnLock: TSpeedButton;
    sbLock: TSpeedButton;
    procedure sbUnLockClick(Sender: TObject);
    procedure sbLockClick(Sender: TObject);
    procedure sbReadMCONClick(Sender: TObject);
    procedure sbWriteMCONClick(Sender: TObject);
    procedure sbResetLoaderClick(Sender: TObject);
  private
    MCON:integer;

    procedure PrepareMCON;
    procedure LoadMCON;

    procedure ReadData;
    procedure VerifyData;
    procedure WriteData;
    procedure SetLock;
    procedure ClearLock;
    procedure ReadMCON;
    procedure WriteMCON;
    function CheckDevice:boolean;
    procedure FreeSendThread;
    procedure ResetLoader;
    function Reset:string;
  public
    procedure DoRead;override;
    procedure DoProgr;override;
    procedure DoStop;override;
    procedure DoVerify;override;
    procedure DoBlankCheck;override;
    Constructor Create(AOwner:TComponent);override;
  end;

var
  frmDeviceDallas: TfrmDeviceDallas;

implementation

uses MainForm, RUtilites, SendThread;

{$R *.DFM}


const
    cmdRequest = Chr($0d);
    cmdReset = Chr(03);
    cmdLoad = 'L'+ Chr($0d);
    cmdDump = 'D';
    cmdLock = 'Z'+ Chr($0d);
    cmdUnLock = 'U'+ Chr($0d);
    cmdReadMCON = 'R'+ Chr($0d);
    cmdWriteMCON = 'W';
    strAnswer = Chr($0d)+Chr($0a)+'>';


Constructor TfrmDeviceDallas.Create(AOwner:TComponent);
begin
  inherited;
  Self.edChipTo.MaxValue:=$7FFF;
  CommPort.FlowControl:=fcSoftware;

  Grid.DataCount:=$8000;
  Grid.DataSize:=dsByte;
  CodeWordSize:=1;
  frmMain.UpdateToolBarExecute(Self);
  frmMain.UpdateStatusBar;

end;



procedure TfrmDeviceDallas.PrepareMCON;
var b:byte;
begin
  MCON:=-1;
  if cbPartition.ItemIndex<0 then
  begin
    MessageDlg('No defined partition!',mtError,[mbOK],0);
    exit;
  end;
  if rgMaxUs.ItemIndex<0 then
  begin
    MessageDlg('No defined maximum usable address!',mtError,[mbOK],0);
    exit;
  end;
  b:=cbPartition.ItemIndex shl 4;
  if rgMaxUs.ItemIndex=1 then b:=b or $08;
  if cbCE2.Checked then b:=b or $04;
  MCON:=b;
end;

procedure TfrmDeviceDallas.LoadMCON;
var b:byte;
begin
  b:=MCON shr 4;
  cbPartition.ItemIndex:=b;
  if (MCON and 08)>0 then
    rgMaxUs.ItemIndex:=1
  else
    rgMaxUs.ItemIndex:=0;
  if (MCON and 04)>0 then
    cbCE2.Checked:=true
  else
    cbCE2.Checked:=false;
end;





procedure TfrmDeviceDallas.DoRead;
begin
  CheckSendThread;
  FSendThread.OnExecuteProcess:=ReadData;
  FSendThread.OnEndProcess:=FreeSendThread;
  FSendThread.Resume;
end;

procedure TfrmDeviceDallas.DoVerify;
begin
  CheckSendThread;
  FSendThread.OnExecuteProcess:=VerifyData;
  FSendThread.OnEndProcess:=FreeSendThread;
  FSendThread.Resume;
end;

procedure TfrmDeviceDallas.DoProgr;
begin
  CheckSendThread;
  FSendThread.OnExecuteProcess:=WriteData;
  FSendThread.OnEndProcess:=FreeSendThread;
  FSendThread.Resume;
end;

procedure TfrmDeviceDallas.DoStop;
begin
  if FSendThread<>Nil then FSendThread.Terminate;
end;

procedure TfrmDeviceDallas.DoBlankCheck;
begin
end;

procedure TfrmDeviceDallas.sbResetLoaderClick(Sender: TObject);
begin
  CheckSendThread;
  FSendThread.OnExecuteProcess:=ResetLoader;
  FSendThread.OnEndProcess:=FreeSendThread;
  FSendThread.Resume;
end;

procedure TfrmDeviceDallas.sbLockClick(Sender: TObject);
begin
  CheckSendThread;
  FSendThread.OnExecuteProcess:=SetLock;
  FSendThread.OnEndProcess:=FreeSendThread;
  FSendThread.Resume;
end;

procedure TfrmDeviceDallas.sbUnLockClick(Sender: TObject);
begin
  CheckSendThread;
  FSendThread.OnExecuteProcess:=ClearLock;
  FSendThread.OnEndProcess:=FreeSendThread;
  FSendThread.Resume;
end;

procedure TfrmDeviceDallas.sbReadMCONClick(Sender: TObject);
begin
  CheckSendThread;
  FSendThread.OnExecuteProcess:=ReadMCON;
  FSendThread.OnEndProcess:=FreeSendThread;
  FSendThread.Resume;
end;

procedure TfrmDeviceDallas.sbWriteMCONClick(Sender: TObject);
begin
  CheckSendThread;
  FSendThread.OnExecuteProcess:=WriteMCON;
  FSendThread.OnEndProcess:=FreeSendThread;
  FSendThread.Resume;
end;




// ----------------------------------------------------------------------------
//
//  Procedures called from SendThread
//
// ----------------------------------------------------------------------------
//



Function TfrmDeviceDallas.Reset:string;
var
    str:string;
    Buf:TThreadBuf;
    FRead:Cardinal;
    i:integer;
begin
  with  FSendThread do
  begin
    Synchronize(BottonsDisable);
    try
      DeviceEnabled:=false;
      PurgePort;
      SetTimeouts;
      buf:=cmdReset;
      WriteToComm(Length(cmdRequest),buf);
      for i:=1 to 5 do
      begin
        buf:=cmdRequest;
        WriteToComm(Length(cmdRequest),buf);
        ReadFromComm(200,Buf,FRead);
        SetString(str,Buf,FRead);
        if Pos(strAnswer,str)>0 then break;

        if Length(str)>=Length(strAnswer) then
          if copy(str,Length(str)-Length(strAnswer)+1,Length(strAnswer))=strAnswer then
            Break;
        if i>4 then Exit;
      end;

      buf:=cmdReset;
      WriteToComm(Length(cmdReset),buf);
      ReadFromComm(200,Buf,FRead);
      SetString(str,Buf,FRead);
      if Pos(strAnswer,str)>0 then DeviceEnabled:=true;
      Result:=str;
    except
      On E:ESendThreadError do MessageDlg(E.Message,mtError,[mbOK],0);
      else Raise;
    end;
  end;
end;



procedure TfrmDeviceDallas.ResetLoader;
var str:string;
begin
  str:=Self.Reset;
  if DeviceEnabled=true then
    MessageDlg('Answer: '+str,mtInformation,[mbOK],0)
  else
    MessageDlg('No Answer!',mtInformation,[mbOK],0)
end;



function TfrmDeviceDallas.CheckDevice:boolean;
begin
  result:=true;
  if not DeviceEnabled then
  begin
    Reset;
    if not DeviceEnabled then
    begin
      result:=false;
      MessageDlg('No Answer!',mtInformation,[mbOK],0)
    end
  end
end;



procedure TfrmDeviceDallas.ReadData;
var
    str:string;
    Buf:TThreadBuf;
    BufLen,OffSet:Cardinal;
    FRead,Count:Cardinal;
    i:integer;
const MaxRead = 100;
begin
  with FSendThread do
  begin
    Synchronize(UpdateGrid);
    Synchronize(BottonsDisable);
    if not CheckDevice then exit;
    PurgePort;
    SetTimeouts;
    try
      str:=cmdDump+format(' %.4x %.4x'+Chr($0d),[edChipFrom.Value,edChipTo.Value]);
      BufLen:=FormatBuf(Buf,SizeOf(Buf),'%s',2,[str]);
      WriteToComm(BufLen,Buf);
      str:='';
      OffSet:=Longint(Grid.BegAddr)-edBufFrom.Value;
      repeat
        ReadFromComm(MaxRead,Buf,FRead);
        for i:=0 to  FRead-1 do
        begin
          str:=str+Buf[i];
          if Buf[i]=Chr($0a) then
          begin
            Count:=HEXStr_to_GridBuf(str,OffSet,Grid.DataBufer);
            if count<>0 then
              FProgressBarPos:=FProgressBarPos+LongInt(count);
            Synchronize(UpdateProgress);
            str:='';
          end;
        end;

      until MaxRead<>FRead;
    finally
      Synchronize(RefreshGrid);
    end;
  end;
end;

procedure TfrmDeviceDallas.VerifyData;
var
    str:string;
    Buf:TThreadBuf;
    BufLen,OffSet:Cardinal;
    FRead,Count:Cardinal;
    i,j:word;
    TmpBuf:array[0..255] of byte;
    addr,HiAddr:word;
const MaxRead = 100;
begin
  with FSendThread do
  begin
    Synchronize(UpdateGrid);
    Synchronize(BottonsDisable);
    if not CheckDevice then exit;
    PurgePort;
    SetTimeouts;
    str:=cmdDump+format(' %.4x %.4x'+Chr($0d),[edChipFrom.Value,edChipTo.Value]);
    BufLen:=FormatBuf(Buf,SizeOf(Buf),'%s',2,[str]);
    WriteToComm(BufLen,Buf);
    str:='';
    repeat
      ReadFromComm(MaxRead,Buf,FRead);
      for i:=0 to  FRead-1 do
      begin
        str:=str+Buf[i];
        if Buf[i]=Chr($0a) then
        begin
          Count:=HEXStr_to_Buf(str,Addr,HiAddr,TmpBuf);
          if count<>0 then
          begin
            FProgressBarPos:=FProgressBarPos+LongInt(count);
            Synchronize(UpdateProgress);
            OffSet:=edBufFrom.Value-Longint(Grid.BegAddr)+Longint(Addr)-edChipFrom.Value;
            for j:=0 to count-1 do
              if Grid.AData[OffSet+j]<>TmpBuf[j] then
              begin
                str:=Format('Buff addr.: %.6x [%.2x]  Chip addr.: %.4x [%.2x]',
                            [edBufFrom.Value+Addr+j,
                            Grid.AData[OffSet+j],
                            edChipFrom.Value+Addr+j,
                            TmpBuf[j]]);
                MessageDlg('Error: '+str,mtInformation,[mbOK],0);
                Abort;
              end
          end;
          str:='';
        end;
      end;

    until MaxRead<>FRead;
  end;
end;

procedure TfrmDeviceDallas.WriteData;
var
    str,AnswStr:string;
    Buf:TThreadBuf;
    BufLen:Cardinal;
    Count:Cardinal;
    Addr,i:Cardinal;
const MaxRead = 100;
begin
  with FSendThread do
  begin
    Synchronize(UpdateGrid);
    Synchronize(BottonsDisable);
    if not CheckDevice then exit;
    PurgePort;
    SetTimeouts;
    str:='L'+chr($0d);
    TimeOuts(10,1,1,0,0);
    BufLen:=FormatBuf(Buf,SizeOf(Buf),'%s',2,[str]);
    try
      WriteToComm(BufLen,Buf);
      Addr:=0;
      AnswStr:='';
      repeat
        if (edChipTo.Value-edChipFrom.Value-Longint(Addr)+1)>16 then
          Count:=16
        else
          Count:=edChipTo.Value-edChipFrom.Value-Longint(Addr)+1;

        str:=GridBuf_To_HEXStr(Count,
                               edChipFrom.Value+Longint(Addr) ,
                               edBufFrom.Value-LongInt(Grid.BegAddr)+Longint(Addr),
                               Grid.DataBufer);
        BufLen:=FormatBuf(Buf,SizeOf(Buf),'%s',2,[str]);
        WriteToComm(BufLen,Buf);
        FProgressBarPos:=FProgressBarPos+LongInt(Count);
        Synchronize(UpdateProgress);
        Addr:=Addr+Count;
        BufLen:=CommPort.InQueCount;
        if BufLen>0 then
        begin
          ReadFromComm(BufLen,Buf,Count);
          for i:=0 to Count do
          begin
            if Buf[i]='E' then
              AnswStr:='E'
            else
              if Length(AnswStr)>0 then AnswStr:=AnswStr+Buf[i];
          end;
          if (Length(AnswStr)>=8) and (Copy(AnswStr,1,2)='E:') then
          begin
            MessageDlg('Error: '+Copy(AnswStr,1,8),mtInformation,[mbOK],0);
            Abort
          end;
        end;
      until (edChipFrom.Value+Longint(Addr))>edChipTo.Value;
      str:=GridBuf_To_HEXStr(0,edChipFrom.Value ,0,Grid.DataBufer);
      BufLen:=FormatBuf(Buf,SizeOf(Buf),'%s',2,[str]);
      WriteToComm(BufLen,Buf);
    finally
      str:=cmdReset;
      BufLen:=FormatBuf(Buf,SizeOf(Buf),'%s',2,[str]);
      WriteToComm(BufLen,Buf);
    end;
  end;
end;

procedure TfrmDeviceDallas.SetLock;
var
    str:string;
    Buf:TThreadBuf;
    BufLen:Cardinal;
    FRead:Cardinal;
begin
  with FSendThread do
  begin
    Synchronize(BottonsDisable);
    if not CheckDevice then exit;
    PurgePort;
    SetTimeouts;
    str:=cmdLock;
    BufLen:=FormatBuf(Buf,SizeOf(Buf),'%s',2,[str]);
    WriteToComm(BufLen,Buf);
    ReadFromComm(100,Buf,FRead);
    SetString(str,Buf,FRead);
    if Pos('LOCKED',str)<>0 then
      MessageDlg(str,mtInformation,[mbOK],0)
    else
      MessageDlg('No answer!',mtInformation,[mbOK],0);
  end;
end;

procedure TfrmDeviceDallas.ClearLock;
var
    str:string;
    Buf:TThreadBuf;
    BufLen:Cardinal;
    FRead:Cardinal;
begin
  with FSendThread do
  begin
    Synchronize(BottonsDisable);
    if not CheckDevice then exit;
    PurgePort;
    TimeOuts(1000,1,1000,0,10);
    str:=cmdUnLock;
    BufLen:=FormatBuf(Buf,SizeOf(Buf),'%s',2,[str]);
    WriteToComm(BufLen,Buf);
    ReadFromComm(100,Buf,FRead);
    SetString(str,Buf,FRead);
    if Pos('UNLOCKED',str)<>0 then
      MessageDlg(str,mtInformation,[mbOK],0)
    else
      MessageDlg('No answer!',mtInformation,[mbOK],0);
  end;
end;

procedure TfrmDeviceDallas.ReadMcon;
var
    str:string;
    Buf:TThreadBuf;
    BufLen:Cardinal;
    FRead:Cardinal;
    k:integer;
begin
  with FSendThread do
  begin
    Synchronize(BottonsDisable);
    if not CheckDevice then exit;
    PurgePort;
    SetTimeouts;
    str:=cmdReadMCON;
    BufLen:=FormatBuf(Buf,SizeOf(Buf),'%s',2,[str]);
    WriteToComm(BufLen,Buf);
    ReadFromComm(100,Buf,FRead);
    SetString(str,Buf,FRead);
    k:=pos(chr($0d)+chr($0a),str);
    if (k>0) and (Length(str)>(k+2)) then
    begin
      if pos('E:',str)>0 then
      begin
        MessageDlg(str,mtInformation,[mbOK],0);
        exit;
      end;
      str:=copy(str,k+2,2);
      MCON:=StrToInt('$'+str);
      Synchronize(LoadMCON);
    end
    else
    begin
      MessageDlg('No answer!',mtInformation,[mbOK],0);
    end;;
  end;
end;

procedure TfrmDeviceDallas.WriteMcon;
var
    str:string;
    Buf:TThreadBuf;
    BufLen:Cardinal;
    FRead:Cardinal;
begin
  with FSendThread do
  begin
    Synchronize(BottonsDisable);
    if not CheckDevice then exit;
    PurgePort;
    SetTimeouts;
    Synchronize(PrepareMCON);
    if MCON<0 then exit;
    str:=cmdWriteMCON+format(' %.2x',[MCON])+chr($0d);
    BufLen:=FormatBuf(Buf,SizeOf(Buf),'%s',2,[str]);
    WriteToComm(BufLen,Buf);
    ReadFromComm(100,Buf,FRead);
  end;
end;

procedure TfrmDeviceDallas.FreeSendThread;
begin
  FProgressBarPos:=0;
  FSendThread.Synchronize(UpdateProgress);
  FSendThread.Synchronize(BottonsEnable);
  FSendThread:=nil;
end;






end.
