/* 
    Данный пример демонстирует работу с модулем LTR210.
    По умолчанию идет работа с первым слотом первого крейта, но это можно изменить
        через параметры командной строки:
    ltr210_recv  slot crate_serial srvip
    где:
        slot         - номер слота (от 1 до 16)
        crate_serial - серийный номер крейта (если крейтов больше одного)
        srvip        - ip-адрес LTR-сервера (если не локальный)
    Параметры опциональны: можно указать только слот, слот и серийный номер крейта или все

    Пример принимает данные от двух каналов в режиме периодического покадрового сбора,
    отображает на экране первые 2 слова кадра, а полный кадр сохраняется в
    файл Frame<номер кадра>.txt (по файлу на каждый кадр) в текстовом виде.

    Пользователь может изменить настройки на свои, поменяв заполнение полей
    структуры конфигурации.

    Сбор идет до нажатия любой клавиши на Windows или  CTRL+C на Linux

    Также пример на ОС Windows предполает наличие файла прошивки в директории запуска
    (можно переопределить через LTR210_FPGA_FIRM_FILE).

    Сборка в VisualStudio:
    Для того чтобы собрать проект в Visual Studio, измените путь к заголовочным файлам
    (Проект (Project) -> Свойства (Properties) -> Свойства конфигурации (Configuration Properties)
    -> С/С++ -> Общие (General) -> Дополнительные каталоги включения (Additional Include Directories))
    на тот, где у вас лежат заголовочный файл l502api.h и измените путь к библиотекам
    (Проект (Project) -> Свойства (Properties) -> Свойства конфигурации (Configuration Properties) ->
    Компановщик (Linker) -> Общие (General) -> Дополнительные катологи библиотек (Additional Library Directories)).

    Внимание!: Если Вы собираете проект под Visual Studio и у Вас некорректно
    отображается вывод русских букв, то нужно изменить кодировку:
    выберите Файл (File) -> Доболнительные параметры сохранения (Advanced Save Options)...
    и в поле Кодировка (Encoding) выберите Юникод (UTF8, с сигнатурой)/Unicode (UTF-8 with signature)
    и сохраните изменения в файле.
*/


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

#ifdef _WIN32
    #include <locale.h>
#endif

#define ERR_INVALID_USAGE           -1
#define ERR_MODULE_NOT_FOUND        -2

extern LTRK416API_DllExport(INT) LTRK416_WriteInfo(TLTRK416 *hnd);

static int f_get_slot(e_LTR01_SUBID req_subid, int *slot, char* serial) {
    TLTR srv;
    int fnd=0;
    INT err = LTR_OK;
    LTR_Init(&srv);
    err=LTR_OpenSvcControl(&srv, LTRD_ADDR_DEFAULT, LTRD_PORT_DEFAULT);
    if (err != LTR_OK) {
        fprintf(stderr, "Не удалось установить связь с LTR-сервером. Ошибка %d: %s!\n",
                err, LTR_GetErrorString(err));
    } else {
        char serial_list[LTR_CRATES_MAX][LTR_CRATE_SERIAL_SIZE];
        err=LTR_GetCrates(&srv, (BYTE*)&serial_list[0][0]);
        LTR_Close(&srv);
        if (err != LTR_OK) {
            fprintf(stderr, "Не удалось получить список крейтов. Ошибка %d: %s!\n",
                    err, LTR_GetErrorString(err));
        } else {
            int crate_ind;
            for (crate_ind = 0 ; (crate_ind < LTR_CRATES_MAX) && !fnd; crate_ind++) {
                if (serial_list[crate_ind][0] != '\0') {
                    TLTR crate;
                    INT crate_err = LTR_OK;
                    LTR_Init(&crate);
                    crate_err = LTR_OpenCrate(&crate, LTRD_ADDR_DEFAULT, LTRD_PORT_DEFAULT,
                                               LTR_CRATE_IFACE_UNKNOWN, serial_list[crate_ind]);
                    if (crate_err == LTR_OK) {
                        WORD mids[LTR_MODULES_PER_CRATE_MAX];
                        crate_err = LTR_GetCrateModules(&crate, mids);
                        if (crate_err == LTR_OK) {
                            int module_ind;
                            for (module_ind = 0; (module_ind < LTR_MODULES_PER_CRATE_MAX) && !fnd; module_ind++) {
                                if (mids[module_ind]==LTR_MID_LTR01) {
                                    WORD subid;
                                    crate_err = LTR01_GetSubID(LTRD_ADDR_DEFAULT, LTRD_PORT_DEFAULT,
                                                               crate.csn, LTR_CC_CHNUM_MODULE1+module_ind,
                                                               &subid, NULL);
                                    if ((crate_err == LTR_OK) && (subid == req_subid)) {
                                        fnd = 1;
                                        strcpy(serial, crate.csn);
                                        *slot = module_ind + LTR_CC_CHNUM_MODULE1;
                                    }
                                }
                            }
                        }
                        LTR_Close(&crate);
                    }
                }
            }
        }
    }

    if (err == LTR_OK) {
        if (!fnd) {
            fprintf(stderr, "Ни одного модуля не было найдено!\n");
            err = ERR_MODULE_NOT_FOUND;
        } else {
            printf("Найден модуль: крейт %s, слот %d\n", serial, *slot);
        }
    }
    return err;
}




#define RX_WORDS_CNT 1024


int main(int argc, char** argv) {
    INT err = LTR_OK, out=0;
    TLTRK416 hltrk416;

    char csn[LTR_CRATE_SERIAL_SIZE];
    int slot=LTR_CC_CHNUM_MODULE1;

#ifdef _WIN32
    /* для вывода русских букв в консоле... */
    setlocale(LC_ALL, "");
#endif
    /* находим нужный модуль */
    if (!err && !out) {
        err = f_get_slot(LTR01_SUBID_LTRK416, &slot, csn);
    }

    if (!err && !out) {
        LTRK416_Init(&hltrk416);
        /* устанавливаем соединение с модулем */
        err = LTRK416_Open(&hltrk416, LTRD_ADDR_DEFAULT, LTRD_PORT_DEFAULT, csn, slot);

#if 0
        if ((err == LTR_ERROR_FLASH_INFO_NOT_PRESENT) || (err == LTR_OK)) {
            strcpy(hltrk416.ModuleInfo.Serial, "1R626719");
            err = LTRK416_WriteInfo(&hltrk416);
        } else if (err != LTR_OK) {
#else
        if (err != LTR_OK) {
#endif
            fprintf(stderr, "Не удалось установить связь с модулем. Ошибка %d (%s)\n",
                    err, LTRK416_GetErrorString(err));
        }

        if (LTRK416_IsOpened(&hltrk416) == LTR_OK) {
            INT ch;


            /* после открытия модуля доступна информация, кроме версии прошивки ПЛИС */
            printf("Модуль открыт успешно!\n");
            printf("  Название модуля    = %s\n", hltrk416.ModuleInfo.Name);
            printf("  Серийный номер     = %s\n", hltrk416.ModuleInfo.Serial);
            printf("  Версия PLD         = %d\n", hltrk416.ModuleInfo.VerPLD);

            DWORD rs_tx[] = {0xA5, 0xb2, 0xc3, 0xc4};
            DWORD mil_tx[] = {
                LTRK416_MIL_DATA_FLAG_CMD | 0x1234,
                0x5AA5,
                0x7889};

            err = LTRK416_SetDACEx(&hltrk416, 0,     0, 5, 5000);
            err = LTRK416_SetDACEx(&hltrk416, 1000,  0, 1, 5000);
            err = LTRK416_SetDACEx(&hltrk416, 0x800, 0, 5, 5000);


            for (ch = 0; ch < LTRK416_RS_CH_CNT; ++ch) {
                hltrk416.Cfg.RS.Ch[ch].RxEn = TRUE;//ch == 3;
                hltrk416.Cfg.RS.Ch[ch].TxEn = ch == 3;
                hltrk416.Cfg.RS.Ch[ch].PauseLen = 10;
                rs_tx[0] = ch;
                err = LTRK416_LoadRsBuf(&hltrk416, ch, rs_tx, sizeof(rs_tx)/sizeof(rs_tx[0]));
            }

            for (ch = 0; ch < LTRK416_MIL_CH_CNT; ++ch) {
                hltrk416.Cfg.MIL.Ch[ch].RxEn = TRUE;//ch == 0;//TRUE; //ch == 1;//TRUE;// ch == 0;
                hltrk416.Cfg.MIL.Ch[ch].TxEn = FALSE;//ch == 0;//TRUE;//ch == 1;
                hltrk416.Cfg.MIL.Ch[ch].PauseLen = 1;

                err = LTRK416_LoadMilBuf(&hltrk416, ch, mil_tx, sizeof(mil_tx)/sizeof(mil_tx[0]));
            }

            err = LTRK416_ExchangeStart(&hltrk416);
            if (err == LTR_OK) {
                static DWORD rx_words[RX_WORDS_CNT];
                static TLTRK416_RX_DATA rx_data[RX_WORDS_CNT];
                int recv_res = LTRK416_Recv(&hltrk416, rx_words, NULL, sizeof(rx_words)/sizeof(rx_words[0]), 1000);
                if (recv_res > 0) {
                    err = LTRK416_ProcessData(&hltrk416, rx_words, rx_data, &recv_res);
                }
                err  = LTRK416_ExchangeStop(&hltrk416);
            }


            /*INT stop_err = LTRK416_SetDAC(&hltrk416, 0, 0);
            if (err == LTR_OK) {
                err = stop_err;
            }*/

        }

        LTRK416_Close(&hltrk416);
    }

    return err;
}
