/** @file ltr210api.h
    Файл содержит определение всех констант, типов и функций, необходимых
    для работы с модулем LTR210 */

#include "ltrapi.h"

#ifndef __LTR210API_H_
#define __LTR210API_H_

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


#pragma pack(4)

/***************************************************************************//**
  @addtogroup const_list Константы и перечисления.
  @{
  *****************************************************************************/

/** Размер строки с именем модуля в структуре #TINFO_LTR210 */
#define LTR210_NAME_SIZE     8
/** Размер строки с серийным номером модуля в структуре #TINFO_LTR210 */
#define LTR210_SERIAL_SIZE   16

/** Количество каналов АЦП в одном модуле */
#define LTR210_CHANNEL_CNT   2
/** Количество диапазонов измерения АЦП */
#define LTR210_RANGE_CNT     5

/** Количество диапазонов, для которых нужно выполнять дополнительную коррекцию
    АЧХ с помощью IIR фильтра */
#define LTR210_AFC_IIR_COR_RANGE_CNT  2

/** Код принятого отсчета АЦП, соответствующий максимальному напряжению
    заданного диапазона */
#define LTR210_ADC_SCALE_CODE_MAX 13000

/** Максимальное значение делителя частоты АЦП */
#define LTR210_ADC_FREQ_DIV_MAX 10
/** Максимальное значение коэффициента прореживания данных от АЦП */
#define LTR210_ADC_DCM_CNT_MAX  256

/** Частота в Герцах, относительно которой задается частота отсчетов АЦП */
#define LTR210_ADC_FREQ_HZ   10000000
/** Частота в Герцах, относительно которой задается частота следования кадров
    в режиме #LTR210_SYNC_MODE_PERIODIC */
#define LTR210_FRAME_FREQ_HZ 1000000

/** Размер внутреннего циклического буфера модуля в отсчетах АЦП */
#define LTR210_INTERNAL_BUFFER_SIZE (16777216)

/** Максимальный размер кадра, который можно установить в одноканальном режиме */
#define LTR210_FRAME_SIZE_MAX (16777216 - 512)


/** @brief Коды ошибок, специфичные для LTR210.

   Коды ошибок, которые определены и используются только в ltr210api.
   Остальные коды ошибок, которые используются разными модулями, определены в ltrapi.h */
typedef enum {
    LTR210_ERR_INVALID_SYNC_MODE            = -10500, /**< Задан неверный код условия сбора кадра*/
    LTR210_ERR_INVALID_GROUP_MODE           = -10501, /**< Задан неверный код режима работы модуля в составе группы */
    LTR210_ERR_INVALID_ADC_FREQ_DIV         = -10502, /**< Задано неверное значение делителя частоты АЦП*/
    LTR210_ERR_INVALID_CH_RANGE             = -10503, /**< Задан неверный код диапазона канала АЦП*/
    LTR210_ERR_INVALID_CH_MODE              = -10504, /**< Задан неверный режим измерения канала*/
    LTR210_ERR_SYNC_LEVEL_EXCEED_RANGE      = -10505, /**< Установленный уровень аналоговой синхронизации
                                                        выходит за границы установленного диапазона*/
    LTR210_ERR_NO_ENABLED_CHANNEL           = -10506, /**< Ни один канал АЦП не был разрешен*/
    LTR210_ERR_PLL_NOT_LOCKED               = -10507, /**< Ошибка захвата PLL*/
    LTR210_ERR_INVALID_RECV_DATA_CNTR       = -10508, /**< Неверное значение счетчика в принятых данных*/
    LTR210_ERR_RECV_UNEXPECTED_CMD          = -10509, /**< Прием неподдерживаемой команды в потоке данных*/
    LTR210_ERR_FLASH_INFO_SIGN              = -10510, /**< Неверный признак информации о модуле во Flash-памяти*/
    LTR210_ERR_FLASH_INFO_SIZE              = -10511, /**< Неверный размер прочитанной из Flash-памяти информации о модуле*/
    LTR210_ERR_FLASH_INFO_UNSUP_FORMAT      = -10512, /**< Неподдерживаемый формат информации о модуле из Flash-памяти*/
    LTR210_ERR_FLASH_INFO_CRC               = -10513, /**< Ошибка проверки CRC информации о модуле из Flash-памяти*/
    LTR210_ERR_FLASH_INFO_VERIFY            = -10514, /**< Ошибка проверки записи информации о модуле во Flash-память*/
    LTR210_ERR_CHANGE_PAR_ON_THE_FLY        = -10515, /**< Часть измененных параметров нельзя изменять на лету */
    LTR210_ERR_INVALID_ADC_DCM_CNT          = -10516, /**< Задан неверный коэффициент прореживания данных АЦП */
    LTR210_ERR_MODE_UNSUP_ADC_FREQ          = -10517, /**< Установленный режим не поддерживает заданную частоту АЦП */
    LTR210_ERR_INVALID_FRAME_SIZE           = -10518, /**< Неверно задан размер кадра */
    LTR210_ERR_INVALID_HIST_SIZE            = -10519, /**< Неверно задан размер предыстории */
    LTR210_ERR_INVALID_INTF_TRANSF_RATE     = -10520, /**< Неверно задано значение скорости выдачи данных в интерфейс */
    LTR210_ERR_INVALID_DIG_BIT_MODE         = -10521, /**< Неверно задан режим работы дополнительного бита */
    LTR210_ERR_SYNC_LEVEL_LOW_EXCEED_HIGH   = -10522, /**< Нижний порог аналоговой синхронизации превышает верхний */
    LTR210_ERR_KEEPALIVE_TOUT_EXCEEDED      = -10523, /**< Не пришло ни одного статуса от модуля за заданный интервал */
    LTR210_ERR_WAIT_FRAME_TIMEOUT           = -10524, /**< Не удалось дождаться прихода кадра за заданное время */
    LTR210_ERR_FRAME_STATUS                 = -10525  /**< Слово статуса в принятом кадре указывает на ошибку данных */
} e_LTR210_ERROR_CODES;

/** Диапазоны канала АЦП */
typedef enum {
    LTR210_ADC_RANGE_10     = 0, /**< Диапазон \f$\pm10\f$ В */
    LTR210_ADC_RANGE_5      = 1, /**< Диапазон \f$\pm5\f$ В */
    LTR210_ADC_RANGE_2      = 2, /**< Диапазон \f$\pm2\f$ В */
    LTR210_ADC_RANGE_1      = 3, /**< Диапазон \f$\pm1\f$ В */
    LTR210_ADC_RANGE_0_5    = 4  /**< Диапазон \f$\pm0.5\f$ В */
} e_LTR210_ADC_RANGE;

/** Режим измерения канала АЦП */
typedef enum {
    LTR210_CH_MODE_ACDC    = 0, /**< Измерение переменной и постоянной составляющей
                                     (открытый вход) */
    LTR210_CH_MODE_AC      = 1, /**< Отсечка постоянной составляющей (закрытый
                                      вход) */
    LTR210_CH_MODE_ZERO    = 2  /**< Режим измерения собственного нуля*/
} e_LTR210_CH_MODE;


/** @brief Режим работы и события синхронизации.

    Определяет режим работы модуля и условие запуска сбора кадра (события синхронизации) */
typedef enum {
    LTR210_SYNC_MODE_INTERNAL     = 0, /**< Режим сбора кадра по программной команде,
                                            передаваемой вызовом LTR210_FrameStart()*/
    LTR210_SYNC_MODE_CH1_RISE     = 1, /**< Режим сбора кадра по фронту сигнала относительно
                                            уровня синхронизации на первом аналоговом канале*/
    LTR210_SYNC_MODE_CH1_FALL     = 2, /**< Режим сбора кадра по спаду сигнала относительно
                                            уровня синхронизации на первом аналоговом канале*/
    LTR210_SYNC_MODE_CH2_RISE     = 3, /**< Режим сбора кадра по фронту сигнала относительно
                                            уровня синхронизации на втором аналоговом канале*/
    LTR210_SYNC_MODE_CH2_FALL     = 4, /**< Режим сбора кадра по спаду сигнала относительно
                                            уровня синхронизации на втором аналоговом канале*/
    LTR210_SYNC_MODE_SYNC_IN_RISE = 5, /**< Режим сбора кадра по фронту цифрового сигнала
                                            на входе SYNC (не от другого модуля!)*/
    LTR210_SYNC_MODE_SYNC_IN_FALL = 6, /**< Режим сбора кадра по спаду цифрового сигнала
                                            на входе SYNC (не от другого модуля!)*/
    LTR210_SYNC_MODE_PERIODIC     = 7, /**< Режим периодического сбора кадров с
                                            установленной частотой следования кадров*/
    LTR210_SYNC_MODE_CONTINUOUS   = 8  /**< Режим непрерывного сбора данных*/
} e_LTR210_SYNC_MODE;

/** @brief Режим работы модуля в группе.

    Определяет режим работы модуля в составе группы. Используется при организации
    цепочки из модулей LTR210, записывающих кадры по одному событию */
typedef enum {
    LTR210_GROUP_MODE_INDIVIDUAL = 0, /**< Модуль работает независимо от остальных */
    LTR210_GROUP_MODE_MASTER     = 1, /**< Режим мастера --- при возникновении заданного 
                                            события синхронизации модуль выдает сигнал 
                                            на выход SYNC.
                                            Этот сигнал могут использовать подчиненные
                                            модули для запуска преобразования
                                            одновременно с мастером. Может использоваться
                                            совместно с любым значением SyncMode, кроме
                                            #LTR210_SYNC_MODE_CONTINUOUS */
    LTR210_GROUP_MODE_SLAVE      = 2 /**< Режим подчиненного модуля --- модуль запускает
                                          сбор кадра от сигнала на входе SYNC,
                                          который должен сгенерировать другой LTR210,
                                          настроенный на режим мастера.
                                          Значение SyncMode при этом не учитывается */
} e_LTR210_GROUP_MODE;


/** @brief Коды асинхронных событий.

    Коды, определяющие, что за асинхронные данные были приняты от модуля и
    какому событию они соответствуют. Возвращаются функцией LTR210_WaitEvent()
    в параметре event */
typedef enum {
    LTR210_RECV_EVENT_TIMEOUT   = 0, /**< Не пришло никакого события от модуля за
                                        указанное время */
    LTR210_RECV_EVENT_KEEPALIVE = 1, /**< Пришел корректный сигнал статуса от модуля
                                          (сигнал жизни) */
    LTR210_RECV_EVENT_SOF       = 2  /**< Пришло начало записанного кадра */
} e_LTR210_RECV_EVENT;

/** @brief Коды, определяющие правильность принятого кадра */
typedef enum
{
    LTR210_FRAME_RESULT_OK       = 0, /**< Кадр принят без ошибок. Данные кадра действительны */
    LTR210_FRAME_RESULT_PENDING  = 1, /**< В обрабатываемых данных не было признака
                                           конца кадра. */
    LTR210_FRAME_RESULT_ERROR    = 2  /**< Кадр принят с ошибкой. Данные кадра недействительны.
                                           Причину ошибки можно узнать по флагам статуса */
} e_LTR210_FRAME_RESULT;

/** @brief  Флаги статуса

    Флаги, указывающие как текущее состояние самого модуля LTR210,
    так и информацию о последнем принятом кадре.
    В виде комбинации данных флагов представляется информация как из
    периодических слов статуса модуля, так и из слов статуса кадра */
typedef enum {
    LTR210_STATUS_FLAG_PLL_LOCK      = 0x0001, /**< Признак захвата PLL в момент
                                                    передачи статуса. Если равен
                                                   нулю, то модуль неработоспособен. */
    LTR210_STATUS_FLAG_PLL_LOCK_HOLD = 0x0002, /**< Признак, что захват PLL не
                                                   пропадал с момента предыдущей
                                                   передачи статуса. Должен быть
                                                   установлен во всех статусах,
                                                   кроме первого */
    LTR210_STATUS_FLAG_OVERLAP      = 0x0004, /**< Признак, что процесс записи обогнал
                                                    процесс чтения. Часть данных в кадре
                                                    может быть недействительна */
    LTR210_STATUS_FLAG_SYNC_SKIP    = 0x0008, /**< Признак, что во время записи
                                                кадра возникло хотя бы одно
                                                событие синхронизации, которое 
                                                было пропущено.
                                                Не влияет на правильность самого
                                                кадра.*/
    LTR210_STATUS_FLAG_INVALID_HIST = 0x0010, /**< Признак того, что предыстория
                                                принятого кадра недействительна
                                                (событие наступило меньше чем через
                                                 HistSize отсчетов после разрешения
                                                 записи) */
    LTR210_STATUS_FLAG_CH1_EN       = 0x0040, /**< Признак, что разрешена запись по
                                                первому каналу */
    LTR210_STATUS_FLAG_CH2_EN       = 0x0080  /**< Признак, что разрешена запись по
                                                второму каналу */
} e_LTR210_STATUS_FLAGS;


/** @brief Дополнительные флаги настроек.

    Набор флагов, управляющих конфигурацией модуля при его настройке.
    Комбинация этих флагов может быть записана в поле Flags структуры
    #TLTR210_CONFIG */
typedef enum {
    /** Разрешение периодической передачи статуса модуля при запущенном сборе */
    LTR210_CFG_FLAGS_KEEPALIVE_EN    = 0x001,
    /** Разрешение режима автоматической приостановки записи на время, пока
        кадр выдается по интерфейсу в крейт. Данный режим позволяет установить
        максимальный размер кадра независимо от частоты сбора АЦП */
    LTR210_CFG_FLAGS_WRITE_AUTO_SUSP = 0x002,
    /** Включение тестого режима, в котором вместо данных передается счетчик */
    LTR210_CFG_FLAGS_TEST_CNTR_MODE  = 0x100
} e_LTR210_CFG_FLAGS;

/** @brief Флаги обработки данных.

    Флаги, управляющие работой функции LTR210_ProcessData() */
typedef enum {
    /** Признак, что нужно перевести коды АЦП в Вольты. Если данный флаг не указан,
        то будут возвращены коды АЦП. При этом код #LTR210_ADC_SCALE_CODE_MAX
        соответствует максимальному напряжению для установленного диапазона. */
    LTR210_PROC_FLAG_VOLT          = 0x0001,

    /** Признак, что необходимо выполнить коррекцию АЧХ на основании записанных
        во Flash-памяти модуля коэффициентов */
    LTR210_PROC_FLAG_AFC_COR       = 0x0002,
    /** Признак, что необходимо выполнить дополнительную коррекцию нуля с помощью
        значений из State.AdcZeroOffset, которые могут быть измерены с помощью
        функции LTR210_MeasAdcZeroOffset() */
    LTR210_PROC_FLAG_ZERO_OFFS_COR = 0x0004,
    /** По умолчанию LTR210_ProcessData() предполагает, что ей на обработку
        передаются все принятые данные и проверяет непрерывность счетчика не только
        внутри переданного блока данных, но и между вызовами.
        Если обрабатываются не все данные или одни и те же данные обрабатываются
        повторно, то нужно указать данный флаг, чтобы счетчик проверялся только
        внутри обрабатываемого блока */
    LTR210_PROC_FLAG_NONCONT_DATA = 0x0100
} e_LTR210_PROC_FLAGS;


/** @brief Скорость выдачи данных в интерфейс.

    Набор констант, которые задают скорость чтения данных из буфера модуля LTR210
    и выдачи их в интерфейс крейта. */
typedef enum {
    LTR210_INTF_TRANSF_RATE_500K  = 0, /**< 500 КСлов/c */
    LTR210_INTF_TRANSF_RATE_200K  = 1, /**< 200 КСлов/c */
    LTR210_INTF_TRANSF_RATE_100K  = 2, /**< 100 КСлов/c */
    LTR210_INTF_TRANSF_RATE_50K   = 3, /**< 50  КСлов/c */
    LTR210_INTF_TRANSF_RATE_25K   = 4, /**< 25  КСлов/c */
    LTR210_INTF_TRANSF_RATE_10K   = 5  /**< 10  КСлов/c */
} e_LTR210_INTF_TRANSF_RATE;

/** @brief Режим работы дополнительного бита во входном потоке.

    Определяет, какое значение будут передаваться в дополнительном бите в
    отсчетах, принятых от модуля. */
typedef enum {
    /** Всегда нулевое значение бита */
    LTR210_DIG_BIT_MODE_ZERO             = 0,
    /** Бит отражает состояние цифрового входа SYNC модуля */
    LTR210_DIG_BIT_MODE_SYNC_IN          = 1,
    /** Бит равен "1", если уровень сигнала для 1-го канала АЦП превысил верхний
        уровень синхронизации и не опустился ниже нижнего */
    LTR210_DIG_BIT_MODE_CH1_LVL          = 2,
    /** Бит равен "1", если уровень сигнала для 2-го канала АЦП превысил верхний
        уровень синхронизации и не опустился ниже нижнего  */
    LTR210_DIG_BIT_MODE_CH2_LVL          = 3,
    /** Бит равен "1" для одного отсчета в момент срабатывания программной
         или периодической синхронизации */
    LTR210_DIG_BIT_MODE_INTERNAL_SYNC    = 4
}e_LTR210_DIG_BIT_MODE;
/** @} */


/***************************************************************************//**
  @addtogroup type_list Типы данных.
  @{
  *****************************************************************************/

/** @brief Калибровочные коэффициенты.

    Структура, хранящая калибровочные коэффициенты для одного канала
    и диапазона. */
typedef struct {
    float   Offset; /**< 15-битный код смещения */
    float   Scale;  /**< Коэффициент шкалы */
} TLTR210_CBR_COEF;

/** @brief Параметры БИХ-фильтра.

    Параметры для рассчета коэффициентов БИХ-фильтра, который используется
    для коррекции АЧХ диапазонов 10 В и 5 В. */
typedef struct {
    double R; /**< Сопротивление эквивалентной цепи фильтра */
    double C; /**< Емкость эквивалентной цепи фильтра */
} TLTR210_AFC_IIR_COEF;


/** @brief Информация о модуле.

    Структура, содержащая информацию о версиях прошивок микросхем модуля и
    информацию, считанную из Flash-памяти модуля (серийный номер, калибровочные
    коэффициенты).

    За исключением VerFPGA все поля действительны после вызова LTR210_Open().
    Поле VerFPGA, если ПЛИС не загружен на момент установления соединения с модулем,
    будет действительно только после успешного вызова LTR210_LoadFPGA(). */
typedef struct {
    CHAR        Name[LTR210_NAME_SIZE];      /**< Название модуля
                                                  (оканчивающаяся нулем ASCII-строка) */
    CHAR        Serial[LTR210_SERIAL_SIZE];  /**< Серийный номер модуля
                                                  (оканчивающаяся нулем ASCII-строка) */
    WORD        VerFPGA;                     /**< Версия прошивки ПЛИС модуля
                                                  (действительна только после ее загрузки) */
    BYTE        VerPLD;                      /**< Версия прошивки PLD  */
    /** Заводские калибровочные коэффициенты (на канал действительны первые
        #LTR210_RANGE_CNT, остальные - резерв) */
    TLTR210_CBR_COEF CbrCoef[LTR210_CHANNEL_CNT][8];
    /** Частота в Гц, которой соответствуют корректировочные коэффициенты АЧХ */
    double AfcCoefFreq;
    /** Коэффициенты, задающие спад АЧХ модуля на частоте AfcCoefFreq. Представляют
        собой отношение амплитуды измеренного синусоидального сигнала на указанной
        частоте к амплитуде реально выставленного сигнала. Коэффициенты загружаются
        из Flash-памяти модуля при открытии связи с ним. Могут быть использованы
        для корректировки АЧХ при необходимости. На канал действительны первые
        #LTR210_RANGE_CNT коэффициентов, остальные - резерв. */
    double AfcCoef[LTR210_CHANNEL_CNT][8];

    /** Параметры для рассчета коэффициентов IIR-фильтра, который используется для
        корректировки АЧХ на диапазонах 10 В и 5 В.
        Данные параметры храняться во Flash-памяти модуля.
        На канал действительны первые #LTR210_AFC_IIR_COR_RANGE_CNT
        коэффициентов, остальные - резерв. */
    TLTR210_AFC_IIR_COEF AfcIirParam[LTR210_CHANNEL_CNT][8];
    DWORD       Reserved[32]; /**< Резервные поля */
} TINFO_LTR210;


/** @brief Настройки канала АЦП.

    Структура, содержащая настройки одного канала АЦП. */
typedef struct {
    BOOLEAN Enabled; /**< Признак, разрешен ли сбор по данному каналу */
    BYTE    Range;   /**< Установленный диапазон --- константа из #e_LTR210_ADC_RANGE */
    BYTE    Mode;    /**< Режим измерения --- константа из #e_LTR210_CH_MODE */
    /** Режим работы дополнительного бита во входном потоке данных данного канала.
        Константа из #e_LTR210_DIG_BIT_MODE */
    BYTE    DigBitMode;
    BYTE    Reserved[4];  /**< Резервные поля (не должны изменяться пользователем) */
    /** Нижний порог гистерезиса при аналоговой синхронизации в Вольтах.
        Спадом считается уменьшение сигнала ниже уровня SyncLevelL,
        если до этого сигнал превышал SyncLevelH. Фронтом --- превышение SyncLevelH,
        если до этого сигнал был ниже SyncLevelL.
        Должен быть в пределах установленного диапазона. */
    double SyncLevelL;
    /** Верхний порог гистерезиса при аналоговой синхронизации в Вольтах.
        Должен быть в пределах установленного диапазона и не меньше SyncLevelL. */
    double SyncLevelH;
    DWORD   Reserved2[10]; /**< Резервные поля (не должны изменяться пользователем) */
} TLTR210_CHANNEL_CONFIG;

/** @brief Настройки модуля.

    Структура содержит все настройки модуля, которые должен заполнить
    пользователь перед вызовом LTR210_SetADC(). */
typedef struct {
    TLTR210_CHANNEL_CONFIG Ch[LTR210_CHANNEL_CNT]; /**< Настройки каналов АЦП */
    DWORD FrameSize; /**< Размер точек на канал в кадре при покадровом сборе */
    /** Размер предыстории (количество точек в кадре на канал,
        измеренных до возникновения события синхронизации) */
    DWORD HistSize;
    /** Условие сбора кадра (событие синхронизации). Одно из значений #e_LTR210_SYNC_MODE */
    BYTE SyncMode;
    /** Режим работы в составе группы модулей. Одно из значений #e_LTR210_GROUP_MODE */
    BYTE GroupMode;
    /** Значение делителя частоты АЦП минус 1. Может быть в диапазоне от 0
        до #LTR210_ADC_FREQ_DIV_MAX-1*/
    WORD AdcFreqDiv;
    /** Значение коэфициент прореживания данных АЦП минус 1. Может быть в диапазоне
        от 0 до #LTR210_ADC_DCM_CNT_MAX-1.*/
    DWORD AdcDcmCnt;
    /** Делитель частоты запуска сбора кадров для SyncMode = #LTR210_SYNC_MODE_PERIODIC.
        Частота кадров равна \f$ \frac{10^6}{FrameFreqDiv + 1} \text{Гц} \f$ */
    DWORD FrameFreqDiv;
    DWORD Flags; /**< Флаги конфигурации (комбинация из #e_LTR210_CFG_FLAGS) */

    /** Скорость выдачи данных в интерфейс (одно из значений из #e_LTR210_INTF_TRANSF_RATE).
        По-умолчанию устанавливается максимальная скорость (500 КСлов/с).
        Если установленная скорость превышает максимальную скорость интерфейса для крейта,
        в который установлен модуль, то будет установлена максимальная скорость,
        поддерживаемая данным крейтом */
    BYTE  IntfTransfRate;


    DWORD Reserved[39]; /**< Резервные поля (не должны изменяться пользователем) */
} TLTR210_CONFIG;

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

    Структура, содержащая параметры модуля, которые пользователь должен использовать
    только для чтения, так как они изменяются только внутри функций ltr210api. */
typedef struct {
    BOOLEAN Run;         /**< Признак, запущен ли сбор данных */
    /** Количество слов в принимаемом кадре, включая статус.
        (устанавливается после вызова LTR210_SetADC()) */
    DWORD RecvFrameSize;
    /** Рассчитанная частота сбора АЦП в Гц (устанавливается после вызова
        LTR210_SetADC()) */
    double AdcFreq;
    /** Рассчитанная частота следования кадров для режима синхронизации
        #LTR210_SYNC_MODE_PERIODIC (устанавливается после вызова
        LTR210_SetADC()) */
    double FrameFreq;
    /** Измеренные значения смещения нуля АЦП в кодах (приведенных к значению 
        #LTR210_ADC_SCALE_CODE_MAX) для текущих настроек. Устанавливаются
        при вызове функции LTR210_MeasAdcZeroOffset(). Могут быть использованы
        для дополнительной коррекции смещения нуля АЦП. */
    double AdcZeroOffset[LTR210_CHANNEL_CNT];
    DWORD Reserved[4]; /**< Резервные поля */
} TLTR210_STATE;


/** @brief Описатель модуля.

    Структура содержит всю информацию о настройках модуля и текущем
    состоянии соединения с модулем. Используется всеми функциями для работы
    с модулем. */
typedef struct {
    INT Size;     /**< Размер структуры. Заполняется в LTR210_Init(). */
    /** Структура, содержащая состояние соединения с программой ltrd или LtrServer.
       Не используется напрямую пользователем. */
    TLTR Channel;
    /** Указатель на непрозрачную структуру с внутренними параметрами,
      используемыми исключительно библиотекой и недоступными для пользователя. */
    PVOID Internal;
    /** Настройки модуля. Заполняются пользователем перед вызовом LTR210_SetADC(). */
    TLTR210_CONFIG Cfg;
    /** Состояние модуля и рассчитанные параметры. Поля изменяются функциями
        библиотеки. Пользовательской программой могут использоваться
        только для чтения. */
    TLTR210_STATE State;
    TINFO_LTR210 ModuleInfo; /**< Информация о модуле */
} TLTR210;


/** @brief Дополнительная информация о принятом отсчете.

   Структура содержит дополнительную информацию о принятом и обработанном
   слове данных, которая извлечена из информационных полей принятого слова. */
typedef struct {
    /** Младший бит соответствует значению дополнительного бита, передаваемого
        вместе с потоком данных. Что означает данный бит задается одной
        из констант из #e_LTR210_DIG_BIT_MODE в поле DigBitMode настроек 
        каждого канала на этапе конфигурации.

        Остальные биты могут быть использованы в будущем, поэтому при анализе
        нужно проверять значение~@verbatim DigBitState & 1 @endverbatim */
    BYTE DigBitState;
    /** Номер канала, которому соответствует принятое слово
        (0 --- первый, 1 --- второй) */
    BYTE Ch;
    BYTE Range;       /**< Диапазон канала, установленный во время 
                           измерения данного отсчета */
    BYTE Reserved;    /**< Резервное поле (всегда равно 0) */
} TLTR210_DATA_INFO;

/** @brief Информация о статусе обработанного кадра

    Данная структура содержит поля, сообщающие о статусе обработанного кадра.
    Ее необходимо проверять, чтобы убедится в том, что данные принятого кадра
    верны и при его записи не произошло ошибок. Для этого можно использовать
    поле Result, а поля Flags предоставляет дополнительную информацию, по
    которой, в частности, можно узнать причину ошибки. */
typedef struct {
    /** Код результата обработки кадра (одно из значений #e_LTR210_FRAME_RESULT).
        Позволяет определить, найден ли был конец кадра и действительны
        ли данные в кадре */
    BYTE Result;
    /** Резервное поле (всегда равно 0) */
    BYTE Reserved;
    /** Дополнительные флаги из #e_LTR210_STATUS_FLAGS,
        представляющие собой информацию о статусе самого
        модуля и принятого кадра. Может быть несколько флагов,
        объединенных через логическое ИЛИ */
    WORD Flags;
} TLTR210_FRAME_STATUS;
#pragma pack()



/** @brief Тип функции для индикации процесса загрузки ПЛИС.

    Тип для callback-функции, вызываемой при выполнении загрузки прошивки ПЛИС модуля,
    которая может быть использована для индикации хода выполнения данного процесса.
    Указатель на функцию данного типа может быть передан в LTR210_LoadFPGA().
    @param[in] cb_data       Указатель, переданный в LTR210_LoadFPGA() в
                             качестве параметра cb_data
    @param[in] hnd           Указатель на описатель модуля, для которого выполняется
                             загрузка прошивки ПЛИС
    @param[in] done_size     Количество байт, которое было успешно записано
    @param[in] full_size     Полный размер файла прошивки в байтах
     */
typedef void (APIENTRY *TLTR210_LOAD_PROGR_CB)(void* cb_data, TLTR210* hnd,
                                               DWORD done_size, DWORD full_size);

/** @} */


#ifdef __cplusplus
extern "C" {  
#endif

/***************************************************************************//**
    @addtogroup func_init Функции инициализации и работы с соединением с модулем.
    @{
*******************************************************************************/


/***************************************************************************//**
  @brief Инициализация описателя модуля.

  Функция инициализирует поля структуры описателя модуля значениями по-умолчанию.
  Эта функция должна вызываться для каждой структуры #TLTR210 перед вызовом
  остальных функций.
   @param[in] hnd       Описатель модуля
   @return              Код ошибки
 ******************************************************************************/
LTR210API_DllExport(INT) LTR210_Init(TLTR210 *hnd);

/***************************************************************************//**
   @brief Открытие соединения с модулем.

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

   @param[in] hnd       Описатель модуля
   @param[in] net_addr  IP-адрес машины, на которой запущен ltrd или LtrServer, в 32-битном
                        формате. Для адреса "a.b.c.d" net_addr = (a<<24)|(b<<16)|(c<<8)|d.
                        Если ltrd или LtrServer запущен на той же машине, то в качестве
                        адреса можно передать LTRD_ADDR_DEFAULT.
   @param[in] net_port  TCP-порт для соединения с ltrd или LtrServer. По-умолчанию
                        используется LTRD_PORT_DEFAULT.
   @param[in] csn       Серийный номер крейта, в котором находится интересующий
                        модуль. Представляет собой оканчивающуюся нулем ASCII-строку.
                        Для соединения с первым найденным крейтом можно передать
                        пустую строку или нулевой указатель.
   @param[in] slot      Номер слота крейта, в котором установлен интересующий модуль.
                        Значение от LTR_CC_CHNUM_MODULE1 до LTR_CC_CHNUM_MODULE16.
   @return              Код ошибки
*******************************************************************************/
LTR210API_DllExport(INT) LTR210_Open(TLTR210 *hnd, DWORD net_addr, WORD net_port,
                                     const CHAR *csn, WORD slot);

/***************************************************************************//**
   @brief Закрытие соединения с модулем.

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

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

/***************************************************************************//**
   @brief Проверка, открыто ли соединение с модулем.

   Функция проверяет, открыто ли в данный момент соединение с модулем. Если
   соединение открыто, функция возвращает LTR_OK, если закрыто --- код ошибки
   LTR_ERROR_CHANNEL_CLOSED.
   @param[in] hnd       Описатель модуля
   @return              Код ошибки (LTR_OK, если соединение установлено)
 ******************************************************************************/
LTR210API_DllExport(INT) LTR210_IsOpened(TLTR210 *hnd);

/***************************************************************************//**
   @brief Проверка, загружена ли прошивка ПЛИС модуля.

   Функция проверяет, загружена ли в данный момент прошивка ПЛИС модуля. Если
   прошивка загружена, то функция возвращает LTR_OK, иначе ---
   LTR_ERROR_FPGA_IS_NOT_LOADED.
   Если ПЛИС не загружен, то необходимо выполнить загрузку с помощью
   LTR210_LoadFPGA().
   @param[in] hnd       Описатель модуля
   @return              Код ошибки (LTR_OK, если прошивка загружена)
 ******************************************************************************/
LTR210API_DllExport(INT) LTR210_FPGAIsLoaded(TLTR210 *hnd);

/***************************************************************************//**
   @brief Загрузка прошивки ПЛИС модуля.

    Функция загружает прошивку ПЛИС модуля из указанного файла. Если в качестве
    имени файла указать нулевой указатель или пустую строку, то для ОС
    Windows загружается версия прошивки, встроенная в библиотеку как ресурс, а
    для ОС Linux в этом случае берется файл по стандартному пути (путь установки
    при сборке библиотеки).

    Данная функция должна выполняться после открытия связи с модулем перед
    дальнейшей работой, если прошивка не была загружена до этого.
    Проверить, загружена ли прошивка ПЛИС можно с помощью LTR210_FPGAIsLoaded().

   @param[in] hnd       Описатель модуля.
   @param[in] filename  Имя файла с прошивкой ПЛИС модуля или пустая строка.
   @param[in] progr_cb  Указатель на функцию, которая будет вызываться в процессе
                        хода загрузки и может быть использована для индикации
                        прогресса загрузки. Если не используется, то может быть
                        передан нулевой указатель.
   @param[in] cb_data   Если указана функция progr_cb, то данный указатель будет
                        передаваться в нее в качестве одноименного параметра.
   @return              Код ошибки
 ******************************************************************************/
LTR210API_DllExport(INT) LTR210_LoadFPGA(TLTR210 *hnd, const char *filename,
                                  TLTR210_LOAD_PROGR_CB progr_cb, void *cb_data);

/** @} */

/***************************************************************************//**
    @addtogroup func_config Функции для изменения настроек модуля
    @{
*******************************************************************************/

/***************************************************************************//**
   @brief Запись настроек в модуль.

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

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

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


/***************************************************************************//**
   @brief Установка заданной частоты сбора АЦП.

   Функция заполняет поля AdcFreqDiv и AdcDcmCnt значениями, для которых
   частота сбора АЦП будет максимально близка к заданной.

   Может быть вызвана перед LTR210_SetADC() вместо ручного заполнения
   указанных полей.

   @param[in]  cfg       Указатель на структуру с конфигурацией модуля
   @param[in]  freq      Частота сбора АЦП в Гц, которую нужно установить
   @param[in]  flags     Флаги (резерв --- всегда должен передаваться 0)
   @param[out] set_freq  В данной переменной сохраняется реальное значение
                         частоты, соответствующее подобранным параметрам.
                         Может быть передан нулевой указатель, если это значение
                         не нужно.
   @return               Код ошибки
 ******************************************************************************/
LTR210API_DllExport(INT) LTR210_FillAdcFreq(TLTR210_CONFIG *cfg, double freq,
                                            DWORD flags, double *set_freq);


/***************************************************************************//**
   @brief Установка заданной частоты следования кадров.

   Функция устанавливает значение поля FrameFreqDiv таким, чтобы частота следования
   кадров в режиме #LTR210_SYNC_MODE_PERIODIC была максимально близка к заданной.

   Может быть вызвана перед LTR210_SetADC() вместо ручного заполнения
   FrameFreqDiv.

   @param[in]  cfg       Указатель на структуру с конфигурацией модуля
   @param[in]  freq      Частота следования кадров в Гц, которую нужно установить
   @param[out] set_freq  В данной переменной сохраняется реальное значение
                         частоты, соответствующее подобранным параметрам.
                         Может быть передан нулевой указатель, если это значение
                         не нужно.
   @return               Код ошибки
 ******************************************************************************/
LTR210API_DllExport(INT) LTR210_FillFrameFreq(TLTR210_CONFIG *cfg, double freq,
                                              double *set_freq);

/** @} */



/***************************************************************************//**
    @addtogroup func_stream Функции для управления сбором данных
    @{
*******************************************************************************/

/***************************************************************************//**
    @brief Запуск сбора данных.

    При вызове данной функции запускается запись данных АЦП модулем.

    При непрерывном сборе данных (SyncMode = #LTR210_SYNC_MODE_CONTINUOUS),
    по этой функции запускается сбор данных с АЦП и выдача их в крейт.

    При покадровом сборе при вызове функции модуль переходит в режим записи во
    внутренний буфер и ожидания событий синхронизации для выдачи кадров в
    крейт. Также после вызова данной функции модуль начинает передавать 
    периодически свой статус, если эта возможность разрешена.  
    
    Хотя бы один из каналов АЦП должен быть до этого разрешен и модуль должен быть
    сконфигурирован с помощью LTR210_SetADC().

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



/***************************************************************************//**
    @brief Останов сбора данных.

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

    При этом вычитываются и выбрасываются все переданные, но непрочитанные 
    данные от модуля.

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


/***************************************************************************//**
    @brief Программный запуск сбора кадра.

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

    Может использоваться исключительно в режиме #LTR210_SYNC_MODE_INTERNAL.

    При вызове этой функции запись данных с АЦП уже должна быть разрешена
    с помощью LTR210_Start().

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


/***************************************************************************//**
   @brief Ожидание асинхронного события от модуля.

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

   Если за заданный таймаут события не произошло, то это считается нормальным
   завершением (функция возвращает LTR_OK), но в качестве кода события возвращается
   #LTR210_RECV_EVENT_TIMEOUT.

   Для непрерывного сбора данных функция всегда возвращает событие
   #LTR210_RECV_EVENT_SOF и не принимает никаких данных.

   @param[in]  hnd       Описатель модуля.
   @param[out] event     В данной переменной возвращается код произошедшего
                         события (#LTR210_RECV_EVENT_TIMEOUT, если никакого
                         события за заданный интервал не произошло).
   @param[out] status    Если указан не NULL, то при событии #LTR210_RECV_EVENT_KEEPALIVE
                         в данную переменную сохраняется информация о статусе
                         модуля в виде комбинации флагов #e_LTR210_STATUS_FLAGS. 
                         При остальных событиях данный параметр не изменяется.
   @param[in]  tout      Время ожидания события в миллисекундах.
   @return               Код ошибки
 ******************************************************************************/
LTR210API_DllExport(INT) LTR210_WaitEvent(TLTR210 *hnd, DWORD *event, DWORD *status, DWORD tout);

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

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

   При покадровом сборе функция используется для приема кадра после обнаружения
   начала кадра помощью LTR210_WaitEvent(), а при непрерывном сборе может вызываться
   без дополнительных вызовов, как и для остальных модулей LTR.

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

   @param[in]  hnd      Описатель модуля.
   @param[out] data     Массив, в который будут сохранены принятые слова. Должен
                        быть размером на size 32-битных слов.
   @param[out] tmark    Указатель на массив размером на size 32-битных слов,
                        в который будут сохранены метки времени,
                        соответствующие принятым данным (генерация меток
                        настраивается для крейта или специального модуля отдельно).
                        Если метки времени не используются, то можно передать
                        в качестве параметра NULL.
   @param[in]  size     Запрашиваемое количество 32-битных слов на прием. При
                        покадровом режиме можно использовать размер кадра
                        из поля RecvFrameSize описателя модуля.
   @param[in]  timeout  Таймаут на выполнение операции в миллисекундах. Если в течение
                        заданного времени не будет принято запрашиваемое количество
                        слов, то функция все равно вернет управление, возвратив
                        в качестве результата реально принятое количество слов
   @return              Значение меньше нуля соответствует коду ошибки. Значение
                        больше или равное нулю соответствует количеству реально
                        принятых и сохраненных в массив data слов.
*******************************************************************************/
LTR210API_DllExport(INT) LTR210_Recv(TLTR210 *hnd, DWORD *data, DWORD *tmark,
                                     DWORD size, DWORD timeout);

/****************************************************************************//**
   @brief Обработка принятых от модуля слов.

   Функция используется для обработки слов, принятых от модуля с помощью LTR210_Recv().
   Функция проверяет служебные поля принятых слов, извлекает полезную информацию
   с отсчетами и, при указании флага #LTR210_PROC_FLAG_VOLT, переводит отсчеты в
   Вольты. Также функция анализирует слово состояние кадра при его наличии и
   возвращает результат в параметре frame_status.

   Для получения дополнительной служебной информации можно передать указатель на массив
   data_info.

   Функция проверяет также целостность данных с помощью счетчика из служебной
   информации. По-умолчанию функция предполагает, что все принятые данные обрабатываются
   и только один раз, проверяя непрерывность счетчика и между вызовами функции.
   Если это условие не выполняется, то нужно передать флаг #LTR210_PROC_FLAG_NONCONT_DATA.

   @param[in] hnd      Описатель модуля.
   @param[in] src      Указатель на массив, содержащий слова, принятые от модуля
                       с помощью LTR210_Recv(), которые нужно обработать.
   @param[out] dest    Указатель на массив, в который будут сохранены обработанные
                       данные. Порядок следования соответствует порядку во входном
                       массиве (т.е. если разрешены оба канала то отсчеты каналов
                       будут чередоваться).
   @param[in,out] size  На входе принимает размер массива src для обработки. На
                        выходе, при успешном завершении, возвращает количество
                        сохраненных отсчетов в массиве dest.
   @param[in]  flags   Флаги из #e_LTR210_PROC_FLAGS, управляющие работой функции.
                        Может быть объединено несколько флагов через логическое
                        ИЛИ.
   @param[out] frame_status  В данной структуре сохраняется состояние принятого
                        кадра, которое формируется на основе слова статуса,
                        переданного за последним словом кадра. По статусу можно
                        судить о правильности данных в кадре. Если слова состояния
                        в обрабатываемых данных не было (т.е. данные соответствуют
                        лишь части кадра, не включая конец), то будет возвращен
                        статус с кодом #LTR210_FRAME_RESULT_PENDING.
   @param[out] data_info Массив, в который будет сохранена информация, извлеченная
                        из служебных полей обработанных слов. В частности, в него
                        сохраняется состояние дополнительного служебного бита.
                        Если эта информация не нужна, то можно передать нулевой 
                        указатель.
   @return              Код ошибки.
  *****************************************************************************/
LTR210API_DllExport(INT) LTR210_ProcessData(TLTR210 *hnd,  const DWORD *src,
                                            double *dest, INT *size, DWORD flags,
                                            TLTR210_FRAME_STATUS *frame_status,
                                            TLTR210_DATA_INFO *data_info);

/** @} */




/***************************************************************************//**
    @addtogroup func_misc Функции вспомогательного характера
    @{
*******************************************************************************/


/***************************************************************************//**
    @brief Измерение смещения нуля

    Функция выполняет сбор одного кадра в режиме измерения собственного нуля,
    используя при этом установленные в конфигурации значения диапазонов, и
    сохраняет результат в поля State.AdcZeroOffset. После измерения
    восстанавливаются прежние настройки АЦП.

    Измеренные значения могут быть использованы для корректировки принятых данных
    при передачи флага #LTR210_PROC_FLAG_ZERO_OFFS_COR в LTR210_ProcessData(), 
    что позволяет учесть уход нуля для конкретных условий.

    Эта функция вызывается после конфигурации модуля непосредственно перед
    запуском записи данных АЦП с помощью LTR210_Start().

    При изменении диапазонов необходимо заново проводить измерение смещения нуля.

    @param[in] hnd      Описатель модуля.
    @param[in] flags    Флаги (резерв - должен передаваться 0)
    @return             Код ошибки.
*******************************************************************************/
LTR210API_DllExport(INT) LTR210_MeasAdcZeroOffset(TLTR210 *hnd, DWORD flags);



/****************************************************************************//**
   @brief Получение прошедшего интервала с момента приема последнего слова.

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

    Если во время сбора при разрешенной посылке статуса это время превысит 
    допустимый интервал (который должен включать допустимые задержки по интерфейсу 
    передачи крейт->ПК), то это событие можно считать неисправностью модуля.

   @param[in] hnd        Описатель модуля.
   @param[out] interval  Время в миллисекундах с момента успешного приема последнего
                         слова.
   @return               Код ошибки.
  *****************************************************************************/
LTR210API_DllExport(INT) LTR210_GetLastWordInterval(TLTR210 *hnd, DWORD *interval);

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

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

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

/***************************************************************************//**
   @brief Загрузка коэффициентов в ПЛИС.

   Функция выполняет загрузку коэффициентов из ModuleInfo.CbrCoef в ПЛИС
   модуля для последующей автокоррекции. Так как в API функциях загрузка
   коэффициентов из Flash-памяти уже выполняется автоматически после загрузки
   ПЛИС, то данная функция введена только для того, чтобы можно было использовать
   свои коэффициенты. Для этого нужно заполнить поля в ModuleInfo.CbrCoef и вызвать
   данную функцию. Функция может вызываться только в случае, если ПЛИС уже загружен.

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


/** @} */


#ifdef __cplusplus
}
#endif


#endif
