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

#include "pic16f630.h"          // переменные для функций работы с PIC16F630 / PIC16F676 / PIC12F629 / PIC12F675
                                // PIC12F635 / PIC12F683 / PIC16F631 / PIC16F636 / PIC16F639 / PIC16F677 / PIC16F684 / PIC16F685 / PIC16F687 / PIC16F688 / PIC16F689 / PIC16F690
#include "PICFunctions.h"       // переменные для функций работы с чипами PIC
#include "PortFunctions.h"      // переменные для функций работы с портом
#include "LogFunctions.h"       // переменные для отправки сообщений в лог
#include "ProgressBar.h"        // для использования прогресс-бара
#include "ChipFunctions.h"      // переменные для работы с чипом
#include "Main.h"               // переменные для работы с главной формой
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
//--- Установка указателя адреса на область конфига -------------------------
//---------------------------------------------------------------------------
bool PIC16F630_SetPCToConfigMemory(void)
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных

  // устанавливаем размер пакета 6 бит (для отправки команд)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x06;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x6");    // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // отправляем команду Load Configuration (чтобы перейти по адресу 0x2000)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
  wr_buf.Data[1]=0x00;          // Load Configuration
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," Load Configuration");         // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // устанавливаем размер пакета 16 бит (для отправки/приёма данных)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x10;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x10");   // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // досылаем два байта данных просто чтобы завершить команду Load Configuration
  // конфиг это действие не перезапишет, поскольку запись происходит только после команды Begin Programming
  wr_buf.Size=3;
  wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
  wr_buf.Data[1]=0x00;          // dummy byte
  wr_buf.Data[2]=0x00;          // dummy byte
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," FastSendPaket_SPI 0x00 0x00");    // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////

  return true;
}
//---------------------------------------------------------------------------
//--- Сдвиг указателя адреса на требуемую величину --------------------------
//---------------------------------------------------------------------------
bool PIC16F630_MakePCOffset(unsigned int Offset, bool PB)
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных

  // устанавливаем размер пакета 6 бит (для отправки команд)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x06;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x06");    // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // выполняем команду Increment Address нужное количество раз
  for(unsigned int i=0; i<Offset; i++)
  { // отправляем команду Increment Address
    wr_buf.Size=2;
    wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
    wr_buf.Data[1]=0x06;          // Increment Address
    if(!WriteTo(wr_buf)) { SendMsgToLog(6," Increment Address");        // ошибка отправки команды
                           CloseHandle(Port);
                           Port=INVALID_HANDLE_VALUE;
                           return 0;
                         }
    Sleep(1);
    Sleep(Delays);//////////
    // если прочитали количество байт кратное 16
    if(PB)
    {   if((i+1)%8==0)
        {       LBar->ProgressBar1->Position=2*100*(i+1)/Offset;    // вычисляем новую позицию прогресс-бара
        }
    }
  }

  return true;
}
//---------------------------------------------------------------------------
//--- Чтение/сравнение слова программы по указанному адресу -----------------
//---------------------------------------------------------------------------
bool PIC16F630_ReadProgramMemory(unsigned int Address, bool Action)     // прочитать/сравнить слово программы по указанному адресу
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных
  unsigned int Temp1, Temp2;    // сюда получим результат чтения очередного слова, или слово для проверки

  // устанавливаем размер пакета 6 бит (для отправки команд)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x06;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x06");    // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////

  if(Address>0)     // если мы собираемся прочитать не первое слово, то сначала сдвигаем адрес
  { // отправляем команду Increment Address
    wr_buf.Size=2;
    wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
    wr_buf.Data[1]=0x06;          // Increment Address
    if(!WriteTo(wr_buf)) { SendMsgToLog(6," Increment Address");        // ошибка отправки команды
                           CloseHandle(Port);
                           Port=INVALID_HANDLE_VALUE;
                           return 0;
                         }
    Sleep(1);
    Sleep(Delays);//////////
  }
  // отправляем команду Read Data From Program Memory
  wr_buf.Size=2;
  wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
  wr_buf.Data[1]=0x04;          // Read Data From Program Memory
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," Read Data From Program Memory");      // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // устанавливаем размер пакета 16 бит (для отправки/приёма данных)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x10;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x10");   // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // читаем два байта из чипа (шина двунаправленная и для чтения нужно отправлять единицы, но старт- и стоп-биты должны быть нули)
  wr_buf.Size=3;
  wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
  wr_buf.Data[1]=0xFE;          // dummy byte with Start bit
  wr_buf.Data[2]=0x7F;          // dummy byte with Stop bit
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," FastSendPaket_SPI 0xFE 0x7F");        // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // запрашиваем значащие байты пакета (14 бит в середине - это и есть прочитанное слово)
  wr_buf.Size=1;
  wr_buf.Data[0]=0x4A;          // ReadSignPaket_SPI
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," ReadSignPaket_SPI");  // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // принимаем запрошенные байты
  rd_buf=ReadFrom(2);                                   // читаем
  if(!rd_buf.Size) { SendMsgToLog(7," from RH-0010");   // ошибка приёма пакета
                     CloseHandle(Port);
                     Port=INVALID_HANDLE_VALUE;
                     return 0;
                   }
  Temp1 = 0x3FFF & ((rd_buf.Data[0] + (rd_buf.Data[1] << 8)) >> 1);     // объединяем считанные байты в одно слово, сдвигаем вправо на 1 бити на всякий случай отрезаем старшие биты по маске

  //--- сохраняем прочитанное слово в нужную область программы или сверяем со словом в памяти ---
  if(!Action)   // если мы читаем слово
  {     SelectedChip.Area1[2*Address] = Temp1;          // сохраняем младший байт прочитанного слова
        SelectedChip.Area1[2*Address+1] = Temp1 >> 8;   // сохраняем старший байт прочитанного слова
  }
  else          // если мы проверяем слово
  {     Temp2 = 256*SelectedChip.Area1[2*Address+1] + SelectedChip.Area1[2*Address];
        if(Temp1 != Temp2)      // если байт не совпадает с тем, что в памяти
        {       return 0;       // запоминаем ошибку, если она случилась
        }
  }
  return true;
}
//---------------------------------------------------------------------------
//--- Чтение/сравнение слова конфигурации по указанному адресу --------------
//---------------------------------------------------------------------------
bool PIC16F630_ReadConfigMemory(unsigned int Address, bool Action)
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных
  unsigned int Temp1, Temp2;    // сюда получим результат чтения очередного слова или слово для проверки

  // устанавливаем размер пакета 6 бит (для отправки команд)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x06;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x06");    // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  if(Address>0)     // если мы собираемся прочитать не первое слово, то сначала сдвигаем адрес
  { // отправляем команду Increment Address
    wr_buf.Size=2;
    wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
    wr_buf.Data[1]=0x06;          // Increment Address
    if(!WriteTo(wr_buf)) { SendMsgToLog(6," Increment Address");        // ошибка отправки команды
                           CloseHandle(Port);
                           Port=INVALID_HANDLE_VALUE;
                           return 0;
                         }
    Sleep(1);
    Sleep(Delays);//////////
  }
  // отправляем команду Read Data From Program Memory
  wr_buf.Size=2;
  wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
  wr_buf.Data[1]=0x04;          // Read Data From Program Memory
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," Read Data From Program Memory");      // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // устанавливаем размер пакета 16 бит (для отправки/приёма данных)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x10;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x10");   // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // читаем два байта из чипа (шина двунаправленная и для чтения нужно отправлять единицы, но старт- и стоп-биты должны быть нули)
  wr_buf.Size=3;
  wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
  wr_buf.Data[1]=0xFE;          // dummy byte with Start bit
  wr_buf.Data[2]=0x7F;          // dummy byte with Stop bit
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," FastSendPaket_SPI 0xFE 0x7F");        // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // запрашиваем значащие байты пакета (14 бит в середине - это и есть прочитанное слово)
  wr_buf.Size=1;
  wr_buf.Data[0]=0x4A;          // ReadSignPaket_SPI
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," ReadSignPaket_SPI");  // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // принимаем запрошенные байты
  rd_buf=ReadFrom(2);                                   // читаем
  if(!rd_buf.Size) { SendMsgToLog(7," from RH-0010");   // ошибка приёма пакета
                     CloseHandle(Port);
                     Port=INVALID_HANDLE_VALUE;
                     return 0;
                   }
  Temp1 = 0x3FFF & ((rd_buf.Data[0] + (rd_buf.Data[1] << 8)) >> 1);     // объединяем считанные байты в одно слово, сдвигаем вправо на 1 бити на всякий случай отрезаем старшие биты по маске

  //--- сохраняем прочитанное слово в нужную область программы или сверяем со словом в памяти ---
  if(!Action)   // если мы читаем слово
  {     SelectedChip.Area3[2*Address] = Temp1;          // сохраняем младший байт прочитанного слова
        SelectedChip.Area3[2*Address+1] = Temp1 >> 8;   // сохраняем старший байт прочитанного слова
  }
  else          // если мы проверяем слово
  {     Temp2 = 256*SelectedChip.Area3[2*Address+1] + SelectedChip.Area3[2*Address];
        if(Temp1 != Temp2)      // если байт не совпадает с тем, что в памяти
        {       return 0;       // запоминаем ошибку, если она случилась
        }
  }
  return true;
}
//---------------------------------------------------------------------------
//--- Чтение слова конфигурации по указанному адресу с сохранением нужных битов (по маске)
//---------------------------------------------------------------------------
bool PIC16F630_ReadConfigMemoryMask(unsigned int Address, unsigned short Mask)
{ WRITE_BUFFER wr_buf;  // буфер для отправки данных
  READ_BUFFER rd_buf;   // буфер для приёма данных
  unsigned int Temp;    // сюда получим результат чтения очередного слова или слово для проверки

  // устанавливаем размер пакета 6 бит (для отправки команд)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x06;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x06");    // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  if(Address>0)     // если мы собираемся прочитать не первое слово, то сначала сдвигаем адрес
  { // отправляем команду Increment Address
    wr_buf.Size=2;
    wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
    wr_buf.Data[1]=0x06;          // Increment Address
    if(!WriteTo(wr_buf)) { SendMsgToLog(6," Increment Address");        // ошибка отправки команды
                           CloseHandle(Port);
                           Port=INVALID_HANDLE_VALUE;
                           return 0;
                         }
    Sleep(1);
    Sleep(Delays);//////////
  }
  // отправляем команду Read Data From Program Memory
  wr_buf.Size=2;
  wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
  wr_buf.Data[1]=0x04;          // Read Data From Program Memory
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," Read Data From Program Memory");      // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // устанавливаем размер пакета 16 бит (для отправки/приёма данных)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x10;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x10");   // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // читаем два байта из чипа (шина двунаправленная и для чтения нужно отправлять единицы, но старт- и стоп-биты должны быть нули)
  wr_buf.Size=3;
  wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
  wr_buf.Data[1]=0xFE;          // dummy byte with Start bit
  wr_buf.Data[2]=0x7F;          // dummy byte with Stop bit
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," FastSendPaket_SPI 0xFE 0x7F");        // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // запрашиваем значащие байты пакета (14 бит в середине - это и есть прочитанное слово)
  wr_buf.Size=1;
  wr_buf.Data[0]=0x4A;          // ReadSignPaket_SPI
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," ReadSignPaket_SPI");  // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // принимаем запрошенные байты
  rd_buf=ReadFrom(2);                                   // читаем
  if(!rd_buf.Size) { SendMsgToLog(7," from RH-0010");   // ошибка приёма пакета
                     CloseHandle(Port);
                     Port=INVALID_HANDLE_VALUE;
                     return 0;
                   }
  // 1 - бит не запрограммирован, 0 - запрограммирован, поэтому биты, которые не нужно сохранять = 1
  Temp = ~Mask | ((rd_buf.Data[0] + (rd_buf.Data[1] << 8)) >> 1);     // объединяем считанные байты в одно слово, сдвигаем вправо на 1 бит и на всякий случай отрезаем старшие биты по маске

  //--- сохраняем прочитанное слово в нужную область конфигурации (по маске) ---
  SelectedChip.Area3[2*Address] |= Temp;        // сохраняем младший байт прочитанного слова
  SelectedChip.Area3[2*Address+1] |= Temp >> 8; // сохраняем старший байт прочитанного слова
  return true;
}
//---------------------------------------------------------------------------
//--- Чтение/сравнение слова данных по указанному адресу --------------------
//---------------------------------------------------------------------------
bool PIC16F630_ReadDataMemory(unsigned int Address, bool Action)        // прочитать/сравнить слово данных по указанному адресу
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных
  unsigned int Temp;            // сюда получим результат чтения очередного слова, или слово для проверки

  // устанавливаем размер пакета 6 бит (для отправки команд)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x06;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x06");    // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////

  if(Address>0)     // если мы собираемся прочитать не первое слово, то сначала сдвигаем адрес
  { // отправляем команду Increment Address
    wr_buf.Size=2;
    wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
    wr_buf.Data[1]=0x06;          // Increment Address
    if(!WriteTo(wr_buf)) { SendMsgToLog(6," Increment Address");        // ошибка отправки команды
                           CloseHandle(Port);
                           Port=INVALID_HANDLE_VALUE;
                           return 0;
                         }
    Sleep(1);
    Sleep(Delays);//////////
  }
  // отправляем команду Read Data From Data Memory
  wr_buf.Size=2;
  wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
  wr_buf.Data[1]=0x05;          // Read Data From Data Memory
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," Read Data From Data Memory");      // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // устанавливаем размер пакета 16 бит (для отправки/приёма данных)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x10;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x10");   // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // читаем два байта из чипа (шина двунаправленная и для чтения нужно отправлять диницы, но старт- и стоп-биты должны быть нули)
  wr_buf.Size=3;
  wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
  wr_buf.Data[1]=0xFE;          // dummy byte with Start bit
  wr_buf.Data[2]=0x7F;          // dummy byte with Stop bit
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," FastSendPaket_SPI 0xFE 0x7F");        // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // запрашиваем значащие байты пакета (14 бит в середине - это и есть прочитанное слово)
  wr_buf.Size=1;
  wr_buf.Data[0]=0x4A;          // ReadSignPaket_SPI
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," ReadSignPaket_SPI");  // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // принимаем запрошенные байты
  rd_buf=ReadFrom(2);                                   // читаем
  if(!rd_buf.Size) { SendMsgToLog(7," from RH-0010");   // ошибка приёма пакета
                     CloseHandle(Port);
                     Port=INVALID_HANDLE_VALUE;
                     return 0;
                   }
  Temp = 0x3FFF & ((rd_buf.Data[0] + (rd_buf.Data[1] << 8)) >> 1);      // объединяем считанные байты в одно слово, сдвигаем вправо на 1 бит и на всякий случай отрезаем старшие биты по маске

  //--- сохраняем прочитанное слово в нужную область программы или сверяем со словом в памяти ---
  if(!Action)   // если мы читаем слово
  {     SelectedChip.Area2[Address] = Temp;     // сохраняем байт прочитанного слова
  }
  else          // если мы проверяем слово
  {     if(Temp != (unsigned int)SelectedChip.Area2[Address])   // если байт не совпадает с тем, что в памяти
        {       return 0;                                       // запоминаем ошибку, если она случилась
        }
  }
  return true;
}
//---------------------------------------------------------------------------
//***************************************************************************
//---------------------------------------------------------------------------
//--- Запись слова программы по указанному адресу (Int/Ext timed) -----------
//---------------------------------------------------------------------------
bool PIC16F630_WriteProgramMemory(unsigned int Address, bool Action)    // записать слово программы по указанному адресу
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных
  unsigned int Temp;            // здесь будем готовить слово для передачи

  // устанавливаем размер пакета 6 бит (для отправки команд)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x06;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x06");    // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////

  if(Address>0)     // если мы собираемся записать не первое слово, то сначала сдвигаем адрес
  { // отправляем команду Increment Address
    wr_buf.Size=2;
    wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
    wr_buf.Data[1]=0x06;          // Increment Address
    if(!WriteTo(wr_buf)) { SendMsgToLog(6," Increment Address");        // ошибка отправки команды
                           CloseHandle(Port);
                           Port=INVALID_HANDLE_VALUE;
                           return 0;
                         }
    Sleep(1);
    Sleep(Delays);//////////
  }
  // готовим два байта для отправки (объединяем байты для передачи в одно слово)
  Temp = (SelectedChip.Area1[2*Address] + (SelectedChip.Area1[2*Address+1] << 8)) << 1;
  if(Temp!=0x7FFE)              // если отправляем не 0x3FFF
  {     // отправляем команду Load Data For Program Memory
        wr_buf.Size=2;
        wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
        wr_buf.Data[1]=0x02;          // Load Data For Program Memory
        if(!WriteTo(wr_buf)) { SendMsgToLog(6," Load Data For Program Memory");       // ошибка отправки команды
                               CloseHandle(Port);
                               Port=INVALID_HANDLE_VALUE;
                               return 0;
                             }
        Sleep(1);
        Sleep(Delays);//////////
        // устанавливаем размер пакета 16 бит (для отправки/приёма данных)
        wr_buf.Size=2;
        wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
        wr_buf.Data[1]=0x10;          // размер пакета
        if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x10");   // ошибка отправки команды
                               CloseHandle(Port);
                               Port=INVALID_HANDLE_VALUE;
                               return 0;
                             }
        Sleep(1);
        Sleep(Delays);//////////
        // отправляем два ранее подготовленных байта
        wr_buf.Size=3;
        wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
        wr_buf.Data[1]=Temp;          // Low byte with Start bit
        wr_buf.Data[2]=Temp>>8;       // High byte with Stop bit
        if(!WriteTo(wr_buf)) { SendMsgToLog(6," FastSendPaket_SPI Low High");        // ошибка отправки команды
                               CloseHandle(Port);
                               Port=INVALID_HANDLE_VALUE;
                               return 0;
                             }
        Sleep(1);
        Sleep(Delays);//////////
        // устанавливаем размер пакета 6 бит (для отправки команд)
        wr_buf.Size=2;
        wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
        wr_buf.Data[1]=0x06;          // размер пакета
        if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x06");    // ошибка отправки команды
                               CloseHandle(Port);
                               Port=INVALID_HANDLE_VALUE;
                               return 0;
                             }
        Sleep(1);
        Sleep(Delays);//////////
        if(!Action)
        {     // отправляем команду Begin Programming (Internally Programmed)
              wr_buf.Size=2;
              wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
              wr_buf.Data[1]=0x08;          // Begin Programming
              if(!WriteTo(wr_buf)) { SendMsgToLog(6," Begin Programming (int)");      // ошибка отправки команды
                                     CloseHandle(Port);
                                     Port=INVALID_HANDLE_VALUE;
                                     return 0;
                                   }
              Sleep(SelectedChip.TwrProgInt);
              Sleep(Delays);//////////
        }
        else
        {     // отправляем команду Begin Programming (Externally Programmed)
              wr_buf.Size=2;
              wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
              wr_buf.Data[1]=0x18;          // Begin Programming
              if(!WriteTo(wr_buf)) { SendMsgToLog(6," Begin Programming (ext)");      // ошибка отправки команды
                                     CloseHandle(Port);
                                     Port=INVALID_HANDLE_VALUE;
                                     return 0;
                                   }
              Sleep(SelectedChip.TwrProgExt);
              Sleep(Delays);//////////
              // отправляем команду End Programming
              wr_buf.Size=2;
              wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
              wr_buf.Data[1]=0x0A;          // End Programming
              if(!WriteTo(wr_buf)) { SendMsgToLog(6," End Programming");      // ошибка отправки команды
                                     CloseHandle(Port);
                                     Port=INVALID_HANDLE_VALUE;
                                     return 0;
                                   }
              Sleep(1);
              Sleep(Delays);//////////
        }
  }
  return true;
}
//---------------------------------------------------------------------------
//--- Запись слова конфигурации по указанному адресу ------------------------
//---------------------------------------------------------------------------
bool PIC16F630_WriteConfigMemory(unsigned int Address, bool Action)
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных
  unsigned int Temp;            // здесь будем готовить слово для передачи

  // устанавливаем размер пакета 6 бит (для отправки команд)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x06;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x06");    // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////

  if(Address>0)     // если мы собираемся записать не первое слово, то сначала сдвигаем адрес
  { // отправляем команду Increment Address
    wr_buf.Size=2;
    wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
    wr_buf.Data[1]=0x06;          // Increment Address
    if(!WriteTo(wr_buf)) { SendMsgToLog(6," Increment Address");        // ошибка отправки команды
                           CloseHandle(Port);
                           Port=INVALID_HANDLE_VALUE;
                           return 0;
                         }
    Sleep(1);
    Sleep(Delays);//////////
  }
  // готовим два байта для отправки (объединяем байты для передачи в одно слово)
  Temp = (SelectedChip.Area3[2*Address] + (SelectedChip.Area3[2*Address+1] << 8)) << 1;
  if(Temp!=0x7FFE)              // если отправляем не 0x3FFF
  {     // отправляем команду Load Data For Program Memory
        wr_buf.Size=2;
        wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
        wr_buf.Data[1]=0x02;          // Load Data For Program Memory
        if(!WriteTo(wr_buf)) { SendMsgToLog(6," Load Data For Program Memory");       // ошибка отправки команды
                               CloseHandle(Port);
                               Port=INVALID_HANDLE_VALUE;
                               return 0;
                             }
        Sleep(1);
        Sleep(Delays);//////////
        // устанавливаем размер пакета 16 бит (для отправки/приёма данных)
        wr_buf.Size=2;
        wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
        wr_buf.Data[1]=0x10;          // размер пакета
        if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x10");   // ошибка отправки команды
                               CloseHandle(Port);
                               Port=INVALID_HANDLE_VALUE;
                               return 0;
                             }
        Sleep(1);
        Sleep(Delays);//////////
        // отправляем два ранее подготовленных байта
        wr_buf.Size=3;
        wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
        wr_buf.Data[1]=Temp;          // low byte with Start bit
        wr_buf.Data[2]=Temp>>8;       // high byte with Stop bit
        if(!WriteTo(wr_buf)) { SendMsgToLog(6," FastSendPaket_SPI Low High");        // ошибка отправки команды
                               CloseHandle(Port);
                               Port=INVALID_HANDLE_VALUE;
                               return 0;
                             }
        Sleep(1);
        Sleep(Delays);//////////
        // устанавливаем размер пакета 6 бит (для отправки команд)
        wr_buf.Size=2;
        wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
        wr_buf.Data[1]=0x06;          // размер пакета
        if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x06");    // ошибка отправки команды
                               CloseHandle(Port);
                               Port=INVALID_HANDLE_VALUE;
                               return 0;
                             }
        Sleep(1);
        Sleep(Delays);//////////
        if(!Action)
        {     // отправляем команду Begin Programming (Internally Programmed)
              wr_buf.Size=2;
              wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
              wr_buf.Data[1]=0x08;          // Begin Programming
              if(!WriteTo(wr_buf)) { SendMsgToLog(6," Begin Programming (int)");      // ошибка отправки команды
                                     CloseHandle(Port);
                                     Port=INVALID_HANDLE_VALUE;
                                     return 0;
                                   }
              Sleep(SelectedChip.TwrProgInt);
              Sleep(Delays);//////////
        }
        else
        {     // отправляем команду Begin Programming (Externally Programmed)
              wr_buf.Size=2;
              wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
              wr_buf.Data[1]=0x18;          // Begin Programming
              if(!WriteTo(wr_buf)) { SendMsgToLog(6," Begin Programming (ext)");      // ошибка отправки команды
                                     CloseHandle(Port);
                                     Port=INVALID_HANDLE_VALUE;
                                     return 0;
                                   }
              Sleep(SelectedChip.TwrProgExt);
              Sleep(Delays);//////////
              // отправляем команду End Programming
              wr_buf.Size=2;
              wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
              wr_buf.Data[1]=0x0A;          // End Programming
              if(!WriteTo(wr_buf)) { SendMsgToLog(6," End Programming");      // ошибка отправки команды
                                     CloseHandle(Port);
                                     Port=INVALID_HANDLE_VALUE;
                                     return 0;
                                   }
              Sleep(1);
              Sleep(Delays);//////////
        }
  }
  return true;
}
//---------------------------------------------------------------------------
//--- Запись слова данных по указанному адресу ------------------------------
//---------------------------------------------------------------------------
bool PIC16F630_WriteDataMemory(unsigned int Address, bool Action)        // прочитать/сравнить слово данных по указанному адресу
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных
  unsigned int Temp;            // здесь будем готовить слово для передачи

  // устанавливаем размер пакета 6 бит (для отправки команд)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x06;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x06");    // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  if(Address>0)     // если мы собираемся записать не первое слово, то сначала сдвигаем адрес
  { // отправляем команду Increment Address
    wr_buf.Size=2;
    wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
    wr_buf.Data[1]=0x06;          // Increment Address
    if(!WriteTo(wr_buf)) { SendMsgToLog(6," Increment Address");        // ошибка отправки команды
                           CloseHandle(Port);
                           Port=INVALID_HANDLE_VALUE;
                           return 0;
                         }
    Sleep(1);
    Sleep(Delays);//////////
  }
  // готовим два байта для отправки (объединяем байты для передачи в одно слово)
  Temp = (SelectedChip.Area2[Address] + (0x0 << 8)) << 1;
  if(Temp!=0x1FE)               // если отправляем не 0xFF
  {     // отправляем команду Load Data For Data Memory
        wr_buf.Size=2;
        wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
        wr_buf.Data[1]=0x03;          // Load Data For Program Memory
        if(!WriteTo(wr_buf)) { SendMsgToLog(6," Load Data For Data Memory");       // ошибка отправки команды
                               CloseHandle(Port);
                               Port=INVALID_HANDLE_VALUE;
                               return 0;
                             }
        Sleep(1);
        Sleep(Delays);//////////
        // устанавливаем размер пакета 16 бит (для отправки/приёма данных)
        wr_buf.Size=2;
        wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
        wr_buf.Data[1]=0x10;          // размер пакета
        if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x10");   // ошибка отправки команды
                               CloseHandle(Port);
                               Port=INVALID_HANDLE_VALUE;
                               return 0;
                             }
        Sleep(1);
        Sleep(Delays);//////////
        // отправляем два ранее подготовленных байта
        wr_buf.Size=3;
        wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
        wr_buf.Data[1]=Temp;          // Low byte with Start bit
        wr_buf.Data[2]=Temp>>8;       // High byte with Stop bit
        if(!WriteTo(wr_buf)) { SendMsgToLog(6," FastSendPaket_SPI Low High");        // ошибка отправки команды
                               CloseHandle(Port);
                               Port=INVALID_HANDLE_VALUE;
                               return 0;
                             }
        Sleep(1);
        Sleep(Delays);//////////
        // устанавливаем размер пакета 6 бит (для отправки команд)
        wr_buf.Size=2;
        wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
        wr_buf.Data[1]=0x06;          // размер пакета
        if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x06");    // ошибка отправки команды
                               CloseHandle(Port);
                               Port=INVALID_HANDLE_VALUE;
                               return 0;
                             }
        Sleep(1);
        Sleep(Delays);//////////
        if(!Action)
        {     // отправляем команду Begin Programming (Internally Programmed)
              wr_buf.Size=2;
              wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
              wr_buf.Data[1]=0x08;          // Begin Programming
              if(!WriteTo(wr_buf)) { SendMsgToLog(6," Begin Programming (int)");      // ошибка отправки команды
                                     CloseHandle(Port);
                                     Port=INVALID_HANDLE_VALUE;
                                     return 0;
                                   }
              Sleep(SelectedChip.TwrDataInt);
              Sleep(Delays);//////////
        }
        else
        {     // отправляем команду Begin Programming (Externally Programmed)
              wr_buf.Size=2;
              wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
              wr_buf.Data[1]=0x18;          // Begin Programming
              if(!WriteTo(wr_buf)) { SendMsgToLog(6," Begin Programming (ext)");      // ошибка отправки команды
                                     CloseHandle(Port);
                                     Port=INVALID_HANDLE_VALUE;
                                     return 0;
                                   }
              Sleep(SelectedChip.TwrDataExt);
              Sleep(Delays);//////////
              // отправляем команду End Programming
              wr_buf.Size=2;
              wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
              wr_buf.Data[1]=0x0A;          // End Programming
              if(!WriteTo(wr_buf)) { SendMsgToLog(6," End Programming");      // ошибка отправки команды
                                     CloseHandle(Port);
                                     Port=INVALID_HANDLE_VALUE;
                                     return 0;
                                   }
              Sleep(1);
              Sleep(Delays);//////////
        }
  }
  return true;
}
//---------------------------------------------------------------------------
//--- Загрузка указанного слова в память программы / конфигурации -----------
//---------------------------------------------------------------------------
bool PIC16F630_LoadDataToProgramMemory(unsigned short Data)           // загрузить слово в память программ
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных

  // устанавливаем размер пакета 6 бит (для отправки команд)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x06;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x06");    // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // отправляем команду Load Data For Program Memory
  wr_buf.Size=2;
  wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
  wr_buf.Data[1]=0x02;          // Load Data For Program Memory
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," Load Data For Program Memory");       // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // устанавливаем размер пакета 16 бит (для отправки/приёма данных)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x10;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x10");   // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // отправляем два байта
  wr_buf.Size=3;
  wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
  wr_buf.Data[1]=Data<<1;       // Low byte with Start bit
  wr_buf.Data[2]=Data>>7;       // High byte with Stop bit
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," FastSendPaket_SPI Low High");        // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  return true;
}
//---------------------------------------------------------------------------
//--- Стирание памяти программы / конфигурации ------------------------------
//---------------------------------------------------------------------------
bool PIC16F630_BulkEraseProgramMemory(void)      // стереть память программы/конфигурации
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных

  // устанавливаем размер пакета 6 бит (для отправки команд)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x06;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x06");    // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // выполняем команду Bulk Erase Program Memory
  wr_buf.Size=2;
  wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
  wr_buf.Data[1]=0x09;          // Bulk Erase Program Memory
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," Bulk Erase Program Memory");        // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(SelectedChip.TerProg);
  Sleep(Delays);//////////

  return true;
}
//---------------------------------------------------------------------------
//--- Стирание памяти данных ------------------------------------------------
//---------------------------------------------------------------------------
bool PIC16F630_BulkEraseDataMemory(void)      // стереть память данных
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных

  // устанавливаем размер пакета 6 бит (для отправки команд)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x06;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadPaketSize_SPI = 0x06");   // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // выполняем команду Bulk Erase Data Memory
  wr_buf.Size=2;
  wr_buf.Data[0]=0x4C;          // FastSendPaket_SPI
  wr_buf.Data[1]=0x0B;          // Bulk Erase Data Memory
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," Bulk Erase Data Memory");     // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(SelectedChip.TerData);
  Sleep(Delays);//////////

  return true;
}
//---------------------------------------------------------------------------


