#ifndef LPW25API_H_
#define LPW25API_H_


#include "ltrapi.h"
#include "ltedsapi_lcard.h"

#ifdef __cplusplus
extern "C" {
#endif


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


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

/** Теоретическое (без калибровки) значение коэффициента передачи (чувствительности)
 *  для преобразователя LPW25-U-2-230 в В/В. */
#define LPW25_DEFAULT_SENS_U_2_230       (0.0077)
/** Теоретическое (без калибровки) значение коэффициента передачи (чувствительности)
 *  для преобразователей LPW25-I-1-5-1 и LPW25-I-1-5-2 в В/А. */
#define LPW25_DEFAULT_SENS_I_1_5         (0.49)

/** Диапазон измерения (пиковое значение) напряжения преобразователя LPW25-U-2-230 в Вольтах. */
#define LPW25_PHYSRANGE_U_2_230           (750)
/** Диапазон измерения (пиковое значение) тока преобразователей LPW25-I-1-5-1 и LPW25-I-1-5-2 в Амперах. */
#define LPW25_PHYSRANGE_I_1_5             (12.5)


/** Выходное сопротивление преобразователя LPW25 при токе питания 2.86 мА*/
#define LPW25_ROUT_ISRC_2_86   (20)
/** Выходное сопротивление преобразователя LPW25 при токе питания 10 мА*/
#define LPW25_ROUT_ISRC_10     (13)

/** Максимальная частота пропускания преобразователей LPW25. */
#define LPW25_MAX_BANDWIDTH            10000

/** Максимальный размер данных TEDS в байтах, который может хранится в
 *  энергонезависимой памяти преобразователя. */
#define LPW25_TEDS_MAX_SIZE (124)




/** @brief Коды ошибок, специфичные для преобразователя LPW25.

   Коды ошибок, которые определены и используются только в lpw25api.
   Помимо этого функции данной библиотеки могут возвращает коды ошибок из
   [ltedsapi](http://www.lcard.ru/download/ltedsapi.pdf).*/
typedef enum {    
    LPW25_ERROR_FD_NOT_SET                  = -10800, /**< Не задана частота дискретизации сигнала */
    LPW25_ERROR_SENS_NOT_SET                = -10801, /**< Не задан коэффициент передачи преобразователя */
    LPW25_ERROR_PROC_NOT_STARTED            = -10802, /**< Не запущена обработка данных */
    LPW25_ERROR_TEDS_MANUFACTURER_ID        = -10803, /**< Неизвестный идентификатор производителя */
    LPW25_ERROR_TEDS_MODEL_ID               = -10804, /**< Неизвестная модель преобразователя */
} e_LPW25_ERROR_CODES;

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

    Флаги, управляющие работой функции LPW25_ProcessData() */
typedef enum {
    /** Флаг указывает, что необходимо выполнить преобразование из электрических
     * величин (напряжение в Вольтах на выходе преобразователя) в физические величины
     * (измеряемый сигнал на входе преобразователя). */
    LPW25_PROC_FLAG_PHYS        = 0x0002,

    /** Признак, что необходимо выполнить коррекцию фазы для компенсации сдвига
     *  фазы сигнала преобразователем с помощью специального фильтра,
     *  как описано в разделе @ref sec_sensor_pha_cor.
     *  Не имеет значение для преобразователей, не предназначенных для измерения
     *  фазовых характеристик (LPW25-I-1-5-2). */
    LPW25_PROC_FLAG_PHASE_COR   = 0x0010,
    /** По умолчанию LPW25_ProcessData() предполагает, что ей на обработку
        передаются все принятые данные в порядке прихода и при обработке
        нового блока использует состояние фильтров предыдущего.
        Если обрабатываются не все данные или одни и те же данные обрабатываются
        повторно, то нужно указать данный флаг. */
    LPW25_PROC_FLAG_NONCONT_DATA = 0x0100,
} e_LPW25_PROC_FLAGS;


/** @} */

/***************************************************************************//**
  @addtogroup type_list Типы данных.
  @{
  *****************************************************************************/
#pragma pack(4)

/** Результаты калибровки шкалы преобразователя */
typedef struct {
    double InputValue; /**< Значение амплитуды сигнала на входе, для которого выполнялась калибровка. */
    double Sens;  /**< Коэффициент передачи (чувствительность) преобразователя, измеренный
                        при указанном входном значении сигнала. */
} TLPW25_CAL_COEF;


/** Набор коэффициентов для коррекции ФЧХ преобразователя */
typedef  struct {
    double PhaseShiftRefFreq; /**< Частота в Гц, на которой измерен сдвиг фазы преобразователя. */
    double PhaseShift; /**< Сдвиг фазы в градусах на соответствующей частоте. */
} TLPW25_PHASE_SHIFT_COEFS;

/** Выходное сопротивление преобразователя для разных токов питания. */
typedef struct {
    double R_I_10; /**< Значение выходного сопротивления преобразователя в Омах для тока питания 10 мА */
    double R_I_2_86; /**< Значение выходного сопротивления преобразователя в Омах для тока питания 2.86 мА */
    double Reserved[6]; /**< Резерв */
} TLPW25_ROUT_COEFS;

/***************************************************************************//**
    @brief Информация о калибровке преобразователя.

    Данная структура содержит как общую информацию о проведении калибровки, так
    и все результирующие коэффициенты и параметры преобразователя, которые могут быть
    специфичны для конкретного экземпляра. */
typedef struct {
    TLTEDS_INFO_DATE CalDate; /**< Дата выполнения калибровки преобразователя. */
    WORD CalPeriod; /**< Интервал между калибровками преобразователя в днях. */
    TLPW25_CAL_COEF CalCoef; /**< Результат калибровки шкалы преобразователя. */
    TLPW25_ROUT_COEFS ROutCoefs; /**< Значение выходного сопротивления
                                      преобразователя в зависимости
                                      от тока питания. */
    TLPW25_PHASE_SHIFT_COEFS PhaseCoefs; /**< Набор коэффициентов для коррекции ФЧХ. */
    DWORD Reserved[16]; /**< Резерв */
} TLPW25_CALIBRATION_INFO;


/***************************************************************************//**
  @brief Информация о преобразователе LPW25

  Данная структура содержит в удобном для использования виде основную информацию
  о конкретном экземпляре преобразователя LPW25, которая содержится в данных TEDS
  преобразователя.

  Поля данной структуры заполняются функцией LPW25_TEDSDecode() значениями,
  извлеченными из данных TEDS.
  *****************************************************************************/
typedef struct {
    DWORD ModelID; /**< Идентификатор, определяющий модель преобразователя. Соответствует
                        одному из идентификаторов модели TEDS преобразователей "Л Кард",
                        определенному в [ltedsapi](http://www.lcard.ru/download/ltedsapi.pdf)
                        в виде перечисления e_LTEDS_LCARD_MODEL_ID. Для многоканальных
                        преобразователей для каждого канала определен свой
                        идентификатор модели. */
    CHAR VersionLetter;  /**< Буквенная версия преобразователя. */
    BYTE VersionNumber;  /**< Численная версия преобразователя. */
    DWORD SerialNumber;  /**< Серийный номер преобразователя. */

    BYTE PhysicalMeasurand; /**< Измеряемая физическая величина. Соответствует
                                  кодам e_LTEDS_INFO_PHYSICAL_\-MEASURAND из
                                  [ltedsapi](http://www.lcard.ru/download/ltedsapi.pdf) */
    double PhysicalRange; /**< Максимальное амплитудное значение измеряемой физической величины. */
    double ElectricalRange; /**< Выходное значение напряжения преобразователя,
                                 соответствующее максимальному значению измереямой физической
                                 величины из  @fieldref{TLPW25_INFO,PhysicalRange} для
                                 теоретического значения (без калибровки) коэффициента
                                 передачи преобразователя. */
    DWORD Reserved[24]; /**< Резерв */
    TLPW25_CALIBRATION_INFO CalInfo; /**< Информация о проведении калибровки и калибровочные коэффициенты. */
    DWORD Reserved2[32]; /**< Резерв */
} TLPW25_INFO;

/***************************************************************************//**
   @brief Контекст обработки данных преобразователя LPW25.

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

   Перед началом использования данная структура должна быть проинициализирована с
   помощью LPW25_ProcessInit().
*******************************************************************************/
typedef struct {
    void   *Internal; /**< Указатель на внутренне (не доступное пользователю)
                           состояние контекста обработки данных. */
    double Sens; /**< Коэффициент передачи (чувствительность) преобразователя.
                      Заполняется при разборе TEDS данных преобразователя. Если TEDS
                      данные не доступны, то поле должно заполняться вручную значением
                      из паспорта преобразователя. */
    double Fd;   /**< Частота дискретизации в Гц, с которой оцифрован обрабатываемый
                      сигнал от преобразователя LPW25. Поле всегда должно заполняться
                      вручную пользователем. */
   TLPW25_PHASE_SHIFT_COEFS PhaseCoefs ; /**< Коэффициенты для коррекции ФЧХ
                                              преобразователя.
                                              При инициализации контекста данные
                                              поля заполняются необходимыми значениями
                                              для преобразователя LPW25.
                                              При разборе данных TEDS заполняются
                                              значениями из TEDS.
                                              Явно пользователю не требуется изменять
                                              значения данного поля. */
    double Reserved[60]; /**< Резерв */
} TLPW25_PROC_CTX;



#pragma pack()

/** @} */



/***************************************************************************//**
    @addtogroup func_proc Функции обработки данных от преобразователя.
    @{
*******************************************************************************/


/***************************************************************************//**
  @brief Инициализация контекста обработки данных преобразователя.

  Функция инициализирует поля структуры контекста обработки данных преобразователя
  LPW25.

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

   @param[in] ctx       Контекст обработки данных
   @return              Код ошибки
 ******************************************************************************/
LPW25API_DllExport(INT) LPW25_ProcessInit(TLPW25_PROC_CTX *ctx);

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

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

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

   Каждому вызову LPW25_ProcessStart() после завершения обработки всех данных должен
   соответствовать вызов LPW25_ProcessStop() для освобождения ресурсов, выделенных
   данной функцией.

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

   @param[in] ctx       Контекст обработки данных
   @return              Код ошибки
 ******************************************************************************/
LPW25API_DllExport(INT) LPW25_ProcessStart(TLPW25_PROC_CTX *ctx);

/***************************************************************************//**
   @brief Обработка данных преобразователя.

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

   Набор действий, выполняемых функцией, определяется набором переданных ей флагов.

   Для вызова данной функции должна быть предварительно запущена обработка данных
   для данного контекста с помощью LPW25_ProcessStart().

   @param[in] ctx       Контекст обработки данных
   @param[in] src      Указатель на массив, содержащий измеренные значения напряжения
                       на выходе преобразователя, которые нужно обработать.
   @param[out] dest    Указатель на массив, в который будут сохранены обработанные
                       данные.
   @param[in] size     Количество обрабатываемых точек. Определяет количество элементов
                       как в массиве для обработки (src), так и количество элементов,
                       сохраняемых в случае успеха в выходном массиве (dest).
   @param[in]  flags   Флаги из #e_LPW25_PROC_FLAGS, управляющие работой функции.
                       Может быть объединено несколько флагов через логическое
                       ИЛИ.
   @return             Код ошибки
 ******************************************************************************/
LPW25API_DllExport(INT) LPW25_ProcessData(TLPW25_PROC_CTX *ctx, const double *src,
                                       double *dest, DWORD size, DWORD flags);

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

   Данная функция должна вызываться после завершения обработки всех данных
   преобразователя для каждого запуска обработки с помощью LPW25_ProcessStart().

   Данная функция освобождает все выделенные ресурсы для обработки.

   @param[in] ctx       Контекст обработки данных
   @return              Код ошибки
 ******************************************************************************/
LPW25API_DllExport(INT) LPW25_ProcessStop(TLPW25_PROC_CTX *ctx);





/***************************************************************************//**
   @brief Проверка, запущена ли обработка данных преобразователя.

   Функция проверяет, запущена ли обработка данных для данного контекста обработки
   (вызвана функция LPW25_ProcessStart() без вызова LPW25_ProcessStop()).
   Если запущена, то функция возвращает значение LTR_OK, в противном случае
   функция вернет код ошибки.

   @param[in] ctx       Контекст обработки данных
   @return              LTR_OK, если обработка запущена, иначе --- код ошибки.
 ******************************************************************************/
LPW25API_DllExport(INT) LPW25_ProcessIsRunning(const TLPW25_PROC_CTX *ctx);



/***************************************************************************//**
  @brief Копирование параметров обработки из другого контекста.

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

  Оба контекста  до вызова функции должны быть уже проинициализированы с помощью
  LPW25_ProcessInit().

   @param[in] dst       Контекст, параметры которого будут заменены соответствующими
                        значениями из контекста источника.
   @param[in] src       Контекст иточник, параметры которого будут скопированы
   @return              Код ошибки
 ******************************************************************************/
LPW25API_DllExport(INT) LPW25_ProcessCopy(TLPW25_PROC_CTX *dst, const TLPW25_PROC_CTX *src);


/** @} */




/***************************************************************************//**
    @addtogroup func_teds_info Функции разбора данных TEDS
    @{
*******************************************************************************/

/***************************************************************************//**
  @brief Инициализация структуры с информацией о преобразователе LPW25.

  Функция инициализирует поля структуры с информацией о преобразователе.

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

   @param[in] info      Структура с информацией о преобразователе.
   @return              Код ошибки.
 ******************************************************************************/
LPW25API_DllExport(INT) LPW25_InfoInit(TLPW25_INFO *info);


/***************************************************************************//**
  @brief Разбор данных TEDS преобразователя LPW25.

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

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

  Для разбора данных функция использует библиотеку
  [ltedsapi](http://www.lcard.ru/download/ltedsapi.pdf).

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


   @param[in] teds_data Массив с прочитанными данными TEDS преобразователя (без
                        байт контрольной суммы), который должен быть разобран.
   @param[in] teds_size Размер массива teds_data в байтах
   @param[in] flags     Флаги для управления работы функцией (резерв, должно
                        передаваться всегда нулевое значение).
   @param[out] procctx  Контекст обработки данных, поля которого необходимо заполнить
                        на основе результатов разбора. Контекст данных до передачи
                        должен быть уже проинициализирован с помощью
                        LPW25_ProcessInit(). Функция не изменяет значения
                        полей, которые не определяются данными TEDS.
                        Может быть передан нулевой указатель, если заполнение
                        контекста обработки не требуется.
   @param[out] info     Структура для сохранения разобранной информации о преобразователе.
                        Может быть передан нулевой указатель, если данная информация
                        не требуется.
   @param[out] all_parsed В данном параметре функция возвращает признак, что данные
                          TEDS были полностью разобраны и найдено их завершение.
                          Может быть передан нулевой указатель, если данная информация
                          не требуется.
   @return              Код ошибки.
 ******************************************************************************/
LPW25API_DllExport(INT) LPW25_TEDSDecode(const BYTE *teds_data, DWORD teds_size, DWORD flags,
                                         TLPW25_PROC_CTX *procctx, TLPW25_INFO *info,
                                         BOOLEAN *all_parsed);

/***************************************************************************//**
  @brief Кодирование данных TEDS преобразователя LPW25.

  Функция выполняет кодирование информации о преобразователе в массив данных в формате
  TEDS.

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

  Массив для сохранения данных TEDS должен иметь достаточно места, в противном
  случае функция вернет ошибку.


   @param[out] teds_data Массив, в который будут сохранены полученные данные в
                         формате TEDS.
   @param[in] teds_size Размер массива teds_data в байтах.
   @param[in] flags     Флаги для управления работы функцией (резерв, должно
                        передаваться всегда нулевое значение).
   @param[in] info      Структура с информацией о преобразователе, которая должна
                        быть закодирована.
   @param[out] result_bitsize Результирующий размер полученных TEDS данных в битах.
                        Размер использованных в массиве teds_data байт может быть
                        получен как \f$  (result_bitsize + 7)/8 \f$.
   @return              Код ошибки.
 ******************************************************************************/
LPW25API_DllExport(INT) LPW25_TEDSEncode(BYTE *teds_data, DWORD teds_size, DWORD flags,
                                         const TLPW25_INFO *info, DWORD *result_bitsize);

/***************************************************************************//**
  @brief Заполнение информации о преобразователе по типу преобразователя.

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

   @param[in] info      Структура с информацией о преобразователе.
   @param[in] model_id  Идентификатор модели преобразователя.
   @return              Код ошибки.
 ******************************************************************************/
LPW25API_DllExport(INT) LPW25_InfoStdFill(TLPW25_INFO *info, DWORD model_id);
/** @} */




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

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

   Функция возвращает строку, соответствующую переданному коду ошибки, в кодировке
   CP1251 для ОС Windows или UTF-8 для ОС Linux. Функция может обработать как ошибки,
   возвращаемые функциями библиотеки lpw25api, как специфичные ошибки библиотеки,
   так и ошибки [ltedsapi](http://www.lcard.ru/download/ltedsapi.pdf).

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


/** @} */

#ifdef __cplusplus
}
#endif

#endif

