#include "ltr/include/ltr43api.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <locale.h>
#include <conio.h>
#else
#include <signal.h>
#include <unistd.h>
#endif

#define TEST_EEPROM

#define STREAM_RECV_SIZE  40000
#define STREAM_RECV_TOUT  5000
#define STREAM_RECV_RATE  100000


/* признак необходимости завершить сбор данных */
static int f_out = 0;

#ifndef _WIN32
/* Обработчик сигнала завершения для Linux */
static void f_abort_handler(int sig) {
    f_out = 1;
}
#endif

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, "Invalid ip address format!!\n");
            err = -1;
        }

        for (i=0; (i < 4) && !err; i++) {
            if ((a[i]<0) || (a[i] > 255)) {
                fprintf(stderr, "invalid ip address!!\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;
    t_open_param par;
    TLTR43 hltr43;

#ifndef _WIN32
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    /* В ОС Linux устанавливаем свой обработчик на сигнал закрытия,
       чтобы завершить сбор корректно */
    sa.sa_handler = f_abort_handler;
    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGABRT, &sa, NULL);
#endif
#ifdef _WIN32
    /* для вывода русских букв в консоль для ОС Windows*/
    setlocale(LC_ALL, "");
#endif
#if 0
    for (;!err;) {
        LTR43_Init(&hltr43);

         err = LTR43_Open(&hltr43, SADDR_DEFAULT, SPORT_DEFAULT, "", CC_MODULE2);
         if (!err) {
             hltr43.RS485.FrameSize = 8;
             hltr43.RS485.Baud = 115200;
             hltr43.RS485.StopBit = 0;
             hltr43.RS485.Parity = 0;
             hltr43.RS485.SendTimeoutMultiplier = 1;
             hltr43.RS485.ReceiveTimeoutMultiplier = 1;
             err = LTR43_Config(&hltr43);
             if (err) {
                fprintf(stderr, "ltr43 config error %d: %s\n", err, LTR43_GetErrorString(err));
             } else {
                printf("ok\n");
             }
             LTR43_Close(&hltr43);
         } else {
             fprintf(stderr, "ltr43 open error %d: %s\n", err, LTR43_GetErrorString(err));
         }
    }
#endif


    err = f_get_params(argc, argv, &par);
    if (!err) {
        LTR43_Init(&hltr43);
        err = LTR43_Open(&hltr43, par.addr, LTRD_PORT_DEFAULT, par.serial, par.slot);
    }

    if (err != LTR_OK) {
        fprintf(stderr, "Не удалось установить соединение с модулем. Ошибка %d: %s\n",
                err, LTR43_GetErrorString(err));
    } else {
        printf("Модуль открыт успешно. Информация о модуле:\n  Название %s\n  Серийный %s\n  Версия прошивки %s\n",
               hltr43.ModuleInfo.Name, hltr43.ModuleInfo.Serial, hltr43.ModuleInfo.FirmwareVersion);
        fflush(stdout);

        if (err==LTR_OK) {

            hltr43.IO_Ports.Port1 = 1;
            hltr43.IO_Ports.Port2 = 1;
            hltr43.IO_Ports.Port3 = 0;
            hltr43.IO_Ports.Port4 = 0;

            hltr43.StreamReadRate = STREAM_RECV_RATE;
            hltr43.Marks.StartMark_Mode = 0;
            hltr43.Marks.SecondMark_Mode = 0;


            hltr43.RS485.FrameSize = 8;
            hltr43.RS485.Baud = 115200;
            hltr43.RS485.Parity = LTR43_RS485_PARITY_NONE;
            hltr43.RS485.StopBit = 0;
            hltr43.RS485.ReceiveTimeoutMultiplier = 0;

            err = LTR43_Config(&hltr43);
            if (err!=LTR_OK) {
                fprintf(stderr, "Невозможно сконфигурировать модуль. Ошибка %d:%s\n",
                        err, LTR43_GetErrorString(err));
            }
        }


        if(err == LTR_OK) {
            err = LTR43_WritePort(&hltr43, 0x55555555);
            if (err!=LTR_OK)
                fprintf(stderr, "Невозможно записать данные в модуль. Ошибка %d:%s\n",
                        err, LTR43_GetErrorString(err));
        }

        if (err==LTR_OK) {
            err = LTR43_StartSecondMark(&hltr43);
        }

        if (err==LTR_OK) {
            err = LTR43_MakeStartMark(&hltr43);
        }

        if (err==LTR_OK) {
            err = LTR43_StopSecondMark(&hltr43);
        }
#if 1
        if (err==LTR_OK) {
            err = LTR43_StartStreamRead(&hltr43);

            while ((err == LTR_OK) && !f_out) {
                DWORD raw_data[2*STREAM_RECV_SIZE], tmark[2*STREAM_RECV_SIZE];
                DWORD res_data[STREAM_RECV_SIZE];
                INT recv_size = LTR43_Recv(&hltr43, raw_data, tmark,
                                           sizeof(raw_data)/sizeof(raw_data[0]),
                                           STREAM_RECV_TOUT);

               // err = LTR43_WritePort(&hltr43, 0x55555555);

                if (recv_size<0) {
                    err = recv_size;
                    fprintf(stderr, "Ошибка приема данных. Ошибка %d:%s\n",
                           err, LTR43_GetErrorString(err));
                } else if (recv_size < (INT)(sizeof(raw_data)/sizeof(raw_data[0]))) {
                    fprintf(stderr, "Принято недостаточно данных. Принято %d, было запрошено %u\n",
                            recv_size, (unsigned)(sizeof(raw_data)/sizeof(raw_data[0])));
                    err = LTR_ERROR_RECV;
                } else {
                    DWORD size = recv_size;
                    err = LTR43_ProcessData(&hltr43, raw_data, res_data, &size);
                    if (err!=LTR_OK) {
                        fprintf(stderr, "Ошибка обработки принятых данных. Ошибка %d:%s\n",
                                err, LTR43_GetErrorString(err));
                    } else {
                        printf("Приянято %d слов. Cлово 0x%08X, старт %d, сек %d\n",
                               size, res_data[0], tmark[0]>>16, tmark[0] & 0xFFFF);
                        fflush(stdout);
                    }
                }
#ifdef _WIN32
                /* проверка нажатия клавиши для выхода */
                if (err==LTR_OK) {
                    if (_kbhit())
                        f_out = 1;
                }
#endif
            }

            err = LTR43_StopStreamRead(&hltr43);
        }
#endif

#if 0
        if (!err)
        {
            err = LTR43_RS485_SetResponseTout(&hltr43, 10000);
            if (!err)
                err = LTR43_RS485_SetIntervalTout(&hltr43, 1750);
            if (!err)
            {
                SHORT snd[256], rcv[256], i;
                DWORD recvd;
                for (i=0; i < 256; i++)
                    snd[i] = i;
                err = LTR43_RS485_ExchangeEx(&hltr43, snd, rcv, 256, 256,
                                             LTR43_RS485_FLAGS_USE_INTERVAL_TOUT,
                                             &recvd);
                if (!err)
                {
                    printf("Принято успешно %d слов", recvd);
                    for (i=0; i < recvd; i++)
                    {

                    }

                }
                else
                {
                    printf("Обмен по RS485 завершен с ошибкой %d: %s. Принято %d слов\n",
                           err, LTR43_GetErrorString(err), recvd);
                }
            }


        }
#endif



#ifdef TEST_EEPROM
        if (err==LTR_OK)
        {
            BYTE eeprom_rd[LTR43_EEPROM_SIZE], eeprom_wr[LTR43_EEPROM_SIZE];
            INT i;

            for (i=0; (i < LTR43_EEPROM_SIZE) && (err==LTR_OK); i++)
            {
                eeprom_wr[i] = i;
                err = LTR43_WriteEEPROM(&hltr43, i, eeprom_wr[i]);
                if (err!=LTR_OK)
                {
                    fprintf(stderr, "Невозможно прочитать EEPROM по адресу %d. Ошибка %d: %s\n",
                            i, err, LTR43_GetErrorString(err));
                }
            }

            for (i=0; (i < LTR43_EEPROM_SIZE) && (err==LTR_OK); i++)
            {
                err = LTR43_ReadEEPROM(&hltr43, i, &eeprom_rd[i]);
                if (err!=LTR_OK)
                {
                    fprintf(stderr, "Невозможно прочитать EEPROM по адресу %d. Ошибка %d: %s\n",
                            i, err, LTR43_GetErrorString(err));
                }
                else if (eeprom_rd[i]!=eeprom_wr[i])
                {
                    fprintf(stderr, "Прочитано неверное значение из EEPROM по адресу %d: Записывали %d, прочитали %d\n",
                            i, eeprom_wr[i], eeprom_rd[i]);
                    err = LTR_ERROR_EXECUTE;
                }
            }

            if (err==LTR_OK)
            {
                printf("EEPROM проверена успешно!\n");
            }
        }
#endif
        LTR43_Close(&hltr43);
    }
    return err;
}
