unit LTR11_ProcessThread;



interface
uses Classes, Math, SyncObjs,StdCtrls,SysUtils, ltr11api, ltrapi;
// Время, за которое будет отображаться среднее значение (в мс)
const RECV_BLOCK_TIME          = 500;
// Дополнительный  постоянный таймаут на прием данных (в мс)
const RECV_TOUT                = 4000;




type TLTR11_ProcessThread = class(TThread)
  public
    //элементы управления для отображения результатов обработки
    edtChAvg : array [0..LTR11_MAX_CHANNEL-1] of TEdit;

    phltr11: pTLTR11; //указатель на описатель модуля

    err : Integer; //код ошибки при выполнении потока сбора
    stop : Boolean; //запрос на останов (устанавливается из основного потока)

    constructor Create(SuspendCreate : Boolean);
    destructor Free();

  private
    { Private declarations }
    // среднее в кадре по каждому каналу
    ChAvg : array [0..LTR11_MAX_CHANNEL-1] of Double;
    // признак, что есть вычесленные данные по каналам в ChAvg
    ChValidData : array [0..LTR11_MAX_CHANNEL-1] of Boolean;

    procedure updateData;
  protected
    procedure Execute; override;
  end;
implementation


  constructor TLTR11_ProcessThread.Create(SuspendCreate : Boolean);
  begin
     Inherited Create(SuspendCreate);
     stop:=False;
     err:=LTR_OK;
  end;

  destructor TLTR11_ProcessThread.Free();
  begin
      Inherited Free();
  end;

  { обновление индикаторов формы результатами последнего измерения.
   Метод должен выполняться только через Synchronize, который нужен
   для доступа к элементам VCL не из основного потока }
  procedure TLTR11_ProcessThread.updateData;
  var
    ch: Integer;
  begin
     for ch:=0 to phltr11^.LChQnt -1 do
        edtChAvg[ch].Text := FloatToStrF(ChAvg[ch], ffFixed, 4, 8);

  end;


  procedure TLTR11_ProcessThread.Execute;
  type WordArray = array[0..0] of LongWord;
  type PWordArray = ^WordArray;
  var
    stoperr, recv_size : Integer;
    rcv_buf  : array of LongWord;  //сырые принятые слова от модуля
    data     : array of Double;    //обработанные данные
    i        : Integer;
    ch       : Integer;
    recv_wrd_cnt : Integer;  //количество принимаемых сырых слов за раз
    recv_data_cnt : Integer; //количество обработанных слов, которые должны принять за раз
    ch_avg   : array  [0..LTR11_MAX_CHANNEL-1] of Double;

    
  data1:array[0..10000]of cardinal;
  Time:array[0..10000]of cardinal;
  VOLTAGE:array[0..10000]of real;
  begin
   { Определяем, сколко преобразований будет выполненно за заданное время
      => будем принимать данные блоками такого размера }
    recv_data_cnt :=  Round(phltr11^.ChRate*RECV_BLOCK_TIME) * phltr11^.LChQnt;
    if recv_data_cnt < phltr11^.LChQnt then
        recv_data_cnt := phltr11^.LChQnt;
    recv_wrd_cnt := recv_data_cnt;

    //выделяем массивы для приема данных
    SetLength(rcv_buf, recv_wrd_cnt);
    SetLength(data,  recv_data_cnt);

    err := LTR11_Start(phltr11^);
    if err=LTR_OK then
    begin
      while not stop and (err = LTR_OK) do
      begin
        { Принимаем данные (здесь используется вариант без синхрометок, но есть
          и перегруженная функция с ними) }
        recv_size := LTR11_Recv(phltr11^, rcv_buf, recv_wrd_cnt, RECV_TOUT + RECV_BLOCK_TIME);
        //Значение меньше нуля соответствуют коду ошибки
        if recv_size < 0 then
          err:=recv_size
        else  if recv_size < recv_wrd_cnt then
          err:=LTR_ERROR_RECV_INSUFFICIENT_DATA
        else
        begin
          //err:=LTR11_ProcessData(phltr11, @rcv_buf[0], @data[0], @recv_size,
          //                      True, True);
          err:=LTR11_ProcessData(phltr11^, rcv_buf, data, recv_size,
                                  true, true);
          if err = LTR_OK then
          begin
            for ch:=0 to phltr11^.LChQnt-1 do
              ch_avg[ch] := 0;

            // получаем кол-во отсчетов на канал
            recv_size := Round(recv_size/phltr11^.LChQnt);

            // рассчет среднего
            for i:=0 to recv_size-1 do
              for ch:=0 to phltr11^.LChQnt-1 do
                ch_avg[ch] :=  ch_avg[ch] + data[phltr11^.LChQnt*i + ch];

            for ch:=0 to phltr11^.LChQnt-1 do
            begin
              ChAvg[ch] := ch_avg[ch]/recv_size;
              ChValidData[ch] := true;
            end;
            // обновляем значения элементов управления
            Synchronize(updateData);
          end;
        end;
      end; //while not stop and (err = LTR_OK) do

      { По выходу из цикла отсанавливаем сбор данных.
        Чтобы не сбросить код ошибки (если вышли по ошибке)
        результат останова сохраняем в отдельную переменную }
      stoperr:= LTR11_Stop(phltr11^);
      if err = LTR_OK then
        err:= stoperr;
    end;
  end;
end.
