#ifndef LTRK71API_H_
#define LTRK71API_H_

#include "ltr01api.h"

#ifdef __cplusplus
extern "C" {                                 // only need to export C interface if
                                             // used by C++ source code
#endif

#ifdef _WIN32
    #ifdef LTRK71API_EXPORTS
      #define LTRK71API_DllExport(type) __declspec(dllexport) type APIENTRY
    #else
      #define LTRK71API_DllExport(type) __declspec(dllimport) type APIENTRY
    #endif
#elif defined __GNUC__
    #define LTRK71API_DllExport(type) __attribute__ ((visibility("default"))) type
#else
    #define LTRK71API_DllExport(type)  type
#endif


/** Размер строки с именем модуля в структуре #TLTRK71_MODULE_INFO */
#define LTRK71_NAME_SIZE                16
/** Размер строки с серийным номером модуля в структуре #TLTRK71_MODULE_INFO */
#define LTRK71_SERIAL_SIZE              24
/** Размер буфера для передачи тестовой последовательности Орбиты */
#define LTRK71_TX_STREAM_BUF_SIZE       (16*1024)
/** Максимальное значение кода периода специального сигнала */
#define LTRK71_SPECSIG_PERIOD_MAX       15


/** Коды ошибок, специфичные для LTRK71. */
typedef enum {
    LTRK71_ERR_INSUF_OUT_CH_BUF_SIZE   = -11130, /**< Превышен размер буфера тестового потока на вывод */
} e_LTRK71_ERROR_CODES;

/** Коды настройки информативности потока данных */
typedef enum {
    LTRK71_INFORMATIVITY_2 = 3, /**< 2-ая информативность */
    LTRK71_INFORMATIVITY_4 = 1, /**< 4-ая информативность */
    LTRK71_INFORMATIVITY_8 = 0, /**< 8-ая информативность */
} e_LTRK71_INFORMATIVITY;

/** Режимы вывода информации на монитор модуля */
typedef enum {
    LTRK71_MON_MODE_FROM_STREAM = 0, /**< На монитор выдаются данные с потока от Орбиты */
    LTRK71_MON_MODE_FROM_BUF    = 1, /**< На монитор выдаются данные из буфера модуля, записанные с помощью LTRK71_MonBufWrite() */
} e_LTRK71_MON_MODE;

/** Источник данных для передачи */
typedef enum {
    LTRK71_TXSRC_BUF            = 0, /**< Передаются записанные в буфер данные */
    LTRK71_TXSRC_SPECSIG        = 1, /**< Передается сигнал специальной формы, сгенерированный ПЛИС */
} e_LTRK71_TXSRC;

typedef enum {
    LTRK71_SPECSIG_TYPE_PHASE_0   = 0, /**< Фаза 0° */
    LTRK71_SPECSIG_TYPE_PHASE_180 = 1, /**< Фаза 180° */
    LTRK71_SPECSIG_TYPE_MEANDER   = 2, /**< Меандр */
} e_LTRK71_SPECSIG_TYPE;

#pragma pack (4)

/** Информация о модуле */
typedef struct {
    CHAR        Name[LTRK71_NAME_SIZE];      /**< Название модуля (оканчивающаяся нулем ASCII-строка) */
    CHAR        Serial[LTRK71_SERIAL_SIZE];  /**< Серийный номер модуля (оканчивающаяся нулем ASCII-строка) */
    BYTE        VerPLD;                      /**< Версия прошивки PLD  */
    DWORD       Reserved[15];                 /**< Резерв */
} TLTRK71_MODULE_INFO;


/** Настройки приема-передачи потока данных Орбиты */
typedef struct {
    BOOLEAN TxEn; /**< Разрешение передачи тестовых данных потока Орбиты.
                       Если TRUE, то после запуска обмена модуль
                       будет циклически передавать тестовый поток данных, загруженных
                       с помощью LTRK71_LoadTxStreamBuf() */
    BOOLEAN RxEn; /**< Разрешение приема. Если TRUE, то после запуска обмена,
                       модуль будет принимать данные с указанного в RxChNum
                       канала и передавать их в ПК */
    BYTE    RxChNum; /**< Номер выхода, с которого принимаются данные - 0, 1, 2 */
    BYTE    Informativity;  /**< Информативность - значение из #e_LTRK71_INFORMATIVITY */
    BYTE    TxSrc;          /**< Источник данных для передачи. Значение из #e_LTRK71_TXSRC */
    BYTE    SpecSigType;    /**< Тип специального сигнала для TxSrc ==  #LTRK71_TXSRC_SPECSIG, значение из #e_LTRK71_SPECSIG_TYPE */
    WORD    SpecSigPeriod;  /**< Период специального сигнала (действительные значения от 0 до #LTRK71_SPECSIG_PERIOD_MAX). */
    DWORD   Reserved[6]; /**< Резерв */
} TLTRK71_STREAM_CONFIG;

/** Настройки модуля */
typedef struct {
    TLTRK71_STREAM_CONFIG Stream; /**< Настройки потока */
    DWORD Reserved[16]; /**< Резерв */
} TLTRK71_CONFIG;



/** Параметры состояния модуля */
typedef struct {
    BOOLEAN ExchangeActive; /**< Признак запущенного обмена потоком данных с Орбитой.
                                 Устанавливается после успешного завершения LTRK71_ExchangeStart()
                                 и сбрасывается после успешного LTRK71_ExchangeStop(). */
    DWORD Reserved[7]; /**< Резерв */
} TLTRK71_STATE;



/** Описатель модуля */
typedef struct {
    INT size;     /**< Размер структуры. Заполняется в LTRK71_Init(). */
    /** Структура, содержащая состояние соединения с сервером.
        Не используется напрямую пользователем. */
    TLTR Channel;
    /** Указатель на непрозрачную структуру с внутренними параметрами,
        используемыми исключительно библиотекой и недоступными для пользователя. */
    PVOID Internal;    
    TLTRK71_CONFIG Cfg; /**< Настройки модуля */
    /** Состояние модуля и рассчитанные параметры. Поля изменяются функциями
        библиотеки. Пользовательской программой могут использоваться
        только для чтения. */
    TLTRK71_STATE State;
    TLTRK71_MODULE_INFO ModuleInfo; /**< Информация о модуле */
} TLTRK71;


/** Информация о принятом слове потока данных с Орбиты. Получается на основе
    стандартного слова LTR в результате обработки данных с помощью
    LTRK71_ProcessData() */
typedef struct {
    WORD Data;              /**< 10-битные данные */
    BOOLEAN ParityVal;         /**< значение бита четности */
    BOOLEAN ParityOk;      /**< признак ошибки четности */
    BOOLEAN PhaseMarker;    /**< Признак наличия маркера фазы */
    BYTE    PhaseWordNum;   /**< Номер слова в двух фазах, начиная с нечетной от маркера фазы */
    BOOLEAN SvcInfo;        /**< Бит служебной информации */
    BYTE    Reserved;       /**< Резерв. Сейчас сохраняется старший байт принятого слова, где все биты = 0, кроме младшего, равного PhaseMarker  */
} TLTRK71_RX_DATA;

#pragma pack ()

/*============================================================================*/

LTRK71API_DllExport(INT) LTRK71_Init(TLTRK71 *hnd);
LTRK71API_DllExport(INT) LTRK71_Open(TLTRK71 *hnd, DWORD net_addr, WORD net_port,
                                       const CHAR *csn, WORD slot);
LTRK71API_DllExport(INT) LTRK71_Close(TLTRK71 *hnd);
LTRK71API_DllExport(INT) LTRK71_IsOpened(TLTRK71 *hnd);



/** Загрузка слова в буфер для вывода на монитор модуля
 *  в режиме #LTRK71_MON_MODE_FROM_BUF
 *
 *  @param[in] hnd       Описатель модуля.
 *  @param[in] addr      Адрес байта в видеобуфере.
 *  @param[in] word      Значение записываемого байта
 *  @return              Код ошибки.
 ******************************************************************************/
LTRK71API_DllExport(INT) LTRK71_MonBufWrite(TLTRK71 *hnd, BYTE addr, BYTE word);


/** Установка режима вывода на экран модуля. Модуль может выводить на экран либо
 *  информацию на основе потока данных от Орбиты, либо загруженные с помощью
 *  LTRK71_MonBufWrite() данные. В первом случае также необходимо указать номер
 *  калибровочного слова для корректного разбора потока Орбиты для отображения/
 *  Функция должна выполняться  при остановленном потоке данных.
 *  @param[in] hnd       Описатель модуля.
 *  @param[in] mode      Режим вывода на монитор. Значение из #e_LTRK71_MON_MODE
 *  @param[in] CbrChNum  Номер калибровочного слова (канала) в потоке данных от Орбиты
 *                       (для режима #LTRK71_MON_MODE_FROM_STREAM)
   @return              Код ошибки.
 ******************************************************************************/
LTRK71API_DllExport(INT) LTRK71_MonSetMode(TLTRK71 *hnd, DWORD mode, DWORD CbrChNum);


/***************************************************************************//**
   @brief Загрузка значений циклического буфера для выдачи тестового потока.

   Функция позволяет загрузить в буфер значения для последующего циклического вывода
   тестового потока данных орбиты.

   Для выдачи тестовой последовательности необходимо сперва загрузить данные в буфер и
   разрешить выдачу в поле TxEn настроек Cfg.Stream, после чего запустить обмен с помощью
   LTRK71_LoadTxStreamBuf().

   @param[in] hnd       Описатель модуля.
   @param[in] data      Массив из size 16-битных слов, в которых содержится 10-бит передаваемых
                        данных. Старшие 4 бита - резерв.
   @param[in] size      Количество слов в буфере data для загрузки в модуль. Может
                        быть от 1 до #LTRK71_TX_STREAM_BUF_SIZE.
   @return              Код ошибки.
 ******************************************************************************/
LTRK71API_DllExport(INT) LTRK71_LoadTxStreamBuf(TLTRK71 *hnd, const WORD *data, WORD size);


/***************************************************************************//**
   @brief Запуск обмена потоковыми данными с Орбитой.

   Функция выполняет запуск приема данных от орбиты с выбранного канала и/или циклическую
   выдачу заранее загруженной тестовой последовательности.

   Настройки обмена потоковыми данными должны быть заполнены в поле Cfg.Stream
   до вызова данной функции.

   Если разрешена выдача тестовой соследовательности, то сами выдаваемые слова должны
   быть предварительно записаны с помощью LTRK71_LoadTxStreamBuf().

   После вызова данной функции не должны измняться настройки модуля, а также
   до завершения обмена с помощью LTRK71_ExchangeStop()
   вызываться любые функции для данного модуля, кроме LTRK71_Recv() и
   обработаны с помощью LTRK71_ProcessData().


   @param[in] hnd       Описатель модуля.
   @return              Код ошибки.
 ******************************************************************************/
LTRK71API_DllExport(INT) LTRK71_ExchangeStart(TLTRK71 *hnd);

/***************************************************************************//**
   @brief Завершение обмена потоковыми данными с Орбитой.

   Функция завершает обмен потоками, запущенный LTRK71_ExchangeStart().
   После успешного вызова обмен завершается и можно использовать другие функции,
   кроме приема данных

   @param[in] hnd       Описатель модуля.
   @return              Код ошибки.
 ******************************************************************************/
LTRK71API_DllExport(INT) LTRK71_ExchangeStop(TLTRK71 *hnd);


/***************************************************************************//**
   @brief Прием данных от модуля

   Функция принимает запрашиваемое число слов от модуля. Возвращаемые слова
   находятся в специальном формате, который включает в себя служебную информацию.

   Для обработки принятых слов и получения значений измерений используется функция
   LTRK415_ProcessData().

   Функция возвращает управление либо когда примет запрошенное количество слов,
   либо по истечению таймаута. При этом реально принятое количество слов можно
   узнать по возвращенному значению.

   @param[in]  hnd      Описатель модуля.
   @param[out] data     Массив, в который будут сохранены принятые слова. Должен
                        быть размером на size 32-битных слов.
   @param[out] tmark    Указатель на массив размером на size 32-битных слов,
                        в который будут сохранены значения счетчиков синхрометок,
                        соответствующие принятым данным. Генерация меток
                        настраивается для крейта или специального модуля отдельно.
                        Синхрометки подробнее описаны в разделе "Синхрометки"
                        @docref_ltrapi{руководства для библиотеки ltrapi}.
                        Если синхрометки не используются, то можно передать
                        в качестве параметра нулевой указатель.
   @param[in]  size     Запрашиваемое количество 32-битных слов на прием.
   @param[in]  timeout  Таймаут на выполнение операции в миллисекундах. Если в течение
                        заданного времени не будет принято запрашиваемое количество
                        слов, то функция все равно вернет управление, возвратив
                        в качестве результата реально принятое количество слов
   @return              Значение меньше нуля соответствует коду ошибки. Значение
                        больше или равное нулю соответствует количеству реально
                        принятых и сохраненных в массив data слов.
*******************************************************************************/
LTRK71API_DllExport(INT) LTRK71_Recv(TLTRK71 *hnd, DWORD *data, DWORD *tstamp, DWORD size, DWORD timeout);


/***************************************************************************//**
    @brief Обработка принятых данных

    Функция позволяет на основе слов, принятых с помощью LTRK71_Recv(), получить
    информацию о принятом слове от орбиты.

    На каждое слово функция возвращает структуру типа #TLTRK71_RX_DATA,
    в которой содержится вся инфомрация из исходного принятого слова.


    @param[in] hnd       Описатель модуля.
    @param[in] src_data  Массив из size 32-битных слов, принятых с помощью LTRK71_Recv().
    @param[out] dst_data Массив из структур типа #TLTRK71_RX_DATA, в котором будет
                         сохранен результат обработки. Количество элементов массива
                         должно быть не меньше переданного значения size. После
                         завершения функции данные количество заполненных элементов
                         будет указанно в измененном значении size.
    @param[in, out] size При вызове фунции в данном параметре должно быть записано
                         количество слов в src_data, которое необходимо обработать.
                         После завершения функции значение size будет обновлено и
                         содержать количество обработанных и сохраненных в dst_data
                         слов. Как правило эти значения должны совпадать, но могут
                         отличаться в случае обнаружения слов неизвестного формата.
    @return              Код ошибки.
 ******************************************************************************/
LTRK71API_DllExport(INT) LTRK71_ProcessData(TLTRK71 *hnd, const DWORD *src_data, TLTRK71_RX_DATA *dst_data, INT *size);

/***************************************************************************//**
   @brief Получение сообщения об ошибке.

   Функция возвращает строку, соответствующую переданному коду ошибки, в кодировке
   CP1251 для Windows или UTF-8 для Linux. Функция может обработать как ошибки
   из LTRK71API, так и общие коды ошибок из ltrapi.

   @param[in] err       Код ошибки
   @return              Указатель на строку, содержащую сообщение об ошибке.
 ******************************************************************************/
LTRK71API_DllExport(LPCSTR) LTRK71_GetErrorString(INT err);


#ifdef __cplusplus
}                                          // only need to export C interface if
                                           // used by C++ source code
#endif

#endif                      /* #ifndef LTR11API_H_ */
