//---------------------------------------------------------------------------
#pragma hdrstop

#include "ATmega8.h"            // переменные для функций работы с чипами ATmega8
#include "PortFunctions.h"      // переменные для функций работы с портом
#include "LogFunctions.h"       // переменные для отправки сообщений в лог
#include "ChipFunctions.h"      // переменные для работы с чипом
#include "Main.h"               // переменные для работы с главной формой
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
//--- ПЕРЕВОД ЧИПА В РЕЖИМ ПРОГРАММИРОВАНИЯ КОМАНДОЙ PROGRAMMING ENABLE -----
//---------------------------------------------------------------------------
bool ATmega8_ProgrammingEnable()
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных

  SendMsgToLog(18," execute the sinchronization with chip");    // сообщаем о попытке синхронизировать чип
  //--- устанавливаем высокий уровень на линии SS ---
  wr_buf.Size=1;
  wr_buf.Data[0]=0x48;                                    // SetSS_SPI
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," 0x48");         // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return false;
                       }
  Sleep(Delays);//////////
  //--- устанавливаем низкий уровень на линии SS ---
  wr_buf.Size=1;
  wr_buf.Data[0]=0x47;                                    // ClearSS_SPI
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," 0x47");         // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return false;
                       }
  //--- ждём минимум 20 мс ---
  Sleep(20);
  //--- загружаем и отправляем пакет с командой Programming Enable ---
  wr_buf.Size=5;
  wr_buf.Data[1]=0x00;                                    // начиная с младшего байта
  wr_buf.Data[2]=0x00;
  wr_buf.Data[3]=0x53;
  wr_buf.Data[4]=0xAC;                                    // и заканчивая старшим
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x44;                                    // LoadPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x44 0x00 0x00 0x53 0xAC");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                wr_buf.Size=1;
                wr_buf.Data[0]=0x46;                                  // StartChange_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x46");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4C;                                    // FastSendPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4C 0x00 0x00 0x53 0xAC");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
  }
  Sleep(Delays);//////////
  //--- Читаем SPI - буфер (там в третьем байте принятого 32-битного пакета должно быть эхо второго байта) ---
  wr_buf.Size=1;
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x45;                                  // ReadPaketSPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x45");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                // принимаем SPI - буфер (третий байт 32-битного пакета SPI окажется в буфере вторым)
                rd_buf=ReadFrom(8);                                   // читаем
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4A;                                   // ReadSignPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4A");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return 0;
                                     }
                // принимаем байт, содержащий SPI - буфер
                rd_buf=ReadFrom(4);                                   // читаем
  }
  if(!rd_buf.Size) { SendMsgToLog(7," (SPI paket)");    // ошибка приёма пакета
                     CloseHandle(Port);
                     Port=INVALID_HANDLE_VALUE;
                     return false;
                   }
  //--- проверяем эхо, если оно есть - пишем, что всё Ок, если нет - выходим с ошибкой
  if(rd_buf.Data[1]!=0x53) return false;                // второй байт буфера (индекс 1)
  SendMsgToLog(19," with success.");                    // сообщаем, что синхронизация выполнена успешно
  return true;
}
//---------------------------------------------------------------------------
//--- СТИРАНИЕ ЧИПА КОМАНДОЙ CHIP ERASE -------------------------------------
//---------------------------------------------------------------------------
bool ATmega8_ChipErase()
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных

  SendMsgToLog(18," erase the chip");    // сообщаем о попытке стереть чип
  //--- загружаем и отправляем пакет с командой ChipErase ---
  wr_buf.Size=5;
  wr_buf.Data[1]=0x00;                                    // начиная с младшего байта
  wr_buf.Data[2]=0x00;
  wr_buf.Data[3]=0x80;
  wr_buf.Data[4]=0xAC;                                    // и заканчивая старшим
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x44;                                    // LoadPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x44 0x00 0x00 0x80 0xAC");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                wr_buf.Size=1;
                wr_buf.Data[0]=0x46;                                  // StartChange_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x46");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4C;                                    // FastSendPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4C 0x00 0x00 0x80 0xAC");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
  }
  Sleep(Delays);//////////
  //--- время на стирание чипа максимум 9 мс ---
  Sleep(9);
  //--- сообщаем, что всё готово ---
  SendMsgToLog(19," with success.");            // чтение выполнено успешно
  return true;
}
//---------------------------------------------------------------------------
///////////////////////////////
// РАБОТА С ПАМЯТЬЮ ПРОГРАММ //
///////////////////////////////
//---------------------------------------------------------------------------
//--- ЧТЕНИЕ БАЙТА ПО УКАЗАННОМУ АДРЕСУ -------------------------------------
//---------------------------------------------------------------------------
bool ATmega8_ReadProgramMemory(unsigned int Address, bool Action)
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных
  unsigned char H;      // показывает, старший у нас байт или младший
  unsigned char a, b;    // младший и старший байты адреса слова

  // младший бит адреса указывает на старшинство байта в слове
  H =(Address&1)<<3;    // отрезаем все биты, кроме самого младшего и сдвигаем в позицию 3-го бита
  b = Address>>1;       // младший байт адреса слова
  a = Address>>9; // старший байт адреса слова (всё, кроме 4 младших бит - отрезаем)

  //--- загружаем и отправляем пакет с командой ReadProgramMemory ---
  wr_buf.Size=5;
  wr_buf.Data[1]=0x0;                           // начиная с младшего байта
  wr_buf.Data[2]=b;
  wr_buf.Data[3]=a;
  wr_buf.Data[4]=0x20|H;                        // и заканчивая старшим
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x44;                          // LoadPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x44 0x00 b a 0x2H");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                wr_buf.Size=1;
                wr_buf.Data[0]=0x46;                                  // StartChange_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x46");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4C;                                    // FastSendPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4C 0x00 b a 0x2H");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
  }
  Sleep(Delays);//////////
  //--- Читаем SPI - буфер (там в четвёртом байте принятого 32-битного пакета должен быть прочитанный байт) ---
  wr_buf.Size=1;
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x45;                                  // ReadPaketSPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x45");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                // принимаем SPI - буфер (четвёртый байт 32-битного пакета SPI окажется в буфере первым)
                rd_buf=ReadFrom(8);                                   // читаем
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4A;                                   // ReadSignPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4A");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return 0;
                                     }
                // принимаем байт, содержащий SPI - буфер
                rd_buf=ReadFrom(4);                                   // читаем
  }
  if(!rd_buf.Size) { SendMsgToLog(7," (SPI paket)");    // ошибка приёма пакета
                     CloseHandle(Port);
                     Port=INVALID_HANDLE_VALUE;
                     return false;
                   }
  //--- сохраняем прочитанный байт в нужную область программы или сверяем с байтом в памяти ---
  if(!Action)   // если мы читаем байт
  {     SelectedChip.Area1[Address] = rd_buf.Data[0];
  }
  else          // если мы проверяем байт
  {     if(SelectedChip.Area1[Address] != rd_buf.Data[0])       // если байт не совпадает с тем, что в памяти
        {       return false;           // выходим с ошибкой
        }
  }
  return true;
}
//---------------------------------------------------------------------------
//--- ЗАГРУЗКА БАЙТА В СТРАНИЦУ БУФЕРА ПО УКАЗАННОМУ АДРЕСУ -----------------
//---------------------------------------------------------------------------
bool ATmega8_LoadProgramMemoryPage(unsigned int Address)
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных
  unsigned char H;      // показывает, старший у нас байт или младший
  unsigned char b;      // байты адреса слова на странице

  // младший бит адреса указывает на старшинство байта в слове
  H =(Address&1)<<3;    // отрезаем все биты, кроме самого младшего и сдвигаем в позицию 3-го бита
  b = Address>>1;       // младший байт адреса слова на странице

  //--- загружаем и отправляем пакет с командой LoadProgramMemory ---
  wr_buf.Size=5;
  wr_buf.Data[1]=SelectedChip.Area1[Address];   // начиная с младшего байта
  wr_buf.Data[2]=b;
  wr_buf.Data[3]=0x0;
  wr_buf.Data[4]=0x40|H;                        // и заканчивая старшим
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x44;                          // LoadPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x44 Data b 0x00 0x4H");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                wr_buf.Size=1;
                wr_buf.Data[0]=0x46;                                  // StartChange_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x46");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4C;                                    // FastSendPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4C Data b 0x00 0x4H");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
  }
  Sleep(Delays);//////////
  return true;
}
//---------------------------------------------------------------------------
//--- ЗАПИСЬ СТРАНИЦЫ БУФЕРА В ПАМЯТЬ ПРОГРАММЫ ПО УКАЗАННОМУ АДРЕСУ --------
//---------------------------------------------------------------------------
bool ATmega8_WriteProgramMemoryPage(unsigned int Address)
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных
  unsigned char a,b;      // байты адреса страницы

  b = Address>>1;       // младший байт адреса страницы
  a = Address>>9; // старший байт адреса страницы (всё, кроме 4 младших бит - отрезаем)

  //--- загружаем и отправляем пакет с командой LoadProgramMemory ---
  wr_buf.Size=5;
  wr_buf.Data[1]=0x0;                           // начиная с младшего байта
  wr_buf.Data[2]=b;
  wr_buf.Data[3]=a;
  wr_buf.Data[4]=0x4C;                          // и заканчивая старшим
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x44;                          // LoadPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x44 0x00 b a 0x4C");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                wr_buf.Size=1;
                wr_buf.Data[0]=0x46;                                  // StartChange_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x46");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4C;                                    // FastSendPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4C 0x00 b a 0x4C");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
  }
  Sleep(Delays);//////////
  Sleep(5);
  return true;
}
//---------------------------------------------------------------------------
/////////////////////////////
// РАБОТА С ПАМЯТЬЮ EEPROM //
/////////////////////////////
//---------------------------------------------------------------------------
//--- ЧТЕНИЕ БАЙТА ИЗ EEPROM ПО УКАЗАННОМУ АДРЕСУ ---------------------------
//---------------------------------------------------------------------------
bool ATmega8_ReadEEPROMMemory(unsigned int Address, bool Action)
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных
  unsigned char a,b;            // байт адреса слова

  a = Address>>8;   // старший байт адреса
  b = Address;          // младший байт адреса

  //--- загружаем и отправляем пакет с командой ReadEEPROMMemory ---
  wr_buf.Size=5;
  wr_buf.Data[1]=0x0;                           // начиная с младшего байта
  wr_buf.Data[2]=b;
  wr_buf.Data[3]=a;
  wr_buf.Data[4]=0xA0;                          // и заканчивая старшим
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x44;                          // LoadPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x44 0x00 b a 0xA0");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                wr_buf.Size=1;
                wr_buf.Data[0]=0x46;                                  // StartChange_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x46");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4C;                                    // FastSendPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4C 0x00 b a 0xA0");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
  }
  Sleep(Delays);//////////
  //--- Читаем SPI - буфер (там в четвёртом байте принятого 32-битного пакета должен быть прочитанный байт) ---
  wr_buf.Size=1;
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x45;                                  // ReadPaketSPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x45");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                // принимаем SPI - буфер (четвёртый байт 32-битного пакета SPI окажется в буфере первым)
                rd_buf=ReadFrom(8);                                   // читаем
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4A;                                   // ReadSignPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4A");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return 0;
                                     }
                // принимаем байт, содержащий SPI - буфер
                rd_buf=ReadFrom(4);                                   // читаем
  }
  if(!rd_buf.Size) { SendMsgToLog(7," (SPI paket)");    // ошибка приёма пакета
                     CloseHandle(Port);
                     Port=INVALID_HANDLE_VALUE;
                     return false;
                   }
  //--- сохраняем прочитанный байт в нужную область данных  или сверяем с байтом в памяти ---
  if(!Action)   // если мы читаем байт
  {     SelectedChip.Area2[Address] = rd_buf.Data[0];
  }
  else          // если мы проверяем байт
  {     if(SelectedChip.Area2[Address] != rd_buf.Data[0])       // если байт не совпадает с тем, что в памяти
        {       return false;           // выходим с ошибкой
        }
  }
  return true;
}
//---------------------------------------------------------------------------
//--- ЗАПИСЬ БАЙТА В ПАМЯТЬ EEPROM ПО УКАЗАННОМУ АДРЕСУ ---------------------
//---------------------------------------------------------------------------
bool ATmega8_WriteEEPROMMemory(unsigned int Address)
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных
  unsigned char a,b;      // байт адреса

  a = Address>>8;   // старший байт адреса
  b = Address;          // младший байт адреса

  //--- загружаем и отправляем пакет с командой LoadProgramMemory ---
  wr_buf.Size=5;
  wr_buf.Data[1]=SelectedChip.Area2[Address];   // начиная с младшего байта
  wr_buf.Data[2]=b;
  wr_buf.Data[3]=a;
  wr_buf.Data[4]=0xC0;                          // и заканчивая старшим
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x44;                          // LoadPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x44 Data b a 0xC0");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                wr_buf.Size=1;
                wr_buf.Data[0]=0x46;                                  // StartChange_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x46");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4C;                                    // FastSendPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4C Data b a 0xC0");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
  }
  Sleep(Delays);//////////
  Sleep(9);
  return true;
}
//---------------------------------------------------------------------------
/////////////////////
// FUSES, LOCK ... //
/////////////////////
//---------------------------------------------------------------------------
//--- ЧТЕНИЕ LOCK-БИТОВ -----------------------------------------------------
//---------------------------------------------------------------------------
bool ATmega8_ReadLockBits()
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных

  SendMsgToLog(18," read lock-bits");    // сообщаем о попытке прочитать Lock-биты
  //--- загружаем и отправляем пакет с командой ReadLockBits ---
  wr_buf.Size=5;
  wr_buf.Data[1]=0x00;                                    // начиная с младшего байта
  wr_buf.Data[2]=0x00;
  wr_buf.Data[3]=0x00;
  wr_buf.Data[4]=0x58;                                    // и заканчивая старшим
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x44;                                    // LoadPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x44 0x00 0x00 0x00 0x58");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                wr_buf.Size=1;
                wr_buf.Data[0]=0x46;                                  // StartChange_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x46");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4C;                                    // FastSendPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4C 0x00 0x00 0x00 0x58");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
  }
  Sleep(Delays);//////////
  //--- Читаем SPI - буфер (там в четвёртом байте принятого 32-битного пакета должны быть прочитанные биты) ---
  wr_buf.Size=1;
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x45;                                  // ReadPaketSPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x45");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                // принимаем SPI - буфер (четвёртый байт 32-битного пакета SPI окажется в буфере первым)
                rd_buf=ReadFrom(8);                                   // читаем
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4A;                                   // ReadSignPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4A");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return 0;
                                     }
                // принимаем байт, содержащий SPI - буфер
                rd_buf=ReadFrom(4);                                   // читаем
  }
  if(!rd_buf.Size) { SendMsgToLog(7," (SPI paket)");    // ошибка приёма пакета
                     CloseHandle(Port);
                     Port=INVALID_HANDLE_VALUE;
                     return false;
                   }
  //--- сохраняем прочитанный байт в нужную область фьюзов ---
  SelectedChip.Area3[2] = rd_buf.Data[0]|0xC0;  // стираем старшие 2 бита
  SendMsgToLog(19," with success.");            // чтение выполнено успешно
  return true;
}
//---------------------------------------------------------------------------
//--- ЗАПИСЬ LOCK-БИТОВ -----------------------------------------------------
//---------------------------------------------------------------------------
bool ATmega8_WriteLockBits()
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных

  SendMsgToLog(18," write lock-bits");    // сообщаем о попытке записать Lock-биты
  //--- загружаем и отправляем пакет с командой WriteLockBits ---
  wr_buf.Size=5;
  wr_buf.Data[1]=SelectedChip.Area3[2]|0xC0;              // начиная с младшего байта
  wr_buf.Data[2]=0x00;
  wr_buf.Data[3]=0xE0;
  wr_buf.Data[4]=0xAC;                                    // и заканчивая старшим
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x44;                                    // LoadPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x44 Lock 0x00 0xE0 0xAC");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                wr_buf.Size=1;
                wr_buf.Data[0]=0x46;                                  // StartChange_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x46");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4C;                                    // FastSendPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4C Lock 0x00 0xE0 0xAC");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
  }
  Sleep(Delays);//////////
  Sleep(5);
  SendMsgToLog(19," with success.");            // запись выполнена успешно
  return true;
}
//---------------------------------------------------------------------------
//--- ЧТЕНИЕ БАЙТОВ СИГНАТУРЫ -----------------------------------------------
//---------------------------------------------------------------------------
unsigned int ATmega8_ReadSignatureBytes()
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных
  unsigned int ChipID, Temp;    // ответ функции

  SendMsgToLog(18," read signature bytes");     // сообщаем о попытке прочитать байты сигнатуры
  ChipID = 0;                                   // обнуляем ответ
  //--- загружаем и отправляем пакет с командой Read Signature Byte ---
  for(unsigned char i=0;i<3;i++)
  {     wr_buf.Size=5;
        wr_buf.Data[1]=0x0;
        wr_buf.Data[2]=i;                                    // номер байта сигнатуры
        wr_buf.Data[3]=0x0;
        wr_buf.Data[4]=0x30;                                 // команда Read Signature Byte
        switch(SelectedProgrammer)
        { case 1:       wr_buf.Data[0]=0x44;                                 // LoadPaket_SPI
                        if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x44 0x00 i 0x00 0x30");   // ошибка отправки команды
                                                CloseHandle(Port);
                                                Port=INVALID_HANDLE_VALUE;
                                                return 0;
                                             }
                        wr_buf.Size=1;
                        wr_buf.Data[0]=0x46;                                  // StartChange_SPI
                        if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x46");       // ошибка отправки команды
                                                CloseHandle(Port);
                                                Port=INVALID_HANDLE_VALUE;
                                                return 0;
                                             }
                        break;
          case 2:
          default:      wr_buf.Data[0]=0x4C;                                    // FastSendPaket_SPI
                        if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4C 0x00 i 0x00 0x30");   // ошибка отправки команды
                                                CloseHandle(Port);
                                                Port=INVALID_HANDLE_VALUE;
                                                return 0;
                                             }
        }
        Sleep(Delays);//////////
        //--- Читаем SPI - буфер (там в четвёртом байте должен быть прочитанный байт сигнатуры) ---
        wr_buf.Size=1;
        switch(SelectedProgrammer)
        { case 1:       wr_buf.Data[0]=0x45;                                  // ReadPaketSPI
                        if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x45");       // ошибка отправки команды
                                                CloseHandle(Port);
                                                Port=INVALID_HANDLE_VALUE;
                                                return 0;
                                             }
                        // принимаем байт, содержащий SPI - буфер
                        rd_buf=ReadFrom(8);                                   // читаем
                        break;
          case 2:
          default:      wr_buf.Data[0]=0x4A;                                   // ReadSignPaket_SPI
                        if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4A");       // ошибка отправки команды
                                                CloseHandle(Port);
                                                Port=INVALID_HANDLE_VALUE;
                                                return 0;
                                             }
                        // принимаем байт, содержащий SPI - буфер
                        rd_buf=ReadFrom(4);                                   // читаем
        }
        if(!rd_buf.Size) { SendMsgToLog(7," (SPI paket)");    // ошибка приёма пакета
                           CloseHandle(Port);
                           Port=INVALID_HANDLE_VALUE;
                           return 0;
                         }
        //--- вычисляем ID чипа
        Temp = rd_buf.Data[0];
        ChipID += (Temp << (8*i));
  }
  SendMsgToLog(19,"");            // чтение байтов сигнатуры завершено
  return ChipID;
}
//---------------------------------------------------------------------------
//--- ЗАПИСЬ FUSE-БИТОВ (LOW FUSE BYTE) -------------------------------------
//---------------------------------------------------------------------------
bool ATmega8_WriteFuseBits()
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных

  SendMsgToLog(18," write fuse low byte");              // сообщаем о попытке записать младший байт фьюзов
  //--- загружаем и отправляем пакет с командой WriteFuseBits ---
  wr_buf.Size=5;
  wr_buf.Data[1]=SelectedChip.Area3[0];                   // начиная с младшего байта
  wr_buf.Data[2]=0x00;
  wr_buf.Data[3]=0xA0;
  wr_buf.Data[4]=0xAC;                                    // и заканчивая старшим
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x44;                                    // LoadPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x44 Fuse Low 0x00 0xA0 0xAC");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                wr_buf.Size=1;
                wr_buf.Data[0]=0x46;                                  // StartChange_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x46");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4C;                                    // FastSendPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4C Fuse Low 0x00 0xA0 0xAC");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
  }
  Sleep(Delays);//////////
  Sleep(5);
  SendMsgToLog(19," with success.");            // запись выполнена успешно
  return true;
}
//---------------------------------------------------------------------------
//--- ЗАПИСЬ FUSE-БИТОВ (HIGH FUSE BYTE) ------------------------------------
//---------------------------------------------------------------------------
bool ATmega8_WriteFuseHighBits()
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных

  SendMsgToLog(18," write fuse high byte");             // сообщаем о попытке записать старший байт фьюзов
  //--- загружаем и отправляем пакет с командой WriteFuseHighBits ---
  wr_buf.Size=5;
  wr_buf.Data[1]=SelectedChip.Area3[1];                   // начиная с младшего байта
  wr_buf.Data[2]=0x00;
  wr_buf.Data[3]=0xA8;
  wr_buf.Data[4]=0xAC;                                    // и заканчивая старшим
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x44;                                    // LoadPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x44 Fuse High 0x00 0xA8 0xAC");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                wr_buf.Size=1;
                wr_buf.Data[0]=0x46;                                  // StartChange_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x46");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4C;                                    // FastSendPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4C Fuse High 0x00 0xA8 0xAC");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
  }
  Sleep(Delays);//////////
  Sleep(5);
  SendMsgToLog(19," with success.");            // запись выполнена успешно
  return true;
}
//---------------------------------------------------------------------------
//--- ЧТЕНИЕ FUSE-БИТОВ (LOW FUSE BYTE) -------------------------------------
//---------------------------------------------------------------------------
bool ATmega8_ReadFuseBits()
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных

  SendMsgToLog(18," read fuse low byte");       // сообщаем о попытке прочитать Low Fuse Byte
  //--- загружаем и отправляем пакет с командой ReadFuseBits ---
  wr_buf.Size=5;
  wr_buf.Data[1]=0x00;                                    // начиная с младшего байта
  wr_buf.Data[2]=0x00;
  wr_buf.Data[3]=0x00;
  wr_buf.Data[4]=0x50;                                    // и заканчивая старшим
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x44;                                    // LoadPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x44 0x00 0x00 0x00 0x50");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                wr_buf.Size=1;
                wr_buf.Data[0]=0x46;                                  // StartChange_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x46");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4C;                                    // FastSendPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4C 0x00 0x00 0x00 0x50");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
  }
  Sleep(Delays);//////////
  //--- Читаем SPI - буфер (там в четвёртом байте принятого 32-битного пакета должны быть прочитанные биты) ---
  wr_buf.Size=1;
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x45;                                  // ReadPaketSPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x45");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                // принимаем SPI - буфер (четвёртый байт 32-битного пакета SPI окажется в буфере первым)
                rd_buf=ReadFrom(8);                                   // читаем
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4A;                                   // ReadSignPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4A");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return 0;
                                     }
                // принимаем байт, содержащий SPI - буфер
                rd_buf=ReadFrom(4);                                   // читаем
  }
  if(!rd_buf.Size) { SendMsgToLog(7," (SPI paket)");    // ошибка приёма пакета
                     CloseHandle(Port);
                     Port=INVALID_HANDLE_VALUE;
                     return false;
                   }
  //--- сохраняем прочитанный байт в нужную область фьюзов ---
  SelectedChip.Area3[0] = rd_buf.Data[0];
  SendMsgToLog(19," with success.");            // чтение выполнено успешно
  return true;
}
//---------------------------------------------------------------------------
//--- ЧТЕНИЕ FUSE-БИТОВ (HIGH FUSE BYTE) ------------------------------------
//---------------------------------------------------------------------------
bool ATmega8_ReadFuseHighBits()
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных

  SendMsgToLog(18," read fuse high byte");       // сообщаем о попытке прочитать High Fuse Byte
  //--- загружаем и отправляем пакет с командой ReadFuseHighBits ---
  wr_buf.Size=5;
  wr_buf.Data[1]=0x00;                                    // начиная с младшего байта
  wr_buf.Data[2]=0x00;
  wr_buf.Data[3]=0x08;
  wr_buf.Data[4]=0x58;                                    // и заканчивая старшим
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x44;                                    // LoadPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x44 0x00 0x00 0x08 0x58");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                wr_buf.Size=1;
                wr_buf.Data[0]=0x46;                                  // StartChange_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x46");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                break;
    case 2:
    default:    wr_buf.Data[0]=0x4C;                                    // FastSendPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4C 0x00 0x00 0x08 0x58");   // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
  }
  Sleep(Delays);//////////
  //--- Читаем SPI - буфер (там в четвёртом байте принятого 32-битного пакета должны быть прочитанные биты) ---
  wr_buf.Size=1;
  switch(SelectedProgrammer)
  { case 1:     wr_buf.Data[0]=0x45;                                  // ReadPaketSPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x45");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return false;
                                     }
                // принимаем SPI - буфер (четвёртый байт 32-битного пакета SPI окажется в буфере первым)
                rd_buf=ReadFrom(8);                                   // читаем
    case 2:
    default:    wr_buf.Data[0]=0x4A;                                   // ReadSignPaket_SPI
                if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4A");       // ошибка отправки команды
                                        CloseHandle(Port);
                                        Port=INVALID_HANDLE_VALUE;
                                        return 0;
                                     }
                // принимаем байт, содержащий SPI - буфер
                rd_buf=ReadFrom(4);                                   // читаем
  }
  if(!rd_buf.Size) { SendMsgToLog(7," (SPI paket)");    // ошибка приёма пакета
                     CloseHandle(Port);
                     Port=INVALID_HANDLE_VALUE;
                     return false;
                   }
  //--- сохраняем прочитанный байт в нужную область фьюзов ---
  SelectedChip.Area3[1] = rd_buf.Data[0];
  SendMsgToLog(19," with success.");            // чтение выполнено успешно
  return true;
}
//---------------------------------------------------------------------------
//--- ЧТЕНИЕ БАЙТОВ КАЛИБРОВКИ ----------------------------------------------
//---------------------------------------------------------------------------
bool ATmega8_ReadCalibrationBytes()
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных

  SendMsgToLog(18," read calibration bytes");   // сообщаем о попытке прочитать байты калибровки
  //--- загружаем и отправляем пакет с командой Read Calibration Byte ---
  for(unsigned char i=0;i<SelectedChip.Area4Size;i++)
  {     wr_buf.Size=5;
        wr_buf.Data[1]=0x0;
        wr_buf.Data[2]=i;                                    // номер байта калибровки
        wr_buf.Data[3]=0x0;
        wr_buf.Data[4]=0x38;                                 // команда Read Calibration Byte
        switch(SelectedProgrammer)
        { case 1:       wr_buf.Data[0]=0x44;                                 // LoadPaket_SPI
                        if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x44 0x00 i 0x00 0x38");   // ошибка отправки команды
                                                CloseHandle(Port);
                                                Port=INVALID_HANDLE_VALUE;
                                                return false;
                                             }
                        wr_buf.Size=1;
                        wr_buf.Data[0]=0x46;                                  // StartChange_SPI
                        if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x46");       // ошибка отправки команды
                                                CloseHandle(Port);
                                                Port=INVALID_HANDLE_VALUE;
                                                return false;
                                             }
                        break;
          case 2:
          default:      wr_buf.Data[0]=0x4C;                                    // FastSendPaket_SPI
                        if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4C 0x00 i 0x00 0x38");   // ошибка отправки команды
                                                CloseHandle(Port);
                                                Port=INVALID_HANDLE_VALUE;
                                                return false;
                                             }
        }
        Sleep(Delays);//////////
        //--- Читаем SPI - буфер (там в четвёртом байте должен быть прочитанный байт калибровки) ---
        wr_buf.Size=1;
        switch(SelectedProgrammer)
        { case 1:       wr_buf.Data[0]=0x45;                                  // ReadPaketSPI
                        if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x45");       // ошибка отправки команды
                                                CloseHandle(Port);
                                                Port=INVALID_HANDLE_VALUE;
                                                return false;
                                             }
                        // принимаем байт, содержащий SPI - буфер
                        rd_buf=ReadFrom(8);                                   // читаем
                        break;
          case 2:
          default:      wr_buf.Data[0]=0x4A;                                   // ReadSignPaket_SPI
                        if(!WriteTo(wr_buf)) {  SendMsgToLog(6," 0x4A");       // ошибка отправки команды
                                                CloseHandle(Port);
                                                Port=INVALID_HANDLE_VALUE;
                                                return 0;
                                             }
                        // принимаем байт, содержащий SPI - буфер
                        rd_buf=ReadFrom(4);                                   // читаем
        }
        if(!rd_buf.Size) { SendMsgToLog(7," (SPI paket)");    // ошибка приёма пакета
                           CloseHandle(Port);
                           Port=INVALID_HANDLE_VALUE;
                           return false;
                         }
        //--- сохраняем прочитанный байт калибровки
        SelectedChip.Area4[i] = rd_buf.Data[0];
  }
  SendMsgToLog(19,"");            // чтение байтов калибровки завершено
  return true;
}
//---------------------------------------------------------------------------
