//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Main.h"               // переменные для работы с главной формой
#include "LogFunctions.h"       // переменные для отправки сообщений в лог
#include "PortFunctions.h"      // переменные для функций работы с портом
#include "FormFunctions.h"      // переменные для работы с формой
#include "About.h"              // для использования окна About
#include "ProgressBar.h"        // для использования прогресс-бара
#include "LockFuses.h"          // для использования окна LockFusesForm
#include "Image.h"              // для использования окна ImageForm
#include "ChipFunctions.h"      // переменные для работы с чипом
#include "PICFunctions.h"       // переменные для функций работы с чипами PIC
#include "pic16f630.h"          // переменные для функций работы с PIC16F630 / PIC16F676 / PIC12F629 / PIC12F675
                                // PIC12F635 / PIC12F683 / PIC16F631 / PIC16F636 / PIC16F639 / PIC16F677 / PIC16F684 / PIC16F685 / PIC16F687 / PIC16F688 / PIC16F689 / PIC16F690
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
//---------------------------------------------------------------------------
//--- ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ -------------------------------------------------
//---------------------------------------------------------------------------
TForm1 *Form1;                  // главная форма
unsigned int Delays;            // здесь будем хранить величину задержек для замедления обмена
//---------------------------------------------------------------------------
//--- ОТКРЫТИЕ ВЫБРАННОГО COM-ПОРТА -----------------------------------------
//---------------------------------------------------------------------------
void OpenPort()
{ //откроем выбранный порт. Чтобы открыть порт на nt-платформе надо указывать
  // "\\.\PortName", в СИ для печати символа \ надо его указывать 2 раза
  char PortName[100]="\\\\.\\";
  strcat(PortName,Form1->ComboBox1->Text.c_str());
  OpenCom(PortName);                            // само открытие порта происходит здесь
  if(Port!=INVALID_HANDLE_VALUE)
  { EnableButtons();                            // включаем кнопки управления, выключаем кнопку Connect
    SendMsgToLog(1,AnsiString(PortName));       // открыт COM-порт
  }
}
//---------------------------------------------------------------------------
//--- ЗАКРЫТИЕ ВЫБРАННОГО COM-ПОРТА -----------------------------------------
//---------------------------------------------------------------------------
void ClosePort()
{ CloseHandle(Port);
  Port=INVALID_HANDLE_VALUE;
  DisableButtons();                     // выключаем кнопки управления, включаем кнопку Connect
  SendMsgToLog(3,"");                   // COM-порт закрыт
}
//---------------------------------------------------------------------------
//--- КОНСТРУИРОВАНИЕ ГЛАВНОЙ ФОРМЫ -----------------------------------------
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{ DisableButtons();                                     // выключаем кнопки управления, включаем кнопку Connect
  Form1->AutoSize               = true;                 // устанавливаем авторазмер формы
  Port                          = INVALID_HANDLE_VALUE; // никакой порт не открыт
  SelectedChip.ID               = 0;                    // не выбран ни один чип
  Delays = Form1->TrackBar1->Position;                  // получаем значение задержек
}
//---------------------------------------------------------------------------
//--- КНОПКА ОТКРЫТИЯ COM-ПОРТА ---------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{ OpenPort();
}
//---------------------------------------------------------------------------
//--- КНОПКА ЗАКРЫТИЯ COM-ПОРТА ---------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{ ClosePort();
}
//---------------------------------------------------------------------------
//--- ЕСЛИ ПОМЕНЯЛИ ВЫБРАННЫЙ COM-ПОРТ --------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::ComboBox1Change(TObject *Sender)
{ // если порт открыт, то его надо закрыть
  if(Port!=INVALID_HANDLE_VALUE) ClosePort();
}
//---------------------------------------------------------------------------
//--- ВЫБРАЛИ В МЕНЮ ПУНКТ EXIT ---------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::Exit1Click(TObject *Sender)
{ if(Port!=INVALID_HANDLE_VALUE) ClosePort();
  Close();
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАНО СОХРАНЕНИЕ ЛОГА ----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::SaveLogas1Click(TObject *Sender)
{ AnsiString FilePath;                                  // полный путь к файлу

  if(SaveDialog1->Execute())                            // если определились куда сохранять (не нажали отмена)
  { FilePath=SaveDialog1->FileName;                     // получаем имя файла для сохранения (с путём)
    Form1->RichEdit5->Lines->SaveToFile(FilePath);      // сохраняем в него данные из RichEdit5
    SendMsgToLog(8,FilePath);                           // выводим в лог сообщение о сохранении
  }
}
//---------------------------------------------------------------------------
//--- ВЫБРАЛИ В МЕНЮ ПУНКТ ABOUT --------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::About1Click(TObject *Sender)
{ AboutBox->Show();
}
//---------------------------------------------------------------------------
//--- ВЫБРАЛИ В МЕНЮ ПУНКТ LOCK & FUSES... ----------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::LockFuses1Click(TObject *Sender)
{ Application->CreateForm(__classid(TLockFusesForm),&LockFusesForm);    // создаём форму с фьюзами
  LockFusesForm->ShowModal();                                           // показываем её в модальном окне
  LockFusesForm->Free();                                                // уничтожаем форму после закрытия
}
//---------------------------------------------------------------------------
//--- ВЫБРАЛИ В МЕНЮ ПУНКТ RH-0010 CONNECTION... ----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::RH0010Connection1Click(TObject *Sender)
{ Application->CreateForm(__classid(TImageForm),&ImageForm);        // создаём форму со схемой подключения
  ImageForm->ShowModal();                                           // показываем её в модальном окне
  ImageForm->Free();                                                // уничтожаем форму после закрытия
}
//---------------------------------------------------------------------------
void __fastcall TForm1::RichEditsKeyPress(TObject *Sender, char &Key)
{  Key=0;
}
//---------------------------------------------------------------------------
//--- РЕДАКТИРОВАНИЕ ПОЛЯ ID WORD -------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::Edit2KeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{ char *Charset1="0123456789abcdefABCDEF";      // допустимые символы
  char Symbol;                                  // символ для замены
  int Position;                                 // позиция курсора

  Position=Form1->Edit2->SelStart;              // позиция курсора в тексте
  switch(Key)
  { // обработчик backspace ***********************************
    case 8:     Position-=1;                            // уменьшаем позицию
                if(Position<0)       Position=4;        // если новая позиция <0, то переходим в начало строки
                else                                    // если новая позиция >=0
                { Form1->Edit2->SelStart=Position;      // устанавливаем курсор
                  Form1->Edit2->SelLength=1;            // выделяем 1 символ
                  if(Position>0)        Symbol=0x46;    // будем писать символ F
                  else                  Symbol=0x33;    // будем писать символ 3
                  Form1->Edit2->SelText=Symbol;         // пишем
                }
                Form1->Edit2->SelStart=Position;        // ставим курсор в нужную позицию
                Form1->Edit2->SelLength=0;              // отменяем выделение
                break;
    // обработчик стрелок *************************************
     case 0x25:
     case 0x26:
     case 0x27:
     case 0x28: return;
     // обработчик delete **************************************
     case 0x2E: if(Position>0)  Key=0x46;       // заменяем на F, а дальше как все остальные вводы
                else            Key=0x33;       // заменяем на 3, а дальше как все остальные вводы
     // обработчик всех остальных кнопок ***********************
     default:   if(Position>3)       Position=-1;             // если позиция >3, то переходим в начало строки
                else if(strchr(Charset1,Key))                 // если символ есть в наборе и позиция не перед пробелом
                { Form1->Edit2->SelStart=Position;            // ставим курсор в нужную позицию
                  Form1->Edit2->SelLength=1;                  // выделяем 1 символ
                  if(Position==0 && Key>0x33)   Key=0x33;     // в нулевой позиции можно вводить только 0,1,2,3
                  Symbol=Key;
                  Form1->Edit2->SelText=Symbol;               // пишем туда введённый символ
                  Form1->Edit2->SelStart=Position;            // ставим курсор в нужную позицию
                  Form1->Edit2->SelLength=1;                  // выделяем 1 символ
                  Form1->Edit2->SelText=UpperCase(Form1->Edit2->SelText); // переводим введённый символ в верхний регистр
                }
                // устанавливаем курсор в нужную позицию
                Position+=1;                          // увеличиваем позицию курсора
                Form1->Edit2->SelStart=Position;      // ставим курсор в нужную позицию
                Form1->Edit2->SelLength=0;            // отменяем выделение
  }
  Key=0;
}
//---------------------------------------------------------------------------
//--- РЕДАКТИРОВАНИЕ ПОЛЯ RICHEDIT1 (Area 1) --------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::RichEdit1KeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{ char *Charset1="0123456789abcdefABCDEF";              // допустимые символы
  char Symbol;                                          // символ для замены
  int  PositionGlobal, LineNumber, PositionLocal;       // глобальная позиция, номер строки, позиция в строке
  int  MaxLineNumber, WordPos, CharPos;                 // максимальный номер строки, позиции слова и символа на другой стороне
  char *InHexBuf, TempBuf[1], OutHexBuf[3];             // для преобразования
  AnsiString SubStr;                                    // для преобразования

  PositionGlobal=Form1->RichEdit1->SelStart;            // глобальная позиция курсора в тексте
  LineNumber=PositionGlobal/74;                         // номер строки, в которой находится курсор  72 символа + CR+LF
  PositionLocal=PositionGlobal-74*LineNumber;           // позиция курсора в строке
  MaxLineNumber=(FormData.RE1Size-1)/16;                // максимальный номер строки
  switch(Key)
  { // обработчик backspace ***********************************
    case 8:     PositionLocal-=1;                       // уменьшаем позицию в строке
                if(PositionLocal<10)
                { PositionLocal=49;                     // если позиция <10, то переходим в начало предыдущей строки
                  LineNumber-=1;
                  if(LineNumber<0)                      // если номер строки <0
                        LineNumber=MaxLineNumber;       // переходим на последнюю строку
                }
                else if(PositionLocal<49)               // если новая позиция в области hex
                { if ((PositionLocal-10)%5!=4)          // если новая позиция не перед пробелом
                  { // меняем область слева
                    Form1->RichEdit1->SelStart=LineNumber*74+PositionLocal;     // устанавливаем курсор
                    Form1->RichEdit1->SelLength=1;      // выделяем 1 символ
                    if((PositionLocal-10)%5==0) Symbol=0x33;                    // будем писать символ 3
                    else                        Symbol=0x46;                    // будем писать символ F
                    Form1->RichEdit1->SelText=Symbol;   // пишем
                    // получаем символ, который будем писать в область справа
                    WordPos=(PositionLocal-10)/5;        // номер слова в строке, в котором нужно поменять байт
                    if((PositionLocal-10)%5<2)  CharPos=1;      // номер байта в слове (старший байт)
                    else                        CharPos=0;      // номер байта в слове (младший байт)
                    Form1->RichEdit1->SelStart=74*LineNumber+10+5*WordPos+2*(1-CharPos);// ставим курсор на начало байта (в области слева)
                    Form1->RichEdit1->SelLength=2;                                      // выделяем 2 символа
                    SubStr=LowerCase(Form1->RichEdit1->SelText);                        // получаем их в строку
                    InHexBuf=SubStr.c_str();            //скопировать в буфер байт для передачи (в виде строки)
                    HexToBin(InHexBuf,TempBuf,1);       //преобразовать строку в целое (байт)
                    Key=TempBuf[0];
                    if(Key<0x1F) Symbol=0x1F;           //заменяем непечатные (TempBuf[0] сравнивать нельзя так как он знаковый)
                    else         Symbol=TempBuf[0];
                    // меняем область справа
                    Form1->RichEdit1->SelStart=LineNumber*74+56+2*WordPos+CharPos;      // устанавливаем курсор
                    Form1->RichEdit1->SelLength=1;      // выделяем 1 символ
                    Form1->RichEdit1->SelText=Symbol;   // пишем туда полученный символ
                  }
                }
                else if(PositionLocal<56)               // если мы между правой и левой областями
                { PositionLocal=72;                     // если позиция <36, то переходим в начало предыдущей строки
                  LineNumber-=1;
                  if(LineNumber<0)                      // если номер строки <0
                        LineNumber=MaxLineNumber;       // переходим на последнюю строку
                }
                else                                    // если мы в области справа
                { // меняем область справа
                  Form1->RichEdit1->SelStart=LineNumber*74+PositionLocal;       // устанавливаем курсор
                  Form1->RichEdit1->SelLength=1;        // выделяем 1 символ
                  if((PositionLocal-56)%2==0)   Symbol=0xFF;                    // будем писать символ я (младший байт)
                  else                          Symbol=0x3F;                    // будем писать символ ? (старший байт)
                  Form1->RichEdit1->SelText=Symbol;     // пишем
                  // получаем символ, который будем менять
                  WordPos=(PositionLocal-56)/2;         // номер слова в строке, в котором нужно поменять байт
                  CharPos=(PositionLocal-56)%2;         // номер байта в слове
                  // меняем область слева
                  Form1->RichEdit1->SelStart=LineNumber*74+10+5*WordPos+2*(1-CharPos);  // устанавливаем курсор
                  Form1->RichEdit1->SelLength=2;        // выделяем 2 символа
                  if(CharPos==0)        Form1->RichEdit1->SelText="FF";       // пишем FF
                  else                  Form1->RichEdit1->SelText="3F";       // пишем 3F
                }
                // устанавливаем курсор в нужную позицию
                Form1->RichEdit1->SelStart=LineNumber*74+PositionLocal;         // ставим курсор в нужную позицию
                Form1->RichEdit1->SelLength=0;                                  // отменяем выделение
                break;
    // обработчик стрелок *************************************
     case 0x25:
     case 0x26:
     case 0x27:
     case 0x28: return;
     // обработчик delete **************************************
     case 0x2E: // если мы в области слева - заменяем на F или 3
                if((PositionLocal>9) && (PositionLocal<49))
                {       if((PositionLocal-10)%5 == 0)   Key=0x33;               // заменяем символ слева на 3
                        else                            Key=0x46;               // заменяем символ слева на F
                }
                // если мы в области справа - заменяем на я или ?
                if(PositionLocal>55)
                {       if((PositionLocal-56)%2 == 0)   Key=0xFF;               // заменяем символ справа на F
                        else                            Key=0x3F;               // заменяем символ справа на ?
                }
     // обработчик всех остальных кнопок ***********************
     default:   if(PositionLocal>71)            // если позиция > 71
                { PositionLocal=55;             // то переходим в начало строки
                  LineNumber+=1;                // увеличиваем номер строки
                  if(LineNumber>MaxLineNumber)
                        LineNumber=0;           // если номер > максимального - переходим на первую строку
                }
                else if(PositionLocal>55)       // если позиция > 55
                { // меняем область справа
                  Form1->RichEdit1->SelStart=LineNumber*74+PositionLocal;       // ставим курсор в нужную позицию
                  Form1->RichEdit1->SelLength=1;                                // выделяем 1 символ
                  if(Key<0x1F)  Key=0x1F;                                       // если символ непечатный (спецсимвол) - заменяем
                  if(((PositionLocal-56)%2!=0) && (Key>0x3F))   Key=0x3F;       // в старшем байте может быть записано максимум 0x3F
                  Symbol=Key;
                  Form1->RichEdit1->SelText=Symbol;                             // пишем туда введённый символ
                  Form1->RichEdit1->SelStart=LineNumber*74+PositionLocal;       // ставим курсор в нужную позицию
                  Form1->RichEdit1->SelLength=1;                                // выделяем 1 символ
                  Form1->RichEdit1->SelText=UpperCase(Form1->RichEdit1->SelText); // переводим введённый символ в верхний регистр
                  // получаем символ, который будем менять
                  WordPos=(PositionLocal-56)/2;         // номер слова в строке, в котором нужно поменять байт
                  CharPos=(PositionLocal-56)%2;         // номер байта в слове (0 - младший, 1 - старший)
                  TempBuf[0]=Key;
                  BinToHex(TempBuf,OutHexBuf,1);        //преобразовать строку в целое (байт)
                  OutHexBuf[2]=0;                       //строка должна заканчиваться нулём
                  // меняем область слева
                  Form1->RichEdit1->SelStart=LineNumber*74+10+5*WordPos+2*(1-CharPos);  // ставим курсор на начало байт
                  Form1->RichEdit1->SelLength=2;                                        // выделяем 2 символа
                  Form1->RichEdit1->SelText=OutHexBuf;
                }
                else if(PositionLocal>48)       // если позиция >48,
                { PositionLocal=9;              // то переходим в начало строки
                  LineNumber+=1;                // увеличиваем номер строки
                  if(LineNumber>MaxLineNumber)
                        LineNumber=0;           // если номер > максимального - переходим на первую строку
                }
                else if(PositionLocal>9)        // если позиция > 9
                { if(strchr(Charset1,Key)&&((PositionLocal-10)%5!=4))            // если символ есть в наборе и позиция не перед пробелом
                  { // меняем область слева
                    Form1->RichEdit1->SelStart=LineNumber*74+PositionLocal;     // ставим курсор в нужную позицию
                    Form1->RichEdit1->SelLength=1;                              // выделяем 1 символ
                    if(((PositionLocal-10)%5==0) && (Key > 0x33)) Key = 0x33;   // старший байт должен быть не более 0x3F
                    Symbol=Key;
                    Form1->RichEdit1->SelText=Symbol;                           // пишем туда введённый символ
                    Form1->RichEdit1->SelStart=LineNumber*74+PositionLocal;     // ставим курсор в нужную позицию
                    Form1->RichEdit1->SelLength=1;                              // выделяем 1 символ
                    Form1->RichEdit1->SelText=UpperCase(Form1->RichEdit1->SelText);     // переводим введённый символ в верхний регистр
                    // получаем символ, который будем писать в область справа
                    WordPos=(PositionLocal-10)/5;        // номер слова в строке, в котором нужно поменять байт
                    if((PositionLocal-10)%5<2)  CharPos=1;      // номер байта в слове (старший байт)
                    else                        CharPos=0;      // номер байта в слове (младший байт)
                    Form1->RichEdit1->SelStart=74*LineNumber+10+5*WordPos+2*(1-CharPos); // ставим курсор на начало байта (в области слева)
                    Form1->RichEdit1->SelLength=2;                              // выделяем 2 символа
                    SubStr=LowerCase(Form1->RichEdit1->SelText);                // получаем их в строку
                    InHexBuf=SubStr.c_str();            //скопировать в буфер байт для передачи (в виде строки)
                    HexToBin(InHexBuf,TempBuf,1);       //преобразовать строку в целое (байт)
                    Key=TempBuf[0];
                    if(Key<0x1F) Symbol=0x1F;           //заменяем непечатные
                    else         Symbol=TempBuf[0];
                    // меняем область справа
                    Form1->RichEdit1->SelStart=LineNumber*74+56+2*WordPos+CharPos;        // устанавливаем курсор
                    Form1->RichEdit1->SelLength=1;      // выделяем 1 символ
                    Form1->RichEdit1->SelText=Symbol;   // пишем туда полученный символ
                  }
                }
                else    PositionLocal=9;        // переходим в начало строки
                // устанавливаем курсор в нужную позицию
                PositionLocal+=1;                                       // увеличиваем позицию курсора
                Form1->RichEdit1->SelStart=LineNumber*74+PositionLocal; // ставим курсор в нужную позицию
                Form1->RichEdit1->SelLength=0;                          // отменяем выделение
  }
  Key=0;
}
//---------------------------------------------------------------------------
//--- РЕДАКТИРОВАНИЕ ПОЛЯ RICHEDIT2 (Area 1) --------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::RichEdit2KeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{ char *Charset1="0123456789abcdefABCDEF";              // допустимые символы
  char Symbol;                                          // символ для замены
  int  PositionGlobal, LineNumber, PositionLocal;       // глобальная позиция, номер строки, позиция в строке
  int  MaxLineNumber, WordPos, CharPos;                 // максимальный номер строки, позиции слова и символа на другой стороне
  char *InHexBuf, TempBuf[1], OutHexBuf[3];             // для преобразования
  AnsiString SubStr;                                    // для преобразования

  PositionGlobal=Form1->RichEdit2->SelStart;            // глобальная позиция курсора в тексте
  LineNumber=PositionGlobal/74;                         // номер строки, в которой находится курсор  72 символа + CR+LF
  PositionLocal=PositionGlobal-74*LineNumber;           // позиция курсора в строке
  MaxLineNumber=(FormData.RE2Size-1)/16;                // максимальный номер строки
  switch(Key)
  { // обработчик backspace ***********************************
    case 8:     PositionLocal-=1;                       // уменьшаем позицию в строке
                if(PositionLocal<10)
                { PositionLocal=49;                     // если позиция <10, то переходим в начало предыдущей строки
                  LineNumber-=1;
                  if(LineNumber<0)                      // если номер строки <0
                        LineNumber=MaxLineNumber;       // переходим на последнюю строку
                }
                else if(PositionLocal<49)               // если новая позиция в области hex
                { if ((PositionLocal-10)%5!=4)          // если новая позиция не перед пробелом
                  { // меняем область слева
                    Form1->RichEdit2->SelStart=LineNumber*74+PositionLocal;     // устанавливаем курсор
                    Form1->RichEdit2->SelLength=1;      // выделяем 1 символ
                    if((PositionLocal-10)%5==0) Symbol=0x33;                    // будем писать символ 3
                    else                        Symbol=0x46;                    // будем писать символ F
                    Form1->RichEdit2->SelText=Symbol;   // пишем
                    // получаем символ, который будем писать в область справа
                    WordPos=(PositionLocal-10)/5;        // номер слова в строке, в котором нужно поменять байт
                    if((PositionLocal-10)%5<2)  CharPos=1;      // номер байта в слове (старший байт)
                    else                        CharPos=0;      // номер байта в слове (младший байт)
                    Form1->RichEdit2->SelStart=74*LineNumber+10+5*WordPos+2*(1-CharPos);// ставим курсор на начало байта (в области слева)
                    Form1->RichEdit2->SelLength=2;                                      // выделяем 2 символа
                    SubStr=LowerCase(Form1->RichEdit2->SelText);                        // получаем их в строку
                    InHexBuf=SubStr.c_str();            //скопировать в буфер байт для передачи (в виде строки)
                    HexToBin(InHexBuf,TempBuf,1);       //преобразовать строку в целое (байт)
                    Key=TempBuf[0];
                    if(Key<0x1F) Symbol=0x1F;           //заменяем непечатные (TempBuf[0] сравнивать нельзя так как он знаковый)
                    else         Symbol=TempBuf[0];
                    // меняем область справа
                    Form1->RichEdit2->SelStart=LineNumber*74+56+2*WordPos+CharPos;      // устанавливаем курсор
                    Form1->RichEdit2->SelLength=1;      // выделяем 1 символ
                    Form1->RichEdit2->SelText=Symbol;   // пишем туда полученный символ
                  }
                }
                else if(PositionLocal<56)               // если мы между правой и левой областями
                { PositionLocal=72;                     // если позиция <36, то переходим в начало предыдущей строки
                  LineNumber-=1;
                  if(LineNumber<0)                      // если номер строки <0
                        LineNumber=MaxLineNumber;       // переходим на последнюю строку
                }
                else                                    // если мы в области справа
                { // меняем область справа
                  Form1->RichEdit2->SelStart=LineNumber*74+PositionLocal;       // устанавливаем курсор
                  Form1->RichEdit2->SelLength=1;        // выделяем 1 символ
                  if((PositionLocal-56)%2==0)   Symbol=0xFF;                    // будем писать символ я (младший байт)
                  else                          Symbol=0x3F;                    // будем писать символ ? (старший байт)
                  Form1->RichEdit2->SelText=Symbol;     // пишем
                  // получаем символ, который будем менять
                  WordPos=(PositionLocal-56)/2;         // номер слова в строке, в котором нужно поменять байт
                  CharPos=(PositionLocal-56)%2;         // номер байта в слове
                  // меняем область слева
                  Form1->RichEdit2->SelStart=LineNumber*74+10+5*WordPos+2*(1-CharPos);  // устанавливаем курсор
                  Form1->RichEdit2->SelLength=2;        // выделяем 2 символа
                  if(CharPos==0)        Form1->RichEdit2->SelText="FF";       // пишем FF
                  else                  Form1->RichEdit2->SelText="3F";       // пишем 3F
                }
                // устанавливаем курсор в нужную позицию
                Form1->RichEdit2->SelStart=LineNumber*74+PositionLocal;         // ставим курсор в нужную позицию
                Form1->RichEdit2->SelLength=0;                                  // отменяем выделение
                break;
    // обработчик стрелок *************************************
     case 0x25:
     case 0x26:
     case 0x27:
     case 0x28: return;
     // обработчик delete **************************************
     case 0x2E: // если мы в области слева - заменяем на F или 3
                if((PositionLocal>9) && (PositionLocal<49))
                {       if((PositionLocal-10)%5 == 0)   Key=0x33;               // заменяем символ слева на 3
                        else                            Key=0x46;               // заменяем символ слева на F
                }
                // если мы в области справа - заменяем на я или ?
                if(PositionLocal>55)
                {       if((PositionLocal-56)%2 == 0)   Key=0xFF;               // заменяем символ справа на F
                        else                            Key=0x3F;               // заменяем символ справа на ?
                }
     // обработчик всех остальных кнопок ***********************
     default:   if(PositionLocal>71)            // если позиция > 71
                { PositionLocal=55;             // то переходим в начало строки
                  LineNumber+=1;                // увеличиваем номер строки
                  if(LineNumber>MaxLineNumber)
                        LineNumber=0;           // если номер > максимального - переходим на первую строку
                }
                else if(PositionLocal>55)       // если позиция > 55
                { // меняем область справа
                  Form1->RichEdit2->SelStart=LineNumber*74+PositionLocal;       // ставим курсор в нужную позицию
                  Form1->RichEdit2->SelLength=1;                                // выделяем 1 символ
                  if(Key<0x1F)  Key=0x1F;                                       // если символ непечатный (спецсимвол) - заменяем
                  if(((PositionLocal-56)%2!=0) && (Key>0x3F))   Key=0x3F;       // в старшем байте может быть записано максимум 0x3F
                  Symbol=Key;
                  Form1->RichEdit2->SelText=Symbol;                             // пишем туда введённый символ
                  Form1->RichEdit2->SelStart=LineNumber*74+PositionLocal;       // ставим курсор в нужную позицию
                  Form1->RichEdit2->SelLength=1;                                // выделяем 1 символ
                  Form1->RichEdit2->SelText=UpperCase(Form1->RichEdit2->SelText); // переводим введённый символ в верхний регистр
                  // получаем символ, который будем менять
                  WordPos=(PositionLocal-56)/2;         // номер слова в строке, в котором нужно поменять байт
                  CharPos=(PositionLocal-56)%2;         // номер байта в слове (0 - младший, 1 - старший)
                  TempBuf[0]=Key;
                  BinToHex(TempBuf,OutHexBuf,1);        //преобразовать строку в целое (байт)
                  OutHexBuf[2]=0;                       //строка должна заканчиваться нулём
                  // меняем область слева
                  Form1->RichEdit2->SelStart=LineNumber*74+10+5*WordPos+2*(1-CharPos);  // ставим курсор на начало байт
                  Form1->RichEdit2->SelLength=2;                                        // выделяем 2 символа
                  Form1->RichEdit2->SelText=OutHexBuf;
                }
                else if(PositionLocal>48)       // если позиция >48,
                { PositionLocal=9;              // то переходим в начало строки
                  LineNumber+=1;                // увеличиваем номер строки
                  if(LineNumber>MaxLineNumber)
                        LineNumber=0;           // если номер > максимального - переходим на первую строку
                }
                else if(PositionLocal>9)        // если позиция > 9
                { if(strchr(Charset1,Key)&&((PositionLocal-10)%5!=4))            // если символ есть в наборе и позиция не перед пробелом
                  { // меняем область слева
                    Form1->RichEdit2->SelStart=LineNumber*74+PositionLocal;     // ставим курсор в нужную позицию
                    Form1->RichEdit2->SelLength=1;                              // выделяем 1 символ
                    if(((PositionLocal-10)%5==0) && (Key > 0x33)) Key = 0x33;   // старший байт должен быть не более 0x3F
                    Symbol=Key;
                    Form1->RichEdit2->SelText=Symbol;                           // пишем туда введённый символ
                    Form1->RichEdit2->SelStart=LineNumber*74+PositionLocal;     // ставим курсор в нужную позицию
                    Form1->RichEdit2->SelLength=1;                              // выделяем 1 символ
                    Form1->RichEdit2->SelText=UpperCase(Form1->RichEdit2->SelText);     // переводим введённый символ в верхний регистр
                    // получаем символ, который будем писать в область справа
                    WordPos=(PositionLocal-10)/5;        // номер слова в строке, в котором нужно поменять байт
                    if((PositionLocal-10)%5<2)  CharPos=1;      // номер байта в слове (старший байт)
                    else                        CharPos=0;      // номер байта в слове (младший байт)
                    Form1->RichEdit2->SelStart=74*LineNumber+10+5*WordPos+2*(1-CharPos); // ставим курсор на начало байта (в области слева)
                    Form1->RichEdit2->SelLength=2;                              // выделяем 2 символа
                    SubStr=LowerCase(Form1->RichEdit2->SelText);                // получаем их в строку
                    InHexBuf=SubStr.c_str();            //скопировать в буфер байт для передачи (в виде строки)
                    HexToBin(InHexBuf,TempBuf,1);       //преобразовать строку в целое (байт)
                    Key=TempBuf[0];
                    if(Key<0x1F) Symbol=0x1F;           //заменяем непечатные
                    else         Symbol=TempBuf[0];
                    // меняем область справа
                    Form1->RichEdit2->SelStart=LineNumber*74+56+2*WordPos+CharPos;        // устанавливаем курсор
                    Form1->RichEdit2->SelLength=1;      // выделяем 1 символ
                    Form1->RichEdit2->SelText=Symbol;   // пишем туда полученный символ
                  }
                }
                else    PositionLocal=9;        // переходим в начало строки
                // устанавливаем курсор в нужную позицию
                PositionLocal+=1;                                       // увеличиваем позицию курсора
                Form1->RichEdit2->SelStart=LineNumber*74+PositionLocal; // ставим курсор в нужную позицию
                Form1->RichEdit2->SelLength=0;                          // отменяем выделение
  }
  Key=0;
}
//---------------------------------------------------------------------------
//--- РЕДАКТИРОВАНИЕ ПОЛЯ RICHEDIT3 (Area 2) --------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::RichEdit3KeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{ char *Charset1="0123456789abcdefABCDEF";              // допустимые символы
  char Symbol;                                          // символ для замены
  int  PositionGlobal, LineNumber, PositionLocal;       // глобальная позиция, номер строки, позиция в строке
  int  MaxLineNumber, CharPos;                          // максимальный номер строки, позиция символа на другой стороне
  char *InHexBuf, TempBuf[1], OutHexBuf[3];             // для преобразования
  AnsiString SubStr;                                    // для преобразования

  PositionGlobal=Form1->RichEdit3->SelStart;            // глобальная позиция курсора в тексте
  LineNumber=PositionGlobal/82;                         // номер строки, в которой находится курсор  76 символов + CR+LF
  PositionLocal=PositionGlobal-82*LineNumber;           // позиция курсора в строке
  MaxLineNumber=(FormData.RE3Size-1)/16;                // максимальный номер строки
  switch(Key)
  { // обработчик backspace ***********************************
    case 8:     PositionLocal-=1;                       // уменьшаем позицию в строке
                if(PositionLocal<10)
                { PositionLocal=57;                     // если позиция <6, то переходим в начало предыдущей строки
                  LineNumber-=1;
                  if(LineNumber<0)                      // если номер строки <0
                        LineNumber=MaxLineNumber;       // переходим на последнюю строку
                }
                else if(PositionLocal<57)               // если новая позиция в области hex
                { if ((PositionLocal-10)%3!=2)           // если новая позиция не перед пробелом
                  { // меняем область слева
                    Form1->RichEdit3->SelStart=LineNumber*82+PositionLocal;     // устанавливаем курсор
                    Form1->RichEdit3->SelLength=1;      // выделяем 1 символ
                    Symbol=0x46;                        // будем писать символ F
                    Form1->RichEdit3->SelText=Symbol;   // пишем
                    // получаем символ, который будем писать в область справа
                    CharPos=(PositionLocal-10)/3;        // номер байта в строке, который нужно поменять
                    Form1->RichEdit3->SelStart=82*LineNumber+10+3*CharPos;       // ставим курсор на начало байта (в области слева)
                    Form1->RichEdit3->SelLength=2;                              // выделяем 2 символа
                    SubStr=LowerCase(Form1->RichEdit3->SelText);                // получаем их в строку
                    InHexBuf=SubStr.c_str();            //скопировать в буфер байт для передачи (в виде строки)
                    HexToBin(InHexBuf,TempBuf,1);       //преобразовать строку в целое (байт)
                    Key=TempBuf[0];
                    if(Key<0x1F) Symbol=0x1F;           //заменяем непечатные (TempBuf[0] сравнивать нельзя так как он знаковый)
                    else         Symbol=TempBuf[0];
                    // меняем область справа
                    Form1->RichEdit3->SelStart=LineNumber*82+64+CharPos;        // устанавливаем курсор
                    Form1->RichEdit3->SelLength=1;      // выделяем 1 символ
                    Form1->RichEdit3->SelText=Symbol;   // пишем туда полученный символ
                  }
                }
                else if(PositionLocal<64)               // если мы между правой и левой областями
                { PositionLocal=80;                     // если позиция <36, то переходим в начало предыдущей строки
                  LineNumber-=1;
                  if(LineNumber<0)                      // если номер строки <0
                        LineNumber=MaxLineNumber;       // переходим на последнюю строку
                }
                else                                    // если мы в области справа
                { // меняем область справа
                  Form1->RichEdit3->SelStart=LineNumber*82+PositionLocal;       // устанавливаем курсор
                  Form1->RichEdit3->SelLength=1;        // выделяем 1 символ
                  Symbol=0xFF;                          // будем писать символ я
                  Form1->RichEdit3->SelText=Symbol;     // пишем
                  // получаем символ, который будем менять
                  CharPos=PositionLocal-64;             // номер байта в строке, который нужно поменять
                  // меняем область слева
                  Form1->RichEdit3->SelStart=LineNumber*82+10+3*CharPos;         // устанавливаем курсор
                  Form1->RichEdit3->SelLength=2;        // выделяем 2 символа
                  Form1->RichEdit3->SelText="FF";       // пишем
                }
                // устанавливаем курсор в нужную позицию
                Form1->RichEdit3->SelStart=LineNumber*82+PositionLocal;         // ставим курсор в нужную позицию
                Form1->RichEdit3->SelLength=0;                                  // отменяем выделение
                break;
    // обработчик стрелок *************************************
     case 0x25:
     case 0x26:
     case 0x27:
     case 0x28: return;
     // обработчик delete **************************************
     case 0x2E: // если мы в области слева - заменяем на F
                if((PositionLocal>9) && (PositionLocal<57))
                {       Key=0x46;                    // заменяем символ слева на F
                }
                // если мы в области справа - заменяем на я
                if(PositionLocal>63)
                {       Key=0xFF;                    // заменяем символ справа на F
                }

     // обработчик всех остальных кнопок ***********************
     default:   if(PositionLocal>79)            // если позиция > 43
                { PositionLocal=63;             // то переходим в начало строки
                  LineNumber+=1;                // увеличиваем номер строки
                  if(LineNumber>MaxLineNumber)
                        LineNumber=0;           // если номер > максимального - переходим на первую строку
                }
                else if(PositionLocal>63)       // если позиция > 35
                { // меняем область справа
                  Form1->RichEdit3->SelStart=LineNumber*82+PositionLocal;       // ставим курсор в нужную позицию
                  Form1->RichEdit3->SelLength=1;                                // выделяем 1 символ
                  if(Key<0x1F)  Key=0x1F;                                       // если символ непечатный (спецсимвол) - заменяем
                  Symbol=Key;
                  Form1->RichEdit3->SelText=Symbol;                             // пишем туда введённый символ
                  Form1->RichEdit3->SelStart=LineNumber*82+PositionLocal;       // ставим курсор в нужную позицию
                  Form1->RichEdit3->SelLength=1;                                // выделяем 1 символ
                  Form1->RichEdit3->SelText=UpperCase(Form1->RichEdit3->SelText); // переводим введённый символ в верхний регистр
                  // получаем символ, который будем менять
                  CharPos=PositionLocal-64;             // номер байта в строке, который нужно поменять
                  TempBuf[0]=Key;
                  BinToHex(TempBuf,OutHexBuf,1);        //преобразовать строку в целое (байт)
                  OutHexBuf[2]=0;                       //строка должна заканчиваться нулём
                  // меняем область слева
                  Form1->RichEdit3->SelStart=LineNumber*82+10+3*CharPos;         // ставим курсор на начало байт
                  Form1->RichEdit3->SelLength=2;                                // выделяем 2 символа
                  Form1->RichEdit3->SelText=OutHexBuf;
                }
                else if(PositionLocal>56)       // если позиция >52,
                { PositionLocal=9;              // то переходим в начало строки
                  LineNumber+=1;                // увеличиваем номер строки
                  if(LineNumber>MaxLineNumber)
                        LineNumber=0;           // если номер > максимального - переходим на первую строку
                }
                else if(PositionLocal>9)        // если позиция > 5
                { if(strchr(Charset1,Key)&&((PositionLocal-10)%3!=2))            // если символ есть в наборе и позиция не перед пробелом
                  { // меняем область слева
                    Form1->RichEdit3->SelStart=LineNumber*82+PositionLocal;     // ставим курсор в нужную позицию
                    Form1->RichEdit3->SelLength=1;                              // выделяем 1 символ
                    Symbol=Key;
                    Form1->RichEdit3->SelText=Symbol;                           // пишем туда введённый символ
                    Form1->RichEdit3->SelStart=LineNumber*82+PositionLocal;     // ставим курсор в нужную позицию
                    Form1->RichEdit3->SelLength=1;                              // выделяем 1 символ
                    Form1->RichEdit3->SelText=UpperCase(Form1->RichEdit3->SelText);     // переводим введённый символ в верхний регистр
                    // получаем символ, который будем писать в область справа
                    CharPos=(PositionLocal-10)/3;        // номер байта в строке, который нужно поменять
                    Form1->RichEdit3->SelStart=82*LineNumber+10+3*CharPos;       // ставим курсор на начало байта (в области слева)
                    Form1->RichEdit3->SelLength=2;                              // выделяем 2 символа
                    SubStr=LowerCase(Form1->RichEdit3->SelText);                // получаем их в строку
                    InHexBuf=SubStr.c_str();            //скопировать в буфер байт для передачи (в виде строки)
                    HexToBin(InHexBuf,TempBuf,1);       //преобразовать строку в целое (байт)
                    Key=TempBuf[0];
                    if(Key<0x1F) Symbol=0x1F;           //заменяем непечатные
                    else         Symbol=TempBuf[0];
                    // меняем область справа
                    Form1->RichEdit3->SelStart=LineNumber*82+64+CharPos;        // устанавливаем курсор
                    Form1->RichEdit3->SelLength=1;      // выделяем 1 символ
                    Form1->RichEdit3->SelText=Symbol;   // пишем туда полученный символ
                  }
                }
                else    PositionLocal=9;        // переходим в начало строки
                // устанавливаем курсор в нужную позицию
                PositionLocal+=1;                                       // увеличиваем позицию курсора
                Form1->RichEdit3->SelStart=LineNumber*82+PositionLocal; // ставим курсор в нужную позицию
                Form1->RichEdit3->SelLength=0;                          // отменяем выделение
  }
  Key=0;
}
//---------------------------------------------------------------------------
//--- РЕДАКТИРОВАНИЕ ПОЛЯ RICHEDIT4 (Area 2) --------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::RichEdit4KeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{ char *Charset1="0123456789abcdefABCDEF";              // допустимые символы
  char Symbol;                                          // символ для замены
  int  PositionGlobal, LineNumber, PositionLocal;       // глобальная позиция, номер строки, позиция в строке
  int  MaxLineNumber, CharPos;                          // максимальный номер строки, позиция символа на другой стороне
  char *InHexBuf, TempBuf[1], OutHexBuf[3];             // для преобразования
  AnsiString SubStr;                                    // для преобразования

  PositionGlobal=Form1->RichEdit4->SelStart;            // глобальная позиция курсора в тексте
  LineNumber=PositionGlobal/82;                         // номер строки, в которой находится курсор  80 символов + CR+LF
  PositionLocal=PositionGlobal-82*LineNumber;           // позиция курсора в строке
  MaxLineNumber=(FormData.RE4Size-1)/16;                // максимальный номер строки
  switch(Key)
  { // обработчик backspace ***********************************
    case 8:     PositionLocal-=1;                       // уменьшаем позицию в строке
                if(PositionLocal<10)
                { PositionLocal=57;                     // если позиция <6, то переходим в начало предыдущей строки
                  LineNumber-=1;
                  if(LineNumber<0)                      // если номер строки <0
                        LineNumber=MaxLineNumber;       // переходим на последнюю строку
                }
                else if(PositionLocal<57)               // если новая позиция в области hex
                { if ((PositionLocal-10)%3!=2)           // если новая позиция не перед пробелом
                  { // меняем область слева
                    Form1->RichEdit4->SelStart=LineNumber*82+PositionLocal;     // устанавливаем курсор
                    Form1->RichEdit4->SelLength=1;      // выделяем 1 символ
                    Symbol=0x46;                        // будем писать символ F
                    Form1->RichEdit4->SelText=Symbol;   // пишем
                    // получаем символ, который будем писать в область справа
                    CharPos=(PositionLocal-10)/3;        // номер байта в строке, который нужно поменять
                    Form1->RichEdit4->SelStart=82*LineNumber+10+3*CharPos;       // ставим курсор на начало байта (в области слева)
                    Form1->RichEdit4->SelLength=2;                              // выделяем 2 символа
                    SubStr=LowerCase(Form1->RichEdit4->SelText);                // получаем их в строку
                    InHexBuf=SubStr.c_str();            //скопировать в буфер байт для передачи (в виде строки)
                    HexToBin(InHexBuf,TempBuf,1);       //преобразовать строку в целое (байт)
                    Key=TempBuf[0];
                    if(Key<0x1F) Symbol=0x1F;           //заменяем непечатные (TempBuf[0] сравнивать нельзя так как он знаковый)
                    else         Symbol=TempBuf[0];
                    // меняем область справа
                    Form1->RichEdit4->SelStart=LineNumber*82+64+CharPos;        // устанавливаем курсор
                    Form1->RichEdit4->SelLength=1;      // выделяем 1 символ
                    Form1->RichEdit4->SelText=Symbol;   // пишем туда полученный символ
                  }
                }
                else if(PositionLocal<64)               // если мы между правой и левой областями
                { PositionLocal=80;                     // если позиция <36, то переходим в начало предыдущей строки
                  LineNumber-=1;
                  if(LineNumber<0)                      // если номер строки <0
                        LineNumber=MaxLineNumber;       // переходим на последнюю строку
                }
                else                                    // если мы в области справа
                { // меняем область справа
                  Form1->RichEdit4->SelStart=LineNumber*82+PositionLocal;       // устанавливаем курсор
                  Form1->RichEdit4->SelLength=1;        // выделяем 1 символ
                  Symbol=0xFF;                          // будем писать символ я
                  Form1->RichEdit4->SelText=Symbol;     // пишем
                  // получаем символ, который будем менять
                  CharPos=PositionLocal-64;             // номер байта в строке, который нужно поменять
                  // меняем область слева
                  Form1->RichEdit4->SelStart=LineNumber*82+10+3*CharPos;         // устанавливаем курсор
                  Form1->RichEdit4->SelLength=2;        // выделяем 2 символа
                  Form1->RichEdit4->SelText="FF";       // пишем
                }
                // устанавливаем курсор в нужную позицию
                Form1->RichEdit4->SelStart=LineNumber*82+PositionLocal;         // ставим курсор в нужную позицию
                Form1->RichEdit4->SelLength=0;                                  // отменяем выделение
                break;
    // обработчик стрелок *************************************
     case 0x25:
     case 0x26:
     case 0x27:
     case 0x28: return;
     // обработчик delete **************************************
     case 0x2E: // если мы в области слева - заменяем на F
                if((PositionLocal>9) && (PositionLocal<57))
                {       Key=0x46;                    // заменяем символ слева на F
                }
                // если мы в области справа - заменяем на я
                if(PositionLocal>63)
                {       Key=0xFF;                    // заменяем символ справа на F
                }

     // обработчик всех остальных кнопок ***********************
     default:   if(PositionLocal>79)            // если позиция > 43
                { PositionLocal=63;             // то переходим в начало строки
                  LineNumber+=1;                // увеличиваем номер строки
                  if(LineNumber>MaxLineNumber)
                        LineNumber=0;           // если номер > максимального - переходим на первую строку
                }
                else if(PositionLocal>63)       // если позиция > 35
                { // меняем область справа
                  Form1->RichEdit4->SelStart=LineNumber*82+PositionLocal;       // ставим курсор в нужную позицию
                  Form1->RichEdit4->SelLength=1;                                // выделяем 1 символ
                  if(Key<0x1F)  Key=0x1F;                                       // если символ непечатный (спецсимвол) - заменяем
                  Symbol=Key;
                  Form1->RichEdit4->SelText=Symbol;                             // пишем туда введённый символ
                  Form1->RichEdit4->SelStart=LineNumber*82+PositionLocal;       // ставим курсор в нужную позицию
                  Form1->RichEdit4->SelLength=1;                                // выделяем 1 символ
                  Form1->RichEdit4->SelText=UpperCase(Form1->RichEdit4->SelText); // переводим введённый символ в верхний регистр
                  // получаем символ, который будем менять
                  CharPos=PositionLocal-64;             // номер байта в строке, который нужно поменять
                  TempBuf[0]=Key;
                  BinToHex(TempBuf,OutHexBuf,1);        //преобразовать строку в целое (байт)
                  OutHexBuf[2]=0;                       //строка должна заканчиваться нулём
                  // меняем область слева
                  Form1->RichEdit4->SelStart=LineNumber*82+10+3*CharPos;         // ставим курсор на начало байт
                  Form1->RichEdit4->SelLength=2;                                // выделяем 2 символа
                  Form1->RichEdit4->SelText=OutHexBuf;
                }
                else if(PositionLocal>56)       // если позиция >52,
                { PositionLocal=9;              // то переходим в начало строки
                  LineNumber+=1;                // увеличиваем номер строки
                  if(LineNumber>MaxLineNumber)
                        LineNumber=0;           // если номер > максимального - переходим на первую строку
                }
                else if(PositionLocal>9)        // если позиция > 5
                { if(strchr(Charset1,Key)&&((PositionLocal-10)%3!=2))            // если символ есть в наборе и позиция не перед пробелом
                  { // меняем область слева
                    Form1->RichEdit4->SelStart=LineNumber*82+PositionLocal;     // ставим курсор в нужную позицию
                    Form1->RichEdit4->SelLength=1;                              // выделяем 1 символ
                    Symbol=Key;
                    Form1->RichEdit4->SelText=Symbol;                           // пишем туда введённый символ
                    Form1->RichEdit4->SelStart=LineNumber*82+PositionLocal;     // ставим курсор в нужную позицию
                    Form1->RichEdit4->SelLength=1;                              // выделяем 1 символ
                    Form1->RichEdit4->SelText=UpperCase(Form1->RichEdit4->SelText);     // переводим введённый символ в верхний регистр
                    // получаем символ, который будем писать в область справа
                    CharPos=(PositionLocal-10)/3;        // номер байта в строке, который нужно поменять
                    Form1->RichEdit4->SelStart=82*LineNumber+10+3*CharPos;       // ставим курсор на начало байта (в области слева)
                    Form1->RichEdit4->SelLength=2;                              // выделяем 2 символа
                    SubStr=LowerCase(Form1->RichEdit4->SelText);                // получаем их в строку
                    InHexBuf=SubStr.c_str();            //скопировать в буфер байт для передачи (в виде строки)
                    HexToBin(InHexBuf,TempBuf,1);       //преобразовать строку в целое (байт)
                    Key=TempBuf[0];
                    if(Key<0x1F) Symbol=0x1F;           //заменяем непечатные
                    else         Symbol=TempBuf[0];
                    // меняем область справа
                    Form1->RichEdit4->SelStart=LineNumber*82+64+CharPos;        // устанавливаем курсор
                    Form1->RichEdit4->SelLength=1;      // выделяем 1 символ
                    Form1->RichEdit4->SelText=Symbol;   // пишем туда полученный символ
                  }
                }
                else    PositionLocal=9;        // переходим в начало строки
                // устанавливаем курсор в нужную позицию
                PositionLocal+=1;                                       // увеличиваем позицию курсора
                Form1->RichEdit4->SelStart=LineNumber*82+PositionLocal; // ставим курсор в нужную позицию
                Form1->RichEdit4->SelLength=0;                          // отменяем выделение
  }
  Key=0;
}
//---------------------------------------------------------------------------
//--- РЕДАКТИРОВАНИЕ ПОЛЯ RICHEDIT6 (Area 3) --------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::RichEdit6KeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{ char *Charset1="0123456789abcdefABCDEF";              // допустимые символы
  char Symbol;                                          // символ для замены
  int  PositionGlobal, LineNumber, PositionLocal;       // глобальная позиция, номер строки, позиция в строке
  int  MaxLineNumber, WordPos, CharPos;                 // максимальный номер строки, позиции слова и символа на другой стороне
  char *InHexBuf, TempBuf[1], OutHexBuf[3];             // для преобразования
  AnsiString SubStr;                                    // для преобразования

  PositionGlobal=Form1->RichEdit6->SelStart;            // глобальная позиция курсора в тексте
  LineNumber=PositionGlobal/74;                         // номер строки, в которой находится курсор  72 символа + CR+LF
  PositionLocal=PositionGlobal-74*LineNumber;           // позиция курсора в строке
  MaxLineNumber=(FormData.RE6Size-1)/16;                // максимальный номер строки
  switch(Key)
  { // обработчик backspace ***********************************
    case 8:     PositionLocal-=1;                       // уменьшаем позицию в строке
                if(PositionLocal<10)
                { PositionLocal=49;                     // если позиция <10, то переходим в начало предыдущей строки
                  LineNumber-=1;
                  if(LineNumber<0)                      // если номер строки <0
                        LineNumber=MaxLineNumber;       // переходим на последнюю строку
                }
                else if(PositionLocal<49)               // если новая позиция в области hex
                { if ((PositionLocal-10)%5!=4)          // если новая позиция не перед пробелом
                  { // меняем область слева
                    Form1->RichEdit6->SelStart=LineNumber*74+PositionLocal;     // устанавливаем курсор
                    Form1->RichEdit6->SelLength=1;      // выделяем 1 символ
                    if((PositionLocal-10)%5==0) Symbol=0x33;                    // будем писать символ 3
                    else                        Symbol=0x46;                    // будем писать символ F
                    Form1->RichEdit6->SelText=Symbol;   // пишем
                    // получаем символ, который будем писать в область справа
                    WordPos=(PositionLocal-10)/5;        // номер слова в строке, в котором нужно поменять байт
                    if((PositionLocal-10)%5<2)  CharPos=1;      // номер байта в слове (старший байт)
                    else                        CharPos=0;      // номер байта в слове (младший байт)
                    Form1->RichEdit6->SelStart=74*LineNumber+10+5*WordPos+2*(1-CharPos);// ставим курсор на начало байта (в области слева)
                    Form1->RichEdit6->SelLength=2;                                      // выделяем 2 символа
                    SubStr=LowerCase(Form1->RichEdit6->SelText);                        // получаем их в строку
                    InHexBuf=SubStr.c_str();            //скопировать в буфер байт для передачи (в виде строки)
                    HexToBin(InHexBuf,TempBuf,1);       //преобразовать строку в целое (байт)
                    Key=TempBuf[0];
                    if(Key<0x1F) Symbol=0x1F;           //заменяем непечатные (TempBuf[0] сравнивать нельзя так как он знаковый)
                    else         Symbol=TempBuf[0];
                    // меняем область справа
                    Form1->RichEdit6->SelStart=LineNumber*74+56+2*WordPos+CharPos;      // устанавливаем курсор
                    Form1->RichEdit6->SelLength=1;      // выделяем 1 символ
                    Form1->RichEdit6->SelText=Symbol;   // пишем туда полученный символ
                  }
                }
                else if(PositionLocal<56)               // если мы между правой и левой областями
                { PositionLocal=72;                     // если позиция <36, то переходим в начало предыдущей строки
                  LineNumber-=1;
                  if(LineNumber<0)                      // если номер строки <0
                        LineNumber=MaxLineNumber;       // переходим на последнюю строку
                }
                else                                    // если мы в области справа
                { // меняем область справа
                  Form1->RichEdit6->SelStart=LineNumber*74+PositionLocal;       // устанавливаем курсор
                  Form1->RichEdit6->SelLength=1;        // выделяем 1 символ
                  if((PositionLocal-56)%2==0)   Symbol=0xFF;                    // будем писать символ я (младший байт)
                  else                          Symbol=0x3F;                    // будем писать символ ? (старший байт)
                  Form1->RichEdit6->SelText=Symbol;     // пишем
                  // получаем символ, который будем менять
                  WordPos=(PositionLocal-56)/2;         // номер слова в строке, в котором нужно поменять байт
                  CharPos=(PositionLocal-56)%2;         // номер байта в слове
                  // меняем область слева
                  Form1->RichEdit6->SelStart=LineNumber*74+10+5*WordPos+2*(1-CharPos);  // устанавливаем курсор
                  Form1->RichEdit6->SelLength=2;        // выделяем 2 символа
                  if(CharPos==0)        Form1->RichEdit6->SelText="FF";       // пишем FF
                  else                  Form1->RichEdit6->SelText="3F";       // пишем 3F
                }
                // устанавливаем курсор в нужную позицию
                Form1->RichEdit6->SelStart=LineNumber*74+PositionLocal;         // ставим курсор в нужную позицию
                Form1->RichEdit6->SelLength=0;                                  // отменяем выделение
                break;
    // обработчик стрелок *************************************
     case 0x25:
     case 0x26:
     case 0x27:
     case 0x28: return;
     // обработчик delete **************************************
     case 0x2E: // если мы в области слева - заменяем на F или 3
                if((PositionLocal>9) && (PositionLocal<49))
                {       if((PositionLocal-10)%5 == 0)   Key=0x33;               // заменяем символ слева на 3
                        else                            Key=0x46;               // заменяем символ слева на F
                }
                // если мы в области справа - заменяем на я или ?
                if(PositionLocal>55)
                {       if((PositionLocal-56)%2 == 0)   Key=0xFF;               // заменяем символ справа на F
                        else                            Key=0x3F;               // заменяем символ справа на ?
                }
     // обработчик всех остальных кнопок ***********************
     default:   if(PositionLocal>71)            // если позиция > 71
                { PositionLocal=55;             // то переходим в начало строки
                  LineNumber+=1;                // увеличиваем номер строки
                  if(LineNumber>MaxLineNumber)
                        LineNumber=0;           // если номер > максимального - переходим на первую строку
                }
                else if(PositionLocal>55)       // если позиция > 55
                { // меняем область справа
                  Form1->RichEdit6->SelStart=LineNumber*74+PositionLocal;       // ставим курсор в нужную позицию
                  Form1->RichEdit6->SelLength=1;                                // выделяем 1 символ
                  if(Key<0x1F)  Key=0x1F;                                       // если символ непечатный (спецсимвол) - заменяем
                  if(((PositionLocal-56)%2!=0) && (Key>0x3F))   Key=0x3F;       // в старшем байте может быть записано максимум 0x3F
                  Symbol=Key;
                  Form1->RichEdit6->SelText=Symbol;                             // пишем туда введённый символ
                  Form1->RichEdit6->SelStart=LineNumber*74+PositionLocal;       // ставим курсор в нужную позицию
                  Form1->RichEdit6->SelLength=1;                                // выделяем 1 символ
                  Form1->RichEdit6->SelText=UpperCase(Form1->RichEdit6->SelText); // переводим введённый символ в верхний регистр
                  // получаем символ, который будем менять
                  WordPos=(PositionLocal-56)/2;         // номер слова в строке, в котором нужно поменять байт
                  CharPos=(PositionLocal-56)%2;         // номер байта в слове (0 - младший, 1 - старший)
                  TempBuf[0]=Key;
                  BinToHex(TempBuf,OutHexBuf,1);        //преобразовать строку в целое (байт)
                  OutHexBuf[2]=0;                       //строка должна заканчиваться нулём
                  // меняем область слева
                  Form1->RichEdit6->SelStart=LineNumber*74+10+5*WordPos+2*(1-CharPos);  // ставим курсор на начало байт
                  Form1->RichEdit6->SelLength=2;                                        // выделяем 2 символа
                  Form1->RichEdit2->SelText=OutHexBuf;
                }
                else if(PositionLocal>48)       // если позиция >48,
                { PositionLocal=9;              // то переходим в начало строки
                  LineNumber+=1;                // увеличиваем номер строки
                  if(LineNumber>MaxLineNumber)
                        LineNumber=0;           // если номер > максимального - переходим на первую строку
                }
                else if(PositionLocal>9)        // если позиция > 9
                { if(strchr(Charset1,Key)&&((PositionLocal-10)%5!=4))            // если символ есть в наборе и позиция не перед пробелом
                  { // меняем область слева
                    Form1->RichEdit6->SelStart=LineNumber*74+PositionLocal;     // ставим курсор в нужную позицию
                    Form1->RichEdit6->SelLength=1;                              // выделяем 1 символ
                    if(((PositionLocal-10)%5==0) && (Key > 0x33)) Key = 0x33;   // старший байт должен быть не более 0x3F
                    Symbol=Key;
                    Form1->RichEdit6->SelText=Symbol;                           // пишем туда введённый символ
                    Form1->RichEdit6->SelStart=LineNumber*74+PositionLocal;     // ставим курсор в нужную позицию
                    Form1->RichEdit6->SelLength=1;                              // выделяем 1 символ
                    Form1->RichEdit6->SelText=UpperCase(Form1->RichEdit6->SelText);     // переводим введённый символ в верхний регистр
                    // получаем символ, который будем писать в область справа
                    WordPos=(PositionLocal-10)/5;        // номер слова в строке, в котором нужно поменять байт
                    if((PositionLocal-10)%5<2)  CharPos=1;      // номер байта в слове (старший байт)
                    else                        CharPos=0;      // номер байта в слове (младший байт)
                    Form1->RichEdit6->SelStart=74*LineNumber+10+5*WordPos+2*(1-CharPos); // ставим курсор на начало байта (в области слева)
                    Form1->RichEdit6->SelLength=2;                              // выделяем 2 символа
                    SubStr=LowerCase(Form1->RichEdit6->SelText);                // получаем их в строку
                    InHexBuf=SubStr.c_str();            //скопировать в буфер байт для передачи (в виде строки)
                    HexToBin(InHexBuf,TempBuf,1);       //преобразовать строку в целое (байт)
                    Key=TempBuf[0];
                    if(Key<0x1F) Symbol=0x1F;           //заменяем непечатные
                    else         Symbol=TempBuf[0];
                    // меняем область справа
                    Form1->RichEdit6->SelStart=LineNumber*74+56+2*WordPos+CharPos;        // устанавливаем курсор
                    Form1->RichEdit6->SelLength=1;      // выделяем 1 символ
                    Form1->RichEdit6->SelText=Symbol;   // пишем туда полученный символ
                  }
                }
                else    PositionLocal=9;        // переходим в начало строки
                // устанавливаем курсор в нужную позицию
                PositionLocal+=1;                                       // увеличиваем позицию курсора
                Form1->RichEdit6->SelStart=LineNumber*74+PositionLocal; // ставим курсор в нужную позицию
                Form1->RichEdit6->SelLength=0;                          // отменяем выделение
  }
  Key=0;
}
//---------------------------------------------------------------------------
//--- РЕДАКТИРОВАНИЕ ПОЛЯ RICHEDIT7 (Area 3) --------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::RichEdit7KeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{ char *Charset1="0123456789abcdefABCDEF";              // допустимые символы
  char Symbol;                                          // символ для замены
  int  PositionGlobal, LineNumber, PositionLocal;       // глобальная позиция, номер строки, позиция в строке
  int  MaxLineNumber, WordPos, CharPos;                 // максимальный номер строки, позиции слова и символа на другой стороне
  char *InHexBuf, TempBuf[1], OutHexBuf[3];             // для преобразования
  AnsiString SubStr;                                    // для преобразования

  PositionGlobal=Form1->RichEdit7->SelStart;            // глобальная позиция курсора в тексте
  LineNumber=PositionGlobal/74;                         // номер строки, в которой находится курсор  72 символа + CR+LF
  PositionLocal=PositionGlobal-74*LineNumber;           // позиция курсора в строке
  MaxLineNumber=(FormData.RE7Size-1)/16;                // максимальный номер строки
  switch(Key)
  { // обработчик backspace ***********************************
    case 8:     PositionLocal-=1;                       // уменьшаем позицию в строке
                if(PositionLocal<10)
                { PositionLocal=49;                     // если позиция <10, то переходим в начало предыдущей строки
                  LineNumber-=1;
                  if(LineNumber<0)                      // если номер строки <0
                        LineNumber=MaxLineNumber;       // переходим на последнюю строку
                }
                else if(PositionLocal<49)               // если новая позиция в области hex
                { if ((PositionLocal-10)%5!=4)          // если новая позиция не перед пробелом
                  { // меняем область слева
                    Form1->RichEdit7->SelStart=LineNumber*74+PositionLocal;     // устанавливаем курсор
                    Form1->RichEdit7->SelLength=1;      // выделяем 1 символ
                    if((PositionLocal-10)%5==0) Symbol=0x33;                    // будем писать символ 3
                    else                        Symbol=0x46;                    // будем писать символ F
                    Form1->RichEdit7->SelText=Symbol;   // пишем
                    // получаем символ, который будем писать в область справа
                    WordPos=(PositionLocal-10)/5;        // номер слова в строке, в котором нужно поменять байт
                    if((PositionLocal-10)%5<2)  CharPos=1;      // номер байта в слове (старший байт)
                    else                        CharPos=0;      // номер байта в слове (младший байт)
                    Form1->RichEdit7->SelStart=74*LineNumber+10+5*WordPos+2*(1-CharPos);// ставим курсор на начало байта (в области слева)
                    Form1->RichEdit7->SelLength=2;                                      // выделяем 2 символа
                    SubStr=LowerCase(Form1->RichEdit7->SelText);                        // получаем их в строку
                    InHexBuf=SubStr.c_str();            //скопировать в буфер байт для передачи (в виде строки)
                    HexToBin(InHexBuf,TempBuf,1);       //преобразовать строку в целое (байт)
                    Key=TempBuf[0];
                    if(Key<0x1F) Symbol=0x1F;           //заменяем непечатные (TempBuf[0] сравнивать нельзя так как он знаковый)
                    else         Symbol=TempBuf[0];
                    // меняем область справа
                    Form1->RichEdit7->SelStart=LineNumber*74+56+2*WordPos+CharPos;      // устанавливаем курсор
                    Form1->RichEdit7->SelLength=1;      // выделяем 1 символ
                    Form1->RichEdit7->SelText=Symbol;   // пишем туда полученный символ
                  }
                }
                else if(PositionLocal<56)               // если мы между правой и левой областями
                { PositionLocal=72;                     // если позиция <36, то переходим в начало предыдущей строки
                  LineNumber-=1;
                  if(LineNumber<0)                      // если номер строки <0
                        LineNumber=MaxLineNumber;       // переходим на последнюю строку
                }
                else                                    // если мы в области справа
                { // меняем область справа
                  Form1->RichEdit7->SelStart=LineNumber*74+PositionLocal;       // устанавливаем курсор
                  Form1->RichEdit7->SelLength=1;        // выделяем 1 символ
                  if((PositionLocal-56)%2==0)   Symbol=0xFF;                    // будем писать символ я (младший байт)
                  else                          Symbol=0x3F;                    // будем писать символ ? (старший байт)
                  Form1->RichEdit7->SelText=Symbol;     // пишем
                  // получаем символ, который будем менять
                  WordPos=(PositionLocal-56)/2;         // номер слова в строке, в котором нужно поменять байт
                  CharPos=(PositionLocal-56)%2;         // номер байта в слове
                  // меняем область слева
                  Form1->RichEdit7->SelStart=LineNumber*74+10+5*WordPos+2*(1-CharPos);  // устанавливаем курсор
                  Form1->RichEdit7->SelLength=2;        // выделяем 2 символа
                  if(CharPos==0)        Form1->RichEdit7->SelText="FF";       // пишем FF
                  else                  Form1->RichEdit7->SelText="3F";       // пишем 3F
                }
                // устанавливаем курсор в нужную позицию
                Form1->RichEdit7->SelStart=LineNumber*74+PositionLocal;         // ставим курсор в нужную позицию
                Form1->RichEdit7->SelLength=0;                                  // отменяем выделение
                break;
    // обработчик стрелок *************************************
     case 0x25:
     case 0x26:
     case 0x27:
     case 0x28: return;
     // обработчик delete **************************************
     case 0x2E: // если мы в области слева - заменяем на F или 3
                if((PositionLocal>9) && (PositionLocal<49))
                {       if((PositionLocal-10)%5 == 0)   Key=0x33;               // заменяем символ слева на 3
                        else                            Key=0x46;               // заменяем символ слева на F
                }
                // если мы в области справа - заменяем на я или ?
                if(PositionLocal>55)
                {       if((PositionLocal-56)%2 == 0)   Key=0xFF;               // заменяем символ справа на F
                        else                            Key=0x3F;               // заменяем символ справа на ?
                }
     // обработчик всех остальных кнопок ***********************
     default:   if(PositionLocal>71)            // если позиция > 71
                { PositionLocal=55;             // то переходим в начало строки
                  LineNumber+=1;                // увеличиваем номер строки
                  if(LineNumber>MaxLineNumber)
                        LineNumber=0;           // если номер > максимального - переходим на первую строку
                }
                else if(PositionLocal>55)       // если позиция > 55
                { // меняем область справа
                  Form1->RichEdit7->SelStart=LineNumber*74+PositionLocal;       // ставим курсор в нужную позицию
                  Form1->RichEdit7->SelLength=1;                                // выделяем 1 символ
                  if(Key<0x1F)  Key=0x1F;                                       // если символ непечатный (спецсимвол) - заменяем
                  if(((PositionLocal-56)%2!=0) && (Key>0x3F))   Key=0x3F;       // в старшем байте может быть записано максимум 0x3F
                  Symbol=Key;
                  Form1->RichEdit7->SelText=Symbol;                             // пишем туда введённый символ
                  Form1->RichEdit7->SelStart=LineNumber*74+PositionLocal;       // ставим курсор в нужную позицию
                  Form1->RichEdit7->SelLength=1;                                // выделяем 1 символ
                  Form1->RichEdit7->SelText=UpperCase(Form1->RichEdit7->SelText); // переводим введённый символ в верхний регистр
                  // получаем символ, который будем менять
                  WordPos=(PositionLocal-56)/2;         // номер слова в строке, в котором нужно поменять байт
                  CharPos=(PositionLocal-56)%2;         // номер байта в слове (0 - младший, 1 - старший)
                  TempBuf[0]=Key;
                  BinToHex(TempBuf,OutHexBuf,1);        //преобразовать строку в целое (байт)
                  OutHexBuf[2]=0;                       //строка должна заканчиваться нулём
                  // меняем область слева
                  Form1->RichEdit7->SelStart=LineNumber*74+10+5*WordPos+2*(1-CharPos);  // ставим курсор на начало байт
                  Form1->RichEdit7->SelLength=2;                                        // выделяем 2 символа
                  Form1->RichEdit7->SelText=OutHexBuf;
                }
                else if(PositionLocal>48)       // если позиция >48,
                { PositionLocal=9;              // то переходим в начало строки
                  LineNumber+=1;                // увеличиваем номер строки
                  if(LineNumber>MaxLineNumber)
                        LineNumber=0;           // если номер > максимального - переходим на первую строку
                }
                else if(PositionLocal>9)        // если позиция > 9
                { if(strchr(Charset1,Key)&&((PositionLocal-10)%5!=4))            // если символ есть в наборе и позиция не перед пробелом
                  { // меняем область слева
                    Form1->RichEdit7->SelStart=LineNumber*74+PositionLocal;     // ставим курсор в нужную позицию
                    Form1->RichEdit7->SelLength=1;                              // выделяем 1 символ
                    if(((PositionLocal-10)%5==0) && (Key > 0x33)) Key = 0x33;   // старший байт должен быть не более 0x3F
                    Symbol=Key;
                    Form1->RichEdit7->SelText=Symbol;                           // пишем туда введённый символ
                    Form1->RichEdit7->SelStart=LineNumber*74+PositionLocal;     // ставим курсор в нужную позицию
                    Form1->RichEdit7->SelLength=1;                              // выделяем 1 символ
                    Form1->RichEdit7->SelText=UpperCase(Form1->RichEdit7->SelText);     // переводим введённый символ в верхний регистр
                    // получаем символ, который будем писать в область справа
                    WordPos=(PositionLocal-10)/5;        // номер слова в строке, в котором нужно поменять байт
                    if((PositionLocal-10)%5<2)  CharPos=1;      // номер байта в слове (старший байт)
                    else                        CharPos=0;      // номер байта в слове (младший байт)
                    Form1->RichEdit7->SelStart=74*LineNumber+10+5*WordPos+2*(1-CharPos); // ставим курсор на начало байта (в области слева)
                    Form1->RichEdit7->SelLength=2;                              // выделяем 2 символа
                    SubStr=LowerCase(Form1->RichEdit7->SelText);                // получаем их в строку
                    InHexBuf=SubStr.c_str();            //скопировать в буфер байт для передачи (в виде строки)
                    HexToBin(InHexBuf,TempBuf,1);       //преобразовать строку в целое (байт)
                    Key=TempBuf[0];
                    if(Key<0x1F) Symbol=0x1F;           //заменяем непечатные
                    else         Symbol=TempBuf[0];
                    // меняем область справа
                    Form1->RichEdit7->SelStart=LineNumber*74+56+2*WordPos+CharPos;        // устанавливаем курсор
                    Form1->RichEdit7->SelLength=1;      // выделяем 1 символ
                    Form1->RichEdit7->SelText=Symbol;   // пишем туда полученный символ
                  }
                }
                else    PositionLocal=9;        // переходим в начало строки
                // устанавливаем курсор в нужную позицию
                PositionLocal+=1;                                       // увеличиваем позицию курсора
                Form1->RichEdit7->SelStart=LineNumber*74+PositionLocal; // ставим курсор в нужную позицию
                Form1->RichEdit7->SelLength=0;                          // отменяем выделение
  }
  Key=0;
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАНО ОТКРЫТИЕ ФАЙЛА С ПРОГРАММОЙ, КОНФИГОМ И ДАННЫМИ
//---------------------------------------------------------------------------
void __fastcall TForm1::LoadAllfromFile1Click(TObject *Sender)
{ AnsiString FilePath, Ext;
  int NameLength;

  if(OpenDialog1->Execute())
  { if(SelectedChip.ID!=0)                                      // если тип чипа определён или выбран чип с перезаписываемым ROM
    { FilePath=OpenDialog1->FileName;                           // получаем имя загружаемого файла
      NameLength=FilePath.Length();                             // длинну всего пути вместе с именем
      Ext=FilePath.SubString(NameLength-2,3);                   // расширение
      Ext=UpperCase(Ext);                                       // переводим в верхний регистр
      if(Ext=="BIN")      LoadFromBinFileToMemory(FilePath,0);  // загружаем программу, конфиг и данные из bin-файла
      else                LoadFromHexFileToMemory(FilePath,0);  // загружаем программу, конфиг и данные из hex- или eep-файла
    }
    else        SendMsgToLog(14,"");                            // чип не выбран
  }
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАНО ОТКРЫТИЕ ФАЙЛА С ПРОГРАММОЙ ----------------
//---------------------------------------------------------------------------
void __fastcall TForm1::LoadProgramfromFile1Click(TObject *Sender)
{ AnsiString FilePath, Ext;
  int NameLength;

  if(OpenDialog1->Execute())
  { if(SelectedChip.ID!=0)                                      // если тип чипа определён или выбран чип с перезаписываемым ROM
    { FilePath=OpenDialog1->FileName;                           // получаем имя загружаемого файла
      NameLength=FilePath.Length();                             // длинну всего пути вместе с именем
      Ext=FilePath.SubString(NameLength-2,3);                   // расширение
      Ext=UpperCase(Ext);                                       // переводим в верхний регистр
      if(Ext=="BIN")      LoadFromBinFileToMemory(FilePath,1);  // загружаем программу из bin-файла
      else                LoadFromHexFileToMemory(FilePath,1);  // загружаем программу из hex- или eep-файла
    }
    else        SendMsgToLog(14,"");                            // чип не выбран
  }
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАНО ОТКРЫТИЕ ФАЙЛА С ДАННЫМИ -------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::Open1Click(TObject *Sender)
{ AnsiString FilePath, Ext;
  int NameLength;

  if(OpenDialog1->Execute())
  { if(SelectedChip.ID!=0)                                      // если тип чипа определён или выбран чип с перезаписываемым ROM
    { FilePath=OpenDialog1->FileName;                           // получаем имя загружаемого файла
      NameLength=FilePath.Length();                             // длинну всего пути вместе с именем
      Ext=FilePath.SubString(NameLength-2,3);                   // расширение
      Ext=UpperCase(Ext);                                       // переводим в верхний регистр
      if(Ext=="BIN")      LoadFromBinFileToMemory(FilePath,2);  // загружаем данные из bin-файла
      else                LoadFromHexFileToMemory(FilePath,2);  // загружаем данные из hex- или eep-файла
    }
    else        SendMsgToLog(14,"");                            // чип не выбран
  }
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАНО ОТКРЫТИЕ ФАЙЛА С КОНФИГОМ ------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::LoadConfigfromFile1Click(TObject *Sender)
{ AnsiString FilePath, Ext;
  int NameLength;

  if(OpenDialog1->Execute())
  { if(SelectedChip.ID!=0)                                      // если тип чипа определён или выбран чип с перезаписываемым ROM
    { FilePath=OpenDialog1->FileName;                           // получаем имя загружаемого файла
      NameLength=FilePath.Length();                             // длинну всего пути вместе с именем
      Ext=FilePath.SubString(NameLength-2,3);                   // расширение
      Ext=UpperCase(Ext);                                       // переводим в верхний регистр
      if(Ext=="BIN")      LoadFromBinFileToMemory(FilePath,3);  // загружаем конфиг из bin-файла
      else                LoadFromHexFileToMemory(FilePath,3);  // загружаем конфиг из hex- или eep-файла
    }
    else        SendMsgToLog(14,"");                            // чип не выбран
  }
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАНО СОХРАНЕНИЕ ФАЙЛА С ПРОГРАММОЙ, КОНФИГОМ И ДАННЫМИ
//---------------------------------------------------------------------------
void __fastcall TForm1::SaveAlltoFile1Click(TObject *Sender)
{ AnsiString FilePath, Ext;                     // полный путь к файлу и расширение
  int FilePathLength;                           // длина полного пути
  bool SelBin, SelHex;                          // какой формат сохранения выбран

  SelBin=false; SelHex=false;                   // сначала формат не выбран
  if(SaveDialog1->Execute())                    // если определились куда сохранять (не нажали отмена)
  { FilePath=SaveDialog1->FileName;             // получаем имя файла для сохранения
    FilePathLength=FilePath.Length();           // вычисляем длину всего пути вместе с именем
    Ext=FilePath.SubString(FilePathLength-2,3); // выделяем расширение (последние 3 символа)
    Ext=UpperCase(Ext);                         // переводим расширение в верхний регистр
    // определяем расширение (куда будем сохранять)
    if(SaveDialog1->FilterIndex == 1)           // выбран формат HEX (он в списке SaveDialog первый)
    { if(Ext!="HEX")    FilePath = FilePath + ".hex";   // если расширение файла не hex - дописываем в конце .hex
      SelHex=true;
    }
    else if(SaveDialog1->FilterIndex == 2)           // выбран формат EEP (он в списке SaveDialog второй)
    { if(Ext!="EEP")    FilePath = FilePath + ".eep";   // если расширение файла не eep - дописываем в конце .eep
      SelHex=true;                              // данные в eep-файле хранятся в формате hex-файла
    }
    else                                        // выбран формат BIN (ну раз не HEX и не EEP, их в списке всего три)
    { if(Ext!="BIN")    FilePath = FilePath + ".bin";   // если расширение файла не bin - дописываем в конце .bin
      SelBin=true;
    }
  }
  //------------------------------------------
  // А теперь, собственно, пишем данные в файл
  //------------------------------------------
  if(SelBin)                                    // если нужно сохранять в bin
  { SaveFromMemoryToBinFile(FilePath,0);        // сохраняем программу, конфиг и данные из памяти в bin-файл
  }
  if(SelHex)                                    // если нужно сохранять в hex
  { SaveFromMemoryToHexFile(FilePath,0);        // сохраняем программу, конфиг и данные из памяти в hex-файл
  }
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАНО СОХРАНЕНИЕ ФАЙЛА С ПРОГРАММОЙ --------------
//---------------------------------------------------------------------------
void __fastcall TForm1::SaveProgramtoFile1Click(TObject *Sender)
{ AnsiString FilePath, Ext;                     // полный путь к файлу и расширение
  int FilePathLength;                           // длина полного пути
  bool SelBin, SelHex;                          // какой формат сохранения выбран

  SelBin=false; SelHex=false;                   // сначала формат не выбран
  if(SaveDialog1->Execute())                    // если определились куда сохранять (не нажали отмена)
  { FilePath=SaveDialog1->FileName;             // получаем имя файла для сохранения
    FilePathLength=FilePath.Length();           // вычисляем длину всего пути вместе с именем
    Ext=FilePath.SubString(FilePathLength-2,3); // выделяем расширение (последние 3 символа)
    Ext=UpperCase(Ext);                         // переводим расширение в верхний регистр
    // определяем расширение (куда будем сохранять)
    if(SaveDialog1->FilterIndex == 1)           // выбран формат HEX (он в списке SaveDialog первый)
    { if(Ext!="HEX")    FilePath = FilePath + ".hex";   // если расширение файла не hex - дописываем в конце .hex
      SelHex=true;
    }
    else if(SaveDialog1->FilterIndex == 2)           // выбран формат EEP (он в списке SaveDialog второй)
    { if(Ext!="EEP")    FilePath = FilePath + ".eep";   // если расширение файла не eep - дописываем в конце .eep
      SelHex=true;                              // данные в eep-файле хранятся в формате hex-файла
    }
    else                                        // выбран формат BIN (ну раз не HEX и не EEP, их в списке всего три)
    { if(Ext!="BIN")    FilePath = FilePath + ".bin";   // если расширение файла не bin - дописываем в конце .bin
      SelBin=true;
    }
  }
  //------------------------------------------
  // А теперь, собственно, пишем данные в файл
  //------------------------------------------
  if(SelBin)                                    // если нужно сохранять в bin
  { SaveFromMemoryToBinFile(FilePath,1);        // сохраняем программу из памяти в bin-файл
  }
  if(SelHex)                                    // если нужно сохранять в hex
  { SaveFromMemoryToHexFile(FilePath,1);        // сохраняем программу из памяти в hex-файл
  }
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАНО СОХРАНЕНИЕ ФАЙЛА С ДАННЫМИ -----------------
//---------------------------------------------------------------------------
void __fastcall TForm1::Save1Click(TObject *Sender)
{ AnsiString FilePath, Ext;                     // полный путь к файлу и расширение
  int FilePathLength;                           // длина полного пути
  bool SelBin, SelHex;                          // какой формат сохранения выбран

  SelBin=false; SelHex=false;                   // сначала формат не выбран
  if(SaveDialog1->Execute())                    // если определились куда сохранять (не нажали отмена)
  { FilePath=SaveDialog1->FileName;             // получаем имя файла для сохранения
    FilePathLength=FilePath.Length();           // вычисляем длину всего пути вместе с именем
    Ext=FilePath.SubString(FilePathLength-2,3); // выделяем расширение (последние 3 символа)
    Ext=UpperCase(Ext);                         // переводим расширение в верхний регистр
    // определяем расширение (куда будем сохранять)
    if(SaveDialog1->FilterIndex == 1)           // выбран формат HEX (он в списке SaveDialog первый)
    { if(Ext!="HEX")    FilePath = FilePath + ".hex";   // если расширение файла не hex - дописываем в конце .hex
      SelHex=true;
    }
    else if(SaveDialog1->FilterIndex == 2)           // выбран формат EEP (он в списке SaveDialog второй)
    { if(Ext!="EEP")    FilePath = FilePath + ".eep";   // если расширение файла не eep - дописываем в конце .eep
      SelHex=true;                              // в eep-файле данные лежат в формате hex-файла
    }
    else                                        // выбран формат BIN (ну раз не HEX и не EEP, их в списке всего три)
    { if(Ext!="BIN")    FilePath = FilePath + ".bin";   // если расширение файла не bin - дописываем в конце .bin
      SelBin=true;
    }
  }
  //------------------------------------------
  // А теперь, собственно, пишем данные в файл
  //------------------------------------------
  if(SelBin)                                    // если нужно сохранять в bin
  { SaveFromMemoryToBinFile(FilePath,2);        // сохраняем данные из памяти в bin-файл
  }
  if(SelHex)                                    // если нужно сохранять в hex
  { SaveFromMemoryToHexFile(FilePath,2);        // сохраняем данные из памяти в hex-файл
  }
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАНО СОХРАНЕНИЕ ФАЙЛА С КОНФИГОМ ----------------
//---------------------------------------------------------------------------
void __fastcall TForm1::SaveConfigtoFile1Click(TObject *Sender)
{ AnsiString FilePath, Ext;                     // полный путь к файлу и расширение
  int FilePathLength;                           // длина полного пути
  bool SelBin, SelHex;                          // какой формат сохранения выбран

  SelBin=false; SelHex=false;                   // сначала формат не выбран
  if(SaveDialog1->Execute())                    // если определились куда сохранять (не нажали отмена)
  { FilePath=SaveDialog1->FileName;             // получаем имя файла для сохранения
    FilePathLength=FilePath.Length();           // вычисляем длину всего пути вместе с именем
    Ext=FilePath.SubString(FilePathLength-2,3); // выделяем расширение (последние 3 символа)
    Ext=UpperCase(Ext);                         // переводим расширение в верхний регистр
    // определяем расширение (куда будем сохранять)
    if(SaveDialog1->FilterIndex == 1)           // выбран формат HEX (он в списке SaveDialog первый)
    { if(Ext!="HEX")    FilePath = FilePath + ".hex";   // если расширение файла не hex - дописываем в конце .hex
      SelHex=true;
    }
    else if(SaveDialog1->FilterIndex == 2)           // выбран формат EEP (он в списке SaveDialog второй)
    { if(Ext!="EEP")    FilePath = FilePath + ".eep";   // если расширение файла не eep - дописываем в конце .eep
      SelHex=true;                              // в eep-файле данные лежат в формате hex-файла
    }
    else                                        // выбран формат BIN (ну раз не HEX и не EEP, их в списке всего три)
    { if(Ext!="BIN")    FilePath = FilePath + ".bin";   // если расширение файла не bin - дописываем в конце .bin
      SelBin=true;
    }
  }
  //------------------------------------------
  // А теперь, собственно, пишем данные в файл
  //------------------------------------------
  if(SelBin)                                    // если нужно сохранять в bin
  { SaveFromMemoryToBinFile(FilePath,3);        // сохраняем данные из памяти в bin-файл
  }
  if(SelHex)                                    // если нужно сохранять в hex
  { SaveFromMemoryToHexFile(FilePath,3);        // сохраняем данные из памяти в hex-файл
  }
}
//---------------------------------------------------------------------------
//--- Изменили позицию трек-бара, определяющего величину задержек -----------
//---------------------------------------------------------------------------
void __fastcall TForm1::TrackBar1Change(TObject *Sender)
{ Delays = Form1->TrackBar1->Position;  // считываем установленную величину задержек
}
//---------------------------------------------------------------------------
//////////////////////////////
// ОБРАБОТКА НАЖАТИЙ КНОПОК //
//////////////////////////////
//---------------------------------------------------------------------------
//--- НАЖАТА КНОПКА АВТОПОИСК ЧИПА ------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{ unsigned int ChipID;  // сюда будем принимать ID чипа из байт сигнатуры
  WRITE_BUFFER wr_buf;  // буфер для отправки данных
  READ_BUFFER rd_buf;   // буфер для приёма данных

  if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
  {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
        return;                         // выходим
  }
  if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
  {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
        return;                         // выходим
  }

  ChipID = ReadSignatureBytes();        // пробуем узнать что у нас за чип,
  //--- выполняем процедуру выхода из режима программирования ---
  //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать оба напряжения одноременно, просто переводя выводы в начальные состояния 
  //--- (по идее это не нужно, но вдруг у кого-то окажется нестандартный алгоритм входа) ---
  if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
  {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выйти из режима программирования
        return;                         // выходим
  }
  //---
  InitChip(ChipID);                     // если мы знаем такой чип - заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- НАЖАТА КНОПКА CHIP ERASE ----------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::Button11Click(TObject *Sender)
{ if (Application->MessageBox("      All previous chip data will be lost (Program, Data, Configuration).\nYou must read and remember OSCCAL and BG-bits before this operation.\n\t        Press OK to continue or Cancel to cancel", "Warning", MB_OKCANCEL|MB_ICONWARNING|MB_DEFBUTTON2|MB_APPLMODAL) == IDOK)
  {     // сначала нужно поместить в память данные с формы, в зависимости от вкладки
        switch(Form1->PageControl1->TabIndex)
        {       case 0: GetDataToMemory(1,1);      // из RichEdit1 в Area1 - Program memory
                        GetDataToMemory(6,3);      // из RichEdit6 в Area3 - Config memory
                        break;
                case 1: GetDataToMemory(2,1);      // из RichEdit2 в Area1 - Program memory
                        GetDataToMemory(7,3);      // из RichEdit7 в Area3 - Config memory
                        break;
                default: break;
        }

        SendMsgToLog(18," erase program, configuration and data memories");      // сообщаем о попытке всё стереть
        // включаем прогресс-бар
        Application->CreateForm(__classid(TLBar),&LBar);      // создаём форму с прогресс-баром
        LBar->Show();                                         // показываем её в немодальном окне

        switch(SelectedChip.ID&0x3FE0)     // отрезаем 5 младших бит при выборе чипа (они определяют ревизию, а не модель)
        { // в чипах 1 калибровочное значение (CONF+9), есть память данных
          case 0x2080:  // выбрано устройство PIC16F887
          case 0x2060:  // выбрано устройство PIC16F886
          case 0x2040:  // выбрано устройство PIC16F884
          case 0x2020:  // выбрано устройство PIC16F883
          case 0x2000:  // выбрано устройство PIC16F882
                        if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений и битов BG в процессе записи
                        {       // 1. Читаем значения OSCCAL-words
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_SetPCToConfigMemory())  // пробуем перейти в область Config Memory
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_MakePCOffset(8,1))      // сдвигаем указатель на адрес перед нужным (в этом чипе 2 слова калибровки по адресам 0x8009 и 0x800A)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                // после этого можно уже и читать
                                if(!PIC16F630_ReadConfigMemory(9,0))  // пробуем прочитать последнее слово программы
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                                //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                SendMsgToLog(0,"    calibration words (CONF + 0x0009, CONF + 0x000A) has been read and stored");  // сообщаем о чтении калибровочных значений
                        }
                        // 2. Стираем память программы, конфигурации и данных
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory (для того, чтобы конфиг тоже стёрся)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // пробуем стереть память программы и конфигурации
                        if(!PIC16F630_BulkEraseProgramMemory()) // пробуем стереть память программы
                        {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // пробуем стереть память данных
                        if(!PIC16F630_BulkEraseDataMemory())    // пробуем стереть память данных
                        {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                              LBar->Free();                   // уничтожаем форму с прогресс-баром
                              return;                         // выходим
                        }
                        // для этого чипа можно калибровочные значения обратно не записывать, так как по даташиту они
                        // при bulk erase стираться не должны (но их можно случайно перезаписать)
                        SendMsgToLog(0,"    there is no need to restore the calibration values for this chip");  // сообщаем о восстановлении калибровочных значений
                        break;
          // в чипах нет калибровочных значений, есть память данных, перед стиранием нужно загрузить 0x3FFF
          case 0x1100:  // выбрано устройство PIC16F648A
          case 0x1060:  // выбрано устройство PIC16F628A
          case 0x1040:  // выбрано устройство PIC16F627A
                        // у этого чипа нет калибровки, поэтому ничего читать не нужно
                        // 1. Стираем память программы, конфигурации и данных
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory (для того, чтобы конфиг тоже стёрся)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // загружаем в Program Memory 0x3FFF
                        if(!PIC16F630_LoadDataToProgramMemory(0x3FFF)) // пробуем стереть память программы
                        {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // пробуем стереть память программы и конфигурации
                        if(!PIC16F630_BulkEraseProgramMemory()) // пробуем стереть память программы
                        {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // пробуем стереть память данных
                        if(!PIC16F630_BulkEraseDataMemory())    // пробуем стереть память данных
                        {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                        {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                              LBar->Free();                   // уничтожаем форму с прогресс-баром
                              return;                         // выходим
                        }
                        // для этого чипа нет калибровочных значений
                        SendMsgToLog(0,"    there are no calibration values in this chip");  // сообщаем о восстановлении калибровочных значений
                        break;
          // в чипах 2 калибровочных значения (CONF+9, CONF+10), есть память данных
          case 0x14A0:  // выбрано устройство PIC16LF1847
          case 0x1480:  // выбрано устройство PIC16F1847
          case 0x1BC0:  // выбрано устройство PIC12LF1840
          case 0x1B80:  // выбрано устройство PIC12F1840
          case 0x27E0:  // выбрано устройство PIC16F1829
          case 0x28C0:  // выбрано устройство PIC16LF1828
          case 0x27C0:  // выбрано устройство PIC16F1828
          case 0x28A0:  // выбрано устройство PIC16LF1827
          case 0x27A0:  // выбрано устройство PIC16F1827
          case 0x2880:  // выбрано устройство PIC16LF1826
          case 0x2780:  // выбрано устройство PIC16F1826
          case 0x2760:  // выбрано устройство PIC16F1825
          case 0x2840:  // выбрано устройство PIC16LF1824
          case 0x2740:  // выбрано устройство PIC16F1824
          case 0x2820:  // выбрано устройство PIC16LF1823
          case 0x2720:  // выбрано устройство PIC16F1823
          case 0x2800:  // выбрано устройство PIC12LF1822
          case 0x2700:  // выбрано устройство PIC12F1822
                        if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений и битов BG в процессе записи
                        {       // 1. Читаем значения OSCCAL-words
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_SetPCToConfigMemory())  // пробуем перейти в область Config Memory
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_MakePCOffset(8,1))      // сдвигаем указатель на адрес перед нужным (в этом чипе 2 слова калибровки по адресам 0x8009 и 0x800A)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                // после этого можно уже и читать
                                if(!PIC16F630_ReadConfigMemory(9,0))  // пробуем прочитать последнее слово программы
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_ReadConfigMemory(10,0)) // пробуем прочитать последнее слово программы
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                                //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                SendMsgToLog(0,"    calibration words (CONF + 0x0009, CONF + 0x000A) has been read and stored");  // сообщаем о чтении калибровочных значений
                        }
                        // 2. Стираем память программы, конфигурации и данных
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory (для того, чтобы конфиг тоже стёрся)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // пробуем стереть память программы и конфигурации
                        if(!PIC16F630_BulkEraseProgramMemory()) // пробуем стереть память программы
                        {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // пробуем стереть память данных
                        if(!PIC16F630_BulkEraseDataMemory())    // пробуем стереть память данных
                        {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                              LBar->Free();                   // уничтожаем форму с прогресс-баром
                              return;                         // выходим
                        }
                        // для этого чипа можно калибровочные значения обратно не записывать, так как по даташиту они
                        // при bulk erase стираться не должны (но их можно случайно перезаписать)
                        SendMsgToLog(0,"    there is no need to restore the calibration values for this chip");  // сообщаем о восстановлении калибровочных значений
                        break;
          // в чипах 2 калибровочных значения (CONF+9, CONF+10), нет памяти данных
          case 0x1900:  // выбрано устройство PIC16LF727
          case 0x1800:  // выбрано устройство PIC16F727
          case 0x1940:  // выбрано устройство PIC16LF724
          case 0x1840:  // выбрано устройство PIC16F724
          case 0x1920:  // выбрано устройство PIC16LF726
          case 0x1820:  // выбрано устройство PIC16F726
          case 0x1B40:  // выбрано устройство PIC16LF723A
          case 0x1B00:  // выбрано устройство PIC16F723A
          case 0x1960:  // выбрано устройство PIC16LF723
          case 0x1860:  // выбрано устройство PIC16F723
          case 0x1B60:  // выбрано устройство PIC16LF722A
          case 0x1B20:  // выбрано устройство PIC16F722A
          case 0x1980:  // выбрано устройство PIC16LF722
          case 0x1880:  // выбрано устройство PIC16F722
          case 0x1C60:  // выбрано устройство PIC16LF721
          case 0x1C20:  // выбрано устройство PIC16F721
          case 0x1C40:  // выбрано устройство PIC16LF720
          case 0x1C00:  // выбрано устройство PIC16F720
          case 0x1AE0:  // выбрано устройство PIC16LF707
          case 0x1AC0:  // выбрано устройство PIC16F707
          case 0x2E00:  // выбрано устройство PIC16LF1509
          case 0x2D40:  // выбрано устройство PIC16F1509
          case 0x2DE0:  // выбрано устройство PIC16LF1508
          case 0x2D20:  // выбрано устройство PIC16F1508
          case 0x2DC0:  // выбрано устройство PIC16LF1507
          case 0x2D00:  // выбрано устройство PIC16F1507
          case 0x2DA0:  // выбрано устройство PIC16LF1503
          case 0x2CE0:  // выбрано устройство PIC16F1503
          case 0x2D80:  // выбрано устройство PIC12LF1501
          case 0x2CC0:  // выбрано устройство PIC12F1501
                        if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений и битов BG в процессе записи
                        {       // 1. Читаем значения OSCCAL-words
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_SetPCToConfigMemory())  // пробуем перейти в область Config Memory
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_MakePCOffset(8,1))      // сдвигаем указатель на адрес перед нужным (в этом чипе 2 слова калибровки по адресам 0x8009 и 0x800A)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                // после этого можно уже и читать
                                if(!PIC16F630_ReadConfigMemory(9,0))  // пробуем прочитать последнее слово программы
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_ReadConfigMemory(10,0)) // пробуем прочитать последнее слово программы
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                                //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                SendMsgToLog(0,"    calibration words (CONF + 0x0009, CONF + 0x000A) has been read and stored");  // сообщаем о чтении калибровочных значений
                        }
                        // 2. Стираем память программы, конфигурации и данных
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory (для того, чтобы конфиг тоже стёрся)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // пробуем стереть память программы и конфигурации
                        if(!PIC16F630_BulkEraseProgramMemory()) // пробуем стереть память программы
                        {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // памяти данных у этого чипа нет, её стирать не нужно
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                              LBar->Free();                   // уничтожаем форму с прогресс-баром
                              return;                         // выходим
                        }
                        // для этого чипа можно калибровочные значения обратно не записывать, так как по даташиту они
                        // при bulk erase стираться не должны (но их можно случайно перезаписать)
                        SendMsgToLog(0,"    there is no need to restore the calibration values for this chip");  // сообщаем о восстановлении калибровочных значений
                        break;
          // в чипах 2 калибровочных значения (CONF+8, CONF+9), нет памяти данных, используются все биты ID (без ревизии)
          case 0x3020:  // возможно это PIC16F753
                        if(SelectedChip.ID == 0x3030)       // если это точно PIC16F753
                        {       if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений и битов BG в процессе записи
                                {       // 1. Читаем значения OSCCAL-words
                                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                                return;                         // выходим
                                        }
                                        if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                                return;                         // выходим
                                        }
                                        if(!PIC16F630_SetPCToConfigMemory())  // пробуем перейти в область Config Memory
                                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                                return;                         // выходим
                                        }
                                        if(!PIC16F630_MakePCOffset(7,1))      // сдвигаем указатель на адрес перед нужным (в этом чипе 2 слова калибровки по адресам 0x2008 и 0x2009)
                                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                                return;                         // выходим
                                        }
                                        // после этого можно уже и читать
                                        if(!PIC16F630_ReadConfigMemory(8,0))  // пробуем прочитать последнее слово программы
                                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                                return;                         // выходим
                                        }
                                        if(!PIC16F630_ReadConfigMemory(9,0))  // пробуем прочитать последнее слово программы
                                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                                return;                         // выходим
                                        }
                                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем
                                        //--- выключать оба напряжения одноременно, просто переводя выводы в начальные состояния 
                                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                                return;                         // выходим
                                        }
                                        SendMsgToLog(0,"    calibration words (0x2008, 0x2009) has been read and stored");  // сообщаем о чтении калибровочных значений
                                }
                                // 2. Стираем память программы, конфигурации. данных нет - стирать не нужно
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory (для того, чтобы конфиг тоже стёрся)
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                // пробуем стереть память программы и конфигурации
                                if(!PIC16F630_BulkEraseProgramMemory()) // пробуем стереть память программы
                                {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                // память данных стирать не нужно, так как её в этом чипе нет
                                //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                                //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                // для этого чипа можно калибровочные значения обратно не записывать, так как по даташиту они
                                // при bulk erase стираться не должны (но их можно случайно перезаписать)
                                SendMsgToLog(0,"    there is no need to restore the calibration values for this chip");  // сообщаем о восстановлении калибровочных значений
                        }
                        else
                        {       SendMsgToLog(15," unknown");    // сообщение в лог, что чип нам неизвестен и выходим
                        }
                        break;
          // в чипах 2 калибровочных значения (CONF+8, CONF+9), нет памяти данных
          case 0x1500:  // выбрано устройство PIC12F752
                        if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений и битов BG в процессе записи
                        {       // 1. Читаем значения OSCCAL-words
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_SetPCToConfigMemory())  // пробуем перейти в область Config Memory
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_MakePCOffset(7,1))      // сдвигаем указатель на адрес перед нужным (в этом чипе 2 слова калибровки по адресам 0x2008 и 0x2009)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                // после этого можно уже и читать
                                if(!PIC16F630_ReadConfigMemory(8,0))  // пробуем прочитать последнее слово программы
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_ReadConfigMemory(9,0))  // пробуем прочитать последнее слово программы
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                                //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                SendMsgToLog(0,"    calibration words (0x2008, 0x2009) has been read and stored");  // сообщаем о чтении калибровочных значений
                        }
                        // 2. Стираем память программы, конфигурации и данных
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory (для того, чтобы конфиг тоже стёрся)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // пробуем стереть память программы и конфигурации
                        if(!PIC16F630_BulkEraseProgramMemory()) // пробуем стереть память программы
                        {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // память данных стирать не нужно, так как её в этом чипе нет
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                              LBar->Free();                   // уничтожаем форму с прогресс-баром
                              return;                         // выходим
                        }
                        // для этого чипа можно калибровочные значения обратно не записывать, так как по даташиту они
                        // при bulk erase стираться не должны (но их можно случайно перезаписать)
                        SendMsgToLog(0,"    there is no need to restore the calibration values for this chip");  // сообщаем о восстановлении калибровочных значений
                        break;
          // в чипах 1 калибровочное значение (CONF+8), нет памяти данных
          case 0x1240:  // выбрано устройство PIC16F616
          case 0x2260:  // выбрано устройство PIC16F610
          case 0x2240:  // выбрано устройство PIC12F609
          case 0x1360:  // выбрано устройство PIC12F617
          case 0x2180:  // выбрано устройство PIC12F615
                        if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений и битов BG в процессе записи
                        {       // 1. Читаем значение OSCCAL-word
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_SetPCToConfigMemory())  // пробуем перейти в область Config Memory
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_MakePCOffset(7,1))      // сдвигаем указатель на адрес перед нужным (в этом чипе 2 слова калибровки по адресам 0x2008 и 0x2009)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                // после этого можно уже и читать
                                if(!PIC16F630_ReadConfigMemory(8,0))  // пробуем прочитать последнее слово программы
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                                //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                SendMsgToLog(0,"    calibration word (CONF + 0x0008) has been read and stored");  // сообщаем о чтении калибровочных значений
                        }
                        // 2. Стираем память программы, конфигурации и данных
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory (для того, чтобы конфиг тоже стёрся)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // пробуем стереть память программы и конфигурации
                        if(!PIC16F630_BulkEraseProgramMemory()) // пробуем стереть память программы
                        {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // память данных стирать не нужно, т.к. её в этом чипе нет
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                              LBar->Free();                   // уничтожаем форму с прогресс-баром
                              return;                         // выходим
                        }
                        // для этого чипа можно калибровочные значения обратно не записывать, так как по даташиту они
                        // при bulk erase стираться не должны (но их можно случайно перезаписать)
                        SendMsgToLog(0,"    there is no need to restore the calibration value for this chip");  // сообщаем о восстановлении калибровочных значений
                        break;
          // в чипах 1 калибровочное значение (CONF+8), есть память данных
          case 0x1400:  // выбрано устройство PIC16F690
          case 0x1340:  // выбрано устройство PIC16F689
          case 0x1180:  // выбрано устройство PIC16F688
          case 0x1320:  // выбрано устройство PIC16F687
          case 0x04A0:  // выбрано устройство PIC16F685
          case 0x1080:  // выбрано устройство PIC16F684
          case 0x1440:  // выбрано устройство PIC16F677
          case 0x1420:  // выбрано устройство PIC16F631
          case 0x0460:  // выбрано устройство PIC12F683
                        if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений и битов BG в процессе записи
                        {       // 1. Читаем значение OSCCAL-word
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_SetPCToConfigMemory())  // пробуем перейти в область Config Memory
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_MakePCOffset(7,1))      // сдвигаем указатель на адрес перед нужным (в этом чипе 2 слова калибровки по адресам 0x2008 и 0x2009)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                // после этого можно уже и читать
                                if(!PIC16F630_ReadConfigMemory(8,0))  // пробуем прочитать последнее слово программы
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                                //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                SendMsgToLog(0,"    calibration word (0x2008) has been read and stored");  // сообщаем о чтении калибровочных значений
                        }
                        // 2. Стираем память программы, конфигурации и данных
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory (для того, чтобы конфиг тоже стёрся)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // пробуем стереть память программы и конфигурации
                        if(!PIC16F630_BulkEraseProgramMemory()) // пробуем стереть память программы
                        {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // пробуем стереть память данных
                        if(!PIC16F630_BulkEraseDataMemory())    // пробуем стереть память данных
                        {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                              LBar->Free();                   // уничтожаем форму с прогресс-баром
                              return;                         // выходим
                        }
                        // для этого чипа можно калибровочные значения обратно не записывать, так как по даташиту они
                        // при bulk erase стираться не должны (но их можно случайно перезаписать)
                        SendMsgToLog(0,"    there is no need to restore the calibration value for this chip");  // сообщаем о восстановлении калибровочных значений
                        break;
          // в чипах 2 калибровочных значения (CONF+8, CONF+9), есть память данных
          case 0x1200:  // выбрано устройство PIC16F785
          case 0x10A0:  // выбрано устройство PIC16F636 / PIC16F639
          case 0x0FA0:  // выбрано устройство PIC12F635
                        if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений и битов BG в процессе записи
                        {       // 1. Читаем значения OSCCAL-words
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_SetPCToConfigMemory())  // пробуем перейти в область Config Memory
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_MakePCOffset(7,1))      // сдвигаем указатель на адрес перед нужным (в этом чипе 2 слова калибровки по адресам 0x2008 и 0x2009)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                // после этого можно уже и читать
                                if(!PIC16F630_ReadConfigMemory(8,0))  // пробуем прочитать последнее слово программы
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_ReadConfigMemory(9,0))  // пробуем прочитать последнее слово программы
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                                //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                SendMsgToLog(0,"    calibration words (CONF + 0x0008, CONF + 0x0009) has been read and stored");  // сообщаем о чтении калибровочных значений
                        }
                        // 2. Стираем память программы, конфигурации и данных
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory (для того, чтобы конфиг тоже стёрся)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // пробуем стереть память программы и конфигурации
                        if(!PIC16F630_BulkEraseProgramMemory()) // пробуем стереть память программы
                        {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // пробуем стереть память данных
                        if(!PIC16F630_BulkEraseDataMemory())    // пробуем стереть память данных
                        {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)м
                        {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                              LBar->Free();                   // уничтожаем форму с прогресс-баром
                              return;                         // выходим
                        }
                        // для этого чипа можно калибровочные значения обратно не записывать, так как по даташиту они
                        // при bulk erase стираться не должны (но их можно случайно перезаписать)
                        SendMsgToLog(0,"    there is no need to restore the calibration values for this chip");  // сообщаем о восстановлении калибровочных значений
                        break;
          // в чипах 1 калибровочное значение (последнее слово памяти программ), есть память данных
          // калибровочное значение и 2 бита конфига нужно восстановить после стирания чипа
          case 0x10C0:  // выбрано устройство PIC16F630
          case 0x10E0:  // выбрано устройство PIC16F676
          case 0x0F80:  // выбрано устройство PIC12F629
          case 0x0FC0:  // выбрано устройство PIC12F675
                        if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений и битов BG в процессе записи
                        {       // 1. Читаем значение OSCCAL-word
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_MakePCOffset(SelectedChip.Area1Size/2-2,1))   // сдвигаем указатель на адрес перед нужным (слово калибровки - последнее слово памяти)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                // после этого можно уже и читать
                                if(!PIC16F630_ReadProgramMemory(SelectedChip.Area1Size/2-1,0))    // пробуем прочитать последнее слово программы
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                // 2. Читаем значение BG-bits
                                if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_MakePCOffset(6,1))          // сдвигаем указатель на адрес перед нужным (7-1=6), сдвиг ещё на единицу произойдёт в функции чтения пред чтением
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                // после этого можно уже и читать
                                if(!PIC16F630_ReadConfigMemoryMask(7,0x3000)) // пробуем прочитать слово конфигурации по адресу 7 (0x2007) по маске 0x3000 (BG-bits)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                                //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                SendMsgToLog(0,"    OSCCAL word & BG-bits has been read and stored");  // сообщаем о восстановлении калибровочных значений
                        }
                        // 3. Стираем память программы, конфигурации и данных
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory (для того, чтобы конфиг тоже стёрся)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // пробуем стереть память программы и конфигурации
                        if(!PIC16F630_BulkEraseProgramMemory()) // пробуем стереть память программы
                        {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // пробуем стереть память данных
                        if(!PIC16F630_BulkEraseDataMemory())    // пробуем стереть память данных
                        {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                              LBar->Free();                   // уничтожаем форму с прогресс-баром
                              return;                         // выходим
                        }
                        if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений и битов BG в процессе записи
                        {       // 4. Записываем в память программы считанное ранее значение OSCCAL)
                                if(!SetInitState())                     // пробуем установить начальные уровни на ногах чипа
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!EnterHVPVMode_VPPfirst())           // пробуем перейти в режим программирования по алгоритму Vpp-first
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                if(!PIC16F630_MakePCOffset(SelectedChip.Area1Size/2-2,1))   // сдвигаем указатель на адрес перед нужным (слово калибровки - последнее слово памяти)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                // после этого можно уже и писать
                                if(!PIC16F630_WriteProgramMemory(SelectedChip.Area1Size/2-1,0))    // пробуем записать последнее слово программы
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось записать
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                                //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                                {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                      LBar->Free();                   // уничтожаем форму с прогресс-баром
                                      return;                         // выходим
                                }
                                // 5. Записываем обратно BG-bits
                                if(!SetInitState())                     // пробуем установить начальные уровни на ногах чипа
                                {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                    LBar->Free();                   // уничтожаем форму с прогресс-баром
                                    return;                         // выходим
                                }
                                if(!EnterHVPVMode_VPPfirst())           // пробуем перейти в режим программирования по алгоритму Vpp-first
                                {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                    LBar->Free();                   // уничтожаем форму с прогресс-баром
                                    return;                         // выходим
                                }
                                if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                                {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                    LBar->Free();                   // уничтожаем форму с прогресс-баром
                                    return;                         // выходим
                                }
                                if(!PIC16F630_MakePCOffset(6,1))          // сдвигаем указатель на адрес перед нужным (7-1=6), сдвиг ещё на единицу произойдёт в функции чтения пред чтением
                                {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                    LBar->Free();                   // уничтожаем форму с прогресс-баром
                                    return;                         // выходим
                                }
                                // после этого можно уже и писать
                                if(!PIC16F630_WriteConfigMemory(7,0))   // пробуем записать слово конфигурации по адресу 7 (0x2007)
                                {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                    LBar->Free();                   // уничтожаем форму с прогресс-баром
                                    return;                         // выходим
                                }
                                //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                                //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                                {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                    LBar->Free();                   // уничтожаем форму с прогресс-баром
                                    return;                         // выходим
                                }
                                SendMsgToLog(0,"    OSCCAL word & BG-bits has been restored");  // сообщаем о восстановлении калибровочных значений
                        }
                        break;
          case 0:  SendMsgToLog(14,"");            // сообщение в лог, что не выбран ни один чип
                   break;                          // выходим
          default: SendMsgToLog(15," unknown");    // сообщение в лог, что чип нам неизвестен и выходим
                   break;                          // выходим
        }
        LBar->Free();                   // уничтожаем форму с прогресс-баром
        SendMsgToLog(19,"");  // сообщаем о завершении операции
  }
  else  SendMsgToLog(0,"Operation cancelled");  // сообщаем об отмене операции
}
//---------------------------------------------------------------------------
//--- НАЖАТА КНОПКА READ OSCCAL ---------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::Button7Click(TObject *Sender)
{ // сначала нужно поместить в память данные с формы, в зависимости от вкладки
  switch(Form1->PageControl1->TabIndex)
  {     case 0: GetDataToMemory(1,1);      // из RichEdit1 в Area1
                GetDataToMemory(6,3);      // из RichEdit6 в Area3
                break;
        case 1: GetDataToMemory(2,1);      // из RichEdit2 в Area1
                GetDataToMemory(7,3);      // из RichEdit7 в Area3
                break;
        default: break;
  }

  SendMsgToLog(18," read factory calibrated values");   // сообщаем о попытке прочитать калибровочные значения

  // включаем прогресс-бар
  Application->CreateForm(__classid(TLBar),&LBar);      // создаём форму с прогресс-баром
  LBar->Show();

  // теперь можно читать калибровочное значение
  switch(SelectedChip.ID&0x3FE0)     // отрезаем 5 младших бит при выборе чипа (они определяют ревизию, а не модель)
  { // в этих чипах одно калибровочное значение по адресу CONF+9
    case 0x2080:        // выбрано устройство PIC16F887
    case 0x2060:        // выбрано устройство PIC16F886
    case 0x2040:        // выбрано устройство PIC16F884
    case 0x2020:        // выбрано устройство PIC16F883
    case 0x2000:        // выбрано устройство PIC16F882
                        if(!SetInitState())                     // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())           // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_MakePCOffset(8,1))        // сдвигаем указатель на адрес перед нужным
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // после этого можно читать слово
                        if(!PIC16F630_ReadConfigMemory(9,0))    // пробуем прочитать слово калибровки (CONF + 0x0009)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                SendEndTimeToLog();             // пишем в лог время окончания операции
                                return;                         // выходим
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        break;
    // в этих чипах вообще нет калибровочных значений
    case 0x1100:        // выбрано устройство PIC16F648A
    case 0x1060:        // выбрано устройство PIC16F628A
    case 0x1040:        // выбрано устройство PIC16F627A
                        SendMsgToLog(15,"       there are no calibration values in this chip");   // сообщение в лог, что чип нам неизвестен и выходим
                        break;                          // выходим
    // в этих чипах по два калибровочных значения по адресам CONF+9, CONF+10
    case 0x1900:        // выбрано устройство PIC16LF727
    case 0x1800:        // выбрано устройство PIC16F727
    case 0x1940:        // выбрано устройство PIC16LF724
    case 0x1840:        // выбрано устройство PIC16F724
    case 0x1920:        // выбрано устройство PIC16LF726
    case 0x1820:        // выбрано устройство PIC16F726
    case 0x1B40:        // выбрано устройство PIC16LF723A
    case 0x1B00:        // выбрано устройство PIC16F723A
    case 0x1960:        // выбрано устройство PIC16LF723
    case 0x1860:        // выбрано устройство PIC16F723
    case 0x1B60:        // выбрано устройство PIC16LF722A
    case 0x1B20:        // выбрано устройство PIC16F722A
    case 0x1980:        // выбрано устройство PIC16LF722
    case 0x1880:        // выбрано устройство PIC16F722
    case 0x1C60:        // выбрано устройство PIC16LF721
    case 0x1C20:        // выбрано устройство PIC16F721
    case 0x1C40:        // выбрано устройство PIC16LF720
    case 0x1C00:        // выбрано устройство PIC16F720
    case 0x1AE0:        // выбрано устройство PIC16LF707
    case 0x1AC0:        // выбрано устройство PIC16F707
    case 0x14A0:        // выбрано устройство PIC16LF1847
    case 0x1480:        // выбрано устройство PIC16F1847
    case 0x1BC0:        // выбрано устройство PIC12LF1840
    case 0x1B80:        // выбрано устройство PIC12F1840
    case 0x27E0:        // выбрано устройство PIC16F1829
    case 0x28C0:        // выбрано устройство PIC16LF1828
    case 0x27C0:        // выбрано устройство PIC16F1828
    case 0x28A0:        // выбрано устройство PIC16LF1827
    case 0x27A0:        // выбрано устройство PIC16F1827
    case 0x2880:        // выбрано устройство PIC16LF1826
    case 0x2780:        // выбрано устройство PIC16F1826
    case 0x2760:        // выбрано устройство PIC16F1825
    case 0x2840:        // выбрано устройство PIC16LF1824
    case 0x2740:        // выбрано устройство PIC16F1824
    case 0x2820:        // выбрано устройство PIC16LF1823
    case 0x2720:        // выбрано устройство PIC16F1823
    case 0x2800:        // выбрано устройство PIC12LF1822
    case 0x2700:        // выбрано устройство PIC12F1822
    case 0x2E00:        // выбрано устройство PIC16LF1509
    case 0x2D40:        // выбрано устройство PIC16F1509
    case 0x2DE0:        // выбрано устройство PIC16LF1508
    case 0x2D20:        // выбрано устройство PIC16F1508
    case 0x2DC0:        // выбрано устройство PIC16LF1507
    case 0x2D00:        // выбрано устройство PIC16F1507
    case 0x2DA0:        // выбрано устройство PIC16LF1503
    case 0x2CE0:        // выбрано устройство PIC16F1503
    case 0x2D80:        // выбрано устройство PIC12LF1501
    case 0x2CC0:        // выбрано устройство PIC12F1501
                        if(!SetInitState())                     // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())           // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_MakePCOffset(8,1))        // сдвигаем указатель на адрес перед нужным (в этом чипе два слова калибровки)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // после этого можно читать два слова
                        if(!PIC16F630_ReadConfigMemory(9,0))    // пробуем прочитать первое слово калибровки (CONF + 0x0009)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                SendEndTimeToLog();             // пишем в лог время окончания операции
                                return;                         // выходим
                        }
                        if(!PIC16F630_ReadConfigMemory(10,0))   // пробуем прочитать второе слово калибровки (CONF + 0x000A)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                SendEndTimeToLog();             // пишем в лог время окончания операции
                                return;                         // выходим
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        break;
    // в этих чипах одно слово калибровки по адресу CONF+8
    case 0x1240:        // выбрано устройство PIC16F616
    case 0x2260:        // выбрано устройство PIC16F610
    case 0x2240:        // выбрано устройство PIC12F609
    case 0x1360:        // выбрано устройство PIC12F617
    case 0x2180:        // выбрано устройство PIC12F615
    case 0x1400:        // выбрано устройство PIC16F690
    case 0x1340:        // выбрано устройство PIC16F689
    case 0x1180:        // выбрано устройство PIC16F688
    case 0x1320:        // выбрано устройство PIC16F687
    case 0x04A0:        // выбрано устройство PIC16F685
    case 0x1080:        // выбрано устройство PIC16F684
    case 0x1440:        // выбрано устройство PIC16F677
    case 0x1420:        // выбрано устройство PIC16F631
    case 0x0460:        // выбрано устройство PIC12F683
                        if(!SetInitState())                     // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())           // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_MakePCOffset(7,1))        // сдвигаем указатель на адрес перед нужным
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // после этого можно читать слово калибровки
                        if(!PIC16F630_ReadConfigMemory(8,0))    // пробуем прочитать первое слово калибровки
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                SendEndTimeToLog();             // пишем в лог время окончания операции
                                return;                         // выходим
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        break;
    // в этих чипах два слова калибровки по адресам CONF+8, CONF+9, сами чипы необычные - в них весь ID - идентификатор, без ревизии
    case 0x3020:     // возможно это PIC16F753
                        if(SelectedChip.ID == 0x3030)       // если это точно PIC16F753
                        {       if(!SetInitState())                     // пробуем установить начальные уровни на ногах чипа
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                if(!EnterHVPVMode_VPPfirst())           // пробуем перейти в режим программирования по алгоритму Vpp-first
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                if(!PIC16F630_MakePCOffset(7,1))        // сдвигаем указатель на адрес перед нужным (в этом чипе два слова калибровки)
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                // после этого можно читать два слова
                                if(!PIC16F630_ReadConfigMemory(8,0))    // пробуем прочитать первое слово калибровки
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                        SendEndTimeToLog();             // пишем в лог время окончания операции
                                        return;                         // выходим
                                }
                                if(!PIC16F630_ReadConfigMemory(9,0))    // пробуем прочитать второе слово калибровки
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                        SendEndTimeToLog();             // пишем в лог время окончания операции
                                        return;                         // выходим
                                }
                                //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                                //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                        }
                        else
                        {       SendMsgToLog(15," unknown");    // сообщение в лог, что чип нам неизвестен и выходим
                        }
                        break;
    // в этих чипах два слова калибровки по адресам CONF+8, CONF+9
    case 0x1200:        // выбрано устройство PIC16F785
    case 0x1500:        // выбрано устройство PIC12F752
    case 0x10A0:        // выбрано устройство PIC16F636 / PIC16F639
    case 0x0FA0:        // выбрано устройство PIC12F635
                        if(!SetInitState())                     // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())           // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_MakePCOffset(7,1))        // сдвигаем указатель на адрес перед нужным (в этом чипе два слова калибровки)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // после этого можно читать два слова
                        if(!PIC16F630_ReadConfigMemory(8,0))    // пробуем прочитать первое слово калибровки
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                SendEndTimeToLog();             // пишем в лог время окончания операции
                                return;                         // выходим
                        }
                        if(!PIC16F630_ReadConfigMemory(9,0))    // пробуем прочитать второе слово калибровки
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                SendEndTimeToLog();             // пишем в лог время окончания операции
                                return;                         // выходим
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        break;
    // в этих чипах слово калибровки вообще не в памяти конфигурации, а в последнем слове памяти программ 
    case 0x10C0:        // выбрано устройство PIC16F630
    case 0x10E0:        // выбрано устройство PIC16F676
    case 0x0F80:        // выбрано устройство PIC12F629
    case 0x0FC0:        // выбрано устройство PIC12F675
                        if(!SetInitState())                     // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())           // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!PIC16F630_MakePCOffset(SelectedChip.Area1Size/2-2,1))   // сдвигаем указатель на адрес перед нужным (слово калибровки - последнее слово памяти)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // после этого можно уже и читать
                        if(!PIC16F630_ReadProgramMemory(SelectedChip.Area1Size/2-1,0))    // пробуем прочитать последнее слово программы
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                SendEndTimeToLog();             // пишем в лог время окончания операции
                                return;                         // выходим
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        break;
    case 0:     SendMsgToLog(14,"");            // сообщение в лог, что не выбран ни один чип
                break;                          // выходим
    default:    SendMsgToLog(15," unknown");    // сообщение в лог, что чип нам неизвестен и выходим
                break;                          // выходим
  }
  LBar->Free();                   // уничтожаем форму с прогресс-баром
  // функция PlaceDataToForm тоже использует прогрессбар, если его выше не уничтожить - будет эксепшн
  // помещаем на форму данные из памяти (в том числе прочитанные)
  switch(Form1->PageControl1->TabIndex)
  {     case 0: PlaceDataToForm(1,1);      // в RichEdit1 из Area1
                PlaceDataToForm(6,3);      // в RichEdit6 из Area3
                break;
        case 1: PlaceDataToForm(2,1);      // в RichEdit2 из Area1
                PlaceDataToForm(7,3);      // в RichEdit7 из Area3
                break;
        default: break;
  }
  SendMsgToLog(19,"");  // сообщаем о завершении операции
}
//---------------------------------------------------------------------------
//--- НАЖАТА КНОПКА VERIFY PROGRAM & CONFIG MEMORY --------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::Button6Click(TObject *Sender)
{ char TempBuf[1], OutHexBuf[3];        // для преобразования
  AnsiString TempStr;                   // временная переменная для вывода адреса

  // сначала нужно поместить в память данные с формы, в зависимости от вкладки
  switch(Form1->PageControl1->TabIndex)
  {       case 0: GetDataToMemory(1,1);      // из RichEdit1 в Area1
                  GetDataToMemory(6,3);      // из RichEdit6 в Area3
                  break;
          case 1: GetDataToMemory(2,1);      // из RichEdit2 в Area1
                  GetDataToMemory(7,3);      // из RichEdit7 в Area3
                  break;
          default: break;
  }

  // включаем прогресс-бар
  Application->CreateForm(__classid(TLBar),&LBar);      // создаём форму с прогресс-баром
  LBar->Show();                                         // показываем её в немодальном окне

  SendMsgToLog(18," verify the program memory");       // сообщаем о попытке прочитать программу
  SendStartTimeToLog();                         // пишем в лог время начала операции
  switch(SelectedChip.ID&0x3FE0)     // отрезаем 5 младших бит при выборе чипа (они определяют ревизию, а не модель)
  { case 0x3020:        // возможно это PIC16F753
                        if(SelectedChip.ID == 0x3030)       // если это точно PIC16F753
                        {       // 1. Проверяем память программы
                                if(!SetInitState())                     // пробуем установить начальные уровни на ногах чипа
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                if(!EnterHVPVMode_VPPfirst())           // пробуем перейти в режим программирования по алгоритму Vpp-first
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                // после перехода в режим программирования можно проверять
                                for(unsigned int i=0; i<SelectedChip.Area1Size/2; i++)  // читаем по словам
                                {       if(!PIC16F630_ReadProgramMemory(i,1))           // пробуем прочитать слово программы
                                        {       TempBuf[0]=i>>8;                        // берём старший байт адреса
                                                BinToHex(TempBuf,OutHexBuf,1);          // преобразуем в строку
                                                OutHexBuf[2]=0;                         // строка должна заканчиваться нулём
                                                TempStr=UpperCase(OutHexBuf);           // переводим в верхний регистр и пишем в строку
                                                TempBuf[0]=i;                           // берём младший байт адреса
                                                BinToHex(TempBuf,OutHexBuf,1);          // преобразуем в строку
                                                OutHexBuf[2]=0;                         // строка должна заканчиваться нулём
                                                TempStr+=UpperCase(OutHexBuf);          // переводим в верхний регистр и дописываем к строке

                                                SendMsgToLog(19," with fail. Address: 0x" + TempStr);   // если вернуло false - не совпало
                                                SendEndTimeToLog();                                     // пишем в лог время окончания операции
                                                LBar->Free();                                           // уничтожаем форму с прогресс-баром
                                                return;                                                 // выходим
                                        }
                                        // если проверили количество байт кратное 8
                                        if((i+1)%8==0)
                                        {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area1Size;  // вычисляем новую позицию прогресс-бара
                                        }
                                }
                                // 2. Проверяем память конфигурации
                                if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                // после перехода в область конфигурации можно проверять
                                for(unsigned int i=0; i<SelectedChip.Area3Size/2; i++)  // читаем по словам
                                {       if(!PIC16F630_ReadConfigMemory(i,1))            // пробуем проверить слово конфигурации
                                        {       TempBuf[0]=(i+SelectedChip.ConfigStart)>>8;     // берём старший байт адреса
                                                BinToHex(TempBuf,OutHexBuf,1);          // преобразуем в строку
                                                OutHexBuf[2]=0;                         // строка должна заканчиваться нулём
                                                TempStr=UpperCase(OutHexBuf);           // переводим в верхний регистр и пишем в строку
                                                TempBuf[0]=(i+SelectedChip.ConfigStart);        // берём младший байт адреса
                                                BinToHex(TempBuf,OutHexBuf,1);          // преобразуем в строку
                                                OutHexBuf[2]=0;                         // строка должна заканчиваться нулём
                                                TempStr+=UpperCase(OutHexBuf);          // переводим в верхний регистр и дописываем к строке

                                                SendMsgToLog(19," with fail. Address: 0x" + TempStr);   // если вернуло false - не совпало
                                                SendEndTimeToLog();                                     // пишем в лог время окончания операции
                                                LBar->Free();                                           // уничтожаем форму с прогресс-баром
                                                return;                                                 // выходим
                                        }
                                        // если проверили количество байт кратное 8
                                        if((i+1)%8==0)
                                        {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area3Size;  // вычисляем новую позицию прогресс-бара
                                        }
                                }
                                //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                                //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                        }
                        else
                        {       SendMsgToLog(15," unknown");    // сообщение в лог, что чип нам неизвестен и выходим
                                SendEndTimeToLog();             // пишем в лог время окончания операции
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        break;
    case 0x2080:        // выбрано устройство PIC16F887
    case 0x2060:        // выбрано устройство PIC16F886
    case 0x2040:        // выбрано устройство PIC16F884
    case 0x2020:        // выбрано устройство PIC16F883
    case 0x2000:        // выбрано устройство PIC16F882
    case 0x1900:        // выбрано устройство PIC16LF727
    case 0x1800:        // выбрано устройство PIC16F727
    case 0x1940:        // выбрано устройство PIC16LF724
    case 0x1840:        // выбрано устройство PIC16F724
    case 0x1920:        // выбрано устройство PIC16LF726
    case 0x1820:        // выбрано устройство PIC16F726
    case 0x1B40:        // выбрано устройство PIC16LF723A
    case 0x1B00:        // выбрано устройство PIC16F723A
    case 0x1960:        // выбрано устройство PIC16LF723
    case 0x1860:        // выбрано устройство PIC16F723
    case 0x1B60:        // выбрано устройство PIC16LF722A
    case 0x1B20:        // выбрано устройство PIC16F722A
    case 0x1980:        // выбрано устройство PIC16LF722
    case 0x1880:        // выбрано устройство PIC16F722
    case 0x1C60:        // выбрано устройство PIC16LF721
    case 0x1C20:        // выбрано устройство PIC16F721
    case 0x1C40:        // выбрано устройство PIC16LF720
    case 0x1C00:        // выбрано устройство PIC16F720
    case 0x1AE0:        // выбрано устройство PIC16LF707
    case 0x1AC0:        // выбрано устройство PIC16F707
    case 0x1100:        // выбрано устройство PIC16F648A
    case 0x1060:        // выбрано устройство PIC16F628A
    case 0x1040:        // выбрано устройство PIC16F627A
    case 0x1200:        // выбрано устройство PIC16F785
    case 0x14A0:        // выбрано устройство PIC16LF1847
    case 0x1480:        // выбрано устройство PIC16F1847
    case 0x1BC0:        // выбрано устройство PIC12LF1840
    case 0x1B80:        // выбрано устройство PIC12F1840
    case 0x28E0:        // выбрано устройство PIC16LF1829
    case 0x27E0:        // выбрано устройство PIC16F1829
    case 0x28C0:        // выбрано устройство PIC16LF1828
    case 0x27C0:        // выбрано устройство PIC16F1828
    case 0x28A0:        // выбрано устройство PIC16LF1827
    case 0x27A0:        // выбрано устройство PIC16F1827
    case 0x2880:        // выбрано устройство PIC16LF1826
    case 0x2780:        // выбрано устройство PIC16F1826
    case 0x2860:        // выбрано устройство PIC16LF1825
    case 0x2760:        // выбрано устройство PIC16F1825
    case 0x2840:        // выбрано устройство PIC16LF1824
    case 0x2740:        // выбрано устройство PIC16F1824
    case 0x2820:        // выбрано устройство PIC16LF1823
    case 0x2720:        // выбрано устройство PIC16F1823
    case 0x2800:        // выбрано устройство PIC12LF1822
    case 0x2700:        // выбрано устройство PIC12F1822
    case 0x1240:        // выбрано устройство PIC16F616
    case 0x2260:        // выбрано устройство PIC16F610
    case 0x2240:        // выбрано устройство PIC12F609
    case 0x1360:        // выбрано устройство PIC12F617
    case 0x2180:        // выбрано устройство PIC12F615
    case 0x2E00:        // выбрано устройство PIC16LF1509
    case 0x2D40:        // выбрано устройство PIC16F1509
    case 0x2DE0:        // выбрано устройство PIC16LF1508
    case 0x2D20:        // выбрано устройство PIC16F1508
    case 0x2DC0:        // выбрано устройство PIC16LF1507
    case 0x2D00:        // выбрано устройство PIC16F1507
    case 0x2DA0:        // выбрано устройство PIC16LF1503
    case 0x2CE0:        // выбрано устройство PIC16F1503
    case 0x2D80:        // выбрано устройство PIC12LF1501
    case 0x2CC0:        // выбрано устройство PIC12F1501
    case 0x1500:        // выбрано устройство PIC12F752
    case 0x1400:        // выбрано устройство PIC16F690
    case 0x1340:        // выбрано устройство PIC16F689
    case 0x1180:        // выбрано устройство PIC16F688
    case 0x1320:        // выбрано устройство PIC16F687
    case 0x04A0:        // выбрано устройство PIC16F685
    case 0x1080:        // выбрано устройство PIC16F684
    case 0x1440:        // выбрано устройство PIC16F677
    case 0x10A0:        // выбрано устройство PIC16F636 / PIC16F639
    case 0x1420:        // выбрано устройство PIC16F631
    case 0x0460:        // выбрано устройство PIC12F683
    case 0x0FA0:        // выбрано устройство PIC12F635
    case 0x10C0:        // выбрано устройство PIC16F630
    case 0x10E0:        // выбрано устройство PIC16F676
    case 0x0F80:        // выбрано устройство PIC12F629
    case 0x0FC0:        // выбрано устройство PIC12F675
                        // 1. Проверяем память программы
                        if(!SetInitState())                     // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())           // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // после перехода в режим программирования можно проверять
                        for(unsigned int i=0; i<SelectedChip.Area1Size/2; i++)  // читаем по словам
                        {       if(!PIC16F630_ReadProgramMemory(i,1))           // пробуем прочитать слово программы
                                {       TempBuf[0]=i>>8;                        // берём старший байт адреса
                                        BinToHex(TempBuf,OutHexBuf,1);          // преобразуем в строку
                                        OutHexBuf[2]=0;                         // строка должна заканчиваться нулём
                                        TempStr=UpperCase(OutHexBuf);           // переводим в верхний регистр и пишем в строку
                                        TempBuf[0]=i;                           // берём младший байт адреса
                                        BinToHex(TempBuf,OutHexBuf,1);          // преобразуем в строку
                                        OutHexBuf[2]=0;                         // строка должна заканчиваться нулём
                                        TempStr+=UpperCase(OutHexBuf);          // переводим в верхний регистр и дописываем к строке

                                        SendMsgToLog(19," with fail. Address: 0x" + TempStr);   // если вернуло false - не совпало
                                        SendEndTimeToLog();                                     // пишем в лог время окончания операции
                                        LBar->Free();                                           // уничтожаем форму с прогресс-баром
                                        return;                                                 // выходим
                                }
                                // если проверили количество байт кратное 8
                                if((i+1)%8==0)
                                {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area1Size;  // вычисляем новую позицию прогресс-бара
                                }
                        }
                        // 2. Проверяем память конфигурации
                        if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // после перехода в область конфигурации можно проверять
                        for(unsigned int i=0; i<SelectedChip.Area3Size/2; i++)  // читаем по словам
                        {       if(!PIC16F630_ReadConfigMemory(i,1))            // пробуем проверить слово конфигурации
                                {       TempBuf[0]=(i+SelectedChip.ConfigStart)>>8;     // берём старший байт адреса
                                        BinToHex(TempBuf,OutHexBuf,1);          // преобразуем в строку
                                        OutHexBuf[2]=0;                         // строка должна заканчиваться нулём
                                        TempStr=UpperCase(OutHexBuf);           // переводим в верхний регистр и пишем в строку
                                        TempBuf[0]=(i+SelectedChip.ConfigStart);        // берём младший байт адреса
                                        BinToHex(TempBuf,OutHexBuf,1);          // преобразуем в строку
                                        OutHexBuf[2]=0;                         // строка должна заканчиваться нулём
                                        TempStr+=UpperCase(OutHexBuf);          // переводим в верхний регистр и дописываем к строке

                                        SendMsgToLog(19," with fail. Address: 0x" + TempStr);   // если вернуло false - не совпало
                                        SendEndTimeToLog();                                     // пишем в лог время окончания операции
                                        LBar->Free();                                           // уничтожаем форму с прогресс-баром
                                        return;                                                 // выходим
                                }
                                // если проверили количество байт кратное 8
                                if((i+1)%8==0)
                                {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area3Size;  // вычисляем новую позицию прогресс-бара
                                }
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        break;
    case 0:     SendMsgToLog(14,"");            // сообщение в лог, что не выбран ни один чип
                SendEndTimeToLog();             // пишем в лог время окончания операции
                LBar->Free();                   // уничтожаем форму с прогресс-баром
                return;                         // выходим
    default:    SendMsgToLog(15," unknown");    // сообщение в лог, что чип нам неизвестен и выходим
                SendEndTimeToLog();             // пишем в лог время окончания операции
                LBar->Free();                   // уничтожаем форму с прогресс-баром
                return;                         // выходим
  }
  LBar->Free();         // уничтожаем форму с прогресс-баром
  SendMsgToLog(19,". No differences found.");  // сообщаем о завершении операции
  SendEndTimeToLog();   // пишем в лог время окончания операции
}
//---------------------------------------------------------------------------
//--- НАЖАТА КНОПКА VERIFY DATA ---------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::Button10Click(TObject *Sender)
{ char TempBuf[1], OutHexBuf[3];        // для преобразования
  AnsiString TempStr;                   // временная переменная для вывода адреса

  // сначала нужно поместить в память данные с формы, в зависимости от вкладки
  switch(Form1->PageControl1->TabIndex)
  {       case 0: GetDataToMemory(3,2);      // из RichEdit3 в Area2
                  break;
          case 1: GetDataToMemory(4,2);      // из RichEdit4 в Area2
                  break;
          default: break;
  }

  // включаем прогресс-бар
  Application->CreateForm(__classid(TLBar),&LBar);      // создаём форму с прогресс-баром
  LBar->Show();                                         // показываем её в немодальном окне

  SendMsgToLog(18," verify the data memory");        // сообщаем о попытке проверить EEPROM
  SendStartTimeToLog();                         // пишем в лог время начала операции
  switch(SelectedChip.ID&0x3FE0)     // отрезаем 5 младших бит при выборе чипа (они определяют ревизию, а не модель)
  { // в этих чипах есть EEPROM
    case 0x2080:        // выбрано устройство PIC16F887
    case 0x2060:        // выбрано устройство PIC16F886
    case 0x2040:        // выбрано устройство PIC16F884
    case 0x2020:        // выбрано устройство PIC16F883
    case 0x2000:        // выбрано устройство PIC16F882
    case 0x1100:        // выбрано устройство PIC16F648A
    case 0x1060:        // выбрано устройство PIC16F628A
    case 0x1040:        // выбрано устройство PIC16F627A
    case 0x1200:        // выбрано устройство PIC16F785
    case 0x14A0:        // выбрано устройство PIC16LF1847
    case 0x1480:        // выбрано устройство PIC16F1847
    case 0x1BC0:        // выбрано устройство PIC12LF1840
    case 0x1B80:        // выбрано устройство PIC12F1840
    case 0x28E0:        // выбрано устройство PIC16LF1829
    case 0x27E0:        // выбрано устройство PIC16F1829
    case 0x28C0:        // выбрано устройство PIC16LF1828
    case 0x27C0:        // выбрано устройство PIC16F1828
    case 0x28A0:        // выбрано устройство PIC16LF1827
    case 0x27A0:        // выбрано устройство PIC16F1827
    case 0x2880:        // выбрано устройство PIC16LF1826
    case 0x2780:        // выбрано устройство PIC16F1826
    case 0x2860:        // выбрано устройство PIC16LF1825
    case 0x2760:        // выбрано устройство PIC16F1825
    case 0x2840:        // выбрано устройство PIC16LF1824
    case 0x2740:        // выбрано устройство PIC16F1824
    case 0x2820:        // выбрано устройство PIC16LF1823
    case 0x2720:        // выбрано устройство PIC16F1823
    case 0x2800:        // выбрано устройство PIC12LF1822
    case 0x2700:        // выбрано устройство PIC12F1822
    case 0x1400:        // выбрано устройство PIC16F690
    case 0x1340:        // выбрано устройство PIC16F689
    case 0x1180:        // выбрано устройство PIC16F688
    case 0x1320:        // выбрано устройство PIC16F687
    case 0x04A0:        // выбрано устройство PIC16F685
    case 0x1080:        // выбрано устройство PIC16F684
    case 0x1440:        // выбрано устройство PIC16F677
    case 0x10A0:        // выбрано устройство PIC16F636 / PIC16F639
    case 0x1420:        // выбрано устройство PIC16F631
    case 0x0460:        // выбрано устройство PIC12F683
    case 0x0FA0:        // выбрано устройство PIC12F635
    case 0x10C0:        // выбрано устройство PIC16F630
    case 0x10E0:        // выбрано устройство PIC16F676
    case 0x0F80:        // выбрано устройство PIC12F629
    case 0x0FC0:        // выбрано устройство PIC12F675
                        if(!SetInitState())                     // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())           // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // после этого можно уже и читать
                        for(unsigned int i=0; i<SelectedChip.Area2Size; i++)
                        {       if(!PIC16F630_ReadDataMemory(i,1))              // пробуем прочитать байт EEPROM
                                {       TempBuf[0]=i>>8;                        // берём старший байт адреса
                                        BinToHex(TempBuf,OutHexBuf,1);          // преобразуем в строку
                                        OutHexBuf[2]=0;                         // строка должна заканчиваться нулём
                                        TempStr=UpperCase(OutHexBuf);           // переводим в верхний регистр и пишем в строку
                                        TempBuf[0]=i;                           // берём младший байт адреса
                                        BinToHex(TempBuf,OutHexBuf,1);          // преобразуем в строку
                                        OutHexBuf[2]=0;                         // строка должна заканчиваться нулём
                                        TempStr+=UpperCase(OutHexBuf);          // переводим в верхний регистр и дописываем к строке

                                        SendMsgToLog(19," with fail. Address: 0x" + TempStr);   // если вернуло false - не совпало
                                        SendEndTimeToLog();                                     // пишем в лог время окончания операции
                                        LBar->Free();                                           // уничтожаем форму с прогресс-баром
                                        return;                                                 // выходим
                                }
                                // если прочитали количество байт кратное 16
                                if((i+1)%8==0)
                                {       LBar->ProgressBar1->Position=100*(i+1)/SelectedChip.Area2Size;  // вычисляем новую позицию прогресс-бара
                                }
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        break;
    case 0x3020:        // возможно это PIC16F753
                        if(SelectedChip.ID == 0x3030)       // если это точно PIC16F753
                        {       SendMsgToLog(0,"function is unavailable for this chip");        // сообщение в лог, что функция недоступна
                                SendEndTimeToLog();             // пишем в лог время окончания операции
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        else
                        {       SendMsgToLog(15," unknown");    // сообщение в лог, что чип нам неизвестен и выходим
                                SendEndTimeToLog();             // пишем в лог время окончания операции
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;
                        }
                        //break; - закомментировано, так как выше выходим в любом случае
    // в этих чипах нет EEPROM
    case 0x1900:        // выбрано устройство PIC16LF727
    case 0x1800:        // выбрано устройство PIC16F727
    case 0x1940:        // выбрано устройство PIC16LF724
    case 0x1840:        // выбрано устройство PIC16F724
    case 0x1920:        // выбрано устройство PIC16LF726
    case 0x1820:        // выбрано устройство PIC16F726
    case 0x1B40:        // выбрано устройство PIC16LF723A
    case 0x1B00:        // выбрано устройство PIC16F723A
    case 0x1960:        // выбрано устройство PIC16LF723
    case 0x1860:        // выбрано устройство PIC16F723
    case 0x1B60:        // выбрано устройство PIC16LF722A
    case 0x1B20:        // выбрано устройство PIC16F722A
    case 0x1980:        // выбрано устройство PIC16LF722
    case 0x1880:        // выбрано устройство PIC16F722
    case 0x1C60:        // выбрано устройство PIC16LF721
    case 0x1C20:        // выбрано устройство PIC16F721
    case 0x1C40:        // выбрано устройство PIC16LF720
    case 0x1C00:        // выбрано устройство PIC16F720
    case 0x1AE0:        // выбрано устройство PIC16LF707
    case 0x1AC0:        // выбрано устройство PIC16F707
    case 0x1240:        // выбрано устройство PIC16F616
    case 0x2260:        // выбрано устройство PIC16F610
    case 0x2240:        // выбрано устройство PIC12F609
    case 0x1360:        // выбрано устройство PIC12F617
    case 0x2180:        // выбрано устройство PIC12F615
    case 0x2E00:        // выбрано устройство PIC16LF1509
    case 0x2D40:        // выбрано устройство PIC16F1509
    case 0x2DE0:        // выбрано устройство PIC16LF1508
    case 0x2D20:        // выбрано устройство PIC16F1508
    case 0x2DC0:        // выбрано устройство PIC16LF1507
    case 0x2D00:        // выбрано устройство PIC16F1507
    case 0x2DA0:        // выбрано устройство PIC16LF1503
    case 0x2CE0:        // выбрано устройство PIC16F1503
    case 0x2D80:        // выбрано устройство PIC12LF1501
    case 0x2CC0:        // выбрано устройство PIC12F1501
    case 0x1500:        // выбрано устройство PIC12F752
                SendMsgToLog(0,"function is unavailable for this chip");        // сообщение в лог, что функция недоступна
                SendEndTimeToLog();             // пишем в лог время окончания операции
                LBar->Free();                   // уничтожаем форму с прогресс-баром
                return;                         // выходим
    case 0:     SendMsgToLog(14,"");            // сообщение в лог, что не выбран ни один чип
                SendEndTimeToLog();             // пишем в лог время окончания операции
                LBar->Free();                   // уничтожаем форму с прогресс-баром
                return;                         // выходим
    default:    SendMsgToLog(15," unknown");    // сообщение в лог, что чип нам неизвестен и выходим
                SendEndTimeToLog();             // пишем в лог время окончания операции
                LBar->Free();                   // уничтожаем форму с прогресс-баром
                return;                         // выходим
  }
  LBar->Free();         // уничтожаем форму с прогресс-баром
  SendMsgToLog(19,". No differences found.");  // сообщаем о завершении операции
  SendEndTimeToLog();   // пишем в лог время окончания операции
}
//---------------------------------------------------------------------------
//--- НАЖАТА КНОПКА WRITE PROGRAM & CONFIG MEMORY ---------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::Button5Click(TObject *Sender)
{ if (Application->MessageBox("Previous data in the Program & Config memory (& maybe in Data memory too) will be lost!\n            Are you sure?", "Warning", MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2|MB_APPLMODAL) == IDYES)
  { // сначала нужно поместить в память данные с формы, в зависимости от вкладки
    switch(Form1->PageControl1->TabIndex)
    {       case 0: GetDataToMemory(1,1);      // из RichEdit1 в Area1 - Program memory
                    GetDataToMemory(6,3);      // из RichEdit6 в Area3 - Config memory
                    break;
            case 1: GetDataToMemory(2,1);      // из RichEdit2 в Area1 - Program memory
                    GetDataToMemory(7,3);      // из RichEdit7 в Area3 - Config memory
                    break;
            default: break;
    }

    if(Form1->CheckBox2->Checked == true)
    {   SendMsgToLog(18," write the program memory & entire config memory");    // сообщаем о попытке записать программу и память конфигурации целиком
    }
    else
    {   SendMsgToLog(18," write the program memory & config word");     // сообщаем о попытке записать программу и слово конфигурации
    }

    SendStartTimeToLog();                         // пишем в лог время начала операции
    // включаем прогресс-бар
    Application->CreateForm(__classid(TLBar),&LBar);      // создаём форму с прогресс-баром
    LBar->Show();

    switch(SelectedChip.ID&0x3FE0)     // отрезаем 5 младших бит при выборе чипа (они определяют ревизию, а не модель)
    { // два слова конфигурации по адресам CONF7, CONF8, одно слово калибровки по адресу CONF9
      // в конфиг пишем 9 байт, при записи - внутреннее тактирование
      case 0x2080:  // выбрано устройство PIC16F887
      case 0x2060:  // выбрано устройство PIC16F886
      case 0x2040:  // выбрано устройство PIC16F884
      case 0x2020:  // выбрано устройство PIC16F883
      case 0x2000:  // выбрано устройство PIC16F882
                    if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений
                    {     // 1. Читаем значение OSCCAL-words
                          if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                          {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                  LBar->Free();                   // уничтожаем форму с прогресс-баром
                                  return;                         // выходим
                          }
                          if(!PIC16F630_MakePCOffset(8,1))      // сдвигаем указатель на адрес перед нужным (первое слово калибровки по адресу 0x2009)
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          // после этого можно уже и читать
                          if(!PIC16F630_ReadConfigMemory(9,0))  // пробуем прочитать слово калибровки
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                          //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                          if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          SendMsgToLog(0,"    calibration words (CONF + 0x0009) has been read and stored");  // сообщаем о чтении калибровочных значений
                    }
                    // 2. Выполняем стирание памяти программы (и при необходимости конфигурации)
                    if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(Form1->CheckBox2->Checked == true)       // если нужно вместе с программой стереть конфигурацию
                    {   if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                        {   SendMsgToLog(19," with fail.");     // если вернуло false - не удалось выполнить требуемое действие
                            LBar->Free();                       // уничтожаем форму с прогресс-баром
                            return;                             // выходим
                        }
                    }
                    if(!PIC16F630_BulkEraseProgramMemory())     // пробуем стереть память данных
                    {   SendMsgToLog(19," with fail.");         // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                           // уничтожаем форму с прогресс-баром
                        return;                                 // выходим
                    }
                    //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                    //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                    if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                    {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                          LBar->Free();                   // уничтожаем форму с прогресс-баром
                          return;                         // выходим
                    }
                    // 3. Записываем память программы
                    if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    for(unsigned int i=0; i<SelectedChip.Area1Size/2; i++)  // пишем по словам
                    {     if(!PIC16F630_WriteProgramMemory(i,0))          // пробуем записать слово программы (int timing)
                          {     SendMsgToLog(19," with fail.");         // если вернуло false - не удалось записать
                                LBar->Free();                           // уничтожаем форму с прогресс-баром
                                return;                                 // выходим
                          }
                          // если записали количество байт кратное 8
                          if((i+1)%8==0)
                          {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area1Size;  // вычисляем новую позицию прогресс-бара
                          }
                     }
                    // 4. Записываем слово конфигурации или память конфигурации целиком
                    if(!PIC16F630_SetPCToConfigMemory()) // пробуем перейти в область Config Memory
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(Form1->CheckBox2->Checked == true) // если записываем память конфигурации целиком (OSCCAL писать не нужно)
                    {   for(unsigned int i=0; i<9; i++)                 // пишем по словам (только первые 9 слов, калибровочные значения писать не нужно, они для этого чипа не стираются при erase, хотя могут быть перезаписаны)
                        {       if(!PIC16F630_WriteConfigMemory(i,0))   // пробуем записать слово в область конфигурации (int timing)
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось записать
                                        SendEndTimeToLog();             // пишем в лог время окончания операции
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                // если записали количество байт кратное 8
                                if((i+1)%8==0)
                                {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area3Size;  // вычисляем новую позицию прогресс-бара
                                }
                        }
                        SendMsgToLog(0,"    there is no need to restore the calibration values for this chip");  // сообщаем о восстановлении калибровочных значений
                    }
                    else                                    // если записываем только слова конфигурации
                    {   if(!PIC16F630_MakePCOffset(6,1))    // сдвигаем указатель на адрес перед нужным (7-1=6), сдвиг ещё на единицу произойдёт в функции записи пред записью
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                        // после этого можно уже и писать
                        if(!PIC16F630_WriteConfigMemory(7,0))   // пробуем записать слово конфигурации по адресу 7 (CONF + 0x0007)
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                        if(!PIC16F630_WriteConfigMemory(8,0))   // пробуем записать слово конфигурации по адресу 8 (CONF + 0x0008)
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                    }
                    //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                    //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                    if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    break;
      // одно слово конфигурации по адресу CONF7, нет слов калибровки, int timing
      case 0x1100:  // выбрано устройство PIC16F648A
      case 0x1060:  // выбрано устройство PIC16F628A
      case 0x1040:  // выбрано устройство PIC16F627A
                    // 1. Выполняем стирание памяти программы (и при необходимости конфигурации)
                    if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(Form1->CheckBox2->Checked == true)       // если нужно вместе с программой стереть конфигурацию
                    {   if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                        {   SendMsgToLog(19," with fail.");     // если вернуло false - не удалось выполнить требуемое действие
                            LBar->Free();                       // уничтожаем форму с прогресс-баром
                            return;                             // выходим
                        }
                    }
                    // загружаем в Program Memory 0x3FFF
                    if(!PIC16F630_LoadDataToProgramMemory(0x3FFF)) // пробуем стереть память программы
                    {       SendMsgToLog(19," with fail."); // если вернуло false - ошибка
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                    }
                    if(!PIC16F630_BulkEraseProgramMemory())     // пробуем стереть память данных
                    {   SendMsgToLog(19," with fail.");         // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                           // уничтожаем форму с прогресс-баром
                        return;                                 // выходим
                    }
                    //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                    //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                    if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                    {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                          LBar->Free();                   // уничтожаем форму с прогресс-баром
                          return;                         // выходим
                    }
                    // 2. Записываем память программы
                    if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    for(unsigned int i=0; i<SelectedChip.Area1Size/2; i++)  // пишем по словам
                    {     if(!PIC16F630_WriteProgramMemory(i,0))        // пробуем записать слово программы (int timing)
                          {     SendMsgToLog(19," with fail.");         // если вернуло false - не удалось записать
                                LBar->Free();                           // уничтожаем форму с прогресс-баром
                                return;                                 // выходим
                          }
                          // если записали количество байт кратное 8
                          if((i+1)%8==0)
                          {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area1Size;  // вычисляем новую позицию прогресс-бара
                          }
                     }
                    // 3. Записываем слово конфигурации или память конфигурации целиком
                    if(!PIC16F630_SetPCToConfigMemory()) // пробуем перейти в область Config Memory
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(Form1->CheckBox2->Checked == true) // если записываем память конфигурации целиком
                    {   for(unsigned int i=0; i<8; i++)                 // пишем по словам (только первые 8 слов, калибровочных значений в этом чипе нет)
                        {       if(!PIC16F630_WriteConfigMemory(i,0))   // пробуем записать слово в область конфигурации (int timing)
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось записать
                                        SendEndTimeToLog();             // пишем в лог время окончания операции
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                // если записали количество байт кратное 8
                                if((i+1)%8==0)
                                {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area3Size;  // вычисляем новую позицию прогресс-бара
                                }
                        }
                        SendMsgToLog(0,"    there is no need to restore the calibration value for this chip");  // сообщаем о восстановлении калибровочных значений
                    }
                    else                                    // если записываем только слово конфигурации
                    {   if(!PIC16F630_MakePCOffset(6,1))    // сдвигаем указатель на адрес перед нужным (7-1=6), сдвиг ещё на единицу произойдёт в функции записи пред записью
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                        // после этого можно уже и писать
                        if(!PIC16F630_WriteConfigMemory(7,0))   // пробуем записать слово конфигурации по адресу 7 (0x2007)
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                    }
                    //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                    //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                    if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    break;
      // два слова конфигурации по адресам CONF7, CONF8, два слова калибровки по адресам CONF9, CONF10
      // в конфиг пишем 9 байт, при записи - внутреннее тактирование
      case 0x1900:  // выбрано устройство PIC16LF727
      case 0x1800:  // выбрано устройство PIC16F727
      case 0x1940:  // выбрано устройство PIC16LF724
      case 0x1840:  // выбрано устройство PIC16F724
      case 0x1920:  // выбрано устройство PIC16LF726
      case 0x1820:  // выбрано устройство PIC16F726
      case 0x1B40:  // выбрано устройство PIC16LF723A
      case 0x1B00:  // выбрано устройство PIC16F723A
      case 0x1960:  // выбрано устройство PIC16LF723
      case 0x1860:  // выбрано устройство PIC16F723
      case 0x1B60:  // выбрано устройство PIC16LF722A
      case 0x1B20:  // выбрано устройство PIC16F722A
      case 0x1980:  // выбрано устройство PIC16LF722
      case 0x1880:  // выбрано устройство PIC16F722
      case 0x1C60:  // выбрано устройство PIC16LF721
      case 0x1C20:  // выбрано устройство PIC16F721
      case 0x1C40:  // выбрано устройство PIC16LF720
      case 0x1C00:  // выбрано устройство PIC16F720
      case 0x1AE0:  // выбрано устройство PIC16LF707
      case 0x1AC0:  // выбрано устройство PIC16F707
      case 0x14A0:  // выбрано устройство PIC16LF1847
      case 0x1480:  // выбрано устройство PIC16F1847
      case 0x1BC0:  // выбрано устройство PIC12LF1840
      case 0x1B80:  // выбрано устройство PIC12F1840
      case 0x28E0:  // выбрано устройство PIC16LF1829
      case 0x27E0:  // выбрано устройство PIC16F1829
      case 0x28C0:  // выбрано устройство PIC16LF1828
      case 0x27C0:  // выбрано устройство PIC16F1828
      case 0x28A0:  // выбрано устройство PIC16LF1827
      case 0x27A0:  // выбрано устройство PIC16F1827
      case 0x2880:  // выбрано устройство PIC16LF1826
      case 0x2780:  // выбрано устройство PIC16F1826
      case 0x2860:  // выбрано устройство PIC16LF1825
      case 0x2760:  // выбрано устройство PIC16F1825
      case 0x2840:  // выбрано устройство PIC16LF1824
      case 0x2740:  // выбрано устройство PIC16F1824
      case 0x2820:  // выбрано устройство PIC16LF1823
      case 0x2720:  // выбрано устройство PIC16F1823
      case 0x2800:  // выбрано устройство PIC12LF1822
      case 0x2700:  // выбрано устройство PIC16F1822
      case 0x2E00:  // выбрано устройство PIC16LF1509
      case 0x2D40:  // выбрано устройство PIC16F1509
      case 0x2DE0:  // выбрано устройство PIC16LF1508
      case 0x2D20:  // выбрано устройство PIC16F1508
      case 0x2DC0:  // выбрано устройство PIC16LF1507
      case 0x2D00:  // выбрано устройство PIC16F1507
      case 0x2DA0:  // выбрано устройство PIC16LF1503
      case 0x2CE0:  // выбрано устройство PIC16F1503
      case 0x2D80:  // выбрано устройство PIC12LF1501
      case 0x2CC0:  // выбрано устройство PIC12F1501
                    if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений
                    {     // 1. Читаем значение OSCCAL-words
                          if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                          {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                  LBar->Free();                   // уничтожаем форму с прогресс-баром
                                  return;                         // выходим
                          }
                          if(!PIC16F630_MakePCOffset(8,1))      // сдвигаем указатель на адрес перед нужным (первое слово калибровки по адресу 0x2009)
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          // после этого можно уже и читать
                          if(!PIC16F630_ReadConfigMemory(9,0))  // пробуем прочитать слово калибровки
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!PIC16F630_ReadConfigMemory(10,0)) // пробуем прочитать слово калибровки
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                          //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                          if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          SendMsgToLog(0,"    calibration words (CONF + 0x0009, CONF + 0x000A) has been read and stored");  // сообщаем о чтении калибровочных значений
                    }
                    // 2. Выполняем стирание памяти программы (и при необходимости конфигурации)
                    if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(Form1->CheckBox2->Checked == true)       // если нужно вместе с программой стереть конфигурацию
                    {   if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                        {   SendMsgToLog(19," with fail.");     // если вернуло false - не удалось выполнить требуемое действие
                            LBar->Free();                       // уничтожаем форму с прогресс-баром
                            return;                             // выходим
                        }
                    }
                    if(!PIC16F630_BulkEraseProgramMemory())     // пробуем стереть память данных
                    {   SendMsgToLog(19," with fail.");         // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                           // уничтожаем форму с прогресс-баром
                        return;                                 // выходим
                    }
                    //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                    //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                    if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                    {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                          LBar->Free();                   // уничтожаем форму с прогресс-баром
                          return;                         // выходим
                    }
                    // 3. Записываем память программы
                    if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    for(unsigned int i=0; i<SelectedChip.Area1Size/2; i++)  // пишем по словам
                    {     if(!PIC16F630_WriteProgramMemory(i,0))          // пробуем записать слово программы (int timing)
                          {     SendMsgToLog(19," with fail.");         // если вернуло false - не удалось записать
                                LBar->Free();                           // уничтожаем форму с прогресс-баром
                                return;                                 // выходим
                          }
                          // если записали количество байт кратное 8
                          if((i+1)%8==0)
                          {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area1Size;  // вычисляем новую позицию прогресс-бара
                          }
                     }
                    // 4. Записываем слово конфигурации или память конфигурации целиком
                    if(!PIC16F630_SetPCToConfigMemory()) // пробуем перейти в область Config Memory
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(Form1->CheckBox2->Checked == true) // если записываем память конфигурации целиком (OSCCAL писать не нужно)
                    {   for(unsigned int i=0; i<9; i++)                 // пишем по словам (только первые 9 слов, калибровочные значения писать не нужно, они для этого чипа не стираются при erase, хотя могут быть перезаписаны)
                        {       if(!PIC16F630_WriteConfigMemory(i,0))   // пробуем записать слово в область конфигурации (int timing)
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось записать
                                        SendEndTimeToLog();             // пишем в лог время окончания операции
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                // если записали количество байт кратное 8
                                if((i+1)%8==0)
                                {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area3Size;  // вычисляем новую позицию прогресс-бара
                                }
                        }
                        SendMsgToLog(0,"    there is no need to restore the calibration values for this chip");  // сообщаем о восстановлении калибровочных значений
                    }
                    else                                    // если записываем только слова конфигурации
                    {   if(!PIC16F630_MakePCOffset(6,1))    // сдвигаем указатель на адрес перед нужным (7-1=6), сдвиг ещё на единицу произойдёт в функции записи пред записью
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                        // после этого можно уже и писать
                        if(!PIC16F630_WriteConfigMemory(7,0))   // пробуем записать слово конфигурации по адресу 7 (CONF + 0x0007)
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                        if(!PIC16F630_WriteConfigMemory(8,0))   // пробуем записать слово конфигурации по адресу 8 (CONF + 0x0008)
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                    }
                    //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                    //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                    if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    break;
      // одно слово конфигурации по адресу CONF7, одно слово калибровки по адресу CONF8
      // в конфиг пишем 8 байт, при записи - внешнее тактирование
      case 0x1240:  // выбрано устройство PIC16F616
      case 0x2260:  // выбрано устройство PIC16F610
      case 0x2240:  // выбрано устройство PIC12F609
      case 0x1360:  // выбрано устройство PIC12F617
      case 0x2180:  // выбрано устройство PIC12F615
                    if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений
                    {     // 1. Читаем значение OSCCAL-word
                          if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                          {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                  LBar->Free();                   // уничтожаем форму с прогресс-баром
                                  return;                         // выходим
                          }
                          if(!PIC16F630_MakePCOffset(7,1))      // сдвигаем указатель на адрес перед нужным (слово калибровки по адресу 0x2008)
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          // после этого можно уже и читать
                          if(!PIC16F630_ReadConfigMemory(8,0))  // пробуем прочитать слово калибровки
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                          //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                          if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          SendMsgToLog(0,"    calibration word (0x2008) has been read and stored");  // сообщаем о чтении калибровочных значений
                    }
                    // 2. Выполняем стирание памяти программы (и при необходимости конфигурации)
                    if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(Form1->CheckBox2->Checked == true)       // если нужно вместе с программой стереть конфигурацию
                    {   if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                        {   SendMsgToLog(19," with fail.");     // если вернуло false - не удалось выполнить требуемое действие
                            LBar->Free();                       // уничтожаем форму с прогресс-баром
                            return;                             // выходим
                        }
                    }
                    if(!PIC16F630_BulkEraseProgramMemory())     // пробуем стереть память данных
                    {   SendMsgToLog(19," with fail.");         // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                           // уничтожаем форму с прогресс-баром
                        return;                                 // выходим
                    }
                    //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                    //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                    if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                    {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                          LBar->Free();                   // уничтожаем форму с прогресс-баром
                          return;                         // выходим
                    }
                    // 3. Записываем память программы
                    if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    for(unsigned int i=0; i<SelectedChip.Area1Size/2; i++)  // пишем по словам
                    {     if(!PIC16F630_WriteProgramMemory(i,1))        // пробуем записать слово программы (ext timing)
                          {     SendMsgToLog(19," with fail.");         // если вернуло false - не удалось записать
                                LBar->Free();                           // уничтожаем форму с прогресс-баром
                                return;                                 // выходим
                          }
                          // если записали количество байт кратное 8
                          if((i+1)%8==0)
                          {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area1Size;  // вычисляем новую позицию прогресс-бара
                          }
                     }
                    // 4. Записываем слово конфигурации или память конфигурации целиком
                    if(!PIC16F630_SetPCToConfigMemory()) // пробуем перейти в область Config Memory
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(Form1->CheckBox2->Checked == true) // если записываем память конфигурации целиком
                    {   for(unsigned int i=0; i<8; i++)                 // пишем по словам (только первые 8 слов, калибровочные значения писать не нужно, они для этого чипа не стираются при erase, хотя могут быть перезаписаны)
                        {       if(!PIC16F630_WriteConfigMemory(i,1))   // пробуем записать слово в область конфигурации (ext timing)
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось записать
                                        SendEndTimeToLog();             // пишем в лог время окончания операции
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                // если записали количество байт кратное 8
                                if((i+1)%8==0)
                                {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area3Size;  // вычисляем новую позицию прогресс-бара
                                }
                        }
                        SendMsgToLog(0,"    there is no need to restore the calibration value for this chip");  // сообщаем о восстановлении калибровочных значений
                    }
                    else                                    // если записываем только слово конфигурации
                    {   if(!PIC16F630_MakePCOffset(6,1))    // сдвигаем указатель на адрес перед нужным (7-1=6), сдвиг ещё на единицу произойдёт в функции записи пред записью
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                        // после этого можно уже и писать
                        if(!PIC16F630_WriteConfigMemory(7,1))   // пробуем записать слово конфигурации по адресу 7 (0x2007)
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                    }
                    //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                    //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                    if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    break;
      // одно слово конфигурации по адресу CONF7, одно слово калибровки по адресу CONF8
      // в конфиг пишем 8 байт, при записи - внутреннее тактирование
      case 0x1400:  // выбрано устройство PIC16F690
      case 0x1340:  // выбрано устройство PIC16F689
      case 0x1180:  // выбрано устройство PIC16F688
      case 0x1320:  // выбрано устройство PIC16F687
      case 0x04A0:  // выбрано устройство PIC16F685
      case 0x1080:  // выбрано устройство PIC16F684
      case 0x1440:  // выбрано устройство PIC16F677
      case 0x1420:  // выбрано устройство PIC16F631
      case 0x0460:  // выбрано устройство PIC12F683
                    if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений
                    {     // 1. Читаем значение OSCCAL-word
                          if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                          {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                  LBar->Free();                   // уничтожаем форму с прогресс-баром
                                  return;                         // выходим
                          }
                          if(!PIC16F630_MakePCOffset(7,1))      // сдвигаем указатель на адрес перед нужным (слово калибровки по адресу 0x2008)
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          // после этого можно уже и читать
                          if(!PIC16F630_ReadConfigMemory(8,0))  // пробуем прочитать слово калибровки
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                          //--- оба напряжения одноременно, просто переводя выводы в начальные состояния 
                          if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          SendMsgToLog(0,"    calibration word (0x2008) has been read and stored");  // сообщаем о чтении калибровочных значений
                    }
                    // 2. Выполняем стирание памяти программы (и при необходимости конфигурации)
                    if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(Form1->CheckBox2->Checked == true)       // если нужно вместе с программой стереть конфигурацию
                    {   if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                        {   SendMsgToLog(19," with fail.");     // если вернуло false - не удалось выполнить требуемое действие
                            LBar->Free();                       // уничтожаем форму с прогресс-баром
                            return;                             // выходим
                        }
                    }
                    if(!PIC16F630_BulkEraseProgramMemory())     // пробуем стереть память данных
                    {   SendMsgToLog(19," with fail.");         // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                           // уничтожаем форму с прогресс-баром
                        return;                                 // выходим
                    }
                    //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                    //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                    if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                    {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                          LBar->Free();                   // уничтожаем форму с прогресс-баром
                          return;                         // выходим
                    }
                    // 3. Записываем память программы
                    if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    for(unsigned int i=0; i<SelectedChip.Area1Size/2; i++)  // пишем по словам
                    {     if(!PIC16F630_WriteProgramMemory(i,0))        // пробуем записать слово программы (int timing)
                          {     SendMsgToLog(19," with fail.");         // если вернуло false - не удалось записать
                                LBar->Free();                           // уничтожаем форму с прогресс-баром
                                return;                                 // выходим
                          }
                          // если записали количество байт кратное 8
                          if((i+1)%8==0)
                          {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area1Size;  // вычисляем новую позицию прогресс-бара
                          }
                     }
                    // 4. Записываем слово конфигурации или память конфигурации целиком
                    if(!PIC16F630_SetPCToConfigMemory()) // пробуем перейти в область Config Memory
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(Form1->CheckBox2->Checked == true) // если записываем память конфигурации целиком
                    {   for(unsigned int i=0; i<8; i++)                 // пишем по словам (только первые 8 слов, калибровочные значения писать не нужно, они для этого чипа не стираются при erase, хотя могут быть перезаписаны)
                        {       if(!PIC16F630_WriteConfigMemory(i,0))   // пробуем записать слово в область конфигурации (int timing)
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось записать
                                        SendEndTimeToLog();             // пишем в лог время окончания операции
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                // если записали количество байт кратное 8
                                if((i+1)%8==0)
                                {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area3Size;  // вычисляем новую позицию прогресс-бара
                                }
                        }
                        SendMsgToLog(0,"    there is no need to restore the calibration value for this chip");  // сообщаем о восстановлении калибровочных значений
                    }
                    else                                    // если записываем только слово конфигурации
                    {   if(!PIC16F630_MakePCOffset(6,1))    // сдвигаем указатель на адрес перед нужным (7-1=6), сдвиг ещё на единицу произойдёт в функции записи пред записью
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                        // после этого можно уже и писать
                        if(!PIC16F630_WriteConfigMemory(7,0))   // пробуем записать слово конфигурации по адресу 7 (0x2007)
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                    }
                    //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                    //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                    if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    break;
      // одно слово конфигурации по адресу CONF7, два слова калибровки по адресам CONF8, CONF9
      // в конфиг пишем 8 байт, при записи - внешнее тактирование
      case 0x3020:  // возможно это PIC16F753
                    if(SelectedChip.ID == 0x3030)       // если это точно PIC16F753
                    {   if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений
                        {       // 1. Читаем значение OSCCAL-words
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                if(!PIC16F630_MakePCOffset(7,1))      // сдвигаем указатель на адрес перед нужным (первое слово калибровки по адресу 0x2008)
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                // после этого можно уже и читать
                                if(!PIC16F630_ReadConfigMemory(8,0))  // пробуем прочитать последнее слово программы
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                if(!PIC16F630_ReadConfigMemory(9,0))  // пробуем прочитать последнее слово программы
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                                //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                SendMsgToLog(0,"    calibration words (0x2008, 0x2009) has been read and stored");  // сообщаем о чтении калибровочных значений
                        }
                        // 2. Выполняем стирание памяти программы (и при необходимости конфигурации)
                        if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(Form1->CheckBox2->Checked == true)       // если нужно вместе с программой стереть конфигурацию
                        {       if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                                {       SendMsgToLog(19," with fail.");     // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                       // уничтожаем форму с прогресс-баром
                                        return;                             // выходим
                                }
                        }
                        if(!PIC16F630_BulkEraseProgramMemory())     // пробуем стереть память данных
                        {       SendMsgToLog(19," with fail.");         // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                           // уничтожаем форму с прогресс-баром
                                return;                                 // выходим
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // 3. Записываем память программы
                        if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        for(unsigned int i=0; i<SelectedChip.Area1Size/2; i++)  // пишем по словам
                        {       if(!PIC16F630_WriteProgramMemory(i,1))        // пробуем записать слово программы (ext timing)
                                {       SendMsgToLog(19," with fail.");         // если вернуло false - не удалось записать
                                        LBar->Free();                           // уничтожаем форму с прогресс-баром
                                        return;                                 // выходим
                                }
                                // если записали количество байт кратное 8
                                if((i+1)%8==0)
                                {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area1Size;  // вычисляем новую позицию прогресс-бара
                                }
                        }
                        // 4. Записываем слово конфигурации или память конфигурации целиком
                        if(!PIC16F630_SetPCToConfigMemory()) // пробуем перейти в область Config Memory
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(Form1->CheckBox2->Checked == true) // если записываем память конфигурации целиком (вместе с новыми значениями OSCCAL)
                        {       for(unsigned int i=0; i<8; i++)                 // пишем по словам (только первые 8 слов, калибровочные значения писать не нужно, они для этого чипа не стираются при erase, хотя могут быть перезаписаны)
                                {       if(!PIC16F630_WriteConfigMemory(i,1))   // пробуем записать слово в область конфигурации (ext timing)
                                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось записать
                                                SendEndTimeToLog();             // пишем в лог время окончания операции
                                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                                return;                         // выходим
                                        }
                                        // если записали количество байт кратное 8
                                        if((i+1)%8==0)
                                        {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area3Size;  // вычисляем новую позицию прогресс-бара
                                        }
                                }
                                SendMsgToLog(0,"    there is no need to restore the calibration values for this chip");  // сообщаем о восстановлении калибровочных значений
                        }
                        else                                    // если записываем только слово конфигурации
                        {       if(!PIC16F630_MakePCOffset(6,1))    // сдвигаем указатель на адрес перед нужным (7-1=6), сдвиг ещё на единицу произойдёт в функции чтения пред чтением
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                // после этого можно уже и писать
                                if(!PIC16F630_WriteConfigMemory(7,1))   // пробуем записать слово конфигурации по адресу 7 (0x2007)
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                    }
                    else
                    {   SendMsgToLog(15," unknown");    // сообщение в лог, что чип нам неизвестен и выходим
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        SendEndTimeToLog();             // пишем в лог время окончания операции
                        return;                         // выходим
                    }
                    break;
      // одно слово конфигурации по адресу CONF7, два слова калибровки по адресам CONF8, CONF9
      // в конфиг пишем 8 байт, при записи - внешнее тактирование
      case 0x1500:  // выбрано устройство PIC12F752
                    if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений
                    {     // 1. Читаем значение OSCCAL-words
                          if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                          {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                  LBar->Free();                   // уничтожаем форму с прогресс-баром
                                  return;                         // выходим
                          }
                          if(!PIC16F630_MakePCOffset(7,1))      // сдвигаем указатель на адрес перед нужным (первое слово калибровки по адресу 0x2008)
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          // после этого можно уже и читать
                          if(!PIC16F630_ReadConfigMemory(8,0))  // пробуем прочитать последнее слово программы
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!PIC16F630_ReadConfigMemory(9,0))  // пробуем прочитать последнее слово программы
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                          //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                          if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          SendMsgToLog(0,"    calibration words (0x2008, 0x2009) has been read and stored");  // сообщаем о чтении калибровочных значений
                    }
                    // 2. Выполняем стирание памяти программы (и при необходимости конфигурации)
                    if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(Form1->CheckBox2->Checked == true)       // если нужно вместе с программой стереть конфигурацию
                    {   if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                        {   SendMsgToLog(19," with fail.");     // если вернуло false - не удалось выполнить требуемое действие
                            LBar->Free();                       // уничтожаем форму с прогресс-баром
                            return;                             // выходим
                        }
                    }
                    if(!PIC16F630_BulkEraseProgramMemory())     // пробуем стереть память данных
                    {   SendMsgToLog(19," with fail.");         // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                           // уничтожаем форму с прогресс-баром
                        return;                                 // выходим
                    }
                    //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                    //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                    if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                    {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                          LBar->Free();                   // уничтожаем форму с прогресс-баром
                          return;                         // выходим
                    }
                    // 3. Записываем память программы
                    if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    for(unsigned int i=0; i<SelectedChip.Area1Size/2; i++)  // пишем по словам
                    {     if(!PIC16F630_WriteProgramMemory(i,1))        // пробуем записать слово программы (ext timing)
                          {     SendMsgToLog(19," with fail.");         // если вернуло false - не удалось записать
                                LBar->Free();                           // уничтожаем форму с прогресс-баром
                                return;                                 // выходим
                          }
                          // если записали количество байт кратное 8
                          if((i+1)%8==0)
                          {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area1Size;  // вычисляем новую позицию прогресс-бара
                          }
                     }
                    // 4. Записываем слово конфигурации или память конфигурации целиком
                    if(!PIC16F630_SetPCToConfigMemory()) // пробуем перейти в область Config Memory
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(Form1->CheckBox2->Checked == true) // если записываем память конфигурации целиком (вместе с новыми значениями OSCCAL)
                    {   for(unsigned int i=0; i<8; i++)                 // пишем по словам (только первые 8 слов, калибровочные значения писать не нужно, они для этого чипа не стираются при erase, хотя могут быть перезаписаны)
                        {       if(!PIC16F630_WriteConfigMemory(i,1))   // пробуем записать слово в область конфигурации (ext timing)
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось записать
                                        SendEndTimeToLog();             // пишем в лог время окончания операции
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                // если записали количество байт кратное 8
                                if((i+1)%8==0)
                                {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area3Size;  // вычисляем новую позицию прогресс-бара
                                }
                        }
                        SendMsgToLog(0,"    there is no need to restore the calibration values for this chip");  // сообщаем о восстановлении калибровочных значений
                    }
                    else                                    // если записываем только слово конфигурации
                    {   if(!PIC16F630_MakePCOffset(6,1))    // сдвигаем указатель на адрес перед нужным (7-1=6), сдвиг ещё на единицу произойдёт в функции чтения пред чтением
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                        // после этого можно уже и писать
                        if(!PIC16F630_WriteConfigMemory(7,1))   // пробуем записать слово конфигурации по адресу 7 (0x2007)
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                    }
                    //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                    //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                    if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    break;
      // одно слово конфигурации по адресу CONF7, два слова калибровки по адресам CONF8, CONF9
      // в конфиг пишем 8 байт, при записи - внутреннее тактирование
      case 0x1200:  // выбрано устройство PIC16F785
      case 0x10A0:  // выбрано устройство PIC16F636 / PIC16F639
      case 0x0FA0:  // выбрано устройство PIC12F635
                    if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений
                    {     // 1. Читаем значение OSCCAL-words
                          if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                          {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                  LBar->Free();                   // уничтожаем форму с прогресс-баром
                                  return;                         // выходим
                          }
                          if(!PIC16F630_MakePCOffset(7,1))      // сдвигаем указатель на адрес перед нужным (первое слово калибровки по адресу 0x2008)
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          // после этого можно уже и читать
                          if(!PIC16F630_ReadConfigMemory(8,0))  // пробуем прочитать последнее слово программы
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!PIC16F630_ReadConfigMemory(9,0))  // пробуем прочитать последнее слово программы
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                          //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                          if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          SendMsgToLog(0,"    calibration words (0x2008, 0x2009) has been read and stored");  // сообщаем о чтении калибровочных значений
                    }
                    // 2. Выполняем стирание памяти программы (и при необходимости конфигурации)
                    if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(Form1->CheckBox2->Checked == true)       // если нужно вместе с программой стереть конфигурацию
                    {   if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                        {   SendMsgToLog(19," with fail.");     // если вернуло false - не удалось выполнить требуемое действие
                            LBar->Free();                       // уничтожаем форму с прогресс-баром
                            return;                             // выходим
                        }
                    }
                    if(!PIC16F630_BulkEraseProgramMemory())     // пробуем стереть память данных
                    {   SendMsgToLog(19," with fail.");         // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                           // уничтожаем форму с прогресс-баром
                        return;                                 // выходим
                    }
                    //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                    //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                    if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                    {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                          LBar->Free();                   // уничтожаем форму с прогресс-баром
                          return;                         // выходим
                    }
                    // 3. Записываем память программы
                    if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    for(unsigned int i=0; i<SelectedChip.Area1Size/2; i++)  // пишем по словам
                    {     if(!PIC16F630_WriteProgramMemory(i,0))          // пробуем записать слово программы (int timing)
                          {     SendMsgToLog(19," with fail.");         // если вернуло false - не удалось записать
                                LBar->Free();                           // уничтожаем форму с прогресс-баром
                                return;                                 // выходим
                          }
                          // если записали количество байт кратное 8
                          if((i+1)%8==0)
                          {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area1Size;  // вычисляем новую позицию прогресс-бара
                          }
                     }
                    // 4. Записываем слово конфигурации или память конфигурации целиком
                    if(!PIC16F630_SetPCToConfigMemory()) // пробуем перейти в область Config Memory
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(Form1->CheckBox2->Checked == true) // если записываем память конфигурации целиком (вместе с новыми значениями OSCCAL)
                    {   for(unsigned int i=0; i<8; i++)                 // пишем по словам (только первые 8 слов, калибровочные значения писать не нужно, они для этого чипа не стираются при erase, хотя могут быть перезаписаны)
                        {       if(!PIC16F630_WriteConfigMemory(i,0))   // пробуем записать слово в область конфигурации (int timing)
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось записать
                                        SendEndTimeToLog();             // пишем в лог время окончания операции
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                // если записали количество байт кратное 8
                                if((i+1)%8==0)
                                {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area3Size;  // вычисляем новую позицию прогресс-бара
                                }
                        }
                        SendMsgToLog(0,"    there is no need to restore the calibration values for this chip");  // сообщаем о восстановлении калибровочных значений
                    }
                    else                                    // если записываем только слово конфигурации
                    {   if(!PIC16F630_MakePCOffset(6,1))    // сдвигаем указатель на адрес перед нужным (7-1=6), сдвиг ещё на единицу произойдёт в функции чтения пред чтением
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                        // после этого можно уже и писать
                        if(!PIC16F630_WriteConfigMemory(7,0))   // пробуем записать слово конфигурации по адресу 7 (0x2007)
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                    }
                    //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                    //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                    if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    break;
      // одно слово конфигурации по адресу CONF7, одно слово калибровки по адресу PROGEND
      // в конфиг пишем 8 байт, при записи - внутреннее тактирование
      case 0x10C0:  // выбрано устройство PIC16F630
      case 0x10E0:  // выбрано устройство PIC16F676
      case 0x0F80:  // выбрано устройство PIC12F629
      case 0x0FC0:  // выбрано устройство PIC12F675
                    if(Form1->CheckBox1->Checked == true)       // если выбрана опция сохранения / восстановления калибровочных значений и битов BG в процессе записи
                    {     // 1. Читаем значение OSCCAL-word
                          if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!EnterHVPVMode_VPPfirst())         // пробуем перейти в режим программирования по алгоритму Vpp-first
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!PIC16F630_MakePCOffset(SelectedChip.Area1Size/2-2,1))     // сдвигаем указатель на адрес перед нужным (слово калибровки - последнее слово памяти)
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          // после этого можно уже и читать
                          if(!PIC16F630_ReadProgramMemory(SelectedChip.Area1Size/2-1,0)) // пробуем прочитать последнее слово программы
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          // 2. Читаем значение BG-bits
                          if(!PIC16F630_SetPCToConfigMemory())  // пробуем перейти в область Config Memory
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          if(!PIC16F630_MakePCOffset(6,1))      // сдвигаем указатель на адрес перед нужным (7-1=6), сдвиг ещё на единицу произойдёт в функции чтения пред чтением
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          // после этого можно уже и читать
                          if(!PIC16F630_ReadConfigMemoryMask(7,0x3000)) // пробуем прочитать слово конфигурации по адресу 7 (0x2007) по маске 0x3000 (BG-bits)
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                          //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                          if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                          {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                          }
                          SendMsgToLog(0,"    OSCCAL word & BG-bits has been read and stored");  // сообщаем о чтении калибровочных значений
                    }
                    // 3. Выполняем стирание памяти программы (и при необходимости конфигурации)
                    if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(Form1->CheckBox2->Checked == true)       // если нужно вместе с программой стереть конфигурацию
                    {   if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                        {   SendMsgToLog(19," with fail.");     // если вернуло false - не удалось выполнить требуемое действие
                            LBar->Free();                       // уничтожаем форму с прогресс-баром
                            return;                             // выходим
                        }
                    }
                    if(!PIC16F630_BulkEraseProgramMemory())     // пробуем стереть память данных
                    {   SendMsgToLog(19," with fail.");         // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                           // уничтожаем форму с прогресс-баром
                        return;                                 // выходим
                    }
                    //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                    //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                    if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                    {     SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                          LBar->Free();                   // уничтожаем форму с прогресс-баром
                          return;                         // выходим
                    }
                    // 4. Записываем память программы (вместе с новым значением OSCCAL)
                    if(!SetInitState())                 // пробуем установить начальные уровни на ногах чипа
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(!EnterHVPVMode_VPPfirst())       // пробуем перейти в режим программирования по алгоритму Vpp-first
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    for(unsigned int i=0; i<SelectedChip.Area1Size/2; i++)  // пишем по словам
                    {     if(!PIC16F630_WriteProgramMemory(i,0))          // пробуем записать слово программы (int timing)
                          {     SendMsgToLog(19," with fail.");         // если вернуло false - не удалось записать
                                LBar->Free();                           // уничтожаем форму с прогресс-баром
                                return;                                 // выходим
                          }
                          // если записали количество байт кратное 8
                          if((i+1)%8==0)
                          {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area1Size;  // вычисляем новую позицию прогресс-бара
                          }
                     }
                    // 5. Записываем слово конфигурации или память конфигурации целиком
                    if(!PIC16F630_SetPCToConfigMemory()) // пробуем перейти в область Config Memory
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(Form1->CheckBox2->Checked == true) // если записываем память конфигурации целиком
                    {   for(unsigned int i=0; i<SelectedChip.Area3Size/2; i++)  // пишем по словам
                        {       if(!PIC16F630_WriteConfigMemory(i,0))           // пробуем записать слово в область конфигурации (int timing)
                                {       SendMsgToLog(19," with fail.");         // если вернуло false - не удалось записать
                                        SendEndTimeToLog();                     // пишем в лог время окончания операции
                                        LBar->Free();                           // уничтожаем форму с прогресс-баром
                                        return;                                 // выходим
                                }
                                // если записали количество байт кратное 8
                                if((i+1)%8==0)
                                {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area3Size;  // вычисляем новую позицию прогресс-бара
                                }
                        }
                    }
                    else                                  // если записываем только слово конфигурации
                    {   if(!PIC16F630_MakePCOffset(6,1))    // сдвигаем указатель на адрес перед нужным (7-1=6), сдвиг ещё на единицу произойдёт в функции чтения пред чтением
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                        // после этого можно уже и писать
                        if(!PIC16F630_WriteConfigMemory(7,0))   // пробуем записать слово конфигурации по адресу 7 (0x2007)
                        {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось прочитать
                            LBar->Free();                   // уничтожаем форму с прогресс-баром
                            return;                         // выходим
                        }
                    }
                    //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                    //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                    if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                    {   SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                        return;                         // выходим
                    }
                    if(Form1->CheckBox1->Checked == true) // если читали калибровочные значения, то они к этому моменту автоматически восстановились
                    {   SendMsgToLog(0,"    OSCCAL & BG-bits has been restored");  // сообщаем о восстановлении калибровочных значений
                    }
                    break;
      case 0:   SendMsgToLog(14,"");            // сообщение в лог, что не выбран ни один чип
                LBar->Free();                   // уничтожаем форму с прогресс-баром
                SendEndTimeToLog();             // пишем в лог время окончания операции
                return;                         // выходим
      default:  SendMsgToLog(15," unknown");    // сообщение в лог, что чип нам неизвестен и выходим
                LBar->Free();                   // уничтожаем форму с прогресс-баром
                SendEndTimeToLog();             // пишем в лог время окончания операции
                return;                         // выходим
    }
    LBar->Free();         // уничтожаем форму с прогресс-баром
    // функция PlaceDataToForm тоже использует прогрессбар, если его выше не уничтожить - будет эксепшн
    // показываем в нужном окне новые значения памяти конфигурации и программы
    switch(Form1->PageControl1->TabIndex)
    {       case 0: PlaceDataToForm(1,1);      // в RichEdit1 из Area1 - Program memory
                    PlaceDataToForm(6,3);      // в RichEdit6 из Area3 - Config memory
                    break;
            case 1: PlaceDataToForm(2,1);      // в RichEdit2 из Area1 - Program memory
                    PlaceDataToForm(7,3);      // в RichEdit7 из Area3 - Config memory
                    break;
            default: break;
    }
    SendMsgToLog(19,"");  // сообщаем о завершении операции
    SendEndTimeToLog();   // пишем в лог время окончания операции
  }
  else  SendMsgToLog(0,"Operation cancelled");         // сообщаем об отмене операции
}
//---------------------------------------------------------------------------
//--- НАЖАТА КНОПКА WRITE DATA MEMORY ---------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::Button9Click(TObject *Sender)
{ if (Application->MessageBox("Previous data in the Data memory will be lost!\n            Are you sure?", "Warning", MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2|MB_APPLMODAL) == IDYES)
  { // сначала нужно поместить в память данные с формы, в зависимости от вкладки
    switch(Form1->PageControl1->TabIndex)
    {   case 0: GetDataToMemory(3,2);      // из RichEdit3 в Area2
                break;
        case 1: GetDataToMemory(4,2);      // из RichEdit4 в Area2
                break;
        default: break;
    }

    // включаем прогресс-бар
    Application->CreateForm(__classid(TLBar),&LBar);    // создаём форму с прогресс-баром
    LBar->Show();                                       // показываем её в немодальном окне

    SendMsgToLog(18," write the data memory");          // сообщаем о попытке записать EEPROM
    SendStartTimeToLog();                    // пишем в лог время начала операции
    switch(SelectedChip.ID&0x3FE0)     // отрезаем 5 младших бит при выборе чипа (они определяют ревизию, а не модель)
    { // в этих чипах есть EEPROM, int timing при записи
      case 0x2080:      // выбрано устройство PIC16F887
      case 0x2060:      // выбрано устройство PIC16F886
      case 0x2040:      // выбрано устройство PIC16F884
      case 0x2020:      // выбрано устройство PIC16F883
      case 0x2000:      // выбрано устройство PIC16F882
      case 0x1100:      // выбрано устройство PIC16F648A
      case 0x1060:      // выбрано устройство PIC16F628A
      case 0x1040:      // выбрано устройство PIC16F627A
      case 0x1200:      // выбрано устройство PIC16F785
      case 0x14A0:      // выбрано устройство PIC16LF1847
      case 0x1480:      // выбрано устройство PIC16F1847
      case 0x1BC0:      // выбрано устройство PIC12LF1840
      case 0x1B80:      // выбрано устройство PIC12F1840
      case 0x28E0:      // выбрано устройство PIC16LF1829
      case 0x27E0:      // выбрано устройство PIC16F1829
      case 0x28C0:      // выбрано устройство PIC16LF1828
      case 0x27C0:      // выбрано устройство PIC16F1828
      case 0x28A0:      // выбрано устройство PIC16LF1827
      case 0x27A0:      // выбрано устройство PIC16F1827
      case 0x2880:      // выбрано устройство PIC16LF1826
      case 0x2780:      // выбрано устройство PIC16F1826
      case 0x2860:      // выбрано устройство PIC16LF1825
      case 0x2760:      // выбрано устройство PIC16F1825
      case 0x2840:      // выбрано устройство PIC16LF1824
      case 0x2740:      // выбрано устройство PIC16F1824
      case 0x2820:      // выбрано устройство PIC16LF1823
      case 0x2720:      // выбрано устройство PIC16F1823
      case 0x2800:      // выбрано устройство PIC12LF1822
      case 0x2700:      // выбрано устройство PIC12F1822
      case 0x1400:      // выбрано устройство PIC16F690
      case 0x1340:      // выбрано устройство PIC16F689
      case 0x1180:      // выбрано устройство PIC16F688
      case 0x1320:      // выбрано устройство PIC16F687
      case 0x04A0:      // выбрано устройство PIC16F685
      case 0x1080:      // выбрано устройство PIC16F684
      case 0x1440:      // выбрано устройство PIC16F677
      case 0x10A0:      // выбрано устройство PIC16F636 / PIC16F639
      case 0x1420:      // выбрано устройство PIC16F631
      case 0x0460:      // выбрано устройство PIC12F683
      case 0x0FA0:      // выбрано устройство PIC12F635
      case 0x10C0:      // выбрано устройство PIC16F630
      case 0x10E0:      // выбрано устройство PIC16F676
      case 0x0F80:      // выбрано устройство PIC12F629
      case 0x0FC0:      // выбрано устройство PIC12F675
                        if(!SetInitState())                     // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())           // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // после этого можно уже и писать
                        for(unsigned int i=0; i<SelectedChip.Area2Size; i++)    // пишем по байтам
                        {       if(!PIC16F630_WriteDataMemory(i,0))             // пробуем записать байт данных (int timing)
                                {       SendMsgToLog(19," with fail.");         // если вернуло false - не удалось прочитать
                                        SendEndTimeToLog();                     // пишем в лог время окончания операции
                                        LBar->Free();                           // уничтожаем форму с прогресс-баром
                                        return;                                 // выходим
                                }
                                // если записали количество байт кратное 16
                                if((i+1)%8==0)
                                {       LBar->ProgressBar1->Position=100*(i+1)/SelectedChip.Area2Size;  // вычисляем новую позицию прогресс-бара
                                }
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        break;
      case 0x3020:        // возможно это PIC16F753
                        if(SelectedChip.ID == 0x3030)       // если это точно PIC16F753
                        {       SendMsgToLog(0,"function is unavailable for this chip");        // сообщение в лог, что функция недоступна
                                SendEndTimeToLog();             // пишем в лог время окончания операции
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        else
                        {       SendMsgToLog(15," unknown");    // сообщение в лог, что чип нам неизвестен и выходим
                                SendEndTimeToLog();             // пишем в лог время окончания операции
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;
                        }
                        //break; - закомментировано, так как выше выходим в любом случае
      // в этих чипах нет EEPROM
      case 0x1900:        // выбрано устройство PIC16LF727
      case 0x1800:        // выбрано устройство PIC16F727
      case 0x1940:        // выбрано устройство PIC16LF724
      case 0x1840:        // выбрано устройство PIC16F724
      case 0x1920:        // выбрано устройство PIC16LF726
      case 0x1820:        // выбрано устройство PIC16F726
      case 0x1B40:        // выбрано устройство PIC16LF723A
      case 0x1B00:        // выбрано устройство PIC16F723A
      case 0x1960:        // выбрано устройство PIC16LF723
      case 0x1860:        // выбрано устройство PIC16F723
      case 0x1B60:        // выбрано устройство PIC16LF722A
      case 0x1B20:        // выбрано устройство PIC16F722A
      case 0x1980:        // выбрано устройство PIC16LF722
      case 0x1880:        // выбрано устройство PIC16F722
      case 0x1C60:        // выбрано устройство PIC16LF721
      case 0x1C20:        // выбрано устройство PIC16F721
      case 0x1C40:        // выбрано устройство PIC16LF720
      case 0x1C00:        // выбрано устройство PIC16F720
      case 0x1AE0:        // выбрано устройство PIC16LF707
      case 0x1AC0:        // выбрано устройство PIC16F707
      case 0x1240:        // выбрано устройство PIC16F616
      case 0x2260:        // выбрано устройство PIC16F610
      case 0x2240:        // выбрано устройство PIC12F609
      case 0x1360:        // выбрано устройство PIC12F617
      case 0x2180:        // выбрано устройство PIC12F615
      case 0x2E00:        // выбрано устройство PIC16LF1509
      case 0x2D40:        // выбрано устройство PIC16F1509
      case 0x2DE0:        // выбрано устройство PIC16LF1508
      case 0x2D20:        // выбрано устройство PIC16F1508
      case 0x2DC0:        // выбрано устройство PIC16LF1507
      case 0x2D00:        // выбрано устройство PIC16F1507
      case 0x2DA0:        // выбрано устройство PIC16LF1503
      case 0x2CE0:        // выбрано устройство PIC16F1503
      case 0x2D80:        // выбрано устройство PIC12LF1501
      case 0x2CC0:        // выбрано устройство PIC12F1501
      case 0x1500:        // выбрано устройство PIC12F752
                SendMsgToLog(0,"function is unavailable for this chip");        // сообщение в лог, что функция недоступна
                SendEndTimeToLog();             // пишем в лог время окончания операции
                LBar->Free();                   // уничтожаем форму с прогресс-баром
                return;                         // выходим
      case 0:  SendMsgToLog(14,"");             // сообщение в лог, что не выбран ни один чип
               SendEndTimeToLog();              // пишем в лог время окончания операции
               LBar->Free();                    // уничтожаем форму с прогресс-баром
               return;                          // выходим
      default: SendMsgToLog(15," unknown");     // сообщение в лог, что чип нам неизвестен и выходим
               SendEndTimeToLog();              // пишем в лог время окончания операции
               LBar->Free();                    // уничтожаем форму с прогресс-баром
               return;                          // выходим
    }
    LBar->Free();         // уничтожаем форму с прогресс-баром
    SendMsgToLog(19,"");  // сообщаем о завершении операции
    SendEndTimeToLog();   // пишем в лог время окончания операции
  }
  else  SendMsgToLog(0,"Operation cancelled");  // сообщаем об отмене операции
}
//---------------------------------------------------------------------------
//--- НАЖАТА КНОПКА READ PROGRAM & CONFIG MEMORY ----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{ unsigned short Temp;

  // включаем прогресс-бар
  Application->CreateForm(__classid(TLBar),&LBar);      // создаём форму с прогресс-баром
  LBar->Show();                                         // показываем её в немодальном окне

  SendMsgToLog(18," read program & config  memory"); // сообщаем о попытке прочитать программу и конфигурацию (целиком)
  SendStartTimeToLog();                         // пишем в лог время начала операции
  switch(SelectedChip.ID&0x3FE0)     // отрезаем 5 младших бит при выборе чипа (они определяют ревизию, а не модель)
  { case 0x3020:        // возможно это PIC16F753
                        if(SelectedChip.ID == 0x3030)       // если это точно PIC16F753
                        {       // 1. читаем программу
                                if(!SetInitState())                     // пробуем установить начальные уровни на ногах чипа
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                if(!EnterHVPVMode_VPPfirst())           // пробуем перейти в режим программирования по алгоритму Vpp-first
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                // после перехода в режим программирования можно читать
                                for(unsigned int i=0; i<SelectedChip.Area1Size/2; i++)  // читаем по словам
                                {       if(!PIC16F630_ReadProgramMemory(i,0))           // пробуем прочитать слово программы
                                        {       SendMsgToLog(19," with fail.");         // если вернуло false - не удалось прочитать
                                                SendEndTimeToLog();                     // пишем в лог время окончания операции
                                                LBar->Free();                           // уничтожаем форму с прогресс-баром
                                                return;                                 // выходим
                                        }
                                        // если прочитали количество байт кратное 8
                                        if((i+1)%8==0)
                                        {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area1Size;  // вычисляем новую позицию прогресс-бара
                                        }
                                }
                                // 2. читаем память конфигурации
                                if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                                // после перехода в область конфигурации можно читать
                                for(unsigned int i=0; i<SelectedChip.Area3Size/2; i++)  // читаем по словам
                                {       if(!PIC16F630_ReadConfigMemory(i,0))            // пробуем прочитать слово программы
                                        {       SendMsgToLog(19," with fail.");         // если вернуло false - не удалось прочитать
                                                SendEndTimeToLog();                     // пишем в лог время окончания операции
                                                LBar->Free();                           // уничтожаем форму с прогресс-баром
                                                return;                                 // выходим
                                        }
                                        // если прочитали количество байт кратное 8
                                        if((i+1)%8==0)
                                        {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area3Size;  // вычисляем новую позицию прогресс-бара
                                        }
                                }
                                //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                                //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                                if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                                {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                        LBar->Free();                   // уничтожаем форму с прогресс-баром
                                        return;                         // выходим
                                }
                        }
                        else
                        {       SendMsgToLog(15," unknown");    // сообщение в лог, что чип нам неизвестен и выходим
                                SendEndTimeToLog();             // пишем в лог время окончания операции
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        break;
    case 0x2080:        // выбрано устройство PIC16F887
    case 0x2060:        // выбрано устройство PIC16F886
    case 0x2040:        // выбрано устройство PIC16F884
    case 0x2020:        // выбрано устройство PIC16F883
    case 0x2000:        // выбрано устройство PIC16F882
    case 0x1900:        // выбрано устройство PIC16LF727
    case 0x1800:        // выбрано устройство PIC16F727
    case 0x1940:        // выбрано устройство PIC16LF724
    case 0x1840:        // выбрано устройство PIC16F724
    case 0x1920:        // выбрано устройство PIC16LF726
    case 0x1820:        // выбрано устройство PIC16F726
    case 0x1B40:        // выбрано устройство PIC16LF723A
    case 0x1B00:        // выбрано устройство PIC16F723A
    case 0x1960:        // выбрано устройство PIC16LF723
    case 0x1860:        // выбрано устройство PIC16F723
    case 0x1B60:        // выбрано устройство PIC16LF722A
    case 0x1B20:        // выбрано устройство PIC16F722A
    case 0x1980:        // выбрано устройство PIC16LF722
    case 0x1880:        // выбрано устройство PIC16F722
    case 0x1C60:        // выбрано устройство PIC16LF721
    case 0x1C20:        // выбрано устройство PIC16F721
    case 0x1C40:        // выбрано устройство PIC16LF720
    case 0x1C00:        // выбрано устройство PIC16F720
    case 0x1AE0:        // выбрано устройство PIC16LF707
    case 0x1AC0:        // выбрано устройство PIC16F707
    case 0x1100:        // выбрано устройство PIC16F648A
    case 0x1060:        // выбрано устройство PIC16F628A
    case 0x1040:        // выбрано устройство PIC16F627A
    case 0x1200:        // выбрано устройство PIC16F785
    case 0x14A0:        // выбрано устройство PIC16LF1847
    case 0x1480:        // выбрано устройство PIC16F1847
    case 0x1BC0:        // выбрано устройство PIC12LF1840
    case 0x1B80:        // выбрано устройство PIC12F1840
    case 0x28E0:        // выбрано устройство PIC16LF1829
    case 0x27E0:        // выбрано устройство PIC16F1829
    case 0x28C0:        // выбрано устройство PIC16LF1828
    case 0x27C0:        // выбрано устройство PIC16F1828
    case 0x28A0:        // выбрано устройство PIC16LF1827
    case 0x27A0:        // выбрано устройство PIC16F1827
    case 0x2880:        // выбрано устройство PIC16LF1826
    case 0x2780:        // выбрано устройство PIC16F1826
    case 0x2860:        // выбрано устройство PIC16LF1825
    case 0x2760:        // выбрано устройство PIC16F1825
    case 0x2840:        // выбрано устройство PIC16LF1824
    case 0x2740:        // выбрано устройство PIC16F1824
    case 0x2820:        // выбрано устройство PIC16LF1823
    case 0x2720:        // выбрано устройство PIC16F1823
    case 0x2800:        // выбрано устройство PIC12LF1822
    case 0x2700:        // выбрано устройство PIC12F1822
    case 0x1240:        // выбрано устройство PIC16F616
    case 0x2260:        // выбрано устройство PIC16F610
    case 0x2240:        // выбрано устройство PIC12F609
    case 0x1360:        // выбрано устройство PIC12F617
    case 0x2180:        // выбрано устройство PIC12F615
    case 0x2E00:        // выбрано устройство PIC16LF1509
    case 0x2D40:        // выбрано устройство PIC16F1509
    case 0x2DE0:        // выбрано устройство PIC16LF1508
    case 0x2D20:        // выбрано устройство PIC16F1508
    case 0x2DC0:        // выбрано устройство PIC16LF1507
    case 0x2D00:        // выбрано устройство PIC16F1507
    case 0x2DA0:        // выбрано устройство PIC16LF1503
    case 0x2CE0:        // выбрано устройство PIC16F1503
    case 0x2D80:        // выбрано устройство PIC12LF1501
    case 0x2CC0:        // выбрано устройство PIC12F1501
    case 0x1500:        // выбрано устройство PIC12F752
    case 0x1400:        // выбрано устройство PIC16F690
    case 0x1340:        // выбрано устройство PIC16F689
    case 0x1180:        // выбрано устройство PIC16F688
    case 0x1320:        // выбрано устройство PIC16F687
    case 0x04A0:        // выбрано устройство PIC16F685
    case 0x1080:        // выбрано устройство PIC16F684
    case 0x1440:        // выбрано устройство PIC16F677
    case 0x10A0:        // выбрано устройство PIC16F636 / PIC16F639
    case 0x1420:        // выбрано устройство PIC16F631
    case 0x0460:        // выбрано устройство PIC12F683
    case 0x0FA0:        // выбрано устройство PIC12F635
    case 0x10C0:        // выбрано устройство PIC16F630
    case 0x10E0:        // выбрано устройство PIC16F676
    case 0x0F80:        // выбрано устройство PIC12F629
    case 0x0FC0:        // выбрано устройство PIC12F675
                        // 1. читаем программу
                        if(!SetInitState())                     // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())           // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // после перехода в режим программирования можно читать
                        for(unsigned int i=0; i<SelectedChip.Area1Size/2; i++)  // читаем по словам
                        {       if(!PIC16F630_ReadProgramMemory(i,0))           // пробуем прочитать слово программы
                                {       SendMsgToLog(19," with fail.");         // если вернуло false - не удалось прочитать
                                        SendEndTimeToLog();                     // пишем в лог время окончания операции
                                        LBar->Free();                           // уничтожаем форму с прогресс-баром
                                        return;                                 // выходим
                                }
                                // если прочитали количество байт кратное 8
                                if((i+1)%8==0)
                                {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area1Size;  // вычисляем новую позицию прогресс-бара
                                }
                        }
                        // 2. читаем память конфигурации
                        if(!PIC16F630_SetPCToConfigMemory())    // пробуем перейти в область Config Memory
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // после перехода в область конфигурации можно читать
                        for(unsigned int i=0; i<SelectedChip.Area3Size/2; i++)  // читаем по словам
                        {       if(!PIC16F630_ReadConfigMemory(i,0))            // пробуем прочитать слово программы
                                {       SendMsgToLog(19," with fail.");         // если вернуло false - не удалось прочитать
                                        SendEndTimeToLog();                     // пишем в лог время окончания операции
                                        LBar->Free();                           // уничтожаем форму с прогресс-баром
                                        return;                                 // выходим
                                }
                                // если прочитали количество байт кратное 8
                                if((i+1)%8==0)
                                {       LBar->ProgressBar1->Position=2*100*(i+1)/SelectedChip.Area3Size;  // вычисляем новую позицию прогресс-бара
                                }
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        break;
    case 0:     SendMsgToLog(14,"");            // сообщение в лог, что не выбран ни один чип
                SendEndTimeToLog();             // пишем в лог время окончания операции
                LBar->Free();                   // уничтожаем форму с прогресс-баром
                return;                         // выходим
    default:    SendMsgToLog(15," unknown");    // сообщение в лог, что чип нам неизвестен и выходим
                SendEndTimeToLog();             // пишем в лог время окончания операции
                LBar->Free();                   // уничтожаем форму с прогресс-баром
                return;                         // выходим
  }
  LBar->Free();         // уничтожаем форму с прогресс-баром

  // помещаем прочитанное на форму в зависимости от вкладки
  switch(Form1->PageControl1->TabIndex)
  {     case 0: PlaceDataToForm(1,1);      // в RichEdit1 из Area1
                PlaceDataToForm(6,3);      // в RichEdit6 из Area3
                break;
        case 1: PlaceDataToForm(2,1);      // в RichEdit2 из Area1
                PlaceDataToForm(7,3);      // в RichEdit7 из Area3
                break;
        default: break;
  }

  // проверяем ChipID и сообщаем, если он не совпадает с выбранным чипом
  Temp = SelectedChip.Area3[2*6] + (SelectedChip.Area3[2*6+1] << 8);
  if( (SelectedChip.ID & 0x3FE0) != (Temp & 0x3FE0))
        Application->MessageBox("The read ChipID does not match the selected one!", "Warning", MB_OK|MB_ICONWARNING|MB_APPLMODAL);

  SendMsgToLog(19,"");  // сообщаем о завершении операции
  SendEndTimeToLog();   // пишем в лог время окончания операции
}
//---------------------------------------------------------------------------
//--- НАЖАТА КНОПКА READ DATA -----------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::Button8Click(TObject *Sender)
{ // включаем прогресс-бар
  Application->CreateForm(__classid(TLBar),&LBar);      // создаём форму с прогресс-баром
  LBar->Show();                                         // показываем её в немодальном окне

  SendMsgToLog(18," read the data memory");          // сообщаем о попытке прочитать программу
  SendStartTimeToLog();                         // пишем в лог время начала операции
  switch(SelectedChip.ID&0x3FE0)     // отрезаем 5 младших бит при выборе чипа (они определяют ревизию, а не модель)
  { // в этих чипах есть EEPROM
    case 0x2080:        // выбрано устройство PIC16F887
    case 0x2060:        // выбрано устройство PIC16F886
    case 0x2040:        // выбрано устройство PIC16F884
    case 0x2020:        // выбрано устройство PIC16F883
    case 0x2000:        // выбрано устройство PIC16F882
    case 0x1100:        // выбрано устройство PIC16F648A
    case 0x1060:        // выбрано устройство PIC16F628A
    case 0x1040:        // выбрано устройство PIC16F627A
    case 0x1200:        // выбрано устройство PIC16F785
    case 0x14A0:        // выбрано устройство PIC16LF1847
    case 0x1480:        // выбрано устройство PIC16F1847
    case 0x1BC0:        // выбрано устройство PIC12LF1840
    case 0x1B80:        // выбрано устройство PIC12F1840
    case 0x28E0:        // выбрано устройство PIC16LF1829
    case 0x27E0:        // выбрано устройство PIC16F1829
    case 0x28C0:        // выбрано устройство PIC16LF1828
    case 0x27C0:        // выбрано устройство PIC16F1828
    case 0x28A0:        // выбрано устройство PIC16LF1827
    case 0x27A0:        // выбрано устройство PIC16F1827
    case 0x2880:        // выбрано устройство PIC16LF1826
    case 0x2780:        // выбрано устройство PIC16F1826
    case 0x2860:        // выбрано устройство PIC16LF1825
    case 0x2760:        // выбрано устройство PIC16F1825
    case 0x2840:        // выбрано устройство PIC16LF1824
    case 0x2740:        // выбрано устройство PIC16F1824
    case 0x2820:        // выбрано устройство PIC16LF1823
    case 0x2720:        // выбрано устройство PIC16F1823
    case 0x2800:        // выбрано устройство PIC12LF1822
    case 0x2700:        // выбрано устройство PIC12F1822
    case 0x1400:        // выбрано устройство PIC16F690
    case 0x1340:        // выбрано устройство PIC16F689
    case 0x1180:        // выбрано устройство PIC16F688
    case 0x1320:        // выбрано устройство PIC16F687
    case 0x04A0:        // выбрано устройство PIC16F685
    case 0x1080:        // выбрано устройство PIC16F684
    case 0x1440:        // выбрано устройство PIC16F677
    case 0x10A0:        // выбрано устройство PIC16F636 / PIC16F639
    case 0x1420:        // выбрано устройство PIC16F631
    case 0x0460:        // выбрано устройство PIC12F683
    case 0x0FA0:        // выбрано устройство PIC12F635
    case 0x10C0:        // выбрано устройство PIC16F630
    case 0x10E0:        // выбрано устройство PIC16F676
    case 0x0F80:        // выбрано устройство PIC12F629
    case 0x0FC0:        // выбрано устройство PIC12F675
                        if(!SetInitState())                     // пробуем установить начальные уровни на ногах чипа
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        if(!EnterHVPVMode_VPPfirst())           // пробуем перейти в режим программирования по алгоритму Vpp-first
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        // после этого можно уже и читать
                        for(unsigned int i=0; i<SelectedChip.Area2Size; i++)    // читаем по байтам
                        {       if(!PIC16F630_ReadDataMemory(i,0))              // пробуем прочитать байт данных
                                {       SendMsgToLog(19," with fail.");         // если вернуло false - не удалось прочитать
                                        SendEndTimeToLog();                     // пишем в лог время окончания операции
                                        LBar->Free();                           // уничтожаем форму с прогресс-баром
                                        return;                                 // выходим
                                }
                                // если прочитали количество байт кратное 16
                                if((i+1)%8==0)
                                {       LBar->ProgressBar1->Position=100*(i+1)/SelectedChip.Area2Size;  // вычисляем новую позицию прогресс-бара
                                }
                        }
                        //--- каким-то чипам для выхода нужен алгоритм Vpp-last, каким-то Vdd-last, мы будем выключать
                        //--- оба напряжения одноременно, просто переводя выводы в начальные состояния
                        if(!SetInitState())                   // пробуем установить начальные уровни на ногах чипа (при этом отключаются Vpp и Vdd)
                        {       SendMsgToLog(19," with fail."); // если вернуло false - не удалось выполнить требуемое действие
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        break;
    case 0x3020:        // возможно это PIC16F753
                        if(SelectedChip.ID == 0x3030)       // если это точно PIC16F753
                        {       SendMsgToLog(0,"function is unavailable for this chip");        // сообщение в лог, что функция недоступна
                                SendEndTimeToLog();             // пишем в лог время окончания операции
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;                         // выходим
                        }
                        else
                        {       SendMsgToLog(15," unknown");    // сообщение в лог, что чип нам неизвестен и выходим
                                SendEndTimeToLog();             // пишем в лог время окончания операции
                                LBar->Free();                   // уничтожаем форму с прогресс-баром
                                return;
                        }
                        //break; - закомментировано, так как выше выходим в любом случае
    // в этих чипах нет EEPROM
    case 0x1900:        // выбрано устройство PIC16LF727
    case 0x1800:        // выбрано устройство PIC16F727
    case 0x1940:        // выбрано устройство PIC16LF724
    case 0x1840:        // выбрано устройство PIC16F724
    case 0x1920:        // выбрано устройство PIC16LF726
    case 0x1820:        // выбрано устройство PIC16F726
    case 0x1B40:        // выбрано устройство PIC16LF723A
    case 0x1B00:        // выбрано устройство PIC16F723A
    case 0x1960:        // выбрано устройство PIC16LF723
    case 0x1860:        // выбрано устройство PIC16F723
    case 0x1B60:        // выбрано устройство PIC16LF722A
    case 0x1B20:        // выбрано устройство PIC16F722A
    case 0x1980:        // выбрано устройство PIC16LF722
    case 0x1880:        // выбрано устройство PIC16F722
    case 0x1C60:        // выбрано устройство PIC16LF721
    case 0x1C20:        // выбрано устройство PIC16F721
    case 0x1C40:        // выбрано устройство PIC16LF720
    case 0x1C00:        // выбрано устройство PIC16F720
    case 0x1AE0:        // выбрано устройство PIC16LF707
    case 0x1AC0:        // выбрано устройство PIC16F707
    case 0x1240:        // выбрано устройство PIC16F616
    case 0x2260:        // выбрано устройство PIC16F610
    case 0x2240:        // выбрано устройство PIC12F609
    case 0x1360:        // выбрано устройство PIC12F617
    case 0x2180:        // выбрано устройство PIC12F615
    case 0x2E00:        // выбрано устройство PIC16LF1509
    case 0x2D40:        // выбрано устройство PIC16F1509
    case 0x2DE0:        // выбрано устройство PIC16LF1508
    case 0x2D20:        // выбрано устройство PIC16F1508
    case 0x2DC0:        // выбрано устройство PIC16LF1507
    case 0x2D00:        // выбрано устройство PIC16F1507
    case 0x2DA0:        // выбрано устройство PIC16LF1503
    case 0x2CE0:        // выбрано устройство PIC16F1503
    case 0x2D80:        // выбрано устройство PIC12LF1501
    case 0x2CC0:        // выбрано устройство PIC12F1501
    case 0x1500:        // выбрано устройство PIC12F752
                SendMsgToLog(0,"function is unavailable for this chip");        // сообщение в лог, что функция недоступна
                SendEndTimeToLog();             // пишем в лог время окончания операции
                LBar->Free();                   // уничтожаем форму с прогресс-баром
                return;                         // выходим
    case 0:     SendMsgToLog(14,"");            // сообщение в лог, что не выбран ни один чип
                SendEndTimeToLog();             // пишем в лог время окончания операции
                LBar->Free();                   // уничтожаем форму с прогресс-баром
                return;                         // выходим
    default:    SendMsgToLog(15," unknown");    // сообщение в лог, что чип нам неизвестен и выходим
                SendEndTimeToLog();             // пишем в лог время окончания операции
                LBar->Free();                   // уничтожаем форму с прогресс-баром
                return;                         // выходим
  }
  LBar->Free();         // уничтожаем форму с прогресс-баром

  // помещаем прочитанное на форму в зависимости от вкладки
  switch(Form1->PageControl1->TabIndex)
  {     case 0: PlaceDataToForm(3,2);      // в RichEdit3 из Area2
                break;
        case 1: PlaceDataToForm(4,2);      // в RichEdit4 из Area2
                break;
        default: break;
  }
  SendMsgToLog(19,"");  // сообщаем о завершении операции
  SendEndTimeToLog();   // пишем в лог время окончания операции
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F630 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F6301Click(TObject *Sender)
{ InitChip(0x10C0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F676 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F6761Click(TObject *Sender)
{ InitChip(0x10E0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC12F629 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC12F6291Click(TObject *Sender)
{ InitChip(0x0F80);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC12F675 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC12F6751Click(TObject *Sender)
{ InitChip(0x0FC0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC12F635 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC12F6351Click(TObject *Sender)
{ InitChip(0x0FA0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC12F683 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC12F6831Click(TObject *Sender)
{ InitChip(0x0460);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F631 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F6311Click(TObject *Sender)
{ InitChip(0x1420);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F636 / PIC16F639 -------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F6361Click(TObject *Sender)
{ InitChip(0x10A0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F677 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F6771Click(TObject *Sender)
{ InitChip(0x1440);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F684 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F6841Click(TObject *Sender)
{ InitChip(0x1080);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F685 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F6851Click(TObject *Sender)
{ InitChip(0x04A0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F687 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F6871Click(TObject *Sender)
{ InitChip(0x1320);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F688 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F6881Click(TObject *Sender)
{ InitChip(0x1180);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F689 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F6891Click(TObject *Sender)
{ InitChip(0x1340);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F690 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F6901Click(TObject *Sender)
{ InitChip(0x1400);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC12F752 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC12F7521Click(TObject *Sender)
{ InitChip(0x1500);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC12F1501 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC12F15011Click(TObject *Sender)
{ InitChip(0x2CC0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC12LF1501 -----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC12LF15011Click(TObject *Sender)
{ InitChip(0x2D80);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F1503 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F15031Click(TObject *Sender)
{ InitChip(0x2CE0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF1503 -----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF15031Click(TObject *Sender)
{ InitChip(0x2DA0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F1507 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F15071Click(TObject *Sender)
{  InitChip(0x2D00);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF1507 -----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF15071Click(TObject *Sender)
{ InitChip(0x2DC0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F1508 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F15081Click(TObject *Sender)
{ InitChip(0x2D20);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF1508 -----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF15081Click(TObject *Sender)
{ InitChip(0x2DE0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F1509 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F15091Click(TObject *Sender)
{ InitChip(0x2D40);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF1509 -----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF15091Click(TObject *Sender)
{ InitChip(0x2E00);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC12F615 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC12F6151Click(TObject *Sender)
{ InitChip(0x2180);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC12F617 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC12F6171Click(TObject *Sender)
{ InitChip(0x1360);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC12F609 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC12F6091Click(TObject *Sender)
{ InitChip(0x2240);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F610 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F6101Click(TObject *Sender)
{ InitChip(0x2260);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F616 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F6161Click(TObject *Sender)
{ InitChip(0x1240);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC12F1822 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC12F18221Click(TObject *Sender)
{ InitChip(0x2700);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC12LF1822 -----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC12LF18221Click(TObject *Sender)
{ InitChip(0x2800);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F1823 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F18231Click(TObject *Sender)
{ InitChip(0x2720);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF1823 -----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF18231Click(TObject *Sender)
{ InitChip(0x2820);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F1824 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F18241Click(TObject *Sender)
{ InitChip(0x2740);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF1824 -----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF18241Click(TObject *Sender)
{ InitChip(0x2840);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F1825 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F18251Click(TObject *Sender)
{ InitChip(0x2760);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF1825 -----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF18251Click(TObject *Sender)
{ InitChip(0x2860);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F1826 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F18261Click(TObject *Sender)
{ InitChip(0x2780);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF1826 -----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF18261Click(TObject *Sender)
{ InitChip(0x2880);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F1827 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F18271Click(TObject *Sender)
{ InitChip(0x27A0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF1827 -----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF18271Click(TObject *Sender)
{ InitChip(0x28A0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F1828 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F18281Click(TObject *Sender)
{ InitChip(0x27C0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF1828 -----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF18281Click(TObject *Sender)
{ InitChip(0x28C0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F1829 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F18291Click(TObject *Sender)
{ InitChip(0x27E0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF1829 -----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF18291Click(TObject *Sender)
{ InitChip(0x28E0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC12F1840 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC12F18401Click(TObject *Sender)
{ InitChip(0x1B80);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC12LF1840 -----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC12LF18401Click(TObject *Sender)
{ InitChip(0x1BC0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F1847 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F18471Click(TObject *Sender)
{ InitChip(0x1480);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF1847 -----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF18471Click(TObject *Sender)
{ InitChip(0x14A0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F753 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F7531Click(TObject *Sender)
{ // у этого чипа нет ревизии в последних 5 битах ID, все биты используются как ID
  InitChip(0x3030);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F753 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F7851Click(TObject *Sender)
{ InitChip(0x1200);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F627A ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F627A1Click(TObject *Sender)
{ InitChip(0x1040);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F628A ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F628A1Click(TObject *Sender)
{ InitChip(0x1060);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F648A ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F648A1Click(TObject *Sender)
{ InitChip(0x1100);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F707 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F7071Click(TObject *Sender)
{ InitChip(0x1AC0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF707 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF7071Click(TObject *Sender)
{ InitChip(0x1AE0);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F720 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F7201Click(TObject *Sender)
{ InitChip(0x1C00);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF720 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF7201Click(TObject *Sender)
{ InitChip(0x1C40);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F721 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F7211Click(TObject *Sender)
{ InitChip(0x1C20);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF721 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF7211Click(TObject *Sender)
{ InitChip(0x1C60);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F722 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F7221Click(TObject *Sender)
{ InitChip(0x1880);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF722 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF7221Click(TObject *Sender)
{ InitChip(0x1980);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F722A ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F722A1Click(TObject *Sender)
{ InitChip(0x1B20);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF722A -----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF722A1Click(TObject *Sender)
{ InitChip(0x1B60);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F723 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F7231Click(TObject *Sender)
{ InitChip(0x1860);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF723 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF7231Click(TObject *Sender)
{ InitChip(0x1960);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F723A ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F723A1Click(TObject *Sender)
{ InitChip(0x1B00);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF723A -----------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF723A1Click(TObject *Sender)
{ InitChip(0x1B40);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F726 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F7261Click(TObject *Sender)
{ InitChip(0x1820);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF726 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF7261Click(TObject *Sender)
{ InitChip(0x1920);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F724 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F7241Click(TObject *Sender)
{ InitChip(0x1840);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF724 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF7241Click(TObject *Sender)
{ InitChip(0x1940);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F727 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F7271Click(TObject *Sender)
{ InitChip(0x1800);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16LF727 ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16LF7271Click(TObject *Sender)
{ InitChip(0x1900);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F882 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F8821Click(TObject *Sender)
{ InitChip(0x2000);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F883 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F8831Click(TObject *Sender)
{ InitChip(0x2020);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F884 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F8841Click(TObject *Sender)
{ InitChip(0x2040);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F886 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F8861Click(TObject *Sender)
{ InitChip(0x2060);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------
//--- ЧЕРЕЗ ВЕРХНЕЕ МЕНЮ ВЫБРАН ЧИП PIC16F887 -------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::PIC16F8871Click(TObject *Sender)
{ InitChip(0x2080);                    // заполняем структуру чипа, инициализируем его память
}
//---------------------------------------------------------------------------

