//---------------------------------------------------------------------------


#pragma hdrstop

#include "LTR24_ProcessThread.h"

// Время, за которое будет отображаться среднее значение (в мс)
#define RECV_BLOCK_TIME          500
// Дополнительный  постоянный таймаут на прием данных (в мс)
#define RECV_TOUT                4000


//---------------------------------------------------------------------------

#pragma package(smart_init)

 __fastcall TLTR24_ProcessThread::TLTR24_ProcessThread(bool CreateSuspended)
    : TThread(CreateSuspended), stop(false), err (LTR_OK) {

}

/* обновление индикаторов формы результатами последнего измерения.
   Метод должен выполняться только через Syncronize, который нужен
   для доступа к элементам VCL не из основного потока */
void __fastcall TLTR24_ProcessThread::updateData() {
    for (int ch=0; ch < LTR24_CHANNEL_NUM; ch++) {
        if (ChValidData[ch]) {
            edtChAvg[ch]->Text = FloatToStrF(ChAvg[ch], ffFixed, 4, 8);
        } else {
            edtChAvg[ch]->Text = "";
        }
    }
}


void __fastcall TLTR24_ProcessThread::Execute() {
    DWORD *rcv_buf=0;
    double *data=0;
    INT err = LTR_OK;
    // номера разрешенных каналов
    BYTE ch_nums  [LTR24_CHANNEL_NUM];
    INT ch_cnt=0;  //количество разрешенных каналов
    INT recv_wrd_cnt;  //количество принимаемых сырых слов за раз
    INT recv_data_cnt; //количество обработанных слов, которые должны принять за раз

    //обнуляем переменные
    for (INT ch=0; ch < LTR24_CHANNEL_NUM; ch++)
        ChValidData[ch]=false;
    Synchronize(updateData);

    //Проверяем, сколько и какие каналы разрешены
    for (INT ch=0; ch < LTR24_CHANNEL_NUM; ch++) {
        if (phltr24->ChannelMode[ch].Enable) {
            ch_nums[ch_cnt] = ch;
            ch_cnt++;
        }
    }

    /* Определяем, сколко преобразований будет выполненно за заданное время
      => будем принимать данные блоками такого размера */
    recv_data_cnt =  (INT)(phltr24->ADCFreq*RECV_BLOCK_TIME/1000) * ch_cnt;
    /* В 24-битном формате каждому отсчету соответствует два слова от модуля,
                   а в 20-битном - одно */
    recv_wrd_cnt = phltr24->DataFmt == LTR24_FORMAT_24 ? 2*recv_data_cnt : recv_data_cnt;

    //выделяем массивы для приема данных
    rcv_buf = new DWORD[recv_wrd_cnt];
    data = new double[recv_data_cnt];

    err = LTR24_Start(phltr24);
    if (err==LTR_OK) {
        while (!stop && (err==LTR_OK)) {
            /* Принимаем данные */
            INT recv_size = LTR24_Recv(phltr24, rcv_buf, 0, recv_wrd_cnt, RECV_TOUT + RECV_BLOCK_TIME);
            //Значение меньше нуля соответствуют коду ошибки
            if (recv_size < 0) {
                err=recv_size;
            } else if (recv_size < recv_wrd_cnt) {
                err=LTR_ERROR_RECV_INSUFFICIENT_DATA;
            } else {
                double ch_avg[LTR24_CHANNEL_NUM];
                bool   ch_valid[LTR24_CHANNEL_NUM];

                err=LTR24_ProcessData(phltr24, rcv_buf, data, &recv_size,
                                        LTR24_PROC_FLAG_CALIBR |
                                        LTR24_PROC_FLAG_VOLT |
										LTR24_PROC_FLAG_AFC_COR_EX |
										LTR24_PROC_FLAG_ICP_PHASE_COR, 0);
                if (err==LTR_OK) {
                    for (INT ch=0; ch < LTR24_CHANNEL_NUM; ch++) {
                        ch_avg[ch] =  0;
                        ch_valid[ch] = false;
                    }

                    // получаем кол-во отсчетов на канал
                    recv_size = (INT) (recv_size/ch_cnt);

                    // рассчет среднего
                    for (INT i=0; i < recv_size; i++) {
                        for (INT ch=0; ch < ch_cnt; ch++) {
                            ch_avg[ch_nums[ch]] +=  data[ch_cnt*i + ch];
                            ch_valid[ch_nums[ch]] = true;
                        }
                    }

                    for (INT ch=0; ch < LTR24_CHANNEL_NUM; ch++) {
                        if (ch_valid[ch])
                            ChAvg[ch]=ch_avg[ch]/recv_size;
                        ChValidData[ch]= ch_valid[ch];
                    }
                    // обновляем значения элементов управления
                    Synchronize(updateData);
                }
            }
        } // while (!stop && (err==LTR_OK))

        /* По выходу из цикла отсанавливаем сбор данных.
            Чтобы не сбросить код ошибки (если вышли по ошибке)
            результат останова сохраняем в отдельную переменную */
        INT stoperr= LTR24_Stop(phltr24);
        if (err == LTR_OK)
            err= stoperr;
    }

    delete []rcv_buf;
    delete []data;
}
