unit FProgMain;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, Buttons, jpeg, Thales, Tasten, ComCtrls, Instrect,
  Thalmisc, Menus, FusesD;

type
  TProgMain = class(TForm)
    Timer1: TTimer;
    OpenDlg: TOpenDialog;
    Panel10: TPanel;
    StatusBar: TStatusBar;
    IniEditor: TIniEditor;
    SearchBtn: TBitBtn;
    SmartTimer: TSmartTimer;
    HintsCheck: TCheckBox;
    Bevel2: TBevel;
    Bevel3: TBevel;
    LdPackFileBtn: TSpeedButton;
    Panel9: TPanel;
    Image1: TImage;
    ProgBtn0: TSpeedButton;
    ProgStatus0: TLabel;
    Gauge0: TGaugeGp;
    DnLdBtn0: TBitBtn;
    LED0: TLedCheck;
    Panel1: TPanel;
    Image2: TImage;
    ProgBtn1: TSpeedButton;
    ProgStatus1: TLabel;
    Gauge1: TGaugeGp;
    DnLdBtn1: TBitBtn;
    LED1: TLedCheck;
    Panel2: TPanel;
    Image3: TImage;
    ProgBtn2: TSpeedButton;
    ProgStatus2: TLabel;
    Gauge2: TGaugeGp;
    DnLdBtn2: TBitBtn;
    LED2: TLedCheck;
    Panel3: TPanel;
    Image4: TImage;
    ProgBtn3: TSpeedButton;
    ProgStatus3: TLabel;
    Gauge3: TGaugeGp;
    DnLdBtn3: TBitBtn;
    LED3: TLedCheck;
    Panel4: TPanel;
    Image5: TImage;
    ProgBtn4: TSpeedButton;
    ProgStatus4: TLabel;
    Gauge4: TGaugeGp;
    DnLdBtn4: TBitBtn;
    LED4: TLedCheck;
    Panel5: TPanel;
    Image6: TImage;
    ProgBtn5: TSpeedButton;
    ProgStatus5: TLabel;
    Gauge5: TGaugeGp;
    DnLdBtn5: TBitBtn;
    LED5: TLedCheck;
    Panel6: TPanel;
    Image7: TImage;
    ProgBtn6: TSpeedButton;
    ProgStatus6: TLabel;
    Gauge6: TGaugeGp;
    DnLdBtn6: TBitBtn;
    LED6: TLedCheck;
    Panel7: TPanel;
    Image8: TImage;
    ProgBtn7: TSpeedButton;
    ProgStatus7: TLabel;
    Gauge7: TGaugeGp;
    DnLdBtn7: TBitBtn;
    LED7: TLedCheck;
    ProgAllBtn: TSpeedButton;
    ProgSerNum0: TLabel;
    ProgSerNum1: TLabel;
    ProgSerNum2: TLabel;
    ProgSerNum3: TLabel;
    ProgSerNum4: TLabel;
    ProgSerNum5: TLabel;
    ProgSerNum6: TLabel;
    ProgSerNum7: TLabel;
    FileList0: TComboBox;
    FileList1: TComboBox;
    FileList2: TComboBox;
    FileList3: TComboBox;
    FileList4: TComboBox;
    FileList5: TComboBox;
    FileList6: TComboBox;
    FileList7: TComboBox;
    FileCheckBtn0: TBitBtn;
    FileCheckBtn1: TBitBtn;
    FileCheckBtn2: TBitBtn;
    FileCheckBtn3: TBitBtn;
    FileCheckBtn4: TBitBtn;
    FileCheckBtn5: TBitBtn;
    FileCheckBtn6: TBitBtn;
    FileCheckBtn7: TBitBtn;
    ProgPopMenu: TPopupMenu;
    progdeviceItem: TMenuItem;
    VerifyDevItem: TMenuItem;
    eraDevItem: TMenuItem;
    N1: TMenuItem;
    progFlashItem: TMenuItem;
    progEEpromItem: TMenuItem;
    progFuseItem: TMenuItem;
    progLockItem: TMenuItem;
    N2: TMenuItem;
    downloadItem: TMenuItem;
    checkFileItem: TMenuItem;
    checkDevItem: TMenuItem;
    delFileItem: TMenuItem;
    N3: TMenuItem;
    checkUPPItem: TMenuItem;
    verifyFlashItem: TMenuItem;
    N4: TMenuItem;
    closeFileItem: TMenuItem;
    FName0: TLabel;
    FName1: TLabel;
    FName2: TLabel;
    FName3: TLabel;
    FName4: TLabel;
    FName5: TLabel;
    FName6: TLabel;
    FName7: TLabel;
    ChipBlockModes: TMenuItem;
    FileBlockModes: TMenuItem;
    ChipBlockTestF: TMenuItem;
    ChipBlockTestE: TMenuItem;
    FileBlockTestF: TMenuItem;
    FileBlockTestE: TMenuItem;
    BitBtn1: TBitBtn;
    LockBMP0: TImage;
    LockBMP1: TImage;
    LockBMP2: TImage;
    LockBMP3: TImage;
    LockBMP4: TImage;
    LockBMP5: TImage;
    LockBMP6: TImage;
    LockBMP7: TImage;
    GroupBox1: TGroupBox;
    EncrBMP0: TImage;
    EncrBMP1: TImage;
    EncrBMP2: TImage;
    EncrBMP3: TImage;
    EncrBMP4: TImage;
    EncrBMP5: TImage;
    EncrBMP6: TImage;
    EncrBMP7: TImage;
    OverWriteChk: TCheckBox;
    OverWriteData: TEdit;
    OverWrAddrLo: TRadioButton;
    OverWrAddrHi: TRadioButton;
    Label1: TLabel;
    ScanOpenBtn: TButton;
    ChainDownBtn: TButton;
    ChainUpBtn: TButton;
    ScanCloseBtn: TButton;
    ReadFuseBtn: TButton;
    procedure StatusInit;
    procedure Timer1Timer(Sender: TObject);
    procedure SearchBtnClick(Sender: TObject);
    procedure DownloadButtonClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ProgFlashClick(Sender: TObject);
    procedure SmartTimerTimerEvent(Sender: TObject; BlinkHigh: Boolean);
    procedure HintsCheckClick(Sender: TObject);
    procedure ScanCloseBtnClick(Sender: TObject);
    procedure ScanOpenBtnClick(Sender: TObject);
    procedure ChainDownBtnClick(Sender: TObject);
    procedure ChainUpBtnClick(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose : Boolean);
    procedure LdPackFileBtnClick(Sender: TObject);
    procedure ProgAllBtnClick(Sender: TObject);
    procedure FileCheckBtn0Click(Sender: TObject);
    procedure FileList0ContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
    procedure progdeviceItemClick(Sender: TObject);
    procedure VerifyDevItemClick(Sender: TObject);
    procedure eraDevItemClick(Sender: TObject);
    procedure progFlashItemClick(Sender: TObject);
    procedure progEEpromItemClick(Sender: TObject);
    procedure progFuseItemClick(Sender: TObject);
    procedure progLockItemClick(Sender: TObject);
    procedure checkFileItemClick(Sender: TObject);
    procedure checkDevItemClick(Sender: TObject);
    procedure delFileItemClick(Sender: TObject);
    procedure verifyFlashItemClick(Sender: TObject);
    procedure closeFileItemClick(Sender: TObject);
    procedure FileBlockTestFClick(Sender: TObject);
    procedure FileBlockTestEClick(Sender: TObject);
    procedure ChipBlockTestFClick(Sender: TObject);
    procedure ChipBlockTestEClick(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure FileList0Click(Sender: TObject);
    procedure OverWriteChkClick(Sender: TObject);
    procedure ReadFuseBtnClick(Sender: TObject);
  private
    { Private-Deklarationen }
    CurProg   : integer;
  public
    { Public-Deklarationen }
  end;

var
  ProgMain: TProgMain;


implementation

uses dParmList;


type
  tProgResult = (resNone, noProg, progFound, MemError, progBusy, progDefect,
                 progIdle, progProtected, eraChip, eraEEp, eraFlash, prgEEp,
                 prgFlash, verifyEEp, verifyFlash, errPwrDown, errSignature,
                 errProtected, errNotEmpty, errVerify, progDone, dwnLoading,
                 dwnLoadErrP, dwnLoadErrE, dwnLoadErrF, dwnLoadErr, invFile,
                 invFName, FileExist, notFound, invPassword, limitExc, errProgType,
                 resOk, progNoJTAG, progNoSupply, errPwrSupply, errParm,
                 MMCprotected, MMCnoMedia);


const
  CR    = #13;
  LF    = #10;

procedure InitChannel(Channel : integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, progFound

procedure CheckProgrammer(Channel: integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, errProgType, progFound

procedure ClosePort(Channel : integer; var res : integer; resStr : PChar); stdcall; external 'UPP_DLL.dll';
// res = resNone, noProg

procedure GetProgIDs(var res : integer; resStr : PChar); stdcall;  external 'UPP_DLL.dll';

procedure GetProgStatus(Channel: integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = resNone, limitExc, eraChip, prgEEp, prgFlash, progDone, errPwrDown,
//       errSignature, errProtected, errNotEmpty, errVerify

procedure AbortAll; stdcall; external 'UPP_DLL.dll'

procedure OpenAfile(Channel : integer; FileName : PChar; var res : integer; resStr : PChar); stdcall; external 'UPP_DLL.dll'

procedure GetFileState(Channel : Integer; var res : integer; resStr : PChar); stdcall; external 'UPP_DLL.dll'

procedure CloseAfile(Channel : integer; var res : integer; resStr : PChar); stdcall; external 'UPP_DLL.dll'

procedure DeleteAfile(Channel: integer; FileName: PChar; var res : integer; resStr : PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, invFName, notFound, errProtected, resOk

procedure DownloadFile(Channel : Integer; ProjName: PChar; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, limitExc, errProgType, progProtected, dwnLoadErrP, dwnLoadErrF,
//       dwnLoadErrE, dwnLoadErr, noProg, resOk

procedure GetFileNames(Channel : integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, resOk

procedure CheckAfile(Channel: integer; ProjName : PChar; var res : integer; resStr : PChar); stdcall; external 'UPP_DLL.dll';
// res = ????????

procedure GetProjParams(Channel : integer; ProjName : PChar; var res : integer; resStr : PChar); stdcall; external 'UPP_DLL.dll';
// res = ????????

procedure GetTargVolt(Channel: integer; var Volt : integer; var res : integer; resStr: PChar); stdcall;  external 'UPP_DLL.dll';
// res = progBusy, noProg, errProgType, resOk

                // "L", "F", "H", "E", "0", "1", "2", "3"
procedure GetFuses(Channel : integer; selfuse : char; var fuse : integer; var res : integer; resStr : PChar); stdcall; external 'UPP_DLL.dll';
// res = resOk, progBusy, noProg, errProgType, errPwrDown, errSignature,
//       notFound, dwnLoadErr

procedure CheckDevice(Channel: Integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = resNone, progBusy, noProg, errProgType, errPwrDown, errSignature,
//       errNotEmpty, errProtected

procedure ProgDevice(Channel: Integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, resOk  rest of states must be done with "GetProgStatus"

procedure ProgFlash(Channel: Integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, resOk  rest of states must be done with "GetProgStatus"

procedure ProgEEprom(Channel: Integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, resOk  rest of states must be done with "GetProgStatus"

procedure ProgFuses(Channel: Integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, resOk  rest of states must be done with "GetProgStatus"

procedure ProgLockBits(Channel: Integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, resOk  rest of states must be done with "GetProgStatus"

procedure EraseDevice(Channel: Integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, resOk  rest of states must be done with "GetProgStatus"

procedure VerifyDevice(Channel: Integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, resOk  rest of states must be done with "GetProgStatus"

procedure VerifyFlashOnly(Channel: Integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, resOk  rest of states must be done with "GetProgStatus"

procedure VerifyEEpromOnly(Channel: Integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, resOk  rest of states must be done with "GetProgStatus"

procedure DownFileBlockF(Channel: Integer; Block : Pointer; dest, count : Integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, progProtected, dwnLoadErr, resOk

procedure DownFileBlockE(Channel: Integer; Block : Pointer; dest, count : Integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, progProtected, dwnLoadErr, resOk

procedure UpFileBlockF(Channel: Integer; Block : Pointer; source, count : Integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, progProtected, dwnLoadErr, resOk

procedure UpFileBlockE(Channel: Integer; Block : Pointer; source, count : Integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, progProtected, dwnLoadErr, resOk

procedure ReadBackChipF(Channel: Integer; Block : Pointer; source : Integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, progProtected, dwnLoadErr, resOk

procedure ReadBackChipE(Channel: Integer; Block : Pointer; source, count : Integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, progProtected, dwnLoadErr, resOk

procedure DownProgBlockF(Channel: Integer; Block : Pointer; dest : Integer; var res : integer; resStr : PChar); stdcall; external 'UPP_DLL.dll';

procedure DownProgBlockE(Channel: Integer; Block : Pointer; dest, count : Integer; var res : integer; resStr : PChar); stdcall; external 'UPP_DLL.dll';

procedure DownOverBlockF(Channel: Integer; Block : Pointer; dest, count : Integer; var res : integer; resStr : PChar); stdcall; external 'UPP_DLL.dll';

procedure DownOverBlockE(Channel: Integer; Block : Pointer; dest, count : Integer; var res : integer; resStr : PChar); stdcall; external 'UPP_DLL.dll';


procedure JTAGBoundaryOpen(Channel: integer; CpuID, BoundaryLen, SupplyVolt, SupplyCurr : integer;
                          var res : integer; resStr: PChar); stdcall;  external 'UPP_DLL.dll';
// res = progBusy, noProg, progNoJTAG, progNoSupply, errPwrSupply, errSignature, resOk

procedure JTAGchainWrite(Channel : Integer; Block : Pointer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, , resOk

procedure JTAGchainRead(Channel : Integer; Block : Pointer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, , resOk

procedure JTAGBoundaryClose(Channel: integer; var res : integer; resStr: PChar); stdcall; external 'UPP_DLL.dll';
// res = progBusy, noProg, resOk


{$R *.DFM}

type
  tChState  = (cUnknown, cMemError, cIdle, cDownLd, cProg, cErase, cVerify, cCheck);

  tChannel  =  record
                 chProgState : tlabel;
                 chFileName  : tlabel;
                 chFileList  : tComboBox;
                 chProgSerNum: tLabel;
                 chDnLdBtn   : tBitBtn;
                 chCheckBtn  : tBitBtn;
                 chProgBtn   : tSpeedButton;
                 chState     : tChState;
                 chGauge     : TGaugeGP;
                 chLedP      : TLedCheck;
                 chLockBMP   : TImage;
                 chEncrBMP   : TImage; 
               end;

var
  status    : array[0..15] of tChannel;

  ScanDownBuffer : array[0..255] of byte;
  ScanUpBuffer   : array[0..255] of byte;


procedure TProgMain.StatusInit;
var idx   : integer;
begin
  for idx:= 0 to 7 do begin
    status[idx].chProgState.caption:= '?';
    Status[idx].chFileName.caption:= '?';
    status[idx].chState:= cUnknown;
    status[idx].chFileList.Clear;
    status[idx].chGauge.Percent:= 0;
    status[idx].chLedP.LedBlink:= false;
    status[idx].chLedP.Checked:= false;
    status[idx].chProgSerNum.caption:= '';

    status[idx].chDnLdBtn.enabled:= false;
    Status[idx].chCheckBtn.Enabled:= false;
    status[idx].chProgBtn.enabled:= false;
    status[idx].chGauge.Percent:= 0;
    status[idx].chLockBMP.Visible:= false;
    status[idx].chEncrBMP.Visible:= false;
  end;
  OverWriteChk.Checked:= false;
  OverWriteData.Enabled:= false;
  OverWrAddrLo.Enabled:= false;
  OverWrAddrHi.Enabled:= false;
end;

procedure TProgMain.FormCreate(Sender: TObject);
begin
  FillChar(Status, sizeOf(Status), 0);

  Status[0].chDnLdBtn:= DnLdBtn0;
  Status[0].chProgBtn:= ProgBtn0;
  Status[0].chCheckBtn:= FileCheckBtn0;
  Status[0].chProgState:= ProgStatus0;
  Status[0].chFileName:= FName0;
  Status[0].chFileList:= FileList0;
  status[0].chProgSerNum:= ProgSerNum0;
  Status[0].chGauge:= Gauge0;
  Status[0].chLedP:= LED0;
  status[0].chLockBMP:= LockBMP0;
  status[0].chEncrBMP:= EncrBMP0;

  Status[1].chDnLdBtn:= DnLdBtn1;
  Status[1].chProgBtn:= ProgBtn1;
  Status[1].chCheckBtn:= FileCheckBtn1;
  Status[1].chProgState:= ProgStatus1;
  Status[1].chFileName:= FName1;
  Status[1].chFileList:= FileList1;
  status[1].chProgSerNum:= ProgSerNum1;
  Status[1].chGauge:= Gauge1;
  Status[1].chLedP:= LED1;
  status[1].chLockBMP:= LockBMP1;
  status[1].chEncrBMP:= EncrBMP1;

  Status[2].chDnLdBtn:= DnLdBtn2;
  Status[2].chProgBtn:= ProgBtn2;
  Status[2].chCheckBtn:= FileCheckBtn2;
  Status[2].chProgState:= ProgStatus2;
  Status[2].chFileName:= FName2;
  Status[2].chFileList:= FileList2;
  status[2].chProgSerNum:= ProgSerNum2;
  Status[2].chGauge:= Gauge2;
  Status[2].chLedP:= LED2;
  status[2].chLockBMP:= LockBMP2;
  status[2].chEncrBMP:= EncrBMP2;

  Status[3].chDnLdBtn:= DnLdBtn3;
  Status[3].chProgBtn:= ProgBtn3;
  Status[3].chCheckBtn:= FileCheckBtn3;
  Status[3].chProgState:= ProgStatus3;
  Status[3].chFileName:= FName3;
  Status[3].chFileList:= FileList3;
  status[3].chProgSerNum:= ProgSerNum3;
  Status[3].chGauge:= Gauge3;
  Status[3].chLedP:= LED3;
  status[3].chLockBMP:= LockBMP3;
  status[3].chEncrBMP:= EncrBMP3;

  Status[4].chDnLdBtn:= DnLdBtn4;
  Status[4].chProgBtn:= ProgBtn4;
  Status[4].chCheckBtn:= FileCheckBtn4;
  Status[4].chProgState:= ProgStatus4;
  Status[4].chFileName:= FName4;
  Status[4].chFileList:= FileList4;
  status[4].chProgSerNum:= ProgSerNum4;
  Status[4].chGauge:= Gauge4;
  Status[4].chLedP:= LED4;
  status[4].chLockBMP:= LockBMP4;
  status[4].chEncrBMP:= EncrBMP4;

  Status[5].chDnLdBtn:= DnLdBtn5;
  Status[5].chProgBtn:= ProgBtn5;
  Status[5].chCheckBtn:= FileCheckBtn5;
  Status[5].chProgState:= ProgStatus5;
  Status[5].chFileName:= FName5;
  Status[5].chFileList:= FileList5;
  status[5].chProgSerNum:= ProgSerNum5;
  Status[5].chGauge:= Gauge5;
  Status[5].chLedP:= LED5;
  status[5].chLockBMP:= LockBMP5;
  status[5].chEncrBMP:= EncrBMP5;

  Status[6].chDnLdBtn:= DnLdBtn6;
  Status[6].chProgBtn:= ProgBtn6;
  Status[6].chCheckBtn:= FileCheckBtn6;
  Status[6].chProgState:= ProgStatus6;
  Status[6].chFileName:= FName6;
  Status[6].chFileList:= FileList6;
  status[6].chProgSerNum:= ProgSerNum6;
  Status[6].chGauge:= Gauge6;
  Status[6].chLedP:= LED6;
  status[6].chLockBMP:= LockBMP6;
  status[6].chEncrBMP:= EncrBMP6;

  Status[7].chDnLdBtn:= DnLdBtn7;
  Status[7].chProgBtn:= ProgBtn7;
  Status[7].chCheckBtn:= FileCheckBtn7;
  Status[7].chProgState:= ProgStatus7;
  Status[7].chFileName:= FName7;
  Status[7].chFileList:= FileList7;
  status[7].chProgSerNum:= ProgSerNum7;
  Status[7].chGauge:= Gauge7;
  Status[7].chLedP:= LED7;
  status[7].chLockBMP:= LockBMP7;
  status[7].chEncrBMP:= EncrBMP7;

  StatusInit;

  ShowHint:= IniEditor.ReadBool('Setup', 'ShowHint', false);
  HintsCheck.checked:= ShowHint;
  StatusBar.SimpleText:= 'ready';
end;

// res = resNone, limitExc, eraChip, prgEEp, prgFlash, progDone, errPwrDown,
//       errSignature, errProtected, errNotEmpty, errVerify
procedure TProgMain.Timer1Timer(Sender: TObject);
var st        : string;
    idx, res  : integer;
    allIdle   : integer;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
    changed   : boolean;
begin
  PstBuffer:= @stBuffer;
  allIdle:= 0;
  changed:= false;
  for idx:= 0 to 7 do begin
    if status[idx].chState in[cProg, cErase, cVerify] then begin
      GetProgStatus(idx, res, PstBuffer);
      st:= PstBuffer;
      if st <> '' then begin
        if status[idx].chProgState.Caption <> st then begin
          status[idx].chProgState.Caption := st;
          changed:= true;
        end
        else changed:= false;
      end;
      case tProgResult(res) of
        progDone     : begin
                         with status[idx] do begin
                           chState:= cIdle;
                           inc(allIdle);
                           chProgState.caption:= st;
                           chGauge.Percent:= 0;
                           chGauge.Refresh;
                         end;
                       end;
        eraChip      : begin
                       end;
        verifyEEp,
        prgEEp       : begin
                         with status[idx] do begin
                           if changed then begin
                             chGauge.Value:= 0;
                             chGauge.Refresh;
                           end;
                           chGauge.value:= chGauge.value+1;
                         end;
                       end;
        verifyFlash,
        prgFlash     : begin
                         with status[idx] do begin
                           chGauge.value:= chGauge.value+1;
                           if chGauge.Percent > 100 then begin
                             chGauge.Percent:= 0;
                             chGauge.Refresh;
                           end;
                         end;
                       end;
        limitExc,
        errPwrDown,
        errSignature,
        errProtected,
        errNotEmpty,
        errVerify    : begin
                         status[idx].chState:= cIdle;
                         inc(allIdle);
                         status[idx].chProgState.caption:= st;
                         Beep;
                       end;
      end;
    end
    else begin
      inc(allIdle);
    end;
  end;
  if allIdle > 7 then begin
    Screen.Cursor:= crDefault;
    Timer1.Enabled := false;
  end;
end;

procedure TProgMain.SearchBtnClick(Sender: TObject);
var st, st1   : string;
    PortName  : string;
    x, u,
    idx, res  : integer;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
    allOk     : boolean;
    FirstOk   : boolean;
begin
  AbortAll;
  StatusInit;
  FirstOk:= false;
  ScanOpenBtn.Enabled:= false;
  ChainDownBtn.Enabled:= false;
  ChainUpBtn.Enabled:= false;
  ScanCloseBtn.Enabled:= false;
  PstBuffer:= @stBuffer;
  Screen.cursor:= crHourGlass;
  Timer1.enabled:= false;
  SearchBtn.enabled:= false;
  LdPackFileBtn.enabled:= false;
  ProgAllBtn.Enabled:= false;
  ReadFuseBtn.Enabled:= false;
  StatusBar.SimpleText:= 'searching UPP';
  GetProgIDs(res, PstBuffer);
  st:= PstBuffer;
  if res = 0 then begin
    StatusBar.SimpleText:= 'no UPPs found';
    Screen.cursor:= crDefault;
    SearchBtn.enabled:= true;
    beep;
    exit;
  end;
  idx:= 1;
  u:= 0;
  while u < res do begin
    st1:= '';
    while st[idx] <> #13 do begin
      st1:= st1+st[idx];
      inc(idx);
    end;
    status[u].chProgSerNum.caption:= st1;
    inc(u);
    inc(idx, 2);
  end;
  allOk:= true;
  for idx:= 0 to 7 do begin
    PortName:= status[idx].chProgSerNum.caption;
    Status[idx].chEncrBMP.Visible:= false;
    if PortName = '' then break;
    InitChannel(idx, res, PstBuffer);
    st:= PstBuffer;
    if tProgResult(res) = noProg then begin
      StatusBar.SimpleText:= 'no UPP found';
      Status[idx].chState:= cUnknown;
    end
    else if tProgResult(res) = progDefect then begin
      StatusBar.SimpleText:= st;
      Status[idx].chProgState.caption:= st;
      Status[idx].chState:= cUnknown;
    end
    else if tProgResult(res) = progBusy then begin
      Beep;
      if MessageDlg('UPP is busy!'+#13+'Reset UPP?',
                     mtWarning, [ mbYes, mbNo],0) = mrYes then begin
        ClosePort(idx, res, PstBuffer);
        InitChannel(idx, res, PstBuffer);
        st:= PstBuffer;
      end;
    end;
    if (tProgResult(res) = progFound) then begin
      if idx = 0 then begin
        ScanOpenBtn.Enabled:= true;
        ChainDownBtn.Enabled:= true;
        ChainUpBtn.Enabled:= true;
        ScanCloseBtn.Enabled:= true;
      end;
      StatusBar.SimpleText:= 'Prog'+IntToStr(idx+1)+' at '+PortName+' found';
      CheckProgrammer(idx, res, PstBuffer);
      st:= PstBuffer;
      if tProgResult(res) = MemError then begin
        Beep;
        Status[idx].chState:= cMemError;
        Status[idx].chDnLdBtn.enabled:= OpenDlg.FileName <> '';
        LdPackFileBtn.enabled:= true;
        Status[idx].chProgBtn.enabled:= false;
        Status[idx].chProgState.caption:= 'UPP found memory error';
        StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' found, but memory error';
        allOk:= false;
      end
      else if tProgResult(res) = MMCnoMedia then begin
        Beep;
        Status[idx].chState:= cMemError;
        Status[idx].chDnLdBtn.enabled:= OpenDlg.FileName <> '';
        LdPackFileBtn.enabled:= true;
        Status[idx].chProgBtn.enabled:= false;
        Status[idx].chProgState.caption:= 'UPP no Media';
        StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' found, but no MMC card';
        allOk:= false;
      end
      else if tProgResult(res) in[progFound, MMCprotected] then begin
        Beep;
        Status[idx].chState:= cIdle;
        Status[idx].chDnLdBtn.enabled:= OpenDlg.FileName <> '';
        LdPackFileBtn.enabled:= true;
        Status[idx].chProgBtn.enabled:= true;
        Status[idx].chProgState.caption:= 'UPP found';
        Status[idx].chLockBMP.Visible:= tProgResult(res) = MMCprotected;
        GetFileNames(idx, res, PstBuffer);
        if tProgResult(res) = resOk then begin
          st:= PstBuffer;
          if st <> '' then begin
            // string contains all files separated by CRLF
            x:= 1;
            repeat
              st1:= '';
              while (length(st) >= x) and not(st[x] in[CR, LF, #0]) do begin
                st1:= st1 + st[x];
                inc(x);
              end;
              Status[idx].chFileList.AddItem(st1, nil);
              while (length(st) >= x) and (st[x] in[CR, LF, #0]) do begin
                inc(x);
              end;
            until x >= length(st);
            try
              Status[idx].chFileList.ItemIndex:= 0;
              Status[idx].chCheckBtn.Enabled:= true;
              st:= UpperCase(ExtractFileExt(Status[idx].chFileList.Text));
              Status[idx].chEncrBMP.Visible:= Pos('.EN', st) = 1;
            except
            end;
          end;
          StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' found';
        end;
      end
      else begin
        Status[idx].chProgState.caption:= 'not found';
        Status[idx].chState:= cUnknown;
        StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' not found';
      end;
    end
    else begin
      StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' not found';
    end;
    if allOk then begin
      ProgAllBtn.Enabled:= true;
      ReadFuseBtn.Enabled:= true;
    end;
  end;
  Screen.cursor:= crDefault;
  SearchBtn.enabled:= true;
  Beep;
end;

procedure TProgMain.FileCheckBtn0Click(Sender: TObject);
var st    : string;
    idx   : integer;
    res   : integer;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
begin
  PstBuffer:= @stBuffer;
  if sender <> nil then begin
    idx:= TButton(Sender).Tag;
  end
  else begin
    idx:= CurProg;
  end;

  GetFileState(idx, res, PstBuffer);
  if tProgResult(res) <> invFName then begin
    Status[idx].chProgState.caption := 'file is open';
    Status[idx].chFileName.caption := PstBuffer;
    beep;
    exit;
  end;

  Status[idx].chFileName.caption:= '?';
  st:= Status[idx].chFileList.Items[Status[idx].chFileList.ItemIndex];
  if st = '' then begin
    Status[idx].chProgState.caption := 'no file selected';
    beep;
    exit;
  end;
  CheckAfile(idx, PChar(st), res, PstBuffer);
  StatusBar.SimpleText:= PstBuffer;
  if tProgResult(res) <> resOk then begin
    Beep;
    MessageDlg('File check of '+st+' failed!', mtError, [ mbOK],0);
    exit;
  end;
  GetProjParams(idx, PChar(st), res, PstBuffer);
  if tProgResult(res) <> resOk then begin
    Beep;
    MessageDlg('Parameter upload of '+st+' failed!', mtError, [ mbOK],0);
    exit;
  end;
  Status[idx].chProgState.caption := 'file closed';
  ParmListDlg.Params:= PstBuffer;
  ParmListDlg.showModal;
end;

procedure TProgMain.DownloadButtonClick(Sender: TObject);
var idx   : byte;
    res   : integer;
    st, st1   : string;
    saveState : tChState;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
begin
  idx:= CurProg;
  PstBuffer:= @stBuffer;
  Timer1.Enabled := False;
  Status[idx].chGauge.Percent:= 0;
  case Status[idx].chState of
    cMemError,
    cIdle    : begin
                 GetFileState(idx, res, PstBuffer);
                 if tProgResult(res) <> invFName then begin
                   Status[idx].chProgState.caption := 'file is open';
                   beep;
                   exit;
                 end;
                 Status[idx].chFileName.caption:= '?';
                 saveState:= Status[idx].chState;
                 Status[idx].chState:= cDownLd;
                 Status[idx].chProgState.caption := 'downloading';
                 st1:= OpenDlg.FileName;
                 screen.Cursor:= crHourGlass;
                 try
                   DownloadFile(idx, PChar(st1), res, PstBuffer);
                   st:= PstBuffer;
                 except
                   st:= 'error';
                 end;
                 screen.Cursor:= crDefault;
                 Beep;
                 st1:= ExtractFileName(OpenDlg.FileName);
                 Status[idx].chProgState.caption := st;
                 // handle result
                 if tProgResult(res) = limitExc then begin
                   Status[idx].chState:= saveState;
                   Status[idx].chProgState.caption:= st;
                   StatusBar.SimpleText:= 'UPP '+st1+' cycle limit exceeded';
//                   Status[idx].chFileList.caption:= '';
                 end
                 else if tProgResult(res) in[invFile, invFName] then begin
                   Status[idx].chState:= saveState;
                   Status[idx].chProgState.caption:= st;
                   StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' invalid file';
//                   Status[idx].chFileList.caption:= '';
                 end
                 else if tProgResult(res) in[FileExist] then begin
                   Status[idx].chState:= saveState;
                   Status[idx].chProgState.caption:= st;
                   StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' file exists';
//                   Status[idx].chFileList.caption:= '';
                 end
                 else if tProgResult(res) in[MemError, dwnLoadErrP, dwnLoadErrE, dwnLoadErrF, dwnLoadErr] then begin
                   Status[idx].chProgState.caption:= 'download error';
                   Status[idx].chState:= cMemError;
                   ProgAllBtn.Enabled:= false;
                   ReadFuseBtn.Enabled:= false;
                   Status[idx].chProgBtn.enabled:= false;
                   StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' download error';
                   Status[idx].chFileList.clear;
                 end
                 else begin
                   Status[idx].chProgState.caption:= 'idle';
                   Status[idx].chState:= cIdle;
                   Status[idx].chProgBtn.enabled:= true;
                   Status[idx].chFileList.AddItem(st1, nil);
                   StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' download ok';
                 end;
               end;
    cDownLd  : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cVerify,
    cErase,
    cProg    : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
  end;
  Screen.cursor:= crDefault;
end;

procedure TProgMain.ProgFlashClick(Sender: TObject);
var idx         : byte;
    res,
    dest, count : integer;
    stBuffer    : array[0..512] of char;
    PstBuffer   : PChar;
    st          : string;
    FName       : string;
    Block       : string;
begin
  PstBuffer:= @stBuffer;
  if sender <> nil then begin
    idx:= TButton(Sender).Tag;
  end
  else begin
    idx:= CurProg;
  end;
  Status[idx].chGauge.Percent:= 0;
  FName:= Status[idx].chFileList.Items[Status[idx].chFileList.ItemIndex];
  if FName = '' then begin
    Status[idx].chProgState.caption := 'no file selected';
    beep;
    exit;
  end;
  case Status[idx].chState of
    cIdle    : begin
                 Screen.cursor:= crHourGlass;
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' programming';
                 Status[idx].chProgState.caption:= 'programming';
                 Status[idx].chState:= cProg;
                 GetFileState(idx, res, PstBuffer);
                 if tProgResult(res) = invFName then begin
                   OpenAfile(idx, PChar(FName), res, PstBuffer);
                   Status[idx].chFileName.caption:= FName;
                 end;
                 count:= length(OverWriteData.Text);
                 if OverWriteChk.Checked and (count > 0) then begin
                   Block:= OverWriteData.Text;
                   if OverWrAddrLo.Checked then dest:= $0123
                   else dest:= $0F35;
                   DownOverBlockF(idx, @Block[1], dest, count, res, PstBuffer);
                   DownOverBlockE(idx, @Block[1], $21, count, res, PstBuffer);
                 end;
                 ProgDevice(idx, res, PstBuffer);
                 Timer1.Enabled := True;
                 st:= PstBuffer;
                 Status[idx].chProgState.caption := st;
                 Status[idx].chState:= cProg;
                 Status[idx].chGauge.ValueMax:= 16;
               end;
    cDownLd  : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cVerify,
    cErase,
    cProg    : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cMemError: begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' memory error';
               end;
  end;
end;

procedure TProgMain.FileList0ContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean);
var xy   : tPoint;
begin
  xy:= TControl(Sender).ClientToScreen(MousePos);
  with Sender as TComboBox do begin
    CurProg:= Tag;
    if (Status[CurProg].chState in[cIdle]) and (ItemIndex >= 0) then begin
      checkFileItem.Enabled:= true;
      delFileItem.Enabled:= true;
      progdeviceItem.Enabled:= true;
      VerifyDevItem.Enabled:= not Status[CurProg].chEncrBMP.Visible;
      eraDevItem.Enabled:= true;
      progFlashItem.Enabled:= not Status[CurProg].chEncrBMP.Visible;
      progEEpromItem.Enabled:= not Status[CurProg].chEncrBMP.Visible;
      progFuseItem.Enabled:= not Status[CurProg].chEncrBMP.Visible;
      progLockItem.Enabled:= not Status[CurProg].chEncrBMP.Visible;
      verifyFlashItem.Enabled:= not Status[CurProg].chEncrBMP.Visible;
      checkDevItem.Enabled:= true;
      ChipBlockModes.enabled:= not Status[CurProg].chEncrBMP.Visible;
      FileBlockModes.enabled:= not Status[CurProg].chEncrBMP.Visible;
    end
    else begin
      checkFileItem.Enabled:= false;
      delFileItem.Enabled:= false;
      progdeviceItem.Enabled:= false;
      VerifyDevItem.Enabled:= false;
      eraDevItem.Enabled:= false;
      progFlashItem.Enabled:= false;
      progEEpromItem.Enabled:= false;
      progFuseItem.Enabled:= false;
      progLockItem.Enabled:= false;
      verifyFlashItem.Enabled:= false;
      checkDevItem.Enabled:= false;
      ChipBlockModes.enabled:= false;
      FileBlockModes.enabled:= false;
    end;
  end;
  if Status[CurProg].chState in[cUnknown, cDownLd..cVerify] then begin
    downloadItem.Enabled:= false;
  end
  else begin
    downloadItem.Enabled:= OpenDlg.FileName <> '';
  end;
  ProgPopMenu.Popup(xy.X, xy.Y);
end;

procedure TProgMain.progdeviceItemClick(Sender: TObject);
begin
  ProgFlashClick(nil);
end;

procedure TProgMain.VerifyDevItemClick(Sender: TObject);
var idx    : byte;
    res    : integer;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
    st        : string;
    FName     : string;
begin
  PstBuffer:= @stBuffer;
  idx:= CurProg;
  Status[idx].chGauge.Percent:= 0;
  FName:= Status[idx].chFileList.Items[Status[idx].chFileList.ItemIndex];
  if FName = '' then begin
    Status[idx].chProgState.caption := 'no file selected';
    beep;
    exit;
  end;
  case Status[idx].chState of
    cIdle    : begin
                 Screen.cursor:= crHourGlass;
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' verify';
                 Status[idx].chProgState.caption:= 'verify';
                 Status[idx].chState:= cVerify;
                 GetFileState(idx, res, PstBuffer);
                 if tProgResult(res) = invFName then begin
                   OpenAfile(idx, PChar(FName), res, PstBuffer);
                   Status[idx].chFileName.caption:= FName;
                 end;
                 VerifyDevice(idx, res, PstBuffer);
                 Timer1.Enabled := True;
                 st:= PstBuffer;
                 Status[idx].chProgState.caption := st;
                 Status[idx].chState:= cVerify;
                 Status[idx].chGauge.ValueMax:= 16;
               end;
    cDownLd  : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cVerify,
    cErase,
    cProg    : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cMemError: begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' memory error';
               end;
  end;
end;

procedure TProgMain.verifyFlashItemClick(Sender: TObject);
var idx    : byte;
    res    : integer;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
    st        : string;
    FName     : string;
begin
  PstBuffer:= @stBuffer;
  idx:= CurProg;
  Status[idx].chGauge.Percent:= 0;
  FName:= Status[idx].chFileList.Items[Status[idx].chFileList.ItemIndex];
  if FName = '' then begin
    Status[idx].chProgState.caption := 'no file selected';
    beep;
    exit;
  end;
  case Status[idx].chState of
    cIdle    : begin
                 Screen.cursor:= crHourGlass;
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' verify';
                 Status[idx].chProgState.caption:= 'verify';
                 Status[idx].chState:= cVerify;
                 GetFileState(idx, res, PstBuffer);
                 if tProgResult(res) = invFName then begin
                   OpenAfile(idx, PChar(FName), res, PstBuffer);
                   Status[idx].chFileName.caption:= FName;
                 end;
                 VerifyFlashOnly(idx, res, PstBuffer);
                 Timer1.Enabled := True;
                 st:= PstBuffer;
                 Status[idx].chProgState.caption := st;
                 Status[idx].chState:= cVerify;
                 Status[idx].chGauge.ValueMax:= 16;
               end;
    cDownLd  : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cVerify,
    cErase,
    cProg    : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cMemError: begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' memory error';
               end;
  end;
end;

procedure TProgMain.eraDevItemClick(Sender: TObject);
var idx    : byte;
    res    : integer;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
    st        : string;
    FName     : string;
begin
  PstBuffer:= @stBuffer;
  idx:= CurProg;
  Status[idx].chGauge.Percent:= 0;
  FName:= Status[idx].chFileList.Items[Status[idx].chFileList.ItemIndex];
  if FName = '' then begin
    Status[idx].chProgState.caption := 'no file selected';
    beep;
    exit;
  end;
  case Status[idx].chState of
    cIdle    : begin
                 Screen.cursor:= crHourGlass;
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' erase';
                 Status[idx].chProgState.caption:= 'erase';
                 Status[idx].chState:= cErase;
                 GetFileState(idx, res, PstBuffer);
                 if tProgResult(res) = invFName then begin
                   OpenAfile(idx, PChar(FName), res, PstBuffer);
                   Status[idx].chFileName.caption:= FName;
                 end;
                 EraseDevice(idx, res, PstBuffer);
                 st:= PstBuffer;
                 Status[idx].chProgState.caption := st;
                 Status[idx].chState:= cIdle;
                 Screen.cursor:= crDefault;
               end;
    cDownLd  : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cVerify,
    cErase,
    cProg    : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cMemError: begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' memory error';
               end;
  end;
end;


procedure TProgMain.progFlashItemClick(Sender: TObject);
var idx    : byte;
    res    : integer;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
    st        : string;
    FName     : string;
begin
  PstBuffer:= @stBuffer;
  idx:= CurProg;
  Status[idx].chGauge.Percent:= 0;
  FName:= Status[idx].chFileList.Items[Status[idx].chFileList.ItemIndex];
  if FName = '' then begin
    Status[idx].chProgState.caption := 'no file selected';
    beep;
    exit;
  end;
  case Status[idx].chState of
    cIdle    : begin
                 Screen.cursor:= crHourGlass;
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' programming';
                 Status[idx].chProgState.caption:= 'programming';
                 Status[idx].chState:= cProg;
                 GetFileState(idx, res, PstBuffer);
                 if tProgResult(res) = invFName then begin
                   OpenAfile(idx, PChar(FName), res, PstBuffer);
                   Status[idx].chFileName.caption:= FName;
                 end;
                 ProgFlash(idx, res, PstBuffer);
                 Timer1.Enabled := True;
                 st:= PstBuffer;
                 Status[idx].chProgState.caption := st;
                 Status[idx].chState:= cProg;
                 Status[idx].chGauge.ValueMax:= 16;
               end;
    cDownLd  : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cVerify,
    cErase,
    cProg    : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cMemError: begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' memory error';
               end;
  end;
end;

procedure TProgMain.progEEpromItemClick(Sender: TObject);
var idx    : byte;
    res    : integer;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
    st        : string;
    FName     : string;
begin
  PstBuffer:= @stBuffer;
  idx:= CurProg;
  Status[idx].chGauge.Percent:= 0;
  FName:= Status[idx].chFileList.Items[Status[idx].chFileList.ItemIndex];
  if FName = '' then begin
    Status[idx].chProgState.caption := 'no file selected';
    beep;
    exit;
  end;
  case Status[idx].chState of
    cIdle    : begin
                 Screen.cursor:= crHourGlass;
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' programming';
                 Status[idx].chProgState.caption:= 'programming';
                 Status[idx].chState:= cProg;
                 GetFileState(idx, res, PstBuffer);
                 if tProgResult(res) = invFName then begin
                   OpenAfile(idx, PChar(FName), res, PstBuffer);
                   Status[idx].chFileName.caption:= FName;
                 end;
                 ProgEEprom(idx, res, PstBuffer);
                 Timer1.Enabled := True;
                 st:= PstBuffer;
                 Status[idx].chProgState.caption := st;
                 Status[idx].chState:= cProg;
                 Status[idx].chGauge.ValueMax:= 16;
               end;
    cDownLd  : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cVerify,
    cErase,
    cProg    : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cMemError: begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' memory error';
               end;
  end;
end;

procedure TProgMain.progFuseItemClick(Sender: TObject);
var idx    : byte;
    res    : integer;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
    st        : string;
    FName     : string;
begin
  PstBuffer:= @stBuffer;
  idx:= CurProg;
  Status[idx].chGauge.Percent:= 0;
  FName:= Status[idx].chFileList.Items[Status[idx].chFileList.ItemIndex];
  if FName = '' then begin
    Status[idx].chProgState.caption := 'no file selected';
    beep;
    exit;
  end;
  case Status[idx].chState of
    cIdle    : begin
                 Screen.cursor:= crHourGlass;
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' check device';
                 Status[idx].chProgState.caption:= 'check device';
                 Status[idx].chState:= cCheck;
                 GetFileState(idx, res, PstBuffer);
                 if tProgResult(res) = invFName then begin
                   OpenAfile(idx, PChar(FName), res, PstBuffer);
                   Status[idx].chFileName.caption:= FName;
                 end;
                 ProgFuses(idx, res, PstBuffer);
                 st:= PstBuffer;
                 Status[idx].chProgState.caption := st;
                 Status[idx].chState:= cIdle;
                 Screen.cursor:= crDefault;
               end;
    cDownLd  : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cVerify,
    cErase,
    cProg    : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cMemError: begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' memory error';
               end;
  end;
end;

procedure TProgMain.progLockItemClick(Sender: TObject);
var idx    : byte;
    res    : integer;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
    st        : string;
    FName     : string;
begin
  PstBuffer:= @stBuffer;
  idx:= CurProg;
  Status[idx].chGauge.Percent:= 0;
  FName:= Status[idx].chFileList.Items[Status[idx].chFileList.ItemIndex];
  if FName = '' then begin
    Status[idx].chProgState.caption := 'no file selected';
    beep;
    exit;
  end;
  case Status[idx].chState of
    cIdle    : begin
                 Screen.cursor:= crHourGlass;
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' check device';
                 Status[idx].chProgState.caption:= 'check device';
                 Status[idx].chState:= cCheck;
                 GetFileState(idx, res, PstBuffer);
                 if tProgResult(res) = invFName then begin
                   OpenAfile(idx, PChar(FName), res, PstBuffer);
                   Status[idx].chFileName.caption:= FName;
                 end;
                 ProgLockbits(idx, res, PstBuffer);
                 st:= PstBuffer;
                 Status[idx].chProgState.caption := st;
                 Status[idx].chState:= cIdle;
                 Screen.cursor:= crDefault;
               end;
    cDownLd  : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cVerify,
    cErase,
    cProg    : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cMemError: begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' memory error';
               end;
  end;
end;

procedure TProgMain.checkFileItemClick(Sender: TObject);
begin
  FileCheckBtn0Click(nil);
end;

procedure TProgMain.ReadFuseBtnClick(Sender: TObject);
var
  Locks,
  fuseLo,
  fusehi,
  fuseext,
  Cal0,
  Cal1,
  Cal2,
  Cal3      : integer;
  idx,
  res       : integer;
  stBuffer  : array[0..512] of char;
  PstBuffer : PChar;
  st        : string;
  FName     : string;
begin
  PstBuffer:= @stBuffer;
  idx:= CurProg;
  FName:= Status[idx].chFileList.Items[Status[idx].chFileList.ItemIndex];
  if FName = '' then begin
    Status[idx].chProgState.caption := 'no file selected';
    beep;
    exit;
  end;
  case Status[idx].chState of
    cIdle    : begin
                 GetFileState(idx, res, PstBuffer);
                 if tProgResult(res) = invFName then begin
                   OpenAfile(idx, PChar(FName), res, PstBuffer);
                   Status[idx].chFileName.caption:= FName;
                 end;
                 // "L", "F", "H", "E", "0", "1", "2", "3"
                 GetFuses(idx, 'L', Locks, res, PstBuffer);
                 GetFuses(idx, 'F', fuseLo, res, PstBuffer);
                 GetFuses(idx, 'H', fuseHi, res, PstBuffer);
                 GetFuses(idx, 'E', fuseExt, res, PstBuffer);
                 GetFuses(idx, '0', Cal0, res, PstBuffer);
                 GetFuses(idx, '1', Cal1, res, PstBuffer);
                 GetFuses(idx, '2', Cal2, res, PstBuffer);
                 GetFuses(idx, '3', Cal3, res, PstBuffer);
                 FusesDlg.LockLab.Caption:=     ': $'+IntToHex(Locks, 2);
                 FusesDlg.FuseLowLab.Caption:=  ': $'+IntToHex(fuseLo, 2);
                 FusesDlg.FuseHighLab.Caption:= ': $'+IntToHex(fusehi, 2);
                 FusesDlg.FuseExtLab.Caption:=  ': $'+IntToHex(fuseext, 2);
                 FusesDlg.OscCal0Lab.Caption:=  ': $'+IntToHex(Cal0, 2);
                 FusesDlg.OscCal1Lab.Caption:=  ': $'+IntToHex(Cal1, 2);
                 FusesDlg.OscCal2Lab.Caption:=  ': $'+IntToHex(Cal2, 2);
                 FusesDlg.OscCal3Lab.Caption:=  ': $'+IntToHex(Cal3, 2);
                 FusesDlg.ShowModal;
               end;
    cDownLd,
    cVerify,
    cErase,
    cProg    : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cMemError: begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' memory error';
               end;
  end;
end;

procedure TProgMain.checkDevItemClick(Sender: TObject);
var idx    : byte;
    res, Volt : integer;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
    st        : string;
    FName     : string;
begin
  PstBuffer:= @stBuffer;
  idx:= CurProg;
  Status[idx].chGauge.Percent:= 0;
  FName:= Status[idx].chFileList.Items[Status[idx].chFileList.ItemIndex];
  if FName = '' then begin
    Status[idx].chProgState.caption := 'no file selected';
    beep;
    exit;
  end;
  case Status[idx].chState of
    cIdle    : begin
                 Screen.cursor:= crHourGlass;
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' check device';
                 Status[idx].chProgState.caption:= 'check device';
                 Status[idx].chState:= cCheck;
                 GetFileState(idx, res, PstBuffer);
                 if tProgResult(res) = invFName then begin
                   OpenAfile(idx, PChar(FName), res, PstBuffer);
                   Status[idx].chFileName.caption:= FName;
                 end;
                 CheckDevice(idx, res, PstBuffer);
                 st:= PstBuffer;
                 Status[idx].chProgState.caption := st;
                 Status[idx].chState:= cIdle;
                 Screen.cursor:= crDefault;
                 if tProgResult(res) in[resOk, errSignature, errProtected, errNotEmpty] then begin
                   GetTargVolt(idx, Volt, res, PstBuffer);
                   st:= st+' '+PstBuffer+'V';
                   Status[idx].chProgState.caption := st;
                   // Volt / 100  -> x.xx
                 end;
               end;
    cDownLd  : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cVerify,
    cErase,
    cProg    : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cMemError: begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' memory error';
               end;
  end;
end;

procedure TProgMain.delFileItemClick(Sender: TObject);
var idx     : byte;
    st      : string;
    res     : integer;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
    FName     : string;
begin
  PstBuffer:= @stBuffer;
  idx:= CurProg;
  Status[idx].chGauge.Percent:= 0;
  FName:= Status[idx].chFileList.Items[Status[idx].chFileList.ItemIndex];
  if FName = '' then begin
    Status[idx].chProgState.caption := 'no file selected';
    beep;
    exit;
  end;
  case Status[idx].chState of
    cIdle    : begin
                 GetFileState(idx, res, PstBuffer);
                 if tProgResult(res) = invFName then begin
                   DeleteAfile(idx, PChar(FName), res, PstBuffer);
                   if tProgResult(res) = resOk then begin
                     Status[idx].chFileList.Items.Delete(Status[idx].chFileList.ItemIndex);
                   end;
                 end
                 else Beep;
                 st:= PstBuffer;
                 Status[idx].chProgState.caption := st;
               end;
    cDownLd  : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cVerify,
    cErase,
    cProg    : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cMemError: begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' memory error';
               end;
  end;
end;

procedure TProgMain.closeFileItemClick(Sender: TObject);
var idx     : byte;
    st      : string;
    res     : integer;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
begin
  PstBuffer:= @stBuffer;
  idx:= CurProg;
  Status[idx].chGauge.Percent:= 0;
  case Status[idx].chState of
    cIdle    : begin
                 CloseAFile(idx, res, PstBuffer);
                 st:= PstBuffer;
                 Status[idx].chProgState.caption := st;
                 Status[idx].chFileName.caption:= '?';
               end;
    cDownLd  : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cVerify,
    cErase,
    cProg    : begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
               end;
    cMemError: begin
                 StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' memory error';
               end;
  end;
end;

procedure TProgMain.ProgAllBtnClick(Sender: TObject);
var idx     : byte;
    st      : string;
    res     : integer;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
    FName     : string;
    doProg    : boolean;
begin
  PstBuffer:= @stBuffer;
  doProg:= false;
  for idx:= 0 to 7 do begin
    FName:= Status[idx].chFileList.Items[Status[idx].chFileList.ItemIndex];
    if FName <> '' then begin
      Status[idx].chGauge.Percent:= 0;
      case Status[idx].chState of
        cIdle    : begin
                     StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' programming';
                     Status[idx].chProgState.caption:= 'programming';
                     Status[idx].chState:= cProg;
                     GetFileState(idx, res, PstBuffer);
                     if tProgResult(res) = invFName then begin
                       OpenAfile(idx, PChar(FName), res, PstBuffer);
                       Status[idx].chFileName.caption:= FName;
                     end;
                     doProg:= true;
                     ProgDevice(idx, res, PstBuffer);
                     st:= PstBuffer;
                     Status[idx].chProgState.caption:= st;
                     Status[idx].chState:= cProg;
                   end;
        cDownLd  : begin
                     StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
                   end;
        cProg    : begin
                     StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' busy';
                   end;
        cMemError: begin
                     StatusBar.SimpleText:= 'UPP '+IntToStr(idx+1)+' memory error';
                   end;
      end;
    end;
  end;
  if doProg then begin
    Screen.cursor:= crHourGlass;
    Timer1.Enabled := True;
  end;
end;

procedure TProgMain.SmartTimerTimerEvent(Sender: TObject; BlinkHigh: Boolean);
var idx     : byte;
begin
  for idx:= 0 to 7 do begin
    case Status[idx].chState of
      cIdle    : begin
                   Status[idx].chLedP.checked:= true;
                 end;
      cVerify,
      cErase,
      cProg,
      cDownLd  : begin
                   Status[idx].chLedP.checked:= BlinkHigh;
                 end;
      cUnknown : begin
                   Status[idx].chLedP.checked:= false;
                 end;
      cMemError: begin
                   Status[idx].chLedP.checked:= BlinkHigh;
                 end;
    end;
  end;
end;

procedure TProgMain.HintsCheckClick(Sender: TObject);
begin
  ShowHint:= HintsCheck.checked;
end;

//function JTAGBoundaryOpen(Channel: integer; CpuID, BoundaryLen, SupplyVolt, SupplyCurr : integer;
//                          var res : integer): PChar; stdcall;  external 'UPP_DLL.dll';
procedure TProgMain.ScanOpenBtnClick(Sender: TObject);
var idx    : byte;
    res    : integer;
    st     : string;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
begin
  PstBuffer:= @stBuffer;
  idx:= 0;
  JTAGBoundaryOpen(idx, $1E9702, 141, 430, 100, res, PstBuffer);
  st:= PstBuffer;
  ProgStatus0.caption:= st;
  if tProgResult(res) <> resOk then begin
    Beep;
    StatusBar.SimpleText:= st;
  end
  else begin
    StatusBar.SimpleText:= st;
  end;
end;

procedure TProgMain.ChainDownBtnClick(Sender: TObject);
var idx    : byte;
    res    : integer;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
begin
  PstBuffer:= @stBuffer;
  idx:= 0;
  JTAGchainWrite(idx, @ScanDownBuffer, res, PstBuffer);
  ProgStatus0.caption:= PstBuffer;
  StatusBar.SimpleText:= PstBuffer;
  Beep;
end;

procedure TProgMain.ChainUpBtnClick(Sender: TObject);
var idx    : byte;
    res    : integer;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
begin
  PstBuffer:= @stBuffer;
  idx:= 0;
  JTAGchainRead(idx, @ScanUpBuffer, res, PstBuffer);
  ProgStatus0.caption:= PstBuffer;
  StatusBar.SimpleText:= PstBuffer;
  Beep;
end;

procedure TProgMain.ScanCloseBtnClick(Sender: TObject);
var idx    : byte;
    res    : integer;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
begin
  PstBuffer:= @stBuffer;
  idx:= 0;
  JTAGBoundaryClose(idx, res, PstBuffer);
  ProgStatus0.caption:= PstBuffer;
  StatusBar.SimpleText:= PstBuffer;
end;

procedure TProgMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  AbortAll;
  Timer1.enabled:= false;
  IniEditor.WriteBool('Setup', 'ShowHint', ShowHint);
  CanClose:= true;
  Application.ProcessMessages;
  Sleep(1000);
end;

procedure TProgMain.LdPackFileBtnClick(Sender: TObject);
var idx    : integer;
begin
  if OpenDlg.Execute and (OpenDlg.FileName <> '') then begin
    for idx:= 0 to 7 do begin
      if Status[idx].chState <> cUnknown then begin
        status[idx].chDnLdBtn.enabled:= true;
      end;
    end;
  end;
end;

procedure TProgMain.FileBlockTestFClick(Sender: TObject);
type
    tUpDnArr  =  array[0..255] of byte;
var UpArr     : tUpDnArr;
    DnArr     : tUpDnArr;
    res, chan : integer;
    st, FName : string;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
begin
  PstBuffer:= @stBuffer;
  FillChar(DnArr, sizeOf(DnArr), 0);
  FillChar(UpArr, sizeOf(DnArr), 0);
  Chan:= CurProg;

  // check if file already open
  FName:= Status[Chan].chFileList.Items[Status[Chan].chFileList.ItemIndex];
  if FName = '' then begin
    Status[Chan].chProgState.caption := 'no file selected';
    beep;
    exit;
  end;
  GetFileState(chan, res, PstBuffer);
  if tProgResult(res) = invFName then begin
    OpenAfile(Chan, PChar(FName), res, PstBuffer);
    Status[Chan].chFileName.caption:= FName;
  end;

  UpFileBlockF(Chan, @DnArr, 512, 256, res, PstBuffer);
  st:= PstBuffer;
  // res = progBusy, noProg, progProtected, dwnLoadErr, resOk
  if tProgResult(res) <> resOk then begin
    StatusBar.SimpleText:= st;
    Beep;
    exit;
  end;

  // change one byte
  DnArr[0]:= $55;

  DownFileBlockF(Chan, @DnArr, 512, 256, res, PstBuffer);
  st:= PstBuffer;
  // res = progBusy, noProg, progProtected, dwnLoadErr, resOk
  if tProgResult(res) <> resOk then begin
    StatusBar.SimpleText:= st;
    Beep;
    exit;
  end;

  UpFileBlockF(Chan, @UpArr, 512, 256, res, PstBuffer);
  st:= PstBuffer;
  // res = progBusy, noProg, progProtected, dwnLoadErr, resOk
  if tProgResult(res) <> resOk then begin
    StatusBar.SimpleText:= st;
    Beep;
    exit;
  end;

  for res:= 0 to 255 do begin
    if DnArr[res] <> UpArr[res] then begin
      StatusBar.SimpleText:= 'Flash compare error';
      exit;
    end;
  end;
  beep;
  StatusBar.SimpleText:= 'File-Flash Up/Download test ok!';
end;

procedure TProgMain.FileBlockTestEClick(Sender: TObject);
type
    tUpDnArr  =  array[0..255] of byte;
var UpArr     : tUpDnArr;
    DnArr     : tUpDnArr;
    res, chan : integer;
    st, FName : string;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
begin
  PstBuffer:= @stBuffer;
  FillChar(DnArr, sizeOf(DnArr), 0);
  FillChar(UpArr, sizeOf(DnArr), 0);
  Chan:= CurProg;

  // check if file already open
  FName:= Status[Chan].chFileList.Items[Status[Chan].chFileList.ItemIndex];
  if FName = '' then begin
    Status[Chan].chProgState.caption := 'no file selected';
    beep;
    exit;
  end;
  GetFileState(chan, res, PstBuffer);
  if tProgResult(res) = invFName then begin
    OpenAfile(Chan, PChar(FName), res, PstBuffer);
    Status[Chan].chFileName.caption:= FName;
  end;

  UpFileBlockE(Chan, @DnArr, 0, 16, res, PstBuffer);
  st:= PstBuffer;
  // res = progBusy, noProg, progProtected, dwnLoadErr, resOk
  if tProgResult(res) <> resOk then begin
    StatusBar.SimpleText:= st;
    Beep;
    exit;
  end;

  // change one byte
  DnArr[0]:= $55;

  DownFileBlockE(Chan, @DnArr, 0, 16, res, PstBuffer);
  st:= PstBuffer;
  // res = progBusy, noProg, progProtected, dwnLoadErr, resOk
  if tProgResult(res) <> resOk then begin
    StatusBar.SimpleText:= st;
    Beep;
    exit;
  end;

  UpFileBlockE(Chan, @UpArr, 0, 16, res, PstBuffer);
  st:= PstBuffer;
  // res = progBusy, noProg, progProtected, dwnLoadErr, resOk
  if tProgResult(res) <> resOk then begin
    Beep;
    StatusBar.SimpleText:= st;
    exit;
  end;

  for res:= 0 to 15 do begin
    if DnArr[res] <> UpArr[res] then begin
      StatusBar.SimpleText:= 'EEprom compare error';
      Beep;
      exit;
    end;
  end;

  Beep;
  StatusBar.SimpleText:= 'File-EEprom Up/Download test ok!';
end;

procedure TProgMain.ChipBlockTestFClick(Sender: TObject);
type
    tUpDnArr  =  array[0..255] of byte;
var UpArr     : tUpDnArr;
    DnArr     : tUpDnArr;
    res, chan : integer;
    st, FName : string;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
begin
  Chan:= CurProg;
  PstBuffer:= @stBuffer;
  FillChar(DnArr, sizeOf(DnArr), 0);
  FillChar(UpArr, sizeOf(DnArr), 0);

  // check if file already open
  FName:= Status[Chan].chFileList.Items[Status[Chan].chFileList.ItemIndex];
  if FName = '' then begin
    Status[Chan].chProgState.caption := 'no file selected';
    beep;
    exit;
  end;
  GetFileState(chan, res, PstBuffer);
  if tProgResult(res) = invFName then begin
    OpenAfile(Chan, PChar(FName), res, PstBuffer);
    Status[Chan].chFileName.caption:= FName;
  end;

  ReadBackChipF(Chan, @DnArr, 256, res, PstBuffer);
  st:= PstBuffer;
  // res = progBusy, noProg, progProtected, dwnLoadErr, resOk
  if tProgResult(res) <> resOk then begin
    StatusBar.SimpleText:= st;
    Status[Chan].chProgState.caption:= st;
    Beep;
    exit;
  end;

  // replace all FFs by 55
  for res:= 0 to 255 do begin
    if DnArr[res] = $FF then begin
      DnArr[res]:= $55;
    end;
  end;

  DownProgBlockF(Chan, @DnArr, 256, res, PstBuffer);
  st:= PstBuffer;
  // res = progBusy, noProg, progProtected, dwnLoadErr, resOk
  if tProgResult(res) <> resOk then begin
    StatusBar.SimpleText:= st;
    Status[Chan].chProgState.caption:= st;
    Beep;
    exit;
  end;

  ReadBackChipF(Chan, @UpArr, 256, res, PstBuffer);
  st:= PstBuffer;
  // res = progBusy, noProg, progProtected, dwnLoadErr, resOk
  if tProgResult(res) <> resOk then begin
    StatusBar.SimpleText:= st;
    Status[Chan].chProgState.caption:= st;
    Beep;
    exit;
  end;

  for res:= 0 to 255 do begin
    if DnArr[res] <> UpArr[res] then begin
      StatusBar.SimpleText:= 'Flash compare error';
      Beep;
      exit;
    end;
  end;

  Status[Chan].chProgState.caption:= st;
  StatusBar.SimpleText:= 'Flash Up/Download test ok!';
  Beep;
end;

procedure TProgMain.ChipBlockTestEClick(Sender: TObject);
type
    tUpDnArr  =  array[0..255] of byte;
var UpArr     : tUpDnArr;
    DnArr     : tUpDnArr;
    res, chan : integer;
    st, FName : string;
    stBuffer  : array[0..512] of char;
    PstBuffer : PChar;
begin
  Chan:= CurProg;
  PstBuffer:= @stBuffer;
  FillChar(DnArr, sizeOf(DnArr), 0);
  FillChar(UpArr, sizeOf(DnArr), 0);

  // check if file already open
  FName:= Status[Chan].chFileList.Items[Status[Chan].chFileList.ItemIndex];
  if FName = '' then begin
    Status[Chan].chProgState.caption := 'no file selected';
    Status[Chan].chProgState.caption:= st;
    beep;
    exit;
  end;
  GetFileState(chan, res, PstBuffer);
  if tProgResult(res) = invFName then begin
    OpenAfile(Chan, PChar(FName), res, PstBuffer);
    Status[Chan].chFileName.caption:= FName;
  end;

  ReadBackChipE(Chan, @DnArr, 0, 16, res, PstBuffer);
  st:= PstBuffer;
  // res = progBusy, noProg, progProtected, dwnLoadErr, resOk
  if tProgResult(res) <> resOk then begin
    StatusBar.SimpleText:= st;
    Status[Chan].chProgState.caption:= st;
    Beep;
    exit;
  end;

  // replace the current EEprom content
  for res:= 0 to 255 do begin
    DnArr[res]:= res;
  end;

  DownProgBlockE(Chan, @DnArr, 0, 16, res, PstBuffer);
  st:= PstBuffer;
  // res = progBusy, noProg, progProtected, dwnLoadErr, resOk
  if tProgResult(res) <> resOk then begin
    StatusBar.SimpleText:= st;
    Status[Chan].chProgState.caption:= st;
    Beep;
    exit;
  end;

  ReadBackChipE(Chan, @UpArr, 0, 16, res, PstBuffer);
  st:= PstBuffer;
  // res = progBusy, noProg, progProtected, dwnLoadErr, resOk
  if tProgResult(res) <> resOk then begin
    StatusBar.SimpleText:= st;
    Status[Chan].chProgState.caption:= st;
    Beep;
    exit;
  end;

  for res:= 0 to 15 do begin
    if DnArr[res] <> UpArr[res] then begin
      StatusBar.SimpleText:= 'EEprom compare error';
      Beep;
      exit;
    end;
  end;

  Status[Chan].chProgState.caption:= st;
  StatusBar.SimpleText:= 'EEprom Up/Download test ok!';
  Beep;
end;

procedure TProgMain.BitBtn1Click(Sender: TObject);
begin
  Application.terminate;
end;

procedure TProgMain.FileList0Click(Sender: TObject);
var st     : string;
    idx    : integer;
begin
  idx:= TControl(Sender).Tag;
  st:= UpperCase(ExtractFileExt(Status[idx].chFileList.Text));
  Status[idx].chEncrBMP.Visible:= Pos('.EN', st) = 1;
end;

procedure TProgMain.OverWriteChkClick(Sender: TObject);
begin
  OverWriteData.Enabled:= OverWriteChk.Checked;
  OverWrAddrLo.Enabled:= OverWriteChk.Checked;
  OverWrAddrHi.Enabled:= OverWriteChk.Checked;
end;

initialization
finalization
end.



