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

#include "PICFunctions.h"       // переменные для функций работы с чипами PIC
#include "PortFunctions.h"      // переменные для функций работы с портом
#include "LogFunctions.h"       // переменные для отправки сообщений в лог
#include "ChipFunctions.h"      // переменные для работы с чипом
#include "Main.h"               // переменные для работы с главной формой
//---------------------------------------------------------------------------
#pragma package(smart_init)
////////////////////////////////////////////////////////////
// В ЭТОМ МОДУЛЕ У НАС ФУНКЦИИ, ОДИНАКОВЫЕ ДЛЯ ВСЕХ ЧИПОВ //
////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------
//--- Перевод линий порта C (и B) в начальные состояния ---------------------
//---------------------------------------------------------------------------
bool SetInitState(void)
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных

  //--- all outputs = 0; all inputs without pull-ups; Clock, DataOut = outputs, all others = inputs ---
  wr_buf.Size=4;
  wr_buf.Data[0]=0x11;                  // PORTCSetup
  wr_buf.Data[1]=0x0;                   // на выходах нули, на входах подтяжек нет
  wr_buf.Data[2]=0x0F;                  // DDRCSetup
  wr_buf.Data[3]=0x30;                  // 0011 0000: Clock, DataOut - выходы
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," set InitState");      // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  // для сигнала PGM добавим настройку линии PB0 на выход, на плате нужно будет припаять резистор 1К
  wr_buf.Size=4;
  wr_buf.Data[0]=0x0D;                  // PORTBSetup
  wr_buf.Data[1]=0x0;                   // на выходах нули, на входах подтяжек нет
  wr_buf.Data[2]=0x0B;                  // DDRBSetup
  wr_buf.Data[3]=0x01;                  // 0000 0001: PB0 - выход
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," set InitState");      // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  return true;
}
//---------------------------------------------------------------------------
//--- Переход в режим программирования, алгоритм VPP-first ------------------
//---------------------------------------------------------------------------
bool EnterHVPVMode_VPPfirst(void)
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных

  wr_buf.Size=2;
  wr_buf.Data[0]=0x1D;          // DoExtendedCommand
  wr_buf.Data[1]=0x04;          // ExecuteVppFirstAlg_PIC (при этом линии управления питанием переключаются на выход)
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," enter programming mode, Vpp-first");  // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  return true;
}
//---------------------------------------------------------------------------
//--- Переход в режим программирования, алгоритм VDD-first ------------------
//---------------------------------------------------------------------------
bool EnterHVPVMode_VDDfirst(void)
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных

  wr_buf.Size=2;
  wr_buf.Data[0]=0x1D;          // DoExtendedCommand
  wr_buf.Data[1]=0x05;          // ExecuteVddFirstAlg_PIC (при этом линии управления питанием переключаются на выход)
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," enter programming mode, Vdd-first");  // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  return true;
}
//---------------------------------------------------------------------------
//--- Выход из режима программирования, алгоритм VPP-last -------------------
//---------------------------------------------------------------------------
bool ExitHVPVMode_VPPlast(void)
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных

  wr_buf.Size=2;
  wr_buf.Data[0]=0x1D;          // DoExtendedCommand
  wr_buf.Data[1]=0x06;          // ExecuteVppLastAlg_PIC (при этом линии управления питанием переключаются на вход)
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," exit programming mode, Vpp-last");    // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  return true;
}
//---------------------------------------------------------------------------
//--- Выход из режима программирования, алгоритм VDD-last -------------------
//---------------------------------------------------------------------------
bool ExitHVPVMode_VDDlast(void)
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных

  wr_buf.Size=2;
  wr_buf.Data[0]=0x1D;          // DoExtendedCommand
  wr_buf.Data[1]=0x07;          // ExecuteVddLastAlg_PIC (при этом линии управления питанием переключаются на вход)
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," exit programming mode, Vdd-last");    // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  return true;
}
//---------------------------------------------------------------------------
//--- Чтение байтов сигнатуры -----------------------------------------------
//---------------------------------------------------------------------------
unsigned int ReadSignatureBytes(void)
{ WRITE_BUFFER wr_buf;          // буфер для отправки данных
  READ_BUFFER rd_buf;           // буфер для приёма данных
  unsigned int ChipID;          // ответ функции

  // устанавливаем размер пакета 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 (чтобы перейти в область конфигурирования)
  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);//////////
  // теперь нужно 6 раз послать команду Increment Address чтобы установить указатель на 0x2006 (здесь хранится слово ID)
  // устанавливаем размер пакета 6 бит (для отправки команд)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x42;          // LoadPaketSize_SPI
  wr_buf.Data[1]=0x06;          // размер пакета
  if(!WriteTo(wr_buf)) { SendMsgToLog(6," LoadaketSize_SPI = 0x06");    // ошибка отправки команды
                         CloseHandle(Port);
                         Port=INVALID_HANDLE_VALUE;
                         return 0;
                       }
  Sleep(1);
  Sleep(Delays);//////////
  for(unsigned char i=0; i<6; 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);//////////
  }
  // отправляем команду 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;
                   }
  //--- вычисляем ID чипа
  ChipID = (rd_buf.Data[0] + (rd_buf.Data[1] << 8)) >> 1;       // объединяем считанные байты в одно слово и сдвигаем вправо на 1 бит
  return ChipID;
}
//---------------------------------------------------------------------------

