/***************************************************************************//**
    @file l502api_compat.h
    Файл содержит определения типов и функций для L502, которые оставлены
    для совместимости с версией библиотеки 1.0.x (до включения поддержки E502).
    Все эти определения имеют аналог в x502api.h, а функции вызывают напрямую
    аналогичные функции X502_xxx из библиотеки x502api

    @note  Не включены недокументированные функцие, такие как L502_OpenByListItem,
           LPCIE_GetDevInfoList и LPCIE_FreeDevInfoList
    @author Borisov Alexey <borisov@lcard.ru>
 ******************************************************************************/

#ifndef L502API_COMPAT_H
#define L502API_COMPAT_H

#ifdef __cplusplus
extern "C" {
#endif

#include "x502api.h"

#define LPCIE_EXPORT(type) X502_EXPORT(type)

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

/** Максимальное количество логических каналов в таблице*/
#define L502_LTABLE_MAX_CH_CNT      256
/** Количество диапазонов для измерения напряжений */
#define L502_ADC_RANGE_CNT            6

/** Максимальное значение для аппаратного усреднения по логическому каналу */
#define L502_LCH_AVG_SIZE_MAX       128
/** Максимальное значения делителя частоты АЦП */
#define L502_ADC_FREQ_DIV_MAX       (1024*1024)
/** Максимальное значение делителя частоты синхронного цифрового ввода */
#define L502_DIN_FREQ_DIV_MAX       (1024*1024)

/** Максимальное значение межкадровой задержки для АЦП */
#define L502_ADC_INTERFRAME_DELAY_MAX  (0x1FFFFF)

/** Таймаут по умолчанию для выполнения команды к BlackFin*/
#define L502_BF_CMD_DEFAULT_TOUT    500

/** Код АЦП, соответствующий максимальному значению шкалы */
#define L502_ADC_SCALE_CODE_MAX     6000000
/** Код ЦАП, соответствующий максимальному значению шкалы */
#define L502_DAC_SCALE_CODE_MAX     30000

/** Максимальное количество символов в строке с названием устройства */
#define L502_DEVNAME_SIZE           32
/** Максимальное количество символов в строке с серийным номером */
#define L502_SERIAL_SIZE            32

/** Максимально возможное значение внешней опорной частоты */
#define L502_EXT_REF_FREQ_MAX  2000000


/** Размер пользовательской области Flash-памяти */
#define L502_FLASH_USER_SIZE   0x100000

/** Стандартный таймаут на выполнение запроса к BlackFin в мс */
#define L502_BF_REQ_TOUT  500


/** Диапазон ЦАП в вольтах */
#define L502_DAC_RANGE  5.

/** Количество каналов ЦАП */
#define L502_DAC_CH_CNT  2


/** слово в потоке, означающее, что произошло переполнение */
#define L502_STREAM_IN_MSG_OVERFLOW  0x01010000


/** Коды ошибок библиотеки */
typedef enum {
    /** Функция выполнена без ошибок */
    L502_ERR_OK                           = 0,    
    /** В функцию передан недействительный описатель модуля */
    L502_ERR_INVALID_HANDLE               = -1,
    /** Ошибка выделения памяти */
    L502_ERR_MEMORY_ALLOC                 = -2,
    /** Попытка открыть уже открытое устройство */
    L502_ERR_ALREADY_OPENED               = -3,
    /** Устройство с заданными параметрами не найдено в системе */
    L502_ERR_DEVICE_NOT_FOUND             = -4,
    /** Доступ к устройству запрещен (Как правило из-за того, что устройство
        уже открыто в другой программе) */
    L502_ERR_DEVICE_ACCESS_DENIED         = -5,
    /** Ошибка открытия устройства */
    L502_ERR_DEVICE_OPEN                  = -6,
    /** В функцию передан недействительный указатель */
    L502_ERR_INVALID_POINTER              = -7,
    /** Функция не может быть выполнена при запущенном потоке сбора данных */
    L502_ERR_STREAM_IS_RUNNING            = -8,
    /** Ошибка чтения данных синхронного ввода */
    L502_ERR_RECV                         = -9,
    /** Ошибка записи данных для синхронного вывода */
    L502_ERR_SEND                         = -10,
    /** Произошло переполнение внутреннего буфера для потока синхронного ввода */
    L502_ERR_STREAM_OVERFLOW              = -11,
    /** Неизвестное сообщение в потоке синхронного ввода */
    L502_ERR_UNSUP_STREAM_MSG             = -12,
    /** Ошибка создания системного мьютекса */
    L502_ERR_MUTEX_CREATE                 = -13,
    /** Неверный описатель мьютекса */
    L502_ERR_MUTEX_INVALID_HANDLE         = -14,
    /** Истекло время ожидания освобождения мьютекса */
    L502_ERR_MUTEX_LOCK_TOUT              = -15,
    /** Ошибка освобождения мьютекса */
    L502_ERR_MUTEX_RELEASE                = -16,
    /** Недостаточно системных ресурсов */
    L502_ERR_INSUFFICIENT_SYSTEM_RESOURCES= -17,
    /** Данная возможность еще не реализована */
    L502_ERR_NOT_IMPLEMENTED              = -18,
    /** Недостаточный размер массива */
    L502_ERR_INSUFFICIENT_ARRAY_SIZE      = -19,
    /** Ошибка чтения регистра FPGA */
    L502_ERR_FPGA_REG_READ                = -20,
    /** Ошибка записи регистра FPGA */
    L502_ERR_FPGA_REG_WRITE               = -21,
    /** Сбор данных уже остановлен */
    L502_ERR_STREAM_IS_NOT_RUNNING        = -22,
    /** Задан неверный размер логической таблицы */
    L502_ERR_INVALID_LTABLE_SIZE          = -102,
    /** Задан неверный номер логического канала */
    L502_ERR_INVALID_LCH_NUMBER           = -103,
    /** Неверно задано значение диапазона АЦП */
    L502_ERR_INVALID_LCH_RANGE            = -104,
    /** Неверно задан режим измерения для логического канала */
    L502_ERR_INVALID_LCH_MODE             = -105,
    /** Неверно задан номер физического канала при настройке логического */
    L502_ERR_INVALID_LCH_PHY_NUMBER       = -106,
    /** Неверно задан размер усреднения для логического канала */
    L502_ERR_INVALID_LCH_AVG_SIZE         = -107,
    /** Неверно задан делитель частоты сбора данных АЦП */
    L502_ERR_INVALID_ADC_FREQ_DIV         = -108,
    /** Неверно задан делитель частоты синхронного ввода цифровых линий */
    L502_ERR_INVALID_DIN_FREQ_DIV         = -108,
    /** Неверно задан режим работы модуля L502 */
    L502_ERR_INVALID_MODE                 = -109,
    /** Неверный номер канала ЦАП */
    L502_ERR_INVALID_DAC_CHANNEL          = -110,
    /** Неверный код выбора опорной частоты синхронизации */
    L502_ERR_INVALID_REF_FREQ             = -111,
    /** Неверно задано значение межкадровой задержки */
    L502_ERR_INVALID_INTERFRAME_DELAY     = -112,
    /** Неверно задан режим синхронизации */
    L502_ERR_INVALID_SYNC_MODE            = -113,
    /** Неверно задан номер канала DMA */
    L502_ERR_INVALID_DMA_CH               = -114,

    /** Ошибка захвата опорной частоты синхронизации */
    L502_ERR_REF_FREQ_NOT_LOCKED          = -131,
    /** Управляющий запрос к драйверу завершен с ошибкой */
    L502_ERR_IOCTL_FAILD                  = -132,
    /** Истек таймаут ожидания завершения выполнения управляющего запроса к драйверу */
    L502_ERR_IOCTL_TIMEOUT                = -133,
    /** Ошибка получения информации о устройстве от драйвера */
    L502_ERR_GET_INFO                     = -134,
    /** За время ожидания не было считано новое слово с цифровых линий */
    L502_ERR_DIG_IN_NOT_RDY               = -135,
    /** Принято недостаточно слов от модуля */
    L502_ERR_RECV_INSUFFICIENT_WORDS      = -136,
    /** Попытка выполнить операцию, требующую наличие ЦАП, при его отсутствии */
    L502_ERR_DAC_NOT_PRESENT              = -137,
    /** Неверный номер канала в обрабатываемом потоке синхронного ввода */
    L502_ERR_PROC_INVALID_CH_NUM          = -140,
    /** Неверный код диапазона в обрабатываемом потоке синхронного ввода */
    L502_ERR_PROC_INVALID_CH_RANGE        = -141,
    /** Задан неверный адрес во Flash-памяти */
    L502_ERR_FLASH_INVALID_ADDR           = -142,
    /** Задан неверный размер блока данных при работе с Flash-памятью */
    L502_ERR_FLASH_INVALID_SIZE           = -143,
    /** Истек таймаут ожидания завершения записи во Flash-память */
    L502_ERR_FLASH_WRITE_TOUT             = -144,
    /** Истек таймаут ожидания завершения стирания блока Flash-памяти */
    L502_ERR_FLASH_ERASE_TOUT             = -145,
    /** Заданная область для стирания Flash-памяти нарушает границу блока в 4 Кбайт */
    L502_ERR_FLASH_SECTOR_BOUNDARY        = -146,
    /** Не удалось открыть файл прошивки BlackFin */
    L502_ERR_LDR_FILE_OPEN                = -180,
    /** Ошибка чтения из фала прошивки BlackFin */
    L502_ERR_LDR_FILE_READ                = -181,
    /** Неверный формат файла прошивки BlackFin */
    L502_ERR_LDR_FILE_FORMAT              = -182,
    /** Используются возможность LDR-файла, недоступные при записи прошивки
        BlackFin по HDMA */
    L502_ERR_LDR_FILE_UNSUP_FEATURE       = -183,
    /** Неверный стартовый адрес программы в прошивке BlackFin */
    L502_ERR_LDR_FILE_UNSUP_STARTUP_ADDR  = -184,
    /** Истек таймаут выполнения запроса на чтения/запись памяти BlackFin */
    L502_ERR_BF_REQ_TIMEOUT               = -185,
    /** Команда для BlackFin все еще находится в процессе обработки */
    L502_ERR_BF_CMD_IN_PROGRESS           = -186,
    /** Истекло время выполнения управляющей команды процессором BlackFin */
    L502_ERR_BF_CMD_TIMEOUT               = -187,
    /** Возвращено недостаточно данных в ответ на команду к BlackFin */
    L502_ERR_BF_CMD_RETURN_INSUF_DATA     = -188,
    /** Истек таймаут ожидания готовности процессора BlackFin к записи прошивки */
    L502_ERR_BF_LOAD_RDY_TOUT             = -189,
    /** Попытка выполнить операцию для которой нужен сигнальный процессор при
        отсутствии сигнального процессора в модуле */
    L502_ERR_BF_NOT_PRESENT               = -190,
    /** Неверный адрес памяти BlackFin при записи или чтении по HDMA */
    L502_ERR_BF_INVALID_ADDR              = -191,
    /** Неверный размер данных, передаваемых с управляющей командой в BlackFin */
    L502_ERR_BF_INVALID_CMD_DATA_SIZE     = -192
} t_lpcie_errs;

/** Флаги, управляющие поиском присутствующих модулей */
typedef enum {
    /** Признак, что нужно вернуть серийные номера только тех устройств,
        которые еще не открыты */
    L502_GETDEVS_FLAGS_ONLY_NOT_OPENED = X502_GETDEVS_FLAGS_ONLY_NOT_OPENED
} t_l502_getdevs_flags;



/** @brief Флаги для управления цифровыми выходами.

    Флаги управления цифровыми выходами. Могут быть объединены через логическое
    “ИЛИ” со значениями цифровых выходов при асинхронном выводе с помощью
    L502_AsyncOutDig() или переданы в L502_PrepareData() при синхронном выводе.*/
typedef enum {
    L502_DIGOUT_WORD_DIS_H = X502_DIGOUT_WORD_DIS_H, /**< Запрещение (перевод в третье состояние)
                                             старшей половины цифровых выходов */
    L502_DIGOUT_WORD_DIS_L = X502_DIGOUT_WORD_DIS_L  /**< Запрещение младшей половины
                                              цифровых выходов */
} t_l502_digout_word_flags;


/** Константы для выбора опорной частоты */
typedef enum {
    L502_REF_FREQ_2000KHZ  = X502_REF_FREQ_2000KHZ, /**< Частота 2МГц */
    L502_REF_FREQ_1500KHZ  = X502_REF_FREQ_1500KHZ /**< Частота 1.5МГц */
} t_l502_ref_freq;


/** Диапазоны измерения для канала АЦП */
typedef enum {
    L502_ADC_RANGE_10 = X502_ADC_RANGE_10, /**< Диапазон +/-10V */
    L502_ADC_RANGE_5  = X502_ADC_RANGE_5, /**< Диапазон +/-5V */
    L502_ADC_RANGE_2  = X502_ADC_RANGE_2, /**< Диапазон +/-2V */
    L502_ADC_RANGE_1  = X502_ADC_RANGE_1, /**< Диапазон +/-1V */
    L502_ADC_RANGE_05 = X502_ADC_RANGE_05, /**< Диапазон +/-0.5V */
    L502_ADC_RANGE_02 = X502_ADC_RANGE_02  /**< Диапазон +/-0.2V */
} t_l502_adc_range;

/** Режим измерения для логического канала */
typedef enum {
    L502_LCH_MODE_COMM = X502_LCH_MODE_COMM, /**< Измерение напряжения относительно общей земли */
    L502_LCH_MODE_DIFF = X502_LCH_MODE_DIFF, /**< Дифференциальное измерение напряжения */
    L502_LCH_MODE_ZERO = X502_LCH_MODE_ZERO  /**< Измерение собственного нуля */
} t_l502_lch_mode;

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

    Режимы задания источника частоты синхронизации и признака начала
    синхронного ввода-вывода */
typedef enum {
    L502_SYNC_INTERNAL        = 0, /**< Внутренний сигнал */
    L502_SYNC_EXTERNAL_MASTER = 1, /**< От внешнего мастера по разъему синхронизации */
    L502_SYNC_DI_SYN1_RISE    = 2, /**< По фронту сигнала DI_SYN1 */
    L502_SYNC_DI_SYN2_RISE    = 3, /**< По фронту сигнала DI_SYN2 */
    L502_SYNC_DI_SYN1_FALL    = 6, /**< По спаду сигнала DI_SYN1 */
    L502_SYNC_DI_SYN2_FALL    = 7  /**< По спаду сигнала DI_SYN2 */
} t_l502_sync_mode;

/** Флаги, управляющие обработкой принятых данных */
typedef enum {
    /** Признак, что нужно преобразовать значения АЦП в вольты */
    L502_PROC_FLAGS_VOLT            = X502_PROC_FLAGS_VOLT,
    /** Признак, что не нужно проверять совпадение номеров каналов
        в принятых данных с каналами из логической таблицы.
        Может использоваться при нестандартной прошивке BlackFin
        при передаче в ПК не всех данных. */
    L502_PROC_FLAGS_DONT_CHECK_CH   = X502_PROC_FLAGS_DONT_CHECK_CH
} t_l502_proc_flags;


/** Флаги для обозначения синхронных потоков данных */
typedef enum {
    L502_STREAM_ADC  = X502_STREAM_ADC, /**< Поток данных от АЦП */
    L502_STREAM_DIN  = X502_STREAM_DIN, /**< Поток данных с цифровых входов */
    L502_STREAM_DAC1 = X502_STREAM_DAC1, /**< Поток данных первого канала ЦАП */
    L502_STREAM_DAC2 = X502_STREAM_DAC2, /**< Поток данных второго канала ЦАП */
    L502_STREAM_DOUT = X502_STREAM_DOUT, /**< Поток данных на цифровые выводы */
    /** Объединение всех флагов, обозначающих потоки данных на ввод */
    L502_STREAM_ALL_IN = X502_STREAM_ALL_IN,
    /** Объединение всех флагов, обозначающих потоки данных на вывод */
    L502_STREAM_ALL_OUT = X502_STREAM_ALL_OUT
} t_l502_streams;

/** Константы, определяющие тип передаваемого отсчета из ПК в модуль */
typedef enum {
    L502_STREAM_OUT_WORD_TYPE_DOUT   = X502_STREAM_OUT_WORD_TYPE_DOUT, /**< Цифровой вывод */
    L502_STREAM_OUT_WORD_TYPE_DAC1   = X502_STREAM_OUT_WORD_TYPE_DAC1, /**< Код для 1-го канала ЦАП */
    L502_STREAM_OUT_WORD_TYPE_DAC2   = X502_STREAM_OUT_WORD_TYPE_DAC2  /**< Код для 2-го канала ЦАП */
} t_l502_stream_out_wrd_type;

/** Режим работы модуля L502 */
typedef enum {
    L502_MODE_FPGA  = X502_MODE_FPGA, /**< Все потоки данных передаются через ПЛИС минуя
                              сигнальный процессор BlackFin */
    L502_MODE_DSP   = X502_MODE_DSP, /**< Все потоки данных передаются через сигнальный
                              процессор, который должен быть загружен
                              прошивкой для обработки этих потоков */
    L502_MODE_DEBUG = X502_MODE_DEBUG  /**< Отладочный режим */
} t_l502_mode;

/** @brief Номера каналов ЦАП.

    Номер каналов ЦАП для указания в L502_AsyncOutDac() */
typedef enum {
    L502_DAC_CH1 = X502_DAC_CH1, /**< Первый канал ЦАП */
    L502_DAC_CH2 = X502_DAC_CH2  /**< Второй канал ЦАП */
} t_l502_dac_ch;

/** @brief Флаги, используемые при выводе данных на ЦАП.

    Флаги, комбинацию которых можно передать в L502_AsyncOutDac() или
    L502_PrepareData(), чтобы определить действия, которые должны выполнить
    эти функции с переданным значением перед выводом их на ЦАП */
typedef enum {
    /** Указывает, что значение задано в Вольтах и при выводе его нужно
        перевести его в коды ЦАП. Если флаг не указан, то считается, что значение
        изначально в кодах */
    L502_DAC_FLAGS_VOLT   = X502_DAC_FLAGS_VOLT,
    /** Указывает, что нужно применить калибровочные коэффициенты перед
        выводом значения на ЦАП. */
    L502_DAC_FLAGS_CALIBR  = X502_DAC_FLAGS_CALIBR
} t_l502_dacout_flags;


/** Номера каналов DMA */
typedef enum {
    L502_DMA_CH_IN  = X502_STREAM_CH_IN, /**< Общий канал DMA на ввод */
    L502_DMA_CH_OUT = X502_STREAM_CH_OUT  /**< Общий канал DMA на вывод */
} t_l502_dma_ch;


/** @brief Цифровые линии, на которых можно включить подтягивающие резисторы

    Флаги, определяющие на каких цифровых входах должны быть включены
    подтягивающие резисторы */
typedef enum {
    L502_PULLUPS_DI_H    = X502_PULLUPS_DI_H, /**< Старшая половина цифровых входов */
    L502_PULLUPS_DI_L    = X502_PULLUPS_DI_L, /**< Младшая половина цифровых входов */
    L502_PULLUPS_DI_SYN1 = X502_PULLUPS_DI_SYN1, /**< Линия SYN1 */
    L502_PULLUPS_DI_SYN2 = X502_PULLUPS_DI_SYN2  /**< Линия SYN2 */
} t_l502_pullups;


/** Флаги, определяющие наличие опций в модуле */
typedef enum {
    /** Признак наличия двухканального канального ЦАП */
    L502_DEVFLAGS_DAC_PRESENT         = X502_DEVFLAGS_DAC_PRESENT,
    /** Признак наличия гальваноразвязки */
    L502_DEVFLAGS_GAL_PRESENT         = X502_DEVFLAGS_GAL_PRESENT,
    /** Признак наличия сигнального процессора BlackFin */
    L502_DEVFLAGS_BF_PRESENT          = X502_DEVFLAGS_BF_PRESENT,
    /** Признак, что во Flash-памяти присутствует информация о модуле */
    L502_DEVFLAGS_FLASH_DATA_VALID    = X502_DEVFLAGS_FLASH_DATA_VALID,
    /** Признак, что во Flash-памяти присутствуют действительные калибровочные
        коэффициенты АЦП */
    L502_DEVFLAGS_FLASH_ADC_CALIBR_VALID = X502_DEVFLAGS_FLASH_ADC_CALIBR_VALID,
    /** Признак, что во Flash-памяти присутствуют действительные калибровочные
        коэффициенты ЦАП */
    L502_DEVFLAGS_FLASH_DAC_CALIBR_VALID = X502_DEVFLAGS_FLASH_DAC_CALIBR_VALID
} t_l502_dev_flags;


/** @brief Флаги для режима циклического вывода

    Данные флаги могут быть переданы в L502_OutCycleSetup() и L502_OutCycleStop() */
typedef enum {
    /** Флаг указывает, что останов или смена сигнала могут произойти без ожидания
        конца цикла предыдущего сигнала. Это позволяет выполнить переключение
        быстрее (однако все равно может быть поставлено на передачу до 256 КСемплов,
        которые должны будут быть переданы), но точка смены или останова
        может быть в любом месте периода */
    L502_OUT_CYCLE_FLAGS_FORCE = X502_OUT_CYCLE_FLAGS_FORCE
} t_l502_out_cycle_flags;

/** @} */

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

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

    Непрозрачный указатель на структуру,
    содержащую информацию о настройках модуля и текущем соединении с ним.
    Пользовательской программе не доступны поля структуры напрямую, а только
    через функции библиотеки.
    Функции управления модулем принимают описатель модуля своим первым параметром.
    Описатель модуля создается с помощью L502_Create() и в конце работы
    освобождается с помощью L502_Free(). */
typedef t_x502_hnd t_l502_hnd;



/** @brief Списко серийный номеров

    Тип определяет массив серийных номеров для количестава модулей, определяемого
    на этапе работы программы. */
typedef t_x502_serial_list t_l502_serial_list;


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

    Структура содержит калибровочные значения смещения нуля и коэффициента
    шкалы для одного диапазона АЦП или ЦАП.Результирующее значение АЦП
    вычисляется как (val-offs)*k, где val - некалиброванное значение */
typedef struct {
    double offs; /**< смещение нуля */
    double k; /**< коэффициент шкалы */
} t_l502_cbr_coef;


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

    Структура, содержащая все калибровочные коэффициенты, которые
    используются модулем L502 */
typedef struct {
    /** Калибровочные коэффициенты АЦП */
    t_l502_cbr_coef adc[L502_ADC_RANGE_CNT];
    uint32_t res1[64]; /**< Резерв */
    /** Калибровочные коэффициенты ЦАП */
    t_l502_cbr_coef dac[L502_DAC_CH_CNT];
    uint32_t res2[20]; /**< Резерв */
} t_l502_cbr;

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

    Структура, содержащая постоянную информация о модуле L502, которая как правило
    не изменяется после открытия */
typedef struct {
    char name[L502_DEVNAME_SIZE]; /**< Название устройства ("L502") */
    char serial[L502_SERIAL_SIZE]; /**< Серийный номер */
    uint32_t devflags; /**< Флаги из #t_l502_dev_flags, описывающие наличие
                            в модуле определенных опций */
    uint16_t fpga_ver; /**< Версия ПЛИС (старший байт - мажорная, младший - минорная) */
    uint8_t  plda_ver; /**< Версия ПЛИС, управляющего аналоговой частью */
    uint8_t  board_rev; /**< Ревизия платы */
    uint8_t res[120]; /**< Резерв */
    t_l502_cbr cbr; /**< Заводские калибровочные коэффициенты (из Flash-памяти) */
} t_l502_info;

/** @} */


/** @addtogroup func_list Функции.
    @{  **/

/***************************************************************************//**
    @addtogroup func_hnd Функции для создания и освобождения описателя модуля.
    @{
*******************************************************************************/

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

    Создание описателя модуля, для последующей работы с модулем L502.
    В случае успешного выделения памяти инициализирует поля описателя
    значениями по-умолчанию.
    @return NULL в случае ошибки, иначе - описатель модуля
*******************************************************************************/
LPCIE_EXPORT(t_l502_hnd) L502_Create(void);

/***************************************************************************//**
    @brief Освобождение описателя модуля.

    Освобождение памяти, выделенной под описатель модуля с помощью L502_Create().
    После этого описатель уже использовать нельзя, независимо от возвращенного
    значения!
    @param[in] hnd     Описатель устройства
    @return            Код ошибки
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_Free(t_l502_hnd hnd);
/** @} */


/***************************************************************************//**
    @addtogroup func_open Функции для открытия и получения информации о модуле.
    @{
*******************************************************************************/


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

    Функция разрывает соединение с модулем L502, если оно было ранее установлено
    (в противном случае ничего не делает).
    Описатель модуля не освобождается.
    Память под описатель модуля должна быть освобождена вызовом L502_Free().
    @param[in] hnd     Описатель модуля.
    @return            Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_Close(t_l502_hnd hnd);


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

    Получение информации о модуле L502, с которым установлена связь.
    @param[in]  hnd     Описатель модуля.
    @param[out] info    Информация о модуле (смотри описание типа #t_l502_info).
    @return             Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_GetDevInfo(t_l502_hnd hnd, t_l502_info* info);



/** @} */

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

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

    Функция выполняет запись текущих настроек (которые были установлены
    с помощью функций L502_SetXXX) в модуль.
    Должна вызываться перед запуском потока данных.
    @param[in] hnd     Описатель модуля.
    @param[in] flags   Флаги (резерв - должно быть равно 0).
    @return            Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_Configure(t_l502_hnd hnd, uint32_t flags);

/***************************************************************************//**
    @brief Установка параметров логического канала.

    Функция устанавливает параметры заданного логического канала в логической
    таблице АЦП.
    @param[in] hnd        Описатель модуля.
    @param[in] lch        Номер логического канала.
                          (от 0 до #L502_LTABLE_MAX_CH_CNT-1)
    @param[in] phy_ch     Номер физического канала АЦП, начиная с 0
                          (0-15 для дифференциального режима,
                          0-31 для режима с общей землей)
    @param[in] mode       Режим измерения канал АЦП (значение типа #t_l502_lch_mode)
    @param[in] range      Диапазон измерения канала (значение типа #t_l502_adc_range)
    @param[in] avg        Коэффициент усреднения по каналу. Нулевое значение
                          соответствует значению коэффициента, определенного
                          библиотекой. Для явного задания коэффициента усреднения
                          нужно перед значение от 1 (отсутствие усреднения) до
                          #L502_LCH_AVG_SIZE_MAX.
                          В случае если значение усреднения превышает делитель
                          частоты, то это значение будет скорректировано
    @return               Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_SetLChannel(t_l502_hnd hnd, uint32_t lch, uint32_t phy_ch,
                      uint32_t mode, uint32_t range, uint32_t avg);

/***************************************************************************//**
    @brief Установка количества логических каналов.

    Функция устанавливает количество логических каналов в логической таблице АЦП.
    @param[in] hnd      Описатель модуля
    @param[in] lch_cnt  Количество логических каналов
                        (от 1 до #L502_LTABLE_MAX_CH_CNT)
    @return             Код ошибки
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_SetLChannelCount(t_l502_hnd hnd, uint32_t lch_cnt);


/***************************************************************************//**
    @brief Получение количества логических каналов.

    Функция возвращает установленное ранее с помощью L502_SetLChannelCount()
    количество логических каналов в управляющей таблице АЦП.
    @param[in] hnd       Описатель модуля
    @param[out] lch_cnt  Количество логических каналов
    @return              Код ошибки
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_GetLChannelCount(t_l502_hnd hnd, uint32_t* lch_cnt);

/***************************************************************************//**
    @brief Установка делителя частоты сбора для АЦП.

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

    Альтернативой этой функции служит L502_SetAdcFreq(), которая рассчитывает
    этот делитель на основании переданной требуемой частоты сбора АЦП.    

    @param[in] hnd           Описатель модуля.
    @param[in] adc_freq_div  Делитель частоты АЦП (от 1 до #L502_ADC_FREQ_DIV_MAX).
    @return                  Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_SetAdcFreqDivider(t_l502_hnd hnd, uint32_t adc_freq_div);

/***************************************************************************//**
    @brief Установка значения межкадровой задержки для АЦП.

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

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

    @param[in] hnd      Описатель модуля.
    @param[in] delay    Значение межкадровой задержки (от 0 до
                        #L502_ADC_INTERFRAME_DELAY_MAX)
    @return             Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_SetAdcInterframeDelay(t_l502_hnd hnd, uint32_t delay);

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

    Частота синхронного ввода данных с цифровых входов получается как результат
    деления опорной частоты синхронизации на делитель, устанавливаемый этой
    функцией.

    Альтернативой этой функции служит L502_SetDinFreq(), которая рассчитывает
    этот делитель на основании переданной требуемой частоты синхронного ввода
    с цифровых линий.

    @param[in] hnd           Описатель модуля.
    @param[in] din_freq_div  Делитель частоты АЦП (от 1 до #L502_DIN_FREQ_DIV_MAX).
    @return                  Код ошибки.
 ******************************************************************************/
LPCIE_EXPORT(int32_t) L502_SetDinFreqDivider(t_l502_hnd hnd, uint32_t din_freq_div);


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

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

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

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

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

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


    @param[in]     hnd      Описатель модуля.
    @param[in,out] f_acq    На входе принимает требуемое значения частоты сбора
                              АЦП в Герцах. На выходе возвращает реально
                              установленное значение частоты.
    @param[in,out] f_frame  На входе принимает требуемое значение частоты сбора
                              кадров (частоты сбора на логический канал) АЦП
                              в Герцах. На выходе возвращает реально
                              установленное значение. Если передан нулевой
                              указатель, то устанавливает максимальную частоту
                              сбора кадров (нулевую межкадровую задержку).
    @return                Код ошибки.
 ******************************************************************************/
LPCIE_EXPORT(int32_t) L502_SetAdcFreq(t_l502_hnd hnd, double *f_acq, double *f_frame);






/***************************************************************************//**
    @brief Установка частоты синхронного ввода с цифровых входов.

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

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

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

    @param[in]     hnd     Описатель модуля.
    @param[in,out] f_din   На входе принимает требуемое значения частоты ввода
                           с цифровых входов в Герцах. На выходе возвращает
                           реально установленное значение частоты.
    @return                Код ошибки.
 ******************************************************************************/
LPCIE_EXPORT(int32_t) L502_SetDinFreq(t_l502_hnd hnd, double *f_din);


/***************************************************************************//**
    @brief Получить текущие значения частот сбора АЦП

    Функция возвращает ткущие установленные для модуля значения частоты сбора
    и частоты кадров АЦП (частоты на логический канал) в Герцах, которые были
    установлены до этого с помощью L502_SetAdcFreq() или с помощью функций
    L502_SetAdcFreqDivider()/L502_SetAdcInterframeDelay().

    @param[in]  hnd      Описатель модуля.
    @param[out] f_acq    Если не NULL, то на выходе возвращается текущее
                         значение частоты сбора АЦП.
    @param[out] f_frame  Если не NULL, то на выходе возвращается текущее
                         значение частоты кадров АЦП.
 ******************************************************************************/
LPCIE_EXPORT(int32_t) L502_GetAdcFreq(t_l502_hnd hnd, double *f_acq, double *f_frame);



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

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

    При использовании внутренней опорной частоты доступны два значения:
    2МГц и 1.5Мгц (2МГц является значением по-умолчанию), для задания которых
    можно использовать константы из #t_l502_ref_freq.

    При использовании внешней опорной частоты для того, чтобы можно было
    правильно установить нужную частоту сбора функциями
    L502_SetAdcFreq()/L502_SetDinFreq() и правильно были установлены значения
    по-умолчанию для размера буфера DMA и шага прерываний, нужно с помощью этой
    функции задать реально подаваемое значение внешней опорной частоты в Герцах.

    @param[in] hnd          Описатель модуля.
    @param[in] freq         Значение из #t_l502_ref_freq, которое задает
                            выбранную опорную частоту.
    @return                 Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_SetRefFreq(t_l502_hnd hnd, uint32_t freq);

/***************************************************************************//**
    @brief Установка режима генерации частоты синхронизации.

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

    В режиме #L502_SYNC_INTERNAL модуль сам будет генерировать для себя
    частоту синхронизации с частотой, заданной L502_SetRefFreq().
    При этом запуск генерации будет осуществлен по вызову L502_StreamsStart()
    или по условию, заданому в L502_SetSyncStartMode(), а останов
    по L502_StreamsStop().

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

    @param[in] hnd          Описатель модуля.
    @param[in] sync_mode    Значение из #t_l502_sync_mode, определяющее кто
                            будет источником частоты синхронизации.
    @return                 Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_SetSyncMode(t_l502_hnd hnd, uint32_t sync_mode);

/***************************************************************************//**
    @brief Установка режима запуска частоты синхронизации.

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

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

    Режимы задания условия запуска синхронизации имеют те же значения,
    что и режимы задания самой частоты (см. тип #t_l502_sync_mode).
    В случае #L502_SYNC_INTERNAL запуск осуществляется при выполнении функции
    L502_StreamsStart(), в противном случае - после выполнения
    L502_StreamsStart() модуль начинает ожидать заданного данной функцией условия.
    Т.е. даже при задании внешних источников синхронизации, все равно необходимо
    вызывать L502_StreamsStart().

    @param[in] hnd              Описатель модуля.
    @param[in] sync_start_mode  Значение из #t_l502_sync_mode, определяющее
                                условие запуска частоты синхронизации.
    @return                     Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_SetSyncStartMode(t_l502_hnd hnd, uint32_t sync_start_mode);


/***************************************************************************//**
    @brief Установить режим работы модуля.

    Функция устанавливает режим работы модуля, который определяет будет ли
    потоки данных обрабатывать ПЛИС или сигнальный процессор BlackFin.
    При включении питания модулем всегда управляет ПЛИС.
    После загрузки прошивки с помощью L502_BfLoadFirmware() модуль переходит
    в режим управления сигнальным процессором.

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

    @param[in] hnd          Описатель модуля.
    @param[in] mode         Режим работы модуля из #t_l502_mode.
    @return                 Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_SetMode(t_l502_hnd hnd, uint32_t mode);
/***************************************************************************//**
    @brief Получение текущего режима работы модуля.

    Функция возвращает текущий режим работы модуля.
    @param[in] hnd          Описатель модуля.
    @param[out] mode        В данном параметре возвращается текущий режим
                            работы модуля (из #t_l502_mode).
    @return                 Код ошибки.
 ******************************************************************************/
LPCIE_EXPORT(int32_t) L502_GetMode(t_l502_hnd hnd, uint32_t* mode);
/***************************************************************************//**
    @brief Установить коэффициенты для калибровки значений АЦП.

    Функция записывает в ПЛИС коэффициенты для калибровки значений АЦП.
    При открытии модуля, библиотека считывает калибровочные коэффициенты из
    защищенной области Flash-памяти модуля и записывает их в ПЛИС для
    выполнения калибровки на лету.

    Результирующее значение АЦП вычисляется по формуле (val+offs)*k, где val -
    некалиброванное значение.

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

    @param[in] hnd          Описатель модуля.
    @param[in] range        Диапазон АЦП (из #t_l502_adc_range).
    @param[in] k            Устанавливаемое значение коэффициента шкалы.
    @param[in] offs         Устанавливаемое значение смещения нуля.
    @return                 Код ошибки.
    ***************************************************************************/
LPCIE_EXPORT(int32_t) L502_SetAdcCoef(t_l502_hnd hnd, uint32_t range, double k, double offs);

/***************************************************************************//**
    @brief Получение текущих калибровочных коэффициентов АЦП.

    Функция возвращает текущие калибровочные коэффициенты для заданного диапазона
    измерения АЦП. Эти коэффициенты могут отличаться от заводских значений,
    сохраненных во Flash-памяти модуля, например, если пользователь использовал
    L502_SetAdcCoef() для установки своих коэффициентов.

    @param[in] hnd          Описатель модуля.
    @param[in] range        Диапазон АЦП (из #t_l502_adc_range).
    @param[in] k            В данной переменной возвращается текущий коэффициент
                            шкалы.
    @param[in] offs         В данной переменной возвращается текущее смещение нуля.
    @return                 Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_GetAdcCoef(t_l502_hnd hnd, uint32_t range, double* k, double* offs);



/***************************************************************************//**
    @brief Установить коэффициенты для калибровки значений ЦАП.

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

    Откалиброванное значение ЦАП в кодах получается как
    (val+offs)*k, где val - некалиброванное значение (в кодах).

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

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

    @param[in] hnd          Описатель модуля.
    @param[in] ch           Канал ЦАП (из #t_l502_dac_ch).
    @param[in] k            Устанавливаемое значение коэффициента шкалы.
    @param[in] offs         Устанавливаемое значение смещения нуля.
    @return                 Код ошибки.
    ***************************************************************************/
LPCIE_EXPORT(int32_t) L502_SetDacCoef(t_l502_hnd hnd, uint32_t ch, double k, double offs);


/***************************************************************************//**
    @brief Получение текущих калибровочных коэффициентов ЦАП.

    Функция возвращает текущие калибровочные коэффициенты для заданного канала ЦАП.
    Эти коэффициенты могут отличаться от заводских значений,
    сохраненных во Flash-памяти модуля, например, если пользователь использовал
    L502_SetDacCoef() для установки своих коэффициентов.

    @param[in] hnd          Описатель модуля.
    @param[in] ch           Канал ЦАП (из #t_l502_dac_ch).
    @param[in] k            В данной переменной возвращается текущий коэффициент
                            шкалы.
    @param[in] offs         В данной переменной возвращается текущее смещение нуля.
    @return                 Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_GetDacCoef(t_l502_hnd hnd, uint32_t ch, double* k, double* offs);



/** @} */


/***************************************************************************//**
    @addtogroup func_async Функции асинхронного ввода-вывода
    @{
*******************************************************************************/

/***************************************************************************//**
    @brief Асинхронный вывод данных на канал ЦАП.

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

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

    @param[in] hnd          Описатель модуля.
    @param[in] ch           Номер канала ЦАП (из #t_l502_dac_ch).
    @param[in] data         Выводимое значение на ЦАП (в кодах или вольтах)
    @param[in] flags        Флаги из #t_l502_dacout_flags.
    @return                 Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_AsyncOutDac(t_l502_hnd hnd, uint32_t ch, double data, uint32_t flags);

/***************************************************************************//**
    @brief Асинхронный вывод данных на цифровые выходы.

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

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

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

    @param[in] hnd          Описатель модуля.
    @param[in] val          Младшая половина - выводимое значение, старшая -
                            флаги из #t_l502_digout_word_flags.
    @param[in] msk          Маска - указанные в маске биты не будут изменяться
                            с предыдущего выведенного состояния (распространяется
                            и на старшую половину val).
    @return                 Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_AsyncOutDig(t_l502_hnd hnd, uint32_t val, uint32_t msk);


/***************************************************************************//**
    @brief Асинхронный ввод значений с цифровых входов.

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

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

    @param[in]  hnd         Описатель модуля.
    @param[out] din         При успешном выполнении в этой переменной
                            возвращается текущее состояние цифровых входов.
                            Действительны младшие 18 бит, старшие 14 - резерв.
                            Резервные биты могут быть использованы в последующих
                            версиях, не следует считать, что они всегда будут
                            равны нулю!
    @return                 Код ошибки.
 ******************************************************************************/
LPCIE_EXPORT(int32_t) L502_AsyncInDig(t_l502_hnd hnd, uint32_t* din);









/***************************************************************************//**
    @brief Асинхронный ввод одного кадра АЦП.

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

    Функция так же выполняет обработку принятых данных АЦП, аналогично
    L502_ProcessAdcData(), и принимает набор флагов, аналогичный
    L502_ProcessAdcData().

    Для работы этой функции не должен быть разрешен синхронный ввод АЦП
    и цифровых линий.

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

    @param[in]  hnd         Описатель модуля.
    @param[in]  flags       Флаги из t_l502_proc_flags
    @param[in]  tout        Таймаут на выполнение функции в мс
    @param[out] data        Массив, в котором в случае успеха будут возвращены
                            отсчеты кадра АЦП. Должен быть размером, достаточным
                            для хранения отсчетов типа double в количестве,
                            равном количеству установленных логических каналов
                            в управляющей таблице АЦП.
    @return                 Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_AsyncGetAdcFrame(t_l502_hnd hnd, uint32_t flags,
                                       uint32_t tout, double* data);

/** @} */




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

/***************************************************************************//**
    @brief Разрешение синхронных потоков на ввод/вывод.

    Функция разрешает прием/передачу для указанных потоков
    Не указанные потоки сохраняют свое разрешенное или запрещенное состояние.
    Может вызываться как до L502_Configure(), так и после.
    Разрешенные потоки устанавливаются как правило до вызова L502_StreamsStart().

    При желании в некоторых ситуациях можно изменять состав разрешенных потоков
    во время запущенного сбора данных, однако если эти потоки сильно различаются
    в частоте, то рассчитанные библиотекой значения буфера и шага прерывания
    могут не подходить для изменившихся значений (см. @ref sect_sync_mode_buf)
    @param[in] hnd     Описатель модуля.
    @param[in] streams Набор флагов #t_l502_streams, указывающих, какие потоки
                       должны быть разрешены.
    @return            Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_StreamsEnable(t_l502_hnd hnd, uint32_t streams);
/****************************************************************************//**
    @brief Запрещение синхронных потоков на ввод/вывод.

    Функция запрещает передачу синхронных данных для указанных потоков.
    Не указанные потоки сохраняют свое разрешенное или запрещенное состояние.
    Функция, противоположная по смыслу L502_StreamsEnable().
    @param[in] hnd     Описатель модуля.
    @param[in] streams Набор флагов #t_l502_streams, указывающих, какие потоки
                       должны быть запрещены.
    @return            Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_StreamsDisable(t_l502_hnd hnd, uint32_t streams);

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

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

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

    @param[in] hnd     Описатель модуля.
    @return            Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_StreamsStart(t_l502_hnd hnd);

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

    Функция останова синхронных потоков ввода/вывода данных. После выполнению
    этой функции модуль завершает генерацию опорной частоты синхронизации (или
    использовать внешную частоту синхронизации) и останавливает синхронную
    передачу данных.
    @param[in] hnd     Описатель модуля.
    @return            Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_StreamsStop(t_l502_hnd hnd);


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

    Функция проверяет запущен ли синхронный ввод вывод с помощью L502_StreamsStart()
    или какой-либо внутренней логикой в прошивки BlackFin.
    Если сбор данных не запущен, то функция возвращает ошибку
    #L502_ERR_STREAM_IS_NOT_RUNNING, если запущен, то нулевой код ошибки

    @param[in] hnd     Описатель модуля.
    @return            Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_IsRunning(t_l502_hnd hnd);

/***************************************************************************//**
    @brief Чтение данных АЦП и цивровых входов из модуля.

    Функция считывает данные от модуля, которые были переданы по DMA в буфер
    драйвера.  Функция принимает отсчеты в специальном индексном формате,
    в котором содержится информация, что это за данные (значения цифровых входов
    или отсчеты АЦП) и дополнительная информация для АЦП (номер канала, режим).
    Для разбора полученных отсчетов используется функция L502_ProcessData().

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

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

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

    @param[in]  hnd     Описатель модуля.
    @param[out] buf     Буфер, в которые будут сохранены отсчеты.
    @param[in]  size    Количество считываемых отсчетов (32-битных слов).
    @param[in]  tout    Таймаут на прием данных в мс.
    @return             Если < 0 - код ошибки.
                        Если >= 0 - количество считанных слов.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_Recv(t_l502_hnd hnd, uint32_t* buf, uint32_t size, uint32_t tout);


/***************************************************************************//**
    @brief Передача потоковых данных ЦАП и цифровых выходов в модуль.

    Функция записывает данные на передачу во внутренний буфер драйвера, после
    чего эти данные будут по DMA переданы в модуль.
    Данные должны быть в специальном формате, который определяет, что это за
    данные (цифровые выходы, канал ЦАП1 или канал ЦАП2). Подготовить данные
    в нужном формате можно с помощью L502_PrepareData().

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

    Возвращение означает что данные переданы в буфер драйвера, а не то что они
    уже дошли до модуля и выведены.

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

    @param[in]  hnd     Описатель модуля.
    @param[in]  buf     Буфер со словами, которые необходимо передать модулю
    @param[in]  size    Количество передаваемых отсчетов (32-битных слов).
    @param[in]  tout    Таймаут на передачу (в буфер драйвера) данных в мс.
    @return             Если < 0 - код ошибки.
                        Если >= 0 - количество записанных слов.
 ******************************************************************************/
LPCIE_EXPORT(int32_t) L502_Send(t_l502_hnd hnd, const uint32_t* buf, uint32_t size, uint32_t tout);



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

    Функция выполняет обработку отсчетов АЦП, прочитанных с помощью L502_Recv().
    Функция проверяет служебную информацию из входного массива и переводит отсчеты
    АЦП либо в коды, либо в вольты (если указан флаг #L502_PROC_FLAGS_VOLT).

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

    Если запущен синхронный ввод с цифровых линий, то следует использовать
    L502_ProcessData(), которая выделяет данные с цифровых линий в отдельный
    массив.

    @param[in]  hnd      Описатель модуля.
    @param[in]  src      Входной массив отсчетов, принятых с помощью L502_Recv().
    @param[out] dest     Массив, в который будут сохранены преобразованные данные
                         от АЦП.
    @param[in,out] size  На входе - количество слов в массиве src, на выходе -
                         количество сохраненных преобразованных значений в
                         массиве dest
    @param[in]  flags    Набор флагов из #t_l502_proc_flags
    @return               Код ошибки.
   ****************************************************************************/
LPCIE_EXPORT(int32_t) L502_ProcessAdcData(t_l502_hnd hnd, const uint32_t* src,  double *dest,
                            uint32_t *size, uint32_t flags);


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

    Функция выполняет обработку данных, прочитанных с помощью L502_Recv().
    Функция проверяет служебную информацию из входного массива, разбивает данные
    на два массива - данные от АЦП, которые переводятся в тип double, и данные
    от синхронного цифрового ввода.

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

    Кроме того, функция разбирает сообщения, передаваемые в потоке данных
    (например, сообщение о переполнении буфера).
    @param[in]  hnd      Описатель модуля.
    @param[in]  src      Входной массив отсчетов, принятый с помощью L502_Recv().
    @param[in]  size     Количество отсчетов (32-битных слов) в массиве src.
    @param[in]  flags    Набор флагов из #t_l502_proc_flags, управляющих
                         поведением функции. Может быть указано несколько флагов
                         через логическое "ИЛИ".
    @param[out] adc_data Массив, в который будут сохранены данные от АЦП,
                         преобразованные в соответствии с указанными флагами.
                         Может быть NULL, если не нужно сохранять данные от АЦП
                         (тогда adc_data_size должен быть тоже NULL, или в
                         переменной передан размер 0).
    @param[in,out] adc_data_size На входе в данном параметре передается резмер
                          буфера adc_data. Если данных от АЦП во входном массиве
                          будет больше adc_data_size, то в adc_data  будет
                          сохранено только первые adc_data_size отсчетов.
                          На выходе при успешном завершении функции в данную
                          переменную записывается количество сохранных отсчетов
                          АЦП.
                          Указатель может быть равен NULL, если adc_data = NULL
    @param[out] din_data  Массив, в который будут сохранены отчеты с синхронного
                          цифрового ввода. Младшие 18 битов соответствуют
                          состояниям линий, старшие 14 - резерв.
                          Может быть NULL, если не нужно сохранять данные от
                          синхронного ввода.
    @param[in,out] din_data_size Аналогично параметру adc_data_size в этом
                          параметре передается размер буфера din_data в отсчетах,
                          а на выходе сохраняется количество реально сохраненных
                          отсчетов цифрового ввода. Может быть NULL, если
                          din_data = NULL.
    @return               Код ошибки.
   ****************************************************************************/
LPCIE_EXPORT(int32_t) L502_ProcessData(t_l502_hnd hnd, const uint32_t* src, uint32_t size,
                     uint32_t flags, double *adc_data, uint32_t *adc_data_size,
                     uint32_t *din_data, uint32_t *din_data_size);

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

    Функция аналогична L502_ProcessData(), но позволяет также выделить
    пользовательские данные из потока. Пользовательскими данными считаются все
    отсчеты, которые не являются данными АЦП, данными цифрового ввода
    или сообщениями.
    Пользовательские данные складываются без изменений в массив usr_data
    (если он не равен нулю).
    Данная функция предназначена в первую очередь для программистов, которые
    будут использовать модифицированную прошивку сигнального процессора BlackFin.
    @param[in]  hnd              Описатель модуля.
    @param[in]  src              Входной массив отсчетов, принятый с помощью
                                 L502_Recv().
    @param[in]  size             Количество отсчетов (32-битных слов) в массиве src.
    @param[in]  flags            Набор флагов из #t_l502_proc_flags.
    @param[out] adc_data         Массив, в который будут сохранены данные от АЦП
                                 (см. L502_ProcessData()).
    @param[in,out] adc_data_size  см. L502_ProcessData()
    @param[out] din_data         Массив, в который будут сохранены отчеты с
                                 синхронного цифрового ввода. См. L502_ProcessData().
    @param[in,out] din_data_size  см. L502_ProcessData().
    @param[out] usr_data         Массив, в который будут сохранены пользовательские
                                данные без изменения их формата.
    @param[in,out] usr_data_size  В этом параметре передается размер буфера usr_data
                                а на выходе сохраняется количество реально сохраненных
                                отсчетов пользовательских данных.
                                Может быть NULL только если usr_data = NULL.
    @return                     Код ошибки.
   ****************************************************************************/
LPCIE_EXPORT(int32_t) L502_ProcessDataWithUserExt(t_l502_hnd hnd, const uint32_t* src, uint32_t size,
                                   uint32_t flags, double *adc_data,
                                   uint32_t *adc_data_size, uint32_t *din_data,
                                   uint32_t *din_data_size,
                                   uint32_t *usr_data, uint32_t *usr_data_size);



/***************************************************************************//**
    @brief Подготовка данных для вывода в модуль.

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

    Выходной массив должен будет содержать n*size отсчетов, где n - количество
    используемых входных массивов (от 1 до 3).

    Значения цифровых выходов представляют собой 32-битные слова, младшие 16-бит
    которых определяют значения выводов, а старшие - флаги из
    #t_l502_digout_word_flags, которые могут использоваться в частности для
    перевода одной (или обеих) из половин выводов в третье состояние.

    В качестве значений ЦАП могут использоваться как коды, так и Вольты,
    в зависимости от переданных флагов, и к выводимым значениям могут быть
    применены калибровочные коэффициенты.
    Если используются коды ЦАП с включенной калибровкой, то код
    #L502_DAC_SCALE_CODE_MAX определяет код, соответствующий +5V.

    @param[in]  hnd             Описатель модуля.
    @param[in]  dac1            Входной массив отсчетов первого канала ЦАП или
                                NULL, если не используется.
    @param[in]  dac2            Входной массив отсчетов второго канала ЦАП или
                                NULL, если не используется.
    @param[in]  digout          Входной массив со значениями цифровых выводов
                                или NULL, если не используется.
    @param[in]  size            Размер каждого из используемых входных массивов.
    @param[in]  flags           Флаги, управляющие работой функции, из
                                #t_l502_dacout_flags.
    @param[out] out_buf         Выходной массив, в который будут сохранены
                                сформированные отсчеты. Должен быть размера
                                n*size (n - количество используемых входных
                                массивов)
    @return                     Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_PrepareData(t_l502_hnd hnd, const double* dac1, const double* dac2,
                            const uint32_t* digout, uint32_t size, int32_t flags,
                            uint32_t* out_buf);

/***************************************************************************//**
    @brief Получить количество отсчетов в буфере потока на ввод.

    Функция возвращает количество отсчетов, которые были приняты из модуля
    во внутренний буфер в драйвере и готовы для считывания с помощью
    L502_Recv().
    То есть если в L502_Recv() передать значение, которое вернула данная функция,
    то L502_Recv() вернет это количество данных без ожидания (так как они уже
    в буфере).
    @param[in]  hnd              Описатель модуля.
    @param[out] rdy_cnt          Количество готовых к приему отсчетов.
    @return                      Код ошибки.
    ***************************************************************************/
LPCIE_EXPORT(int32_t) L502_GetRecvReadyCount(t_l502_hnd hnd, uint32_t *rdy_cnt);


/***************************************************************************//**
    @brief Получить размер свободного места в буфере потока на вывод.

    Функция возвращает количество отсчетов, соответствующее свободному месту
    в буфере драйвера на передачу в модуль.
    Это количество отсчетов может быть передано с помощью L502_Send() без
    ожидания.
    @param[in]  hnd              Описатель модуля.
    @param[out] rdy_cnt          Количество свободных отсчетов в буфере
                                 на передачу.
    @return                      Код ошибки.
    ***************************************************************************/
LPCIE_EXPORT(int32_t) L502_GetSendReadyCount(t_l502_hnd hnd, uint32_t *rdy_cnt);


/***************************************************************************//**
    @brief Получить номер следующего ожидаемого логического канала АЦП для
           обработки.

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

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

    Например, если установлено 7 логических каналов, а в L502_ProcessData()
    передано для обработки кратное 7 количество отсчетов, то последующий вызов
    L502_GetNextExpectedLchNum() вернет номер канала равный 0 (так как обработано
    целое число кадров и ожидается снова начало кадра).
    Если в L502_ProcessData() передан массив с 7*n + 5 отсчетами АЦП, то следующим
    ожидаемым каналом будет логический канал с номером 5 (обработаны каналы
    0,1,2,3,4 из неполного кадра).

    @param[in]  hnd              Описатель модуля.
    @param[out] lch              Номер логического канала (начиная с нуля).
    @return                      Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_GetNextExpectedLchNum(t_l502_hnd hnd, uint32_t *lch);


/***************************************************************************//**
    @brief Начало подготовки вывода синхронных данных

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

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

    @param[in] hnd        Описатель модуля.
    @return               Код ошибки.
    ***************************************************************************/
LPCIE_EXPORT(int32_t) L502_PreloadStart(t_l502_hnd hnd);



/***************************************************************************//**
    @brief Начало загрузки циклического сигнала на вывод

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

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

    @param[in] hnd        Описатель модуля.
    @param[in] size       Количество отсчетов в выводимом циклическом сигнале
                          суммарно для всех используемых каналов вывода.
    @return               Код ошибки.
    ***************************************************************************/
LPCIE_EXPORT(int32_t) L502_OutCycleLoadStart(t_l502_hnd hnd, uint32_t size);

/***************************************************************************//**
    @brief Установка ранее загруженного циклического сигнала на вывод

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

    Если до этого уже выводился циклический сигнал, то смена на новый произойдет
    в конце цикла предыдущего сигнала, если не указан флаг
    #L502_OUT_CYCLE_FLAGS_FORCE.

    Данная функция должна быть вызвана только после вызова L502_OutCycleLoadStart()
    и загрузки указанного в ней количества отсчетов в буфер!

    @param[in] hnd        Описатель модуля.
    @param[in] flags      Флаги из #t_l502_out_cycle_flags.
    @return               Код ошибки.
    ***************************************************************************/
LPCIE_EXPORT(int32_t) L502_OutCycleSetup(t_l502_hnd hnd, uint32_t flags);


/***************************************************************************//**
    @brief Останов вывода циклического сигнала

    По вызову этой функции прекращается выдача ранее установленного циклического
    сигнала с помощью L502_OutCycleSetup(). Остановка осуществляется по
    после выдачи последнего семпла в периоде (но функция возвращает управление
    сразу, делая только запрос на останов), что позволяет знать какие значения
    останутся на выходах.

    При вызове же L502_StreamsStop() (или при запрещении всех потоков
    на вывод через L502_StreamsDisable()) останов всех потоков происходит сразу
    и точную точка не извествна.

    @param[in] hnd        Описатель модуля.
    @param[in] flags      Флаги из #t_l502_out_cycle_flags.
    @return               Код ошибки.
    ***************************************************************************/
LPCIE_EXPORT(int32_t) L502_OutCycleStop(t_l502_hnd hnd, uint32_t flags);





/***************************************************************************//**
    @brief Установка размера буфера в драйвере для синхронного ввода или вывода.

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

    @param[in] hnd        Описатель модуля.
    @param[in] dma_ch     Определяет, устанавливается размер буфера на ввод
                          или на вывод (значение из #t_l502_dma_ch).
    @param[in] size       Размер буфера в 32-битных отсчетах
    @return               Код ошибки.
 ******************************************************************************/
LPCIE_EXPORT(int32_t) L502_SetDmaBufSize(t_l502_hnd hnd, uint32_t dma_ch, uint32_t size);

/***************************************************************************//**
    @brief Установка шага прерывания при передаче потока по DMA.

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

    @param[in] hnd        Описатель модуля.
    @param[in] dma_ch     Определяет, шаг прерывания устанавливается на ввод
                          или на вывод (значение из #t_l502_dma_ch).
    @param[in] step       Шаг прерывания в 32-битных отсчетах
    @return               Код ошибки.
 ******************************************************************************/
LPCIE_EXPORT(int32_t) L502_SetDmaIrqStep(t_l502_hnd hnd, uint32_t dma_ch, uint32_t step);

/** @} */




/***************************************************************************//**
    @addtogroup func_dsp Функции для работы с сигнальным процессором
    @{
*******************************************************************************/
/***************************************************************************//**
    @brief Загрузка прошивки сигнального процессора BlackFin.

    Функция загружает прошивку сигнального процессора из указанного файла в
    процессор и запускает ее, проверяет правильность загрузки путем получения
    версии прошивки (через специальную команду).
    Прошивка должна быть в бинарном формате LDR.
    @param[in] hnd           Описатель модуля.
    @param[in] filename      Имя файла с загружаемой прошивкой.
    @return                  Код ошибки.
  *****************************************************************************/
LPCIE_EXPORT(int32_t) L502_BfLoadFirmware(t_l502_hnd hnd, const char* filename);



/***************************************************************************//**
    @brief Проверка, загружена ли прошивка BlackFIn.

    Функция передает команды процессору BlackFin для получения версии прошивки и
    ее состояния. Успешное выполнение команд свидетельствует о том, что в
    BlackFin загружена действительная прошивка.
    Кроме того прошивке передается информация о модуле (наличие опций, версия
    ПЛИС и т.д.) для внутреннего использования.
    В случае успеха модуль переводится в режим DSP.

    Данная функция может служить для проверки была ли загружена прошивка раньше
    (чтобы не загружать повторно) или для проверки была ли она загружена через
    JTAG-интерфейс.

    @param[in]  hnd          Описатель модуля.
    @param[out] version      Если указатель не нулевой, то в данной переменной
                             возвращается версия прошивки BlackFin в случае
                             успешной проверки.
    @return                  Код ошибки.
  *****************************************************************************/
LPCIE_EXPORT(int32_t) L502_BfCheckFirmwareIsLoaded(t_l502_hnd hnd, uint32_t *version);

/***************************************************************************//**
    @brief Чтение блока данных из памяти сигнального процессора.

    Функция считывает блок данных напрямую из памяти процессора. Может быть
    прочитаны данные, как из внутренней памяти (L1), так и из внешней SDRAM.
    Для выполнения этой функции в BlackFin должна быть загружена его прошивка.

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

    @param[in] hnd           Описатель модуля.
    @param[in] addr          Адрес памяти, начиная с которого будет считан блок
                             данных.
    @param[out] regs         Массив, в который будут сохранено прочитанное
                             содержимое памяти.
    @param[in] size          Количество считываемых 32-битных слов.
    @return                  Код ошибки.
 ******************************************************************************/
LPCIE_EXPORT(int32_t) L502_BfMemRead(t_l502_hnd hnd, uint32_t addr, uint32_t* regs,
                                uint32_t size);

/***************************************************************************//**
    @brief Запись блока данных в память сигнального процессора.

    Функция записывает блок данных напрямую в памяти процессора BlackFin. Блок
    данных должен быть всегда кратен 8 32-битным словам (32 байтам).
    Запись может осуществляться как во внутреннюю память (L1), так и во внешнюю SDRAM.
    Для выполнения этой функции в BlackFin должна быть загружена его прошивка.

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

    @note Следует быть осторожным, т.к. запись в область данных, используемую
    программой может привести к ее неработоспособности.

    @param[in] hnd           Описатель модуля.
    @param[in] addr          Адрес памяти, начиная с которого будет записан блок
                             данных.
    @param[out] regs         Массив с данными для записи в сигнальный процессор.
    @param[in] size          Количество записываемых данных в 32-битных словах
                             (должно быть кратно 8).
    @return                  Код ошибки.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_BfMemWrite(t_l502_hnd hnd, uint32_t addr,
                                 const uint32_t* regs, uint32_t size);


/***************************************************************************//**
    @brief Передача управляющей команды сигнальному процессору.

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

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

    Команды делаться на стандартные, которые используются библиотекой l502api и
    пользовательские, которые может пользователь определять по своему усмотрению.
    Пользовательские команды начинаются с кода L502_BF_CMD_CODE_USER (0x8000).

    @param[in] hnd           Описатель модуля.
    @param[in] cmd_code      Код команды - определяет, что за команда выполняется.
    @param[in] par           Параметр, передаваемый с командой (значение зависит
                             от кода команды).
    @param[in] snd_data      Опциональные данные, передаваемые вместе с командой.
                             Если данные не передаются, то должен передаваться
                             нулевой указатель и snd_size = 0.
    @param[in] snd_size      Количество 32-битных слов, передаваемых в snd_data
    @param[out] rcv_data     Массив, в который будут переданы данные, возвращенные
                             процессором по завершению команды. Если данные не
                             должны возвращаться, то должен передаваться нулевой
                             указатель, а rcv_size = 0.
    @param[in] rcv_size      Количество 32-битных слов, которое ожидается, что
                             вернет процессор по выполнению команды. Массив
                             rcv_data должен быть рассчитан на данное количество
                             слов.
    @param[in] tout          Таймаут в течении которого будет ожидаться, когда
                             процессор завершит выполнение команды. Функция
                             возвратит управление либо по завершению команды,
                             либо по таймауту.
    @param[out] recvd_size   Если не является нулевым указателем, то в эту
                             переменную будет сохранено количество 32-битных слов,
                             которое реально вернул процессор после выполнения
                             команды (процессор имеет право вернуть меньше данных,
                             чем запрашивалось в rcv_size).
    @return                  Код ошибки. Если процессор выполнил команду с ненулевым
                             кодом завершения, то этот код и будет возвращен
                             функцией.
*******************************************************************************/
LPCIE_EXPORT(int32_t) L502_BfExecCmd(t_l502_hnd hnd, uint16_t cmd_code, uint32_t par,
                const uint32_t* snd_data, uint32_t snd_size,
                uint32_t* rcv_data, uint32_t rcv_size, uint32_t tout, uint32_t* recvd_size);
/** @} */



/***************************************************************************//**
    @addtogroup func_flash Функции для работы с Flash-памятью модуля
    @{
*******************************************************************************/

/***************************************************************************//**
    @brief Чтение блока данных из Flash-памяти.

    Функция считывает массив данных из Flash-памяти модуля в массив, переданный
    пользователем. Для считывания не нужно специальное разрешение - оно доступно
    всегда.
    @param[in]  hnd     Описатель модуля.
    @param[in]  addr    Адрес начала блока.
    @param[out] data    Массив, куда будут сохранены считанные данные
                          (должен быть не меньше size байт).
    @param[in]  size    Количество байт для чтения.
    @return             Код ошибки.
 ******************************************************************************/
LPCIE_EXPORT(int32_t) L502_FlashRead(t_l502_hnd hnd, uint32_t addr, uint8_t* data,
                                uint32_t size);
/***************************************************************************//**
    @brief Запись блока данных во Flash-память модуля.

    Функция записывает переданный массив данных во Flash-память модуля.
    Эта область должна быть предварительно стерта с помощью L502_FlashErase() и
    до начала изменения должна быть вызвана функция L502_FlashWriteEnable(),
    чтобы разрешить любое изменение содержимого Flash-памяти.
    Пользователю для записи доступны только первые #L502_FLASH_USER_SIZE байт
    Flash-памяти.
    @param[in]  hnd     Описатель модуля.
    @param[in]  addr    Адрес начала блока.
    @param[in]  data    Массив c записываемыми данными (должен быть не меньше
                        size байт).
    @param[in]  size    Количество байт для записи.
    @return             Код ошибки.
 ******************************************************************************/
LPCIE_EXPORT(int32_t) L502_FlashWrite(t_l502_hnd hnd, uint32_t addr,
                                 const uint8_t* data, uint32_t size);
/***************************************************************************//**
    @brief Стирание блока во Flash-памяти.

    Функция стирает блок во Flash-памяти модуля (все ячейки будут читаться как
    0xFF). Адрес и размер должны быть кратны 4096 байт!
    Перед вызовом этой функции запись должна быть разрешена запись
    в пользовательскую область с помощью L502_FlashWriteEnable().
    @param[in]  hnd     Описатель модуля.
    @param[in]  addr    Адрес начала блока (должен быть кратен 4K).
    @param[in]  size    Количество байт для стирания (кратно 4K).
    @return             Код ошибки.
 ******************************************************************************/
LPCIE_EXPORT(int32_t) L502_FlashErase(t_l502_hnd hnd, uint32_t addr, uint32_t size);
/***************************************************************************//**
    @brief Разрешение записи в пользовательскую область Flash-памяти.

    Функция разрешает запись в пользовательскую область Flash-памяти (первые
    #L502_FLASH_USER_SIZE байт). Должна быть вызвана до того, как
    можно будет использовать L502_FlashErase() и L502_FlashWrite() для изменения
    содержимого пользовательской области памяти. После завершения изменения
    следует вызвать L502_FlashWriteDisable().
    @param[in]  hnd     Описатель модуля.
    @return             Код ошибки.
 ******************************************************************************/
LPCIE_EXPORT(int32_t) L502_FlashWriteEnable(t_l502_hnd hnd);
/***************************************************************************//**
    @brief Запрет записи в пользовательскую область Flash-памяти.

    Функция запрещает запись в пользовательскую область Flash-памяти модуля
    (первые #L502_FLASH_USER_SIZE байт). Должна быть вызвана после того, как
    нужные данные в пользовательской области были изменены с помощью
    L502_FlashErase() и L502_FlashWrite(), чтобы защитить пользовательскую
    область от случайной изменения в дальнейшем.
    @param[in]  hnd     Описатель модуля.
    @return             Код ошибки.
 ******************************************************************************/
LPCIE_EXPORT(int32_t) L502_FlashWriteDisable(t_l502_hnd hnd);

/** @} */

/***************************************************************************//**
    @addtogroup func_misc Дополнительные вспомогательные функции.
    @{
*******************************************************************************/
/**************************************************************************//**
  @brief Получить версию библиотеки.

  Функция возвращает версию библиотеки l502api.dll.
  Версия возвращается в виде 32-битного числа.
  Строковое представление возвращенной версии - четыре числа,
  старшее соответствует старшему байту, младшее - младшему.

  Старший байт - можорная версия, второй по старшинству байт - минорная,
  третий - ревизия, четвертый - номер сборки (не используется - всегда 0)

  @return 32-битное число, представляющее собой версию библиотеки
  *****************************************************************************/
LPCIE_EXPORT(uint32_t) L502_GetDllVersion(void);



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

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

    @note Следует учесть, что в ОС Windows строка возвращается в
    стандартной для Windows кодировке CP1251, в то время как в Linux
    используется кодировка UTF-8.
    @param[in] err   Код ошибки, для которого нужно вернуть строку.
    @return          Указатель на строку, соответствующую коду ошибки
 ******************************************************************************/
LPCIE_EXPORT(const char*) L502_GetErrorString(int32_t err);


/***************************************************************************//**
   @brief Моргание светодиодом на передней панели.

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

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

    @param[in]  hnd     Описатель модуля.
    @return             Код ошибки.
 ******************************************************************************/
LPCIE_EXPORT(int32_t) L502_LedBlink(t_l502_hnd hnd);

/***************************************************************************//**
   @brief Установка подтягивающих резисторов на входных линиях.

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

    @param[in] hnd      Описатель модуля.
    @param[in] pullups  Флаги (из #t_l502_pullups), определяющие, на каких
                        линиях включены подтягивающие резисторы.
    @return             Код ошибки.
 ******************************************************************************/
LPCIE_EXPORT(int32_t) L502_SetDigInPullup(t_l502_hnd hnd, uint32_t pullups);

/** @} */
/** @} */

#ifdef __cplusplus
}
#endif

#endif

