unit RUtilites;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Menus, StdCtrls, ToolWin, HexGrid;

Type DataBuf = array[0..255] of byte;

Function HexB(B : Byte) : string;
Function Buf_to_HEXStr(N,Addr:Word;const Buf: array of byte):String;
Function HEXStr_to_Buf(str:string;var Addr,HiAddr:word;var Buf: array of byte):integer;
Function HEXStr_to_GridBuf(str:string;OffSet:Cardinal ;Buf:PDataBuf ):Word;
Function GridBuf_To_HEXStr(N,Addr:Word;OffSet:Longint ;const Buf: PDataBuf): String;
Function Addr_To_HEXstr(Addr:Longint): String;
Function GetCRC(str:String):string;
Function CalculateCRC(Divisor,DividerHigh,DividerLow:Cardinal):Cardinal;
implementation


function HexB(B : Byte) : string;
const
  Digits : array[0..$F] of Char = '0123456789ABCDEF';
begin
  SetLength(Result, 2);
  HexB[1] := Digits[B shr 4];
  HexB[2] := Digits[B and $F];
end;

Function Buf_To_HEXStr(N,Addr:Word;const Buf: array of byte): String;
var str:string;
    i:byte;
    CRC:byte;
begin

  if N=0 then begin
    Buf_To_HEXStr:=':00000001FF';
    Exit;
  end;
  CRC:=N+Lo(Addr)+Hi(Addr);
  str:=':'+HexB(N)+HexB(Hi(Addr))+HexB(Lo(Addr))+'00';
  for i:=0 to N-1 do
  begin
    str:=str+HexB(Buf[i]);
    CRC:=CRC+Buf[i];
  end;
  Buf_To_HEXStr:=str+HexB((not CRC) + 1);
end;

Function GridBuf_To_HEXStr(N,Addr:Word;OffSet:Longint ;const Buf: PDataBuf): String;
var str:string;
    i,b:byte;
    CRC:byte;
begin

  if N=0 then begin
    Result:=':00000001FF'+Chr($0d);
    Exit;
  end;
  CRC:=N+Lo(Addr)+Hi(Addr);
  str:=':'+HexB(N)+HexB(Hi(Addr))+HexB(Lo(Addr))+'00';
  for i:=0 to N-1 do
  begin
    b:=Buf^.data[i+OffSet];
    str:=str+HexB(b);
    CRC:=CRC+b;
  end;
  Result:=str+HexB((not CRC) + 1)+Chr($0d);
end;

Function Addr_To_HEXstr(Addr:Longint): String;
var CRC:byte;
begin
  CRC:=6;
  Result:=':02000004'+HexB(Hi(Word(Addr)))+HexB(Lo(Word(Addr)));
  CRC:=CRC+Hi(Word(Addr))+Lo(Word(Addr));
  Result:=Result+HexB((not CRC) + 1)+#13+#10;
end;


Function HEXStr_to_Buf(str:string; var Addr,HiAddr:word; var Buf: array of byte):integer;
var i:integer;
    K,B,CRC:byte;
begin
  result:=0;
  Addr:=0;
  if str[1]<>':' then exit;
  if copy(str,8,2)='01' then exit;
  CRC:=0;
  try
   K:=StrToInt('$'+copy(str,2,2));
   Addr:=StrToInt('$'+copy(str,4,4));
  except
    Raise Exception.Create('Невозможна конвертация адресной части HEX строки:'+
                           #13+#10+Str);
  end;
  try
    for i:=0 to K-1 do
    begin
      B:=StrToInt('$'+copy(str,10+i*2,2));
      Buf[i]:=B;
      CRC:=CRC+B;
    end;
  except
    Raise Exception.Create('Невозможна конвертация данных HEX строки:'+#13+#10+Str);
  end;
  // Проверка контрольной суммы
  CRC:=CRC+K+StrToInt('$'+copy(str,4,2))+StrToInt('$'+copy(str,6,2))+StrToInt('$'+copy(str,8,2));
  if HexB((CRC xor $FF)+1)<>copy(str,10+K*2,2) then
    Raise Exception.Create('Несовпадение контрольной суммы в HEX строке:'
                            +#13+#10+Str+#13+#10+'CRC='+HexB((CRC xor $FF)+1));
  if copy(str,8,2)='04' then
  begin
    result:=0;
    HiAddr:=StrToInt('$'+copy(str,10,4))
  end
  else
    result:=K;
end;

Function HEXStr_to_GridBuf(str:string;OffSet:Cardinal ;Buf:PDataBuf ):word;
var i:word;
    K,CRC:byte;
    Addr:Cardinal;
begin
  result:=0;
  if str[1]<>':' then
  begin
    result:=0;
    exit;
  end;
  if copy(str,8,2)='01' then exit;
  CRC:=0;
  K:=StrToInt('$'+copy(str,2,2));
  Addr:=StrToInt('$'+copy(str,4,4));
  for i:=0 to K-1 do
  begin
    CRC:=CRC+StrToInt('$'+copy(str,10+i*2,2));;
  end;
  // Проверка контрольной суммы
  CRC:=CRC+K+StrToInt('$'+copy(str,4,2))+StrToInt('$'+copy(str,6,2));
  if HexB((CRC xor $FF)+1)<>copy(str,10+K*2,2) then  exit;
  for i:=0 to K-1 do
  begin
    Buf^.data[i+OffSet+Addr]:=StrToInt('$'+copy(str,10+i*2,2))
  end;
  result:=k;
end;


Function GetCRC(str:String):string;
var i:integer;
    crc:byte;
begin
  result:='';
  crc:=0;
  str:=Copy(str,2,Length(str)-1);
  for i:=0 to (Length(str) div 2)-1 do
    crc:=crc+StrToInt(Copy(str,i*2+1,2));
  crc:=(crc xor $FF)+1;
  result:=Format('%.2x',[crc]);
end;

Function CalculateCRC(Divisor,DividerHigh,DividerLow:Cardinal):Cardinal;
begin


  Result:=0;
end;

end.
