//---------------------------------------------------------------------------
// Функции для работы с чипами AN1990 / TM-2004 (based on K1446VG5)
//---------------------------------------------------------------------------
#pragma hdrstop
#include "AN1990.h"
#include "ProgressBar.h"        // для использования прогресс-бара
#include "MainProgram.h"        // для работы с формой
#include "ChipFunctions.h"      // переменные для работы с памятью чипа
#include "PortFunctions.h"      // для работы с портом
#include "CalcCRC.h"            // для расчёта CRC
#include "SendMsgFunctions.h"   // для отправки сообщений в лог
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
//--- ЧТЕНИЕ ТЕКУЩЕГО УСТАНОВЛЕННОГО ROM (0x33) -----------------------------
//---------------------------------------------------------------------------
// output:      Success
AN1990_OUTPUT_DATA AN1990_ReadROM()
{ WRITE_BUFFER wr_buf;                  // буфер для отправки данных
  READ_BUFFER rd_buf;                   // буфер для приёма данных
  AN1990_OUTPUT_DATA OutputData;        // результат выполнения команды

  OutputData.Success=false;             // инициализируем результаты нулями

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

  // посылаем Reset
  wr_buf.Size=1;
  wr_buf.Data[0]=0x60;
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // посылаем Read ROM
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=0x33;                                  // Read ROM
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // читаем 8 байт ROM
  for(unsigned int i=0; i<8; i++)                       // перебираем все биты ROM
  { // посылаем команду чтения байта
    wr_buf.Size=1;
    wr_buf.Data[0]=0x62;                                // ReadByte_1W
    if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                           LBar->Free();          // уничтожаем форму с прогресс-баром
                           ClosePort();
                           return OutputData;
                         }
    Sleep(1);
    // читаем очередной байт
    rd_buf=ReadFrom();                              // читаем
    if(!rd_buf.Size) { SendMsgToLogForm(21,"");          // ошибка приёма пакета
                       LBar->Free();                    // уничтожаем форму с прогресс-баром
                       ClosePort();
                       return OutputData;
                     }
    SelectedChip.ROM[i]=rd_buf.Data[0];               // сохраняем прочитанный байт (текущее состояние 0x0 или 0xFF)
    Sleep(1);
  }
  // посылаем Reset когда всё записали
  wr_buf.Size=1;
  wr_buf.Data[0]=0x60;
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  LBar->Free();                                         // уничтожаем форму с прогресс-баром
  OutputData.Success=true;
  return OutputData;          // посылаем принятый ранее Test в качестве ответа
}
//---------------------------------------------------------------------------
//--- ЗАПИСЬ НОВОГО ЗНАЧЕНИЯ ROM (0x3C) -------------------------------------
//---------------------------------------------------------------------------
// output:      Success
AN1990_OUTPUT_DATA AN1990_WriteROM()
{ WRITE_BUFFER wr_buf;                  // буфер для отправки данных
  READ_BUFFER rd_buf;                   // буфер для приёма данных
  AN1990_OUTPUT_DATA OutputData;        // здесь формируем ответ
  unsigned int CurrentByte, CurrentBit; // текущие передаваемый байт и бит
  unsigned char CRC8;                   // для вычисления CRC8

  OutputData.Success=false;             // инициализируем ответ

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

  // посылаем Reset
  wr_buf.Size=1;
  wr_buf.Data[0]=0x60;
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // посылаем Write ROM (0x3C)
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=0x3C;                                  // посылаем команду записи
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");       // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // инициализируем и начинаем вычислять CRC8
  CRC8=0;
  for(unsigned int j=0;j<8;j++)
  { CRC8=CalcCRC8(CRC8,wr_buf.Data[1]); // вычисляем CRC
    wr_buf.Data[1]=wr_buf.Data[1]>>1;   // следующий бит
  }
  //****************************************************************************
  // Здесь не очень понятно, в доке на K1446VG5 написано, что нужно передавать 2
  // байта TA1, TA2, а в доке на AN1990 (которая сделана на чипе K1446VG5), -
  // что нужно передавать 7 младших бит адреса. Хуй знает кому верить. Наши
  // тупые бараны даже доку не могут нормальную сделать! Нужны эксперименты.
  //****************************************************************************
  // Интернет вроде говорит, что верить нужно доке на К1446ВГ5. Пусть пока так.
  //****************************************************************************
  // отправляем 16 бит адреса (TA1=0, TA2=0)
  for(unsigned int i=0;i<16;i++)
  { //отправляем бит в шину
      wr_buf.Size=2;
      wr_buf.Data[0]=0x63;
      wr_buf.Data[1]=0;         // пишем с нулевого адреса, поэтому все 16 бит - нули
      if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");                 // ошибка загрузки пакета
                             LBar->Free();                         // уничтожаем форму с прогресс-баром
                             ClosePort();
                             return OutputData;
                           }
      Sleep(1);         // выдерживаем паузу после каждого бита
      CRC8=CalcCRC8(CRC8,wr_buf.Data[1]);       // вычисляем CRC
  }
  // отправляем 8 байт данных ROM
  for(unsigned int i=0;i<8;i++)
  {   // отправляем 8 бит данных
      for(unsigned int j=0;j<8;j++)
      { //отправляем бит в шину
        wr_buf.Size=2;
        wr_buf.Data[0]=0x63;
        wr_buf.Data[1]=SelectedChip.ROM[i]>>j;                  // вычисляем и отправляем очередной передаваемый бит
        if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");                 // ошибка загрузки пакета
                               LBar->Free();                         // уничтожаем форму с прогресс-баром
                               ClosePort();
                               return OutputData;
                             }
        Sleep(1);         // выдерживаем паузу после каждого бита
        CRC8=CalcCRC8(CRC8,wr_buf.Data[1]);       // вычисляем CRC
      }
      // принимаем CRC8
      wr_buf.Size=1;
      wr_buf.Data[0]=0x62;                                  // команда чтения байта
      if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                             LBar->Free();            // уничтожаем форму с прогресс-баром
                             ClosePort();
                             return OutputData;
                           }
      Sleep(1);
      // принимаем пакет (CRC8)
      rd_buf=ReadFrom();                                // читаем
      if(!rd_buf.Size) { SendMsgToLogForm(21,"");          // ошибка приёма пакета
                         LBar->Free();                      // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
      Sleep(1);
      for(unsigned int j=0;j<8;j++)
      { CRC8=CalcCRC8(CRC8, rd_buf.Data[0]>>j);         // продолжаем вычислять CRC8 (результат должен быть равен нулю)
      }
      if(CRC8)  SendMsgToLogForm(14,"");          // ошибка CRC8
      // посылаем Program Pulse (тайм-слот передачи нуля)
      //отправляем бит 0 в шину
      wr_buf.Size=2;
      wr_buf.Data[0]=0x63;
      wr_buf.Data[1]=0;
      if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");                 // ошибка загрузки пакета
                             LBar->Free();                         // уничтожаем форму с прогресс-баром
                             ClosePort();
                             return OutputData;
                           }
      Sleep(52);        // выдерживаем паузу 50+ мс
      // принимаем записанный байт
      wr_buf.Size=1;
      wr_buf.Data[0]=0x62;                                  // команда чтения байта
      if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                             LBar->Free();            // уничтожаем форму с прогресс-баром
                             ClosePort();
                             return OutputData;
                           }
      Sleep(1);
      // принимаем пакет (переданный ранее байт)
      rd_buf=ReadFrom();                                // читаем
      if(!rd_buf.Size) { SendMsgToLogForm(21,"");          // ошибка приёма пакета
                         LBar->Free();                      // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
      Sleep(1);
      if(SelectedChip.ROM[i]!=rd_buf.Data[0]) { SendMsgToLogForm(105,"");          // ошибка записи
                                                LBar->Free();                      // уничтожаем форму с прогресс-баром
                                                // порт закрывать не будем
                                                return OutputData;
                                              }
      // если байт успешно записан - начинаем вычислять CRC8 для нового байта
      CRC8=0;
      for(unsigned int j=0;j<8;j++)
      { CRC8=CalcCRC8(CRC8, (i+1)>>j);      // продолжаем вычислять CRC8
      }
  }
  // посылаем Reset
  wr_buf.Size=1;
  wr_buf.Data[0]=0x60;
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  LBar->Free();                                         // уничтожаем форму с прогресс-баром
  OutputData.Success=true;
  return OutputData;
}
//---------------------------------------------------------------------------
//--- БЛОКИРОВКА ТЕКУЩЕГО УСТАНОВЛЕННОГО ROM (0x35) -------------------------
//---------------------------------------------------------------------------
// output:      Success
AN1990_OUTPUT_DATA AN1990_BlockROM()
{ WRITE_BUFFER wr_buf;                  // буфер для отправки данных
  READ_BUFFER rd_buf;                   // буфер для приёма данных
  AN1990_OUTPUT_DATA OutputData;        // результат выполнения команды

  OutputData.Success=false;             // инициализируем результаты нулями

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

  switch(SelectedProgrammer)
  { case 1:     // выбран программатор RH-0004
                //***************
                // подготавливаем I/O для формирования импульса блокировки
                // *** все I/O на вход, во все защёлки нули ***
                // посылаем IO0ConfigInput
                wr_buf.Size=1;
                wr_buf.Data[0]=0x0C;
                if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                                       LBar->Free();            // уничтожаем форму с прогресс-баром
                                       ClosePort();
                                       return OutputData;
                                     }
                // посылаем IO1ConfigInput
                wr_buf.Size=1;
                wr_buf.Data[0]=0x10;
                if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                                       LBar->Free();            // уничтожаем форму с прогресс-баром
                                       ClosePort();
                                       return OutputData;
                                     }
                // посылаем IO2ConfigInput
                wr_buf.Size=1;
                wr_buf.Data[0]=0x14;
                if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                                       LBar->Free();            // уничтожаем форму с прогресс-баром
                                       ClosePort();
                                       return OutputData;
                                     }
                // *** во все защёлки нули ***
                // посылаем IO0Output0
                wr_buf.Size=1;
                wr_buf.Data[0]=0x0D;
                if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                                       LBar->Free();            // уничтожаем форму с прогресс-баром
                                       ClosePort();
                                       return OutputData;
                                     }
                // посылаем IO1Output0
                wr_buf.Size=1;
                wr_buf.Data[0]=0x11;
                if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                                       LBar->Free();            // уничтожаем форму с прогресс-баром
                                       ClosePort();
                                       return OutputData;
                                     }
                // посылаем IO2Output0
                wr_buf.Size=1;
                wr_buf.Data[0]=0x15;
                if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                                       LBar->Free();            // уничтожаем форму с прогресс-баром
                                       ClosePort();
                                       return OutputData;
                                     }
                break;
    case 2:     // выбран программатор RH-0010
                // подготовка не требуется
    default:    break;
  }
  //***************
  // посылаем Reset
  wr_buf.Size=1;
  wr_buf.Data[0]=0x60;
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // посылаем Block ROM
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=0x35;                                  // Block ROM
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // посылаем импульс управления для запуска формирования импульса блокировки
  switch(SelectedProgrammer)
  { case 1:     // для программатора RH-0004
                // посылаем IO0ConfigOutput
                wr_buf.Size=1;
                wr_buf.Data[0]=0x0B;
                if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                                       LBar->Free();            // уничтожаем форму с прогресс-баром
                                       ClosePort();
                                       return OutputData;
                                     }
                Sleep(1);
                // посылаем IO0ConfigInput
                wr_buf.Size=1;
                wr_buf.Data[0]=0x0C;
                if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                                       LBar->Free();            // уничтожаем форму с прогресс-баром
                                       ClosePort();
                                       return OutputData;
                                     }
    case 2:     // для программатора RH-0010
                // посылаем Get110ms_Pulse_1W (0x6A)
                wr_buf.Size=1;
                wr_buf.Data[0]=0x6A;
                if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                                       LBar->Free();            // уничтожаем форму с прогресс-баром
                                       ClosePort();
                                       return OutputData;
                                     }
                break;
    default:    break;
  }
  Sleep(1000);
  // посылаем Reset когда всё записали
  wr_buf.Size=1;
  wr_buf.Data[0]=0x60;
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  LBar->Free();                                         // уничтожаем форму с прогресс-баром
  OutputData.Success=true;
  return OutputData;          // посылаем принятый ранее Test в качестве ответа
}
//---------------------------------------------------------------------------