#include "ltr/include/ltr22api.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#if defined _WIN32 || defined __QNX4__
#include <locale.h>
#endif



#define STREAM_RECV_SIZE  4096*3
#define STREAM_RECV_TOUT  5000
#define STREAM_RECV_COUNT 512


typedef struct
{
    int slot;
    const char *serial;
    DWORD addr;
} t_open_param;

static int f_get_params(int argc, char** argv, t_open_param* par)
{
    int err = 0;
    par->slot = LTR_CC_CHNUM_MODULE1;
    par->serial = "";
    par->addr = LTRD_ADDR_DEFAULT;


    if (argc > 1)
        par->slot = atoi(argv[1]);
    if (argc > 2)
        par->serial = argv[2];
    if (argc > 3)
    {
        int a[4],i;
        if (sscanf(argv[3], "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3])!=4)
        {
            fprintf(stderr, "Неверный формат адреса сервера!!\n");
            err = -1;
        }

        for (i=0; (i < 4) && !err; i++)
        {
            if ((a[i]<0) || (a[i] > 255))
            {
                fprintf(stderr, "Неверный формат адреса сервера!!\n");
                err = -1;
            }
        }

        if (!err)
        {
            par->addr = (a[0] << 24) | (a[1]<<16) | (a[2]<<8) | a[3];
        }
    }
    return err;
}

static INT f_recv_block(TLTR22 *hltr22, int set_ch_cnt, int block_cnt)
{
    INT err = LTR_OK;
    INT ch;

    /* устанавливаем какие каналы разрешены, какие запрещены */
    for (ch=0; (ch < 4) && (err==LTR_OK); ch++)
    {

        err = LTR22_SetADCChannel(hltr22, ch, ch < set_ch_cnt);
        if (err!=LTR_OK)
        {
            fprintf(stderr, "Не могу запретить канала АЦП. Ошибка %d:%s\n",
                    err, LTR22_GetErrorString(err));
        }
    }

    if (err==LTR_OK)
    {
        err = LTR22_SetFreq(hltr22, FALSE, 1 );
        if (err!=LTR_OK)
        {
            fprintf(stderr, "Ошибка установки частот АЦП. Ошибка %d:%s\n",
                    err, LTR22_GetErrorString(err));
        }
    }

    if (err==LTR_OK)
    {
        /* отключаем режим измерения собственного нуля */
        err = LTR22_SwitchMeasureADCZero(hltr22, FALSE);
        if (err!=LTR_OK)
        {
            fprintf(stderr, "Ошибка отключения режима измерения собственного нуля. Ошибка %d:%s\n",
                    err, LTR22_GetErrorString(err));
        }
    }

    if (err==LTR_OK)
    {
        /* настройка режима отсечки постоянной составляющей */
        err = LTR22_SwitchACDCState(hltr22, FALSE);
        if (err!=LTR_OK)
        {
            fprintf(stderr, "Ошибка настройки режима отсечки постоянной составляющей. Ошибка %d:%s\n",
                    err, LTR22_GetErrorString(err));
        }
    }


    if (err==LTR_OK)
    {
        err=LTR22_StartADC(hltr22, FALSE);
        if (err!=LTR_OK)
        {
            fprintf(stderr, "Не могу запустить сбор данных АЦП. Ошибка %d:%s\n",
                    err, LTR22_GetErrorString(err));
        }
        else
        {
            static DWORD rbuf[STREAM_RECV_SIZE];
            static double proc_buf[STREAM_RECV_SIZE];
            INT recvd;
            BYTE ovfls[4];
            INT stop_err;
            INT i=0;
            INT ch_cnt = 0;
            for (ch=0; ch < LTR22_CHANNEL_CNT; ch++)
            {
                if (hltr22->ChannelEnabled[ch])
                    ch_cnt++;
            }

            for (i=0 ; (err==LTR_OK) && (i < block_cnt); i++)
            {
                recvd = LTR22_Recv(hltr22, rbuf, NULL, sizeof(rbuf)/sizeof(rbuf[0]), STREAM_RECV_TOUT);
                if (recvd<0)
                {
                    err = recvd;
                    fprintf(stderr, "Ошибка приема данных. Ошибка %d:%s\n",
                            err, LTR22_GetErrorString(err));
                }
                else if (recvd!=STREAM_RECV_SIZE)
                {
                    fprintf(stderr, "Принято недостаточно данных. Запрашивали %d, приняли %d\n",
                            STREAM_RECV_SIZE, recvd);
                    err = LTR_ERROR_RECV;
                }
                else
                {
                    err = LTR22_ProcessData(hltr22, rbuf, proc_buf, recvd,
                                            1, 1, ovfls);
                    if (err!=LTR_OK)
                    {
                        fprintf(stderr, "Ошибка обработки данных. Ошибка %d:%s\n",
                                err, LTR22_GetErrorString(err));
                    }
                    else
                    {
                        unsigned cur_ch;
                        printf("Блок %d", i+1);
                        for (ch=0, cur_ch=0; ch < LTR22_CHANNEL_CNT; ch++)
                        {
                            if (hltr22->ChannelEnabled[ch])
                            {
                                printf(" ch[%d]=%.6f", ch+1, proc_buf[recvd/ch_cnt*cur_ch]);
                                cur_ch++;
                            }
                        }

                        printf("\n");
                        fflush(stdout);
                    }
                }
            }


            stop_err = LTR22_StopADC(hltr22);
            if (stop_err!=LTR_OK)
            {
                fprintf(stderr, "Ошибка останова сбора данных. Ошибка %d:%s\n",
                        stop_err, LTR22_GetErrorString(stop_err));
                if (err==LTR_OK)
                    err = stop_err;
            }
            else
            {
                stop_err = LTR22_ClearBuffer(hltr22, TRUE);
                if (stop_err!=LTR_OK)
                {
                    fprintf(stderr, "Ошибка очистки буфера. Ошибка %d:%s\n",
                            stop_err, LTR22_GetErrorString(stop_err));
                    if (err==LTR_OK)
                        err = stop_err;
                }
            }
        }
    }
    return err;

}

int main(int argc, char** argv)
{
    INT err = LTR_OK;
    TLTR22 hltr22;
    t_open_param par;

#ifdef _WIN32
    setlocale(LC_ALL, "");
#endif

    err = f_get_params(argc, argv, &par);

    if (!err)
    {
        LTR22_Init(&hltr22);
        err = LTR22_Open(&hltr22, par.addr, LTRD_PORT_DEFAULT, par.serial, par.slot);
        if (err)
        {
            fprintf(stderr, "Не могу открыть модуль. Ошибка %d (%s)\n",
                    err, LTR22_GetErrorString(err));
        }
        else
        {
            printf("Модуль открыт успешно. Информация:\n Название модуля: %s\n Серийный номер: %s\n"
                   " CPU: %s\n Версия прошивки: %d.%d.%d.%d\n Ревизия: %d\n",
                   hltr22.ModuleInfo.Description.DeviceName,
                   hltr22.ModuleInfo.Description.SerialNumber,
                   hltr22.ModuleInfo.CPU.Name,
                   (hltr22.ModuleInfo.CPU.FirmwareVersion>>24) & 0xFF,
                   (hltr22.ModuleInfo.CPU.FirmwareVersion>>16) & 0xFF,
                   (hltr22.ModuleInfo.CPU.FirmwareVersion>>8) & 0xFF,
                   (hltr22.ModuleInfo.CPU.FirmwareVersion>>0) & 0xFF,
                   hltr22.ModuleInfo.Description.Revision
                   );
            fflush(stdout);


            /* устанавливаем нужные диапазоны для каналов */
            err = LTR22_SetADCRange(&hltr22, 0, 5);		//-+3В
            if (err==LTR_OK)
                err = LTR22_SetADCRange(&hltr22, 1, 5);
            if (err==LTR_OK)
                err = LTR22_SetADCRange(&hltr22, 2, 5);
            if (err==LTR_OK)
                err = LTR22_SetADCRange(&hltr22, 3, 5);
            if (err)
            {
                fprintf(stderr, "Не могу установить диапазон АЦП. Ошибка %d:%s\n",
                        err, LTR22_GetErrorString(err));
            }

            if (err==LTR_OK)
            {
                printf("Чтение с 4 каналов!\n");
                err = f_recv_block(&hltr22, 4, 256);
            }

            if (err==LTR_OK)
            {
                printf("Чтение с 2 каналов!\n");
                err = f_recv_block(&hltr22, 2, 2048);
            }








            LTR22_Close(&hltr22);
        }


    }






    return err;
}
