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

    Пример устанавливает связь с модулем, настраивает порты 1 и 2 на вывод, а 3 и 4 на ввод.
    После этого выполняется вывод значения на выходы и ввод значений с входов с их отображением.
    Далее пример разрывает связь с модулем и завершает работу.

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

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


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

#include "ltr/include/ltr43api.h"


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

/* Разбор параметров командной строки. Если указано меньше, то используются
 * значения по умолчанию:
 * 1 параметр - номер слота (от 1 до 16)
 * 2 параметр - серийный номер крейта
 * 3 параметр - ip-адрес сервера */
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, "Неверный формат IP-адреса!!\n");
            err = -1;
        }

        for (i=0; (i < 4) && !err; i++) {
            if ((a[i]<0) || (a[i] > 255)) {
                fprintf(stderr, "Недействительный IP-адрес!!\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;
    TLTR43 hltr43;
    t_open_param par;

#ifdef _WIN32
    /* для вывода русских букв в консоль для ОС Windows*/
    setlocale(LC_ALL, "");
#endif

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

    if (err == LTR_OK) {
        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");
            printf("  Название:        %s\n", hltr43.ModuleInfo.Name);
            printf("  Серийный номер:  %s\n", hltr43.ModuleInfo.Serial);
            printf("  Версия прошивки: %s\n", hltr43.ModuleInfo.FirmwareVersion);
            printf("  Дата прошивки:   %s\n", hltr43.ModuleInfo.FirmwareDate);


            /* конфигурация модуля (для примера используем порт 3-4 на ввод, а 1-2 - на вывод */
            hltr43.IO_Ports.Port1 = LTR43_PORT_DIR_OUT;
            hltr43.IO_Ports.Port2 = LTR43_PORT_DIR_OUT;
            hltr43.IO_Ports.Port3 = LTR43_PORT_DIR_IN;
            hltr43.IO_Ports.Port4 = LTR43_PORT_DIR_IN;
            err = LTR43_Config(&hltr43);
            if (err != LTR_OK) {
                fprintf(stderr, "Не удалось сконфигурировать модуль. Ошибка %d (%s)\n",
                        err, LTR43_GetErrorString(err));
            }
        }

        if (err == LTR_OK) {
            /* слово для вывода. т.к. мы настроили на вывод только 1 и 2 порт,
             * то имеют значения только младшие 16 бит */
            DWORD wrd = 0x00005A42;
            err = LTR43_WritePort(&hltr43, wrd);
            if (err != LTR_OK) {
                fprintf(stderr, "Не удалось записать значения портов модуля. Ошибка %d (%s)\n",
                        err, LTR43_GetErrorString(err));
            } else {
                printf("Значения записаны успешно!\n");
            }
        }

        if (err == LTR_OK) {
            DWORD wrd;
            /* так как на ввод настроены только 3 и 4 порт, то имеют значения
             * только старшие 16 бит */
            err = LTR43_ReadPort(&hltr43, &wrd);
            if (err != LTR_OK) {
                fprintf(stderr, "Не удалось прочитать значения портов модуля. Ошибка %d (%s)\n",
                        err, LTR43_GetErrorString(err));
            } else {
                DWORD msk;
                printf("Успешно считано значение (биты 31-16): ");
                for (msk = (1 << 31); msk != (1 << 15); msk>>=1)
                    printf("%d ", wrd & msk ? 1 : 0);
                printf("\n");
            }
        }

        if (LTR43_IsOpened(&hltr43) == LTR_OK)
            LTR43_Close(&hltr43);
    }


    return err;
}
