#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 4096*4096


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;
}

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)
            {
                err = LTR22_SetADCChannel(&hltr22, 0, TRUE);
                if (err==LTR_OK)
                    err = LTR22_SetADCChannel(&hltr22, 1, TRUE);
                if (err==LTR_OK)
                    err = LTR22_SetADCChannel(&hltr22, 2, FALSE);
                if (err==LTR_OK)
                    err = LTR22_SetADCChannel(&hltr22, 3, FALSE);
                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_SyncPhazeStart(&hltr22);
                if (err == LTR_OK) {
                    //int done = 0;
                    err = LTR22_SyncPhazeWaitDone(&hltr22, 5000);

                }
            }


            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;
                    DWORD i=0;
                    INT ch_cnt = 0,ch;
                    for (ch=0; ch < LTR22_CHANNEL_CNT; ch++)
                    {
                        if (hltr22.ChannelEnabled[ch])
                            ch_cnt++;
                    }

                    for (i=0 ; (err==LTR_OK) && (i < STREAM_RECV_COUNT); 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;
                        }
                    }
                }
            }


            LTR22_Close(&hltr22);
        }


    }






    return err;
}
