//---------------------------------------------------------------------------
// Функции для работы с чипами DS18B20, DS1822
//---------------------------------------------------------------------------
#pragma hdrstop
#include "DS18B20.h"
#include "ProgressBar.h"        // для использования прогресс-бара
#include "MainProgram.h"        // для работы с формой
#include "ChipFunctions.h"      // переменные для работы с памятью чипа
#include "PortFunctions.h"      // для работы с портом
#include "CalcCRC.h"            // для расчёта CRC
#include "SendMsgFunctions.h"   // для отправки сообщений в лог
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
//--- ЗАПИСЬ В SCRATCHPAD (0x4E) (только из области 1) ----------------------
//---------------------------------------------------------------------------
// output:      Test - байт, принятый после отправки всех данных (0xFF) + Success
DS18B20_OUTPUT_DATA DS18B20_WriteToScratchpad()
{ WRITE_BUFFER wr_buf;                  // буфер для отправки данных
  READ_BUFFER rd_buf;                   // буфер для приёма данных
  DS18B20_OUTPUT_DATA OutputData;       // результат выполнения команды

  OutputData.Test=0;
  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);
  // посылаем Match ROM
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=0x55;                                  // Match ROM
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // посылаем 8 байт ROM-адреса
  for(unsigned int i=0; i<8; i++)                       // перебираем все слова
  { wr_buf.Size=2;
    wr_buf.Data[0]=0x61;                                // SendByte_1W
    wr_buf.Data[1]=SelectedChip.ROM[i];                 // ROM Bytes
    if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                           LBar->Free();          // уничтожаем форму с прогресс-баром
                           ClosePort();
                           return OutputData;
                         }
    Sleep(1);
  }
  // посылаем Write Scratchpad
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=0x4E;                                  // Write Scratchpad
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  //*** отправляем содержимое нужной области ***
  // посылаем TH
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=SelectedChip.Area1[2];                 // второй байт блокнота
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  LBar->ProgressBar1->Position=100*1/3;      // вычисляем новую позицию прогресс-бара
  //посылаем TL
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=SelectedChip.Area1[3];                 // третий байт блокнота
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  LBar->ProgressBar1->Position=100*2/3;      // вычисляем новую позицию прогресс-бара
  //посылаем CONFIG
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=SelectedChip.Area1[4];                 // четвёртый байт блокнота
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(10);
  LBar->ProgressBar1->Position=100*3/3;      // вычисляем новую позицию прогресс-бара
  // посылаем 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 в качестве ответа
}
//---------------------------------------------------------------------------
//--- ЧТЕНИЕ ИЗ SCRATCHPAD (0xBE) (только в область 1) ----------------------
//---------------------------------------------------------------------------
// output:      Test + Success
DS18B20_OUTPUT_DATA DS18B20_ReadFromScratchpad()
{ WRITE_BUFFER wr_buf;                  // буфер для отправки данных
  READ_BUFFER rd_buf;                   // буфер для приёма данных
  DS18B20_OUTPUT_DATA OutputData;       // здесь формируем ответ
  unsigned char CRC8;                   // для вычисления CRC8

  OutputData.Test=0;
  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);
  // посылаем Match ROM
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=0x55;                                  // Match ROM
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // посылаем 8 байт ROM-адреса
  for(unsigned int i=0; i<8; i++)                       // перебираем все слова
  { wr_buf.Size=2;
    wr_buf.Data[0]=0x61;                                // SendByte_1W
    wr_buf.Data[1]=SelectedChip.ROM[i];                 // ROM Bytes
    if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                           LBar->Free();          // уничтожаем форму с прогресс-баром
                           ClosePort();
                           return OutputData;
                         }
    Sleep(1);
  }
  //команда чтения Scratchpad-а
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=0xBE;                                  // Read Scratchpad
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  CRC8=0;                                       // инициализируем и начинаем вычислять CRC8
  Sleep(10);
  //*** читаем содержимое блокнота ***
  for(unsigned int i=0; i<SelectedChip.Area1Size; i++)  // перебираем все слова блокнота
  { // посылаем команду чтения
    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.Area1[i]=rd_buf.Data[0];       // сохраняем прочитанный байт в блокнот (Area1)
    // вычисляем CRC8 (CRC8 у меня вычисляется побитно, нужно перебрать все биты, начиная с младшего)
    for(unsigned int j=0;j<8;j++)
    { CRC8=CalcCRC8(CRC8, rd_buf.Data[0]);                      // продолжаем вычислять CRC8
      rd_buf.Data[0]>>=1;                                       // сдвигаем вправо (делаем следующий бит младшим)
    }
    LBar->ProgressBar1->Position=100*(i+1)/SelectedChip.Area1Size;      // вычисляем новую позицию прогресс-бара
    Sleep(1);
  }
  // читаем CRC8 (1 байт, неинвертированный)
  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);
  // продолжаем вычислять CRC8
  for(unsigned int j=0;j<8;j++)
  { CRC8=CalcCRC8(CRC8, rd_buf.Data[0]);                      // продолжаем вычислять CRC8
    rd_buf.Data[0]>>=1;                                       // сдвигаем вправо (делаем следующий бит младшим)
  }
  // проверяем результат
  if(CRC8!=0)   SendMsgToLogForm(14,"");          // ошибка CRC8   // если всё нормально - принятый байт совпадает с вычисленным 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;
}
//---------------------------------------------------------------------------
//--- КОПИРОВАНИЕ ИЗ SCRATCHPAD В EEPROM (0x48) -----------------------------
//---------------------------------------------------------------------------
// output:      Status + Success
DS18B20_OUTPUT_DATA DS18B20_CopyScratchpadToMemory()
{ WRITE_BUFFER wr_buf;                  // буфер для отправки данных
  READ_BUFFER rd_buf;                   // буфер для приёма данных
  DS18B20_OUTPUT_DATA OutputData;       // здесь формируем ответ

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

  // посылаем Reset
  wr_buf.Size=1;
  wr_buf.Data[0]=0x60;
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // посылаем Match ROM
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=0x55;                                  // Match ROM
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // посылаем 8 байт ROM-адреса
  for(unsigned int i=0; i<8; i++)                       // перебираем все слова
  { wr_buf.Size=2;
    wr_buf.Data[0]=0x61;                                // SendByte_1W
    wr_buf.Data[1]=SelectedChip.ROM[i];                 // ROM Bytes
    if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                           LBar->Free();          // уничтожаем форму с прогресс-баром
                           ClosePort();
                           return OutputData;
                         }
    Sleep(1);
  }
  // посылаем Copy Scratchpad
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=0x48;                                  // Copy Scratchpad
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(10);
  // посылаем команду чтения чтобы прочитать ещё один байт (Test)
  Sleep(1);
  wr_buf.Size=1;
  wr_buf.Data[0]=0x62;                                  // команда чтения байта
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // принимаем ещё один байт (Test)
  rd_buf=ReadFrom();                                // читаем
  if(!rd_buf.Size) { SendMsgToLogForm(21,"");          // ошибка приёма пакета
                     LBar->Free();                      // уничтожаем форму с прогресс-баром
                     ClosePort();
                     return OutputData;
                   }
  OutputData.Test=rd_buf.Data[0];
  Sleep(1);
  // посылаем Reset когда всё записали
  wr_buf.Size=1;
  wr_buf.Data[0]=0x60;
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  OutputData.Success=true;
  return OutputData;            // посылаем принятый ранее Test в качестве ответа
}
//---------------------------------------------------------------------------
//--- КОПИРОВАНИЕ ИЗ EEPROM В SCRATCHPAD (0xB8) -----------------------------
//---------------------------------------------------------------------------
// output:      Status + Success
DS18B20_OUTPUT_DATA DS18B20_RecallE2()
{ WRITE_BUFFER wr_buf;                  // буфер для отправки данных
  READ_BUFFER rd_buf;                   // буфер для приёма данных
  DS18B20_OUTPUT_DATA OutputData;       // здесь формируем ответ

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

  // посылаем Reset
  wr_buf.Size=1;
  wr_buf.Data[0]=0x60;
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // посылаем Match ROM
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=0x55;                                  // Match ROM
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // посылаем 8 байт ROM-адреса
  for(unsigned int i=0; i<8; i++)                       // перебираем все слова
  { wr_buf.Size=2;
    wr_buf.Data[0]=0x61;                                // SendByte_1W
    wr_buf.Data[1]=SelectedChip.ROM[i];                 // ROM Bytes
    if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                           LBar->Free();          // уничтожаем форму с прогресс-баром
                           ClosePort();
                           return OutputData;
                         }
    Sleep(1);
  }
  // посылаем Recall E2
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=0xB8;                                  // Recall E2
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(10);
  // посылаем команду чтения чтобы прочитать ещё один байт (Test)
  Sleep(1);
  wr_buf.Size=1;
  wr_buf.Data[0]=0x62;                                  // команда чтения байта
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // принимаем ещё один байт (Test)
  rd_buf=ReadFrom();                                // читаем
  if(!rd_buf.Size) { SendMsgToLogForm(21,"");          // ошибка приёма пакета
                     LBar->Free();                      // уничтожаем форму с прогресс-баром
                     ClosePort();
                     return OutputData;
                   }
  OutputData.Test=rd_buf.Data[0];
  Sleep(1);
  // посылаем Reset когда всё записали
  wr_buf.Size=1;
  wr_buf.Data[0]=0x60;
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  OutputData.Success=true;
  return OutputData;            // посылаем принятый ранее Test в качестве ответа
}
//---------------------------------------------------------------------------
//--- ЧТЕНИЕ СОСТОЯНИЯ ЛИНИИ POWER (0xB4) -----------------------------------
//---------------------------------------------------------------------------
// output:      Status + Success
DS18B20_OUTPUT_DATA DS18B20_ReadPowerSupply()
{ WRITE_BUFFER wr_buf;                  // буфер для отправки данных
  READ_BUFFER rd_buf;                   // буфер для приёма данных
  DS18B20_OUTPUT_DATA OutputData;       // здесь формируем ответ

  OutputData.Test=0x55;                 // 0x0 - parasite power, 0xFF - separate power
  OutputData.Success=false;             // инициализируем ответ

  // посылаем Reset
  wr_buf.Size=1;
  wr_buf.Data[0]=0x60;
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // посылаем Match ROM
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=0x55;                                  // Match ROM
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // посылаем 8 байт ROM-адреса
  for(unsigned int i=0; i<8; i++)                       // перебираем все слова
  { wr_buf.Size=2;
    wr_buf.Data[0]=0x61;                                // SendByte_1W
    wr_buf.Data[1]=SelectedChip.ROM[i];                 // ROM Bytes
    if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                           LBar->Free();          // уничтожаем форму с прогресс-баром
                           ClosePort();
                           return OutputData;
                         }
    Sleep(1);
  }
  // посылаем Read Power Supply
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=0xB4;                                  // Read Power Supply
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // посылаем команду чтения чтобы прочитать ещё один байт (Test)
  Sleep(1);
  wr_buf.Size=1;
  wr_buf.Data[0]=0x62;                                  // команда чтения байта
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // принимаем ещё один байт (Test)
  rd_buf=ReadFrom();                                // читаем
  if(!rd_buf.Size) { SendMsgToLogForm(21,"");          // ошибка приёма пакета
                     LBar->Free();                      // уничтожаем форму с прогресс-баром
                     ClosePort();
                     return OutputData;
                   }
  OutputData.Test=rd_buf.Data[0];               // сохраняем принятое значение 
  Sleep(1);
  // посылаем Reset когда всё записали
  wr_buf.Size=1;
  wr_buf.Data[0]=0x60;
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  OutputData.Success=true;
  // расшифровывать и выводить значение на форму будем в основной программе
  return OutputData;            // посылаем принятый ранее Test в качестве ответа
}
//---------------------------------------------------------------------------
//--- ЗАПУСК ПРЕОБРАЗОВАНИЯ (0x44) ------------------------------------------
//---------------------------------------------------------------------------
// output:      Status + Success
DS18B20_OUTPUT_DATA DS18B20_ConvertT()
{ WRITE_BUFFER wr_buf;                  // буфер для отправки данных
  READ_BUFFER rd_buf;                   // буфер для приёма данных
  DS18B20_OUTPUT_DATA OutputData;       // здесь формируем ответ

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

  // посылаем Reset
  wr_buf.Size=1;
  wr_buf.Data[0]=0x60;
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // посылаем Match ROM
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=0x55;                                  // Match ROM
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // посылаем 8 байт ROM-адреса
  for(unsigned int i=0; i<8; i++)                       // перебираем все слова
  { wr_buf.Size=2;
    wr_buf.Data[0]=0x61;                                // SendByte_1W
    wr_buf.Data[1]=SelectedChip.ROM[i];                 // ROM Bytes
    if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                           LBar->Free();          // уничтожаем форму с прогресс-баром
                           ClosePort();
                           return OutputData;
                         }
    Sleep(1);
  }
  // посылаем Convert Temperature
  wr_buf.Size=2;
  wr_buf.Data[0]=0x61;                                  // SendByte_1W
  wr_buf.Data[1]=0x44;                                  // Convert T
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(10);
  // посылаем команду чтения чтобы прочитать ещё один байт (Test)
  Sleep(1);
  wr_buf.Size=1;
  wr_buf.Data[0]=0x62;                                  // команда чтения байта
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  Sleep(1);
  // принимаем ещё один байт (Test)
  rd_buf=ReadFrom();                                // читаем
  if(!rd_buf.Size) { SendMsgToLogForm(21,"");          // ошибка приёма пакета
                     LBar->Free();                      // уничтожаем форму с прогресс-баром
                     ClosePort();
                     return OutputData;
                   }
  OutputData.Test=rd_buf.Data[0];
  Sleep(1);
  // посылаем Reset когда всё записали
  wr_buf.Size=1;
  wr_buf.Data[0]=0x60;
  if(!WriteTo(wr_buf)) { SendMsgToLogForm(11,"");          // ошибка загрузки пакета
                         LBar->Free();            // уничтожаем форму с прогресс-баром
                         ClosePort();
                         return OutputData;
                       }
  OutputData.Success=true;
  return OutputData;            // посылаем принятый ранее Test в качестве ответа
}
//---------------------------------------------------------------------------
//--- ВЫЧИСЛЕНИЕ ЗНАЧЕНИЯ ТЕМПЕРАТУРЫ ---------------------------------------
//---------------------------------------------------------------------------
float DS18B20_DecodeTemperature()
{ float OutputValue, Temp1;     // сюда сформируем ответ + временная переменная (для вычисления степени двойки)
  unsigned int R1R0, Temp2;     // количество значащих бит + временная переменная (для хранения значащих бит)
  unsigned char Mask;           // маска для значащих битов

  // сначала определяем, сколько у нас значащих бит и формируем маску
  R1R0=(SelectedChip.Area1[4]&0x60)>>5; // выделяем биты 5,6 и сдвигаем их к младшим разрядам
  switch(R1R0)
  { case 0:  Mask=0xF8;         // 0b11111000 - 9-bits format
             break;
    case 1:  Mask=0xFC;         // 0b11111100 - 10-bits format
             break;
    case 2:  Mask=0xFE;         // 0b11111110 - 11-bits format
             break;
    case 3:
    default: Mask=0xFF;         // 0b11111111 - 12-bits format
             break;
  }
  // инициализируем и начинаем вычислять OutputValue
  OutputValue=0; Temp1=0.0625;                          // начальное значение 0, Temp1 = 2^-4
  Temp2=SelectedChip.Area1[1]&0x0F;                     // пишем значащие биты MSB
  Temp2=(Temp2<<8)+(SelectedChip.Area1[0]&Mask);        // сдвигаем и добавляем значащие биты LSB
  // перебираем все значащие биты (кроме знака) и вычисляем значение температуры
  for(unsigned int i=0; i<11; i++)
  { OutputValue+=Temp1*(Temp2&1);
    Temp2>>=1;  // берём следующий значащий бит
    Temp1*=2;   // вычисляем новый вес значащего бита (следующая степень двойки)
  }
  // определяем знак (в Temp2 у нас как раз остался только бит знака)
  if(Temp2)     OutputValue*=-1.0;      // если самый старший бит не ноль, значит число отрицательное
  return OutputValue;
}
//---------------------------------------------------------------------------
//--- РАСШИФРОВКА КОНФИГУРАЦИИ И ВЫЧИСЛЕНИЕ ПОРОГОВ -------------------------
//---------------------------------------------------------------------------
void DS18B20_DecodeConfigAndThresholds()
{ unsigned int R1R0, Temp;      // количество значащих бит и переменная для вычисления степени
  int TH, TL;                   // пороговые значения
  unsigned char THByte, TLByte; // временные хранилища значащих байт
  AnsiString TempStr;           // заготовка под ответ

  // сначала определяем конфигурацию (сколько у нас значащих бит)
  R1R0=(SelectedChip.Area1[4]&0x60)>>5; // выделяем биты 5,6 и сдвигаем их к младшим разрядам
  switch(R1R0)
  { case 0:  // 0b11111000 - 9-bits format
             TempStr="The chip has 9-bits temperature format (0.5 oC accuracy)";
             break;
    case 1:  // 0b11111100 - 10-bits format
             TempStr="The chip has 10-bits temperature format (0.25 oC accuracy)";
             break;
    case 2:  // 0b11111110 - 11-bits format
             TempStr="The chip has 11-bits temperature format (0.125 oC accuracy)";
             break;
    case 3:  // 0b11111111 - 12-bits format
             TempStr="The chip has 12-bits temperature format (0.0625 oC accuracy)";
             break;
    default: // unknown format
             TempStr="The chip has unknown temperature format";
             break;
  }
  // определяем значения порогов
  TH=0; TL=0; Temp=1;
  THByte=SelectedChip.Area1[2]; TLByte=SelectedChip.Area1[3];
  for(unsigned int i=0; i<7; i++)
  { TH+=(THByte&1)*Temp;        // обрабатываем младший бит
    TL+=(TLByte&1)*Temp;        // обрабатываем младший бит
    THByte>>=1;  TLByte>>=1;    // переходим к следующему биту
    Temp*=2;
  }
  // определяем знаки порогов
  if(THByte)    TH*=-1;         // если самый старший бит не 0, значит значение отрицательное
  if(TLByte)    TL*=-1;         // если самый старший бит не 0, значит значение отрицательное
  // дописываем строку с учётом вычисленных значений
  TempStr+=", TH="+IntToStr(TH)+" oC, TL="+IntToStr(TL)+" oC.";
  // выводим сформированную строку в лог
  Form1->RichEdit9->Lines->Add(TempStr);       // выводим в RichEdit9
  return;
}
//---------------------------------------------------------------------------
