/* 
    Данный пример демонстирует работу с модулем 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/ltrk511api.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 LTRK511API_DllExport(INT) LTRK511_WriteInfo(TLTRK511 *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;
}







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

    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_LTRK511, &slot, csn);
    }

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

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

        if (LTRK511_IsOpened(&hltrk511) == LTR_OK) {



            /* после открытия модуля доступна информация, кроме версии прошивки ПЛИС */
            printf("Модуль открыт успешно!\n");
            printf("  Название модуля    = %s\n", hltrk511.ModuleInfo.Name);
            printf("  Серийный номер     = %s\n", hltrk511.ModuleInfo.Serial);
            printf("  Версия PLD         = %d\n", hltrk511.ModuleInfo.VerPLD);
            printf("  Модификация        = %d\n", hltrk511.ModuleInfo.Modification);
            printf("  Каналов ключей     = %d\n", hltrk511.ModuleInfo.OutSwCnt);
            printf("  Тип ключей         = %s\n", hltrk511.ModuleInfo.OutSwType == LTRK511_OUT_SW_TYPE_ADG444 ? "ADG444" :
                                                  hltrk511.ModuleInfo.OutSwType == LTRK511_OUT_SW_TYPE_ADG453 ? "ADG453" : "?");
            printf("  Каналов реле       = %d\n", hltrk511.ModuleInfo.RelayCnt);
            printf("  Наличие ЦАП        = %s\n", hltrk511.ModuleInfo.Flags & LTRK511_INFO_FLAG_SUPPORT_DAC ? "Да" : "Нет");


            TLTRK511_OUT_STATE state;
            memset(&state, 0, sizeof(state));
            state.Dac.Data = 1024;
            state.RelayStates = 1 << 1;
            state.Sw[1] = LTRK511_OUT_SW_STATE_EXT_SIG;
            state.Sw[9] = LTRK511_OUT_SW_STATE_INT_DIV;
            state.Sw[22] = LTRK511_OUT_SW_STATE_INT_DIV;
            state.Sw[31] = LTRK511_OUT_SW_STATE_INT_DIV;

            err = LTRK511_SetModuleOutState(&hltrk511, &state, 0);
            if (err != LTR_OK) {
                fprintf(stderr, "Не удалось установить выходные сигналы. Ошибка %d (%s)\n",
                        err, LTRK511_GetErrorString(err));
            }
        }

        LTRK511_Close(&hltrk511);
    }

    return err;
}
