manually merged with ARM version
This commit is contained in:
31
x502/fast_crc_cfg.h
Normal file
31
x502/fast_crc_cfg.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*================================================================================================*
|
||||
* Конфигурация библиотеки FAST_CRC
|
||||
*================================================================================================*/
|
||||
|
||||
#ifndef FAST_CRC_CFG_H_
|
||||
#define FAST_CRC_CFG_H_
|
||||
|
||||
#include "lcard_pstdint.h"
|
||||
|
||||
/*================================================================================================*/
|
||||
/* Типы */
|
||||
#define FASTCRC_U8_TYPE uint8_t
|
||||
#define FASTCRC_U16_TYPE uint16_t
|
||||
#define FASTCRC_U32_TYPE uint32_t
|
||||
#define FASTCRC_SIZE_TYPE size_t
|
||||
|
||||
/* Начальные значения CRC */
|
||||
#define CRC16_START_VAL 0
|
||||
#define CRC32_START_VAL 0
|
||||
/*================================================================================================*/
|
||||
|
||||
/*================================================================================================*/
|
||||
/* Разрешение компиляции отдельных функций */
|
||||
#define FASTCRC_CRC16_ADD8 1 /* добавление в CRC16 байта */
|
||||
#define FASTCRC_CRC16_ADD16 1 /* добавление в CRC16 16-битного слова */
|
||||
#define FASTCRC_CRC16_BLOCK8 1 /* Вычисление CRC16 блока байтов */
|
||||
#define FASTCRC_CRC16_BLOCK16 1 /* Вычисление CRC16 блока 16-битных слов */
|
||||
#define FASTCRC_CRC32_BLOCK8 1 /* Вычисление CRC32 блока байтов */
|
||||
/*================================================================================================*/
|
||||
|
||||
#endif /* FAST_CRC_CFG_H_ */
|
||||
167
x502/l502_bf_cmd_defs.h
Normal file
167
x502/l502_bf_cmd_defs.h
Normal file
@ -0,0 +1,167 @@
|
||||
/*********************************************************************//**
|
||||
@addtogroup cmd_process
|
||||
@{
|
||||
@file l502_bf_cmd_defs.h Файл содержит определения,
|
||||
которые используются для передачи команд от ПК в DSP
|
||||
(определения команд, их параметров, результатов выполнения)
|
||||
@date 28.03.2012
|
||||
@author Borisov Alexey <borisov@lcard.ru>
|
||||
*************************************************************************/
|
||||
#ifndef L502_BF_CMD_DEFS_H_
|
||||
#define L502_BF_CMD_DEFS_H_
|
||||
|
||||
/** Максимальный размер данных, передавемых с командой в 32-битных словах */
|
||||
#define L502_BF_CMD_DATA_SIZE_MAX (1024)
|
||||
|
||||
|
||||
|
||||
/** Статус команд управления сигнальным процессором */
|
||||
typedef enum {
|
||||
L502_BF_CMD_STATUS_IDLE = 0x0, /**< Начальное состояние (команда вообщен не выполнялась) */
|
||||
L502_BF_CMD_STATUS_REQ = 0x5A01, /**< Передан запрос на обработку команды от ПК*/
|
||||
L502_BF_CMD_STATUS_PROGRESS = 0x5A02, /**< Сигнальный процессор начал обработку команды */
|
||||
L502_BF_CMD_STATUS_DONE = 0x5A03 /**< Команда выполнена. Результат выполнения в поле ret_code */
|
||||
} t_l502_bf_cmd_status;
|
||||
|
||||
|
||||
/** Коды команд управления сигнальным процессором */
|
||||
typedef enum {
|
||||
L502_BF_CMD_CODE_TEST = 0x01, /**< Запуск теста (параметр определяет тип теста) */
|
||||
L502_BF_CMD_CODE_SET_PARAM = 0x02, /**< Установить параметр (код параметра в поле param) */
|
||||
L502_BF_CMD_CODE_GET_PARAM = 0x03, /**< Прочитать текущее значение параметра */
|
||||
L502_BF_CMD_CODE_CONFIGURE = 0x04, /**< Сконфигурировать модуль в соответствии с ранее установленными параметрами */
|
||||
L502_BF_CMD_CODE_STREAM_EN = 0x05, /**< Разрешение потоков ввода/вывода */
|
||||
L502_BF_CMD_CODE_STREAM_DIS = 0x06, /**< Запрещение потоков ввода/вывода */
|
||||
L502_BF_CMD_CODE_STREAM_START = 0x07, /**< Запуск потоков ввода/вывода */
|
||||
L502_BF_CMD_CODE_STREAM_STOP = 0x08, /**< Останов потоков ввода/вывода */
|
||||
L502_BF_CMD_CODE_PRELOAD = 0x09, /**< Предзагрузка данных на ЦАП */
|
||||
L502_BF_CMD_CODE_ASYNC_OUT = 0x10, /**< Асинхронный вывод (куда - зависит от параметра) */
|
||||
L502_BF_CMD_CODE_ASYNC_DIG_IN = 0x11, /**< Асинхронный ввод с цифровых линий */
|
||||
L502_BF_CMD_CODE_ADC_GET_FRAME = 0x12, /**< Асинхронный ввод карда АЦП */
|
||||
L502_BF_CMD_CODE_FPGA_REG_WR = 0x13, /**< Запись в регистр FPGA (param --- адрес регистра, data0 --- значение) */
|
||||
L502_BF_CMD_CODE_FPGA_REG_RD = 0x14, /**< Чтение из регистра FPGA (param --- адрес регистра, ответ: resp0 --- значение) */
|
||||
L502_BF_CMD_CODE_GET_OUT_STATUS= 0x15, /**< Получение флагов статуса вывода */
|
||||
} t_l502_bf_cmd_code;
|
||||
|
||||
#define L502_BF_CMD_CODE_USER 0x8000U /**< Код, с которого начинаются пользовательские команды */
|
||||
|
||||
|
||||
|
||||
/** @brief Варианты тестов
|
||||
|
||||
Коды тестов, передающиеся в параметре команды #L502_BF_CMD_CODE_TEST */
|
||||
typedef enum {
|
||||
L502_BF_CMD_TEST_STOP = 0x00, /**< Останов выполняемого теста */
|
||||
L502_BF_CMD_TEST_GET_RESULT = 0x01, /**< Получение результата теста */
|
||||
L502_BF_CMD_TEST_ECHO = 0x10, /**< Тест эхо - возвращает те же данные что передавались */
|
||||
L502_BF_CMD_TEST_SPORT = 0x11, /**< Тест интерфейса SPORT в кольцевом режиме */
|
||||
L502_BF_CMD_TEST_SDRAM = 0x12, /**< Тест SDRAM памяти */
|
||||
L502_BF_CMD_TEST_SPI = 0x13 /**< Тест интерфейса SPI */
|
||||
} t_l502_bf_test_code;
|
||||
|
||||
|
||||
/** @brief Устанавливаемые параметры
|
||||
|
||||
Коды пареметров, устанавливаемых командой #L502_BF_CMD_CODE_SET_PARAM или
|
||||
получаемых с помщью команды #L502_BF_CMD_CODE_GET_PARAM */
|
||||
typedef enum {
|
||||
L502_BF_PARAM_FIRM_VERSION = 0x00, /**< Версия прошивки - 4 байта */
|
||||
L502_BF_PARAM_STREAM_MODE = 0x01, /**< Режим работы (запущен поток или нет) */
|
||||
L502_BF_PARAM_ENABLED_STREAMS = 0x02, /**< Какие потоки разрешены */
|
||||
L502_BF_PARAM_MODULE_INFO = 0x03, /**< Запись информации о модуле */
|
||||
L502_BF_PARAM_IN_BUF_SIZE = 0x10, /**< Размер буфера на преием */
|
||||
L502_BF_PARAM_CYCLE_BUF_SIZE = 0x11, /**< Размер буфера для записи циклического сигнала */
|
||||
L502_BF_PARAM_LCH_CNT = 0x20, /**< Количество логических каналов в таблице */
|
||||
L502_BF_PARAM_LCH = 0x21, /**< Параметры логического канала */
|
||||
L502_BF_PARAM_ADC_FREQ_DIV = 0x22, /**< Делитель частоты АЦП */
|
||||
L502_BF_PARAM_REF_FREQ_SRC = 0x23, /**< Выбор опорной частоты */
|
||||
L502_BF_PARAM_ADC_FRAME_DELAY = 0x24, /**< Значение межкадровой задержки */
|
||||
L502_BF_PARAM_SYNC_MODE = 0x25, /**< Режим синхронизации */
|
||||
L502_BF_PARAM_SYNC_START_MODE = 0x26, /**< Условие запуска синхронных потоков сбора данных */
|
||||
L502_BF_PARAM_ADC_COEF = 0x27, /**< Установка коэффициентов для заданного диапазона АЦП */
|
||||
L502_BF_PARAM_DAC_COEF = 0x28, /**< Установка коэффициентов для заданного канала ЦАП */
|
||||
L502_BF_PARAM_DIN_FREQ_DIV = 0x30, /**< Делитель частоты цифрового ввода */
|
||||
L502_BF_PARAM_DAC_FREQ_DIV = 0x31, /**< Делитель частоты вывода на ЦАП */
|
||||
L502_BF_PARAM_IN_STEP_SIZE = 0x32, /**< Шаг для обработки входных данных */
|
||||
L502_BF_PARAM_IN_STREAM_MODE = 0x100 /**< Режим работы потока на ввод */
|
||||
} t_l502_bf_params;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** @brief Тип асинхронного вывода
|
||||
|
||||
Код, задающий в параметре команды команды #L502_BF_CMD_CODE_ASYNC_OUT,
|
||||
куда должно выводится передаваемое значение */
|
||||
typedef enum {
|
||||
L502_BF_CMD_ASYNC_TYPE_DOUT = 0x0, /**< Вывод на цифровые линии */
|
||||
L502_BF_CMD_ASYNC_TYPE_DAC1 = 0x1, /**< Вывод на первый канал ЦАП */
|
||||
L502_BF_CMD_ASYNC_TYPE_DAC2 = 0x2 /**< Вывод на второй канал ЦАП */
|
||||
} t_l502_bf_cmd_async_type;
|
||||
|
||||
/** Коды завершения команд */
|
||||
typedef enum {
|
||||
L502_BF_ERR_SUCCESS = 0, /**< Команда выполнена успешно */
|
||||
L502_BF_ERR_FIRST_CODE = -512, /**< Код ошибки, с которого начинаются отсальные коды.
|
||||
Используется, чтобы разделить на верхнем уровне ошибки библиотеки и
|
||||
возвращенные сигнальным процессором */
|
||||
L502_BF_ERR_UNSUP_CMD = -512, /**< Неизвестный код команды */
|
||||
L502_BF_ERR_CMD_OVERRUN = -513, /**< Пришла команда до того, как была завершена предыдущая */
|
||||
L502_BF_ERR_INVALID_CMD_PARAMS = -514, /**< Неверное значение параметра команды */
|
||||
L502_BF_ERR_INSUF_CMD_DATA = -515, /**< Недостаточное кол-во данных передано с командой */
|
||||
L502_BF_ERR_STREAM_RUNNING = -516, /**< Команда не допустима при запущеном сборе, а сбор запущен */
|
||||
L502_BF_ERR_STREAM_STOPPED = -517, /**< Команда допустима только при запущеном сборе, а сбор остановлен */
|
||||
L502_BF_ERR_NO_TEST_IN_PROGR = -518, /**< Сейчас не выполняется никакого теста */
|
||||
L502_BF_ERR_TEST_VALUE = -519 /**< Считано неверное значение при выполнении теста */
|
||||
} t_l502_bf_err_code;
|
||||
|
||||
|
||||
/** Режим работы сигнального процессора */
|
||||
typedef enum {
|
||||
L502_BF_MODE_IDLE = 0, /**< Ждущий режим, поток не запущен */
|
||||
L502_BF_MODE_STREAM = 1, /**< Запущены потоки ввода-вывода */
|
||||
L502_BF_MODE_TEST = 2 /**< Тестовый режим */
|
||||
} t_l502_bf_mode;
|
||||
|
||||
/** Возможности, поддерживаемые прошивкой blackfin */
|
||||
typedef enum {
|
||||
L502_BF_FEATURE_FPGA_REG_ACCESS = 0x1, /**< Признак, что реализованы команды
|
||||
прямого доступа к регистрам FPGA */
|
||||
L502_BF_FEATURE_OUT_STATUS_FLAGS = 0x2 /**< Признак, что реализована команда
|
||||
#L502_BF_CMD_CODE_GET_OUT_STATUS */
|
||||
} t_l502_bf_features;
|
||||
|
||||
/** @brief Параметры команды
|
||||
|
||||
Структура описывает расположение полей в области памяти BlackFin, используемой
|
||||
для передачи команд между персональным компьютером и сигнальным процессором */
|
||||
typedef struct {
|
||||
uint16_t code; /**< Код команды из #t_l502_bf_cmd_code */
|
||||
uint16_t status; /**< Статус выполнения - в обработчике не изменяется */
|
||||
uint32_t param; /**< Параметр команды */
|
||||
int32_t result; /**< Код результата выполнения команды */
|
||||
uint32_t data_size; /**< Количество данных, переданных с командой или возвращенных с ответом в 32-битных словах */
|
||||
uint32_t data[L502_BF_CMD_DATA_SIZE_MAX]; /**< Данные, передаваемые с командой и/или в качестве результата */
|
||||
} t_l502_bf_cmd;
|
||||
|
||||
|
||||
/** @brief Результат выполнения теста
|
||||
|
||||
Структура описывает параметры выполняемого теста, возвращаемые в качестве
|
||||
данных на команду #L502_BF_CMD_CODE_TEST с параметром
|
||||
#L502_BF_CMD_TEST_GET_RESULT */
|
||||
typedef struct {
|
||||
uint32_t test; /**< Номер выполняемого теста */
|
||||
uint32_t run; /**< Признак, запущен ли сейчас тест */
|
||||
uint32_t stage; /**< Этап выполнения теста */
|
||||
uint32_t cntr; /**< Счетчик - сколько раз прошел тест */
|
||||
int32_t err; /**< Код ошибки выполнения теста */
|
||||
uint32_t last_addr; /**< Последний используемый адрес */
|
||||
uint32_t last_wr; /**< Последнее записанное значение */
|
||||
uint32_t last_rd; /**< Последнее считанное значение */
|
||||
} t_l502_bf_test_res;
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif
|
||||
270
x502/lboot_req.h
Normal file
270
x502/lboot_req.h
Normal file
@ -0,0 +1,270 @@
|
||||
/***************************************************************************//**
|
||||
@file lcspec.h
|
||||
|
||||
Файл содержит константы и типы, которые использует как загрузчик lboot,
|
||||
так и приложение:
|
||||
- константы и типы для запроса на перепрошивку со стороны application
|
||||
- константы и типы для определения информации о прошивке, которая хранится
|
||||
внутри прошивки и проверяется bootloader'ом
|
||||
|
||||
!!Файл должен быть один (или одинаковый) для обоих проектов!!
|
||||
|
||||
@date 16.11.2010
|
||||
@author: Borisov Alexey <borisov@lcard.ru>
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef LBOOT_REQ_H_
|
||||
#define LBOOT_REQ_H_
|
||||
|
||||
|
||||
/** адрес, по которому должен быть сформирован запрос на перепрошивку */
|
||||
#define LBOOT_REQ_ADDR 0x10000000
|
||||
/** Адрес, начиная с кторого хранится информация о загрузчике */
|
||||
#define LBOOT_INFO_ADDR 0x200
|
||||
|
||||
/******************* размеры полей ***************************************/
|
||||
#define LBOOT_DEVNAME_SIZE 32
|
||||
#define LBOOT_SERIAL_SIZE 32
|
||||
#define LBOOT_SOFTVER_SIZE 32
|
||||
#define LBOOT_REVISION_SIZE 16
|
||||
#define LBOOT_IMPLEMENTATION_SIZE 16
|
||||
#define LBOOT_SPECINFO_SIZE 64
|
||||
|
||||
#define LBOOT_MAC_ADDR_SIZE 6
|
||||
|
||||
#define LBOOT_REQ_MAX_FILENAME_SIZE 256
|
||||
#define LBOOT_REQ_MAX_SIZE 4096
|
||||
|
||||
|
||||
/** различные коды режимов загрузки */
|
||||
#define LBOOT_BOOTMODE_MODBUS_RTU 0x100
|
||||
#define LBOOT_BOOTMODE_TFTP_CLIENT 0x200
|
||||
#define LBOOT_BOOTMODE_TFTP_SERVER 0x201
|
||||
#define LBOOT_BOOTMODE_USB 0x300
|
||||
#define LBOOT_BOOTMODE_CAN_LSS 0x400
|
||||
|
||||
#define LBOOT_BOOTMODE_TFTP LBOOT_BOOTMODE_TFTP_CLIENT
|
||||
|
||||
//режим работы устройства (application/bootloader) - в modbus сразу за device info
|
||||
#define LBOOT_MODE_BOOT 0x1
|
||||
#define LBOOT_MODE_APPL 0x2
|
||||
|
||||
#define LBOOT_TFTP_FLAGS_PACKED 0x2
|
||||
|
||||
|
||||
#define LBOOT_SEED_CODE_NOSIGN 0xFFAA5500
|
||||
|
||||
|
||||
/** признак, находящийся в информации о прошивке, по которому можно узнать
|
||||
наличие этой информации. Признак означает, что поддерживается защита этой
|
||||
информации CRC */
|
||||
#define LBOOT_INFO_SIGNATURE 0x4C42A55A
|
||||
|
||||
|
||||
|
||||
/** общие для всех интерфейсов флаги, определяющие поведение загрузчика */
|
||||
typedef enum {
|
||||
/** - при активном запросе прошивки (tftp) - признак,
|
||||
что перезависывется резервная копия, а не основная прошивка
|
||||
- при пассивном приеме (mbrtu, usb, can_lss) - признак,
|
||||
что разрешено перезаписывать резервную копию */
|
||||
LBOOT_REQ_FLAGS_RECOVERY_WR = 0x01,
|
||||
/** признак, что не нужно сверять имя устройства в прошивке */
|
||||
LBOOT_REQ_FLAGS_DONT_CHECK_NAME = 0x02,
|
||||
/** не проверять, что записывается стабильная прошивка (установлен флаг
|
||||
#LBOOT_APP_FLAGS_STABLE в информации о прошивке)*/
|
||||
LBOOT_REQ_FLAGS_DONT_CHECK_STABLE = 0x04,
|
||||
/** разрешение записывать прошивку для разработчика (с установленным флагом
|
||||
#LBOOT_APP_FLAGS_DEVELOP в информации о прошивке)*/
|
||||
LBOOT_REQ_FLAGS_ENABLE_DEVELOP = 0x08,
|
||||
/** разрешение записи прошивки без подписи (если поддерживается загрузчиком) */
|
||||
LBOOT_REQ_FLAGS_ENABLE_NO_SIGN = 0x10
|
||||
} t_lboot_req_flags;
|
||||
|
||||
/** флаги из #t_app_info */
|
||||
typedef enum {
|
||||
/** признак, что прошивка стабильная */
|
||||
LBOOT_APP_FLAGS_STABLE = 0x1,
|
||||
/** признак, что это прошивка для разработчиков */
|
||||
LBOOT_APP_FLAGS_DEVELOP = 0x2
|
||||
} t_lboot_app_flags;
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma pack(1)
|
||||
/** Информация о программе, содержащаяся в прошивке */
|
||||
struct st_app_info {
|
||||
uint32_t size; /**< размер информции о прошивке */
|
||||
uint32_t flags; /**< флаги */
|
||||
/** название устройства, для которого предназначена прошивка*/
|
||||
char devname[LBOOT_DEVNAME_SIZE];
|
||||
};
|
||||
typedef struct st_app_info t_app_info;
|
||||
|
||||
|
||||
|
||||
|
||||
/** Информация о загрузчике, находящаяся непосредственно
|
||||
в коде самого загрузчика */
|
||||
struct lboot_info_st {
|
||||
/** версия загрузчика (младший байт - минорная, старший - мажорная) */
|
||||
uint16_t ver;
|
||||
uint16_t flags; /**< флаги - резерв */
|
||||
/** серийный номер устройства */
|
||||
char serial[LBOOT_SERIAL_SIZE];
|
||||
uint8_t mac[6]; /**< mac-адрес устройства */
|
||||
/** ревизия платы (если вшита в загрузчик)*/
|
||||
char brd_revision[LBOOT_REVISION_SIZE];
|
||||
/** модификация (если вшита в загрузчик)*/
|
||||
char brd_impl[LBOOT_IMPLEMENTATION_SIZE];
|
||||
char creation_date[18]; /**< дата создания загрузчика */
|
||||
/** признак, что эта структура действительна (только с v1.3) */
|
||||
uint32_t sign;
|
||||
/** размер структуры (включая два байта crc)
|
||||
- для определения положения crc */
|
||||
uint32_t size;
|
||||
char devname[LBOOT_DEVNAME_SIZE];
|
||||
/** поддерживаемые возможности загрузчика */
|
||||
uint32_t features;
|
||||
uint32_t reserv;
|
||||
uint8_t ip_addr[4]; /**< ip-адрес устройства по-умолчанию */
|
||||
uint8_t ip_mask[4]; /**< маска устройства по-умолчанию */
|
||||
uint8_t gate[4]; /**< адрес шлюза по-умолчанию */
|
||||
/** crc (но при проверке следует брать ее не отсюда,
|
||||
а по адресу = адрес начала структуры + size - 2) */
|
||||
uint16_t crc;
|
||||
};
|
||||
typedef struct lboot_info_st t_lboot_info;
|
||||
|
||||
/** информация о устройстве и прошивке */
|
||||
struct lboot_devinfo_st {
|
||||
char devname[LBOOT_DEVNAME_SIZE]; /**< название устройства */
|
||||
char serial[LBOOT_SERIAL_SIZE]; /**< серийный номер */
|
||||
char soft_ver[LBOOT_SOFTVER_SIZE]; /**< версия прошивки */
|
||||
char brd_revision[LBOOT_REVISION_SIZE]; /**< ревизия платы */
|
||||
char brd_impl[LBOOT_IMPLEMENTATION_SIZE]; /**< опции платы */
|
||||
char spec_info[LBOOT_SPECINFO_SIZE]; /**< резерв */
|
||||
};
|
||||
typedef struct lboot_devinfo_st t_lboot_devinfo;
|
||||
|
||||
|
||||
/** стандартный заголовок запроса на перепрошивку */
|
||||
struct lboot_params_hdr_st {
|
||||
uint32_t size; /**< размер структуры запроса (включая
|
||||
специфические для интерфейса данные и crc) */
|
||||
uint32_t bootmode; /**< режим загрузки - определяет интерфейс */
|
||||
uint32_t flags; /**< общие флаги */
|
||||
uint32_t timeout; /**< таймаут в мс - сколько загрузчик будет ожидать
|
||||
запроса на перепрошивку (0 - бесконечно) */
|
||||
uint32_t reserv[2]; /**< резерв */
|
||||
t_lboot_devinfo devinfo; /**< информация о устройстве и прошивке */
|
||||
};
|
||||
typedef struct lboot_params_hdr_st t_lboot_params_hdr;
|
||||
|
||||
|
||||
//специфические для tftp параметры
|
||||
struct st_lboot_specpar_tftp {
|
||||
uint16_t flags; //спец флаги (резерв)
|
||||
uint16_t server_port;
|
||||
uint8_t mac[6]; //mac-адрес
|
||||
uint8_t l_ip[4]; //свой ip-адрес
|
||||
uint8_t mask[4]; //mask - маска сети
|
||||
uint8_t gate[4]; //адрес шлюза
|
||||
uint8_t r_ip[4]; //адрес сервера tftp
|
||||
char filename[LBOOT_REQ_MAX_FILENAME_SIZE]; //имя файла с прошивкой
|
||||
uint16_t crc;
|
||||
};
|
||||
typedef struct st_lboot_specpar_tftp t_lboot_specpar_tftp;
|
||||
|
||||
//параметры для запроса прошивки по tftp
|
||||
struct st_lboot_params_tftp {
|
||||
t_lboot_params_hdr hdr;
|
||||
uint16_t tftp_flags; //спец флаги (резерв)
|
||||
uint16_t server_port;
|
||||
uint8_t mac[6]; //mac-адрес
|
||||
uint8_t l_ip[4]; //свой ip-адрес
|
||||
uint8_t mask[4]; //mask - маска сети
|
||||
uint8_t gate[4]; //адрес шлюза
|
||||
uint8_t r_ip[4]; //адрес сервера tftp
|
||||
char filename[LBOOT_REQ_MAX_FILENAME_SIZE]; //имя файла с прошивкой
|
||||
uint16_t crc;
|
||||
};
|
||||
typedef struct st_lboot_params_tftp t_lboot_params_tftp;
|
||||
|
||||
|
||||
|
||||
struct st_lboot_specpar_modbus_rtu {
|
||||
uint16_t flags ; //спец флаги
|
||||
uint8_t addr ; //адрес устройства в modbus сети
|
||||
uint8_t parity ;
|
||||
uint16_t res ;
|
||||
uint32_t baud_rate; //скорость передачи по rs-485/232
|
||||
uint16_t crc;
|
||||
};
|
||||
typedef struct st_lboot_specpar_modbus_rtu t_lboot_specpar_modbus_rtu;
|
||||
|
||||
//параметры для перепрошивки по Modbus RTU
|
||||
struct st_lboot_params_modbus_rtu {
|
||||
t_lboot_params_hdr hdr ;
|
||||
uint16_t flags ; //спец флаги
|
||||
uint8_t addr ; //адрес устройства в modbus сети
|
||||
uint8_t parity ;
|
||||
uint16_t res ;
|
||||
uint32_t baud_rate; //скорость передачи по rs-485/232
|
||||
uint16_t crc;
|
||||
};
|
||||
typedef struct st_lboot_params_modbus_rtu t_lboot_params_modbus_rtu;
|
||||
|
||||
|
||||
|
||||
struct st_lboot_specpar_usb {
|
||||
uint16_t flags ; //спец флаги
|
||||
uint16_t crc;
|
||||
};
|
||||
typedef struct st_lboot_specpar_usb t_lboot_specpar_usb;
|
||||
|
||||
//параметры для перепрошивки по USB
|
||||
struct st_lboot_params_usb {
|
||||
t_lboot_params_hdr hdr ;
|
||||
uint16_t flags ; //спец флаги
|
||||
uint16_t crc;
|
||||
};
|
||||
typedef struct st_lboot_params_usb t_lboot_params_usb;
|
||||
|
||||
struct st_lboot_specpar_can_lss {
|
||||
uint16_t flags;
|
||||
uint8_t br_index; /* BaudRate Index */
|
||||
uint8_t res;
|
||||
uint32_t vid;
|
||||
uint32_t pid;
|
||||
uint32_t rev;
|
||||
uint16_t crc;
|
||||
};
|
||||
typedef struct st_lboot_specpar_can_lss t_lboot_specpar_can_lss;
|
||||
|
||||
struct st_lboot_params_can_lss {
|
||||
t_lboot_params_hdr hdr;
|
||||
t_lboot_specpar_can_lss can;
|
||||
};
|
||||
typedef struct st_lboot_params_can_lss t_lboot_params_can_lss;
|
||||
|
||||
|
||||
|
||||
struct st_lboot_params {
|
||||
t_lboot_params_hdr hdr ;
|
||||
union {
|
||||
t_lboot_specpar_tftp tftp;
|
||||
t_lboot_specpar_modbus_rtu mbrtu;
|
||||
t_lboot_specpar_usb usb;
|
||||
t_lboot_specpar_can_lss can;
|
||||
};
|
||||
};
|
||||
typedef struct st_lboot_params t_lboot_params;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* LBOOT_REQ_H_ */
|
||||
810
x502/lcard_pstdint.h
Normal file
810
x502/lcard_pstdint.h
Normal file
@ -0,0 +1,810 @@
|
||||
/* A portable stdint.h
|
||||
****************************************************************************
|
||||
* BSD License:
|
||||
****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2005-2011 Paul Hsieh
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
* Version 0.1.12
|
||||
*
|
||||
* The ANSI C standard committee, for the C99 standard, specified the
|
||||
* inclusion of a new standard include file called stdint.h. This is
|
||||
* a very useful and long desired include file which contains several
|
||||
* very precise definitions for integer scalar types that is
|
||||
* critically important for making portable several classes of
|
||||
* applications including cryptography, hashing, variable length
|
||||
* integer libraries and so on. But for most developers its likely
|
||||
* useful just for programming sanity.
|
||||
*
|
||||
* The problem is that most compiler vendors have decided not to
|
||||
* implement the C99 standard, and the next C++ language standard
|
||||
* (which has a lot more mindshare these days) will be a long time in
|
||||
* coming and its unknown whether or not it will include stdint.h or
|
||||
* how much adoption it will have. Either way, it will be a long time
|
||||
* before all compilers come with a stdint.h and it also does nothing
|
||||
* for the extremely large number of compilers available today which
|
||||
* do not include this file, or anything comparable to it.
|
||||
*
|
||||
* So that's what this file is all about. Its an attempt to build a
|
||||
* single universal include file that works on as many platforms as
|
||||
* possible to deliver what stdint.h is supposed to. A few things
|
||||
* that should be noted about this file:
|
||||
*
|
||||
* 1) It is not guaranteed to be portable and/or present an identical
|
||||
* interface on all platforms. The extreme variability of the
|
||||
* ANSI C standard makes this an impossibility right from the
|
||||
* very get go. Its really only meant to be useful for the vast
|
||||
* majority of platforms that possess the capability of
|
||||
* implementing usefully and precisely defined, standard sized
|
||||
* integer scalars. Systems which are not intrinsically 2s
|
||||
* complement may produce invalid constants.
|
||||
*
|
||||
* 2) There is an unavoidable use of non-reserved symbols.
|
||||
*
|
||||
* 3) Other standard include files are invoked.
|
||||
*
|
||||
* 4) This file may come in conflict with future platforms that do
|
||||
* include stdint.h. The hope is that one or the other can be
|
||||
* used with no real difference.
|
||||
*
|
||||
* 5) In the current verison, if your platform can't represent
|
||||
* int32_t, int16_t and int8_t, it just dumps out with a compiler
|
||||
* error.
|
||||
*
|
||||
* 6) 64 bit integers may or may not be defined. Test for their
|
||||
* presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX.
|
||||
* Note that this is different from the C99 specification which
|
||||
* requires the existence of 64 bit support in the compiler. If
|
||||
* this is not defined for your platform, yet it is capable of
|
||||
* dealing with 64 bits then it is because this file has not yet
|
||||
* been extended to cover all of your system's capabilities.
|
||||
*
|
||||
* 7) (u)intptr_t may or may not be defined. Test for its presence
|
||||
* with the test: #ifdef PTRDIFF_MAX. If this is not defined
|
||||
* for your platform, then it is because this file has not yet
|
||||
* been extended to cover all of your system's capabilities, not
|
||||
* because its optional.
|
||||
*
|
||||
* 8) The following might not been defined even if your platform is
|
||||
* capable of defining it:
|
||||
*
|
||||
* WCHAR_MIN
|
||||
* WCHAR_MAX
|
||||
* (u)int64_t
|
||||
* PTRDIFF_MIN
|
||||
* PTRDIFF_MAX
|
||||
* (u)intptr_t
|
||||
*
|
||||
* 9) The following have not been defined:
|
||||
*
|
||||
* WINT_MIN
|
||||
* WINT_MAX
|
||||
*
|
||||
* 10) The criteria for defining (u)int_least(*)_t isn't clear,
|
||||
* except for systems which don't have a type that precisely
|
||||
* defined 8, 16, or 32 bit types (which this include file does
|
||||
* not support anyways). Default definitions have been given.
|
||||
*
|
||||
* 11) The criteria for defining (u)int_fast(*)_t isn't something I
|
||||
* would trust to any particular compiler vendor or the ANSI C
|
||||
* committee. It is well known that "compatible systems" are
|
||||
* commonly created that have very different performance
|
||||
* characteristics from the systems they are compatible with,
|
||||
* especially those whose vendors make both the compiler and the
|
||||
* system. Default definitions have been given, but its strongly
|
||||
* recommended that users never use these definitions for any
|
||||
* reason (they do *NOT* deliver any serious guarantee of
|
||||
* improved performance -- not in this file, nor any vendor's
|
||||
* stdint.h).
|
||||
*
|
||||
* 12) The following macros:
|
||||
*
|
||||
* PRINTF_INTMAX_MODIFIER
|
||||
* PRINTF_INT64_MODIFIER
|
||||
* PRINTF_INT32_MODIFIER
|
||||
* PRINTF_INT16_MODIFIER
|
||||
* PRINTF_LEAST64_MODIFIER
|
||||
* PRINTF_LEAST32_MODIFIER
|
||||
* PRINTF_LEAST16_MODIFIER
|
||||
* PRINTF_INTPTR_MODIFIER
|
||||
*
|
||||
* are strings which have been defined as the modifiers required
|
||||
* for the "d", "u" and "x" printf formats to correctly output
|
||||
* (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t,
|
||||
* (u)least32_t, (u)least16_t and (u)intptr_t types respectively.
|
||||
* PRINTF_INTPTR_MODIFIER is not defined for some systems which
|
||||
* provide their own stdint.h. PRINTF_INT64_MODIFIER is not
|
||||
* defined if INT64_MAX is not defined. These are an extension
|
||||
* beyond what C99 specifies must be in stdint.h.
|
||||
*
|
||||
* In addition, the following macros are defined:
|
||||
*
|
||||
* PRINTF_INTMAX_HEX_WIDTH
|
||||
* PRINTF_INT64_HEX_WIDTH
|
||||
* PRINTF_INT32_HEX_WIDTH
|
||||
* PRINTF_INT16_HEX_WIDTH
|
||||
* PRINTF_INT8_HEX_WIDTH
|
||||
* PRINTF_INTMAX_DEC_WIDTH
|
||||
* PRINTF_INT64_DEC_WIDTH
|
||||
* PRINTF_INT32_DEC_WIDTH
|
||||
* PRINTF_INT16_DEC_WIDTH
|
||||
* PRINTF_INT8_DEC_WIDTH
|
||||
*
|
||||
* Which specifies the maximum number of characters required to
|
||||
* print the number of that type in either hexadecimal or decimal.
|
||||
* These are an extension beyond what C99 specifies must be in
|
||||
* stdint.h.
|
||||
*
|
||||
* Compilers tested (all with 0 warnings at their highest respective
|
||||
* settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32
|
||||
* bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio
|
||||
* .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3
|
||||
*
|
||||
* This file should be considered a work in progress. Suggestions for
|
||||
* improvements, especially those which increase coverage are strongly
|
||||
* encouraged.
|
||||
*
|
||||
* Acknowledgements
|
||||
*
|
||||
* The following people have made significant contributions to the
|
||||
* development and testing of this file:
|
||||
*
|
||||
* Chris Howie
|
||||
* John Steele Scott
|
||||
* Dave Thorup
|
||||
* John Dill
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LCARD_PSTDINT
|
||||
#define LCARD_PSTDINT
|
||||
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
|
||||
/*
|
||||
* For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and
|
||||
* do nothing else. On the Mac OS X version of gcc this is _STDINT_H_.
|
||||
*/
|
||||
|
||||
#if ((defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) \
|
||||
|| (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || (__WATCOMC__ >= 1250))) \
|
||||
|| (defined(__GNUC__)) \
|
||||
|| (defined (_MSC_VER) && (_MSC_VER >= 1600)) \
|
||||
|| (defined (__BORLANDC__) && (__BORLANDC__ >= 0x560))) && !defined (_PSTDINT_H_INCLUDED)
|
||||
#include <stdint.h>
|
||||
#define _PSTDINT_H_INCLUDED
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "ll"
|
||||
# endif
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER "l"
|
||||
# endif
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER "h"
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_MODIFIER
|
||||
# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
|
||||
# endif
|
||||
# ifndef PRINTF_INT64_HEX_WIDTH
|
||||
# define PRINTF_INT64_HEX_WIDTH "16"
|
||||
# endif
|
||||
# ifndef PRINTF_INT32_HEX_WIDTH
|
||||
# define PRINTF_INT32_HEX_WIDTH "8"
|
||||
# endif
|
||||
# ifndef PRINTF_INT16_HEX_WIDTH
|
||||
# define PRINTF_INT16_HEX_WIDTH "4"
|
||||
# endif
|
||||
# ifndef PRINTF_INT8_HEX_WIDTH
|
||||
# define PRINTF_INT8_HEX_WIDTH "2"
|
||||
# endif
|
||||
# ifndef PRINTF_INT64_DEC_WIDTH
|
||||
# define PRINTF_INT64_DEC_WIDTH "20"
|
||||
# endif
|
||||
# ifndef PRINTF_INT32_DEC_WIDTH
|
||||
# define PRINTF_INT32_DEC_WIDTH "10"
|
||||
# endif
|
||||
# ifndef PRINTF_INT16_DEC_WIDTH
|
||||
# define PRINTF_INT16_DEC_WIDTH "5"
|
||||
# endif
|
||||
# ifndef PRINTF_INT8_DEC_WIDTH
|
||||
# define PRINTF_INT8_DEC_WIDTH "3"
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_HEX_WIDTH
|
||||
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_DEC_WIDTH
|
||||
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
|
||||
# endif
|
||||
|
||||
/*
|
||||
* Something really weird is going on with Open Watcom. Just pull some of
|
||||
* these duplicated definitions from Open Watcom's stdint.h file for now.
|
||||
*/
|
||||
|
||||
# if defined (__WATCOMC__) && __WATCOMC__ >= 1250
|
||||
# if !defined (INT64_C)
|
||||
# define INT64_C(x) (x + (INT64_MAX - INT64_MAX))
|
||||
# endif
|
||||
# if !defined (UINT64_C)
|
||||
# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX))
|
||||
# endif
|
||||
# if !defined (INT32_C)
|
||||
# define INT32_C(x) (x + (INT32_MAX - INT32_MAX))
|
||||
# endif
|
||||
# if !defined (UINT32_C)
|
||||
# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX))
|
||||
# endif
|
||||
# if !defined (INT16_C)
|
||||
# define INT16_C(x) (x)
|
||||
# endif
|
||||
# if !defined (UINT16_C)
|
||||
# define UINT16_C(x) (x)
|
||||
# endif
|
||||
# if !defined (INT8_C)
|
||||
# define INT8_C(x) (x)
|
||||
# endif
|
||||
# if !defined (UINT8_C)
|
||||
# define UINT8_C(x) (x)
|
||||
# endif
|
||||
# if !defined (UINT64_MAX)
|
||||
# define UINT64_MAX 18446744073709551615ULL
|
||||
# endif
|
||||
# if !defined (INT64_MAX)
|
||||
# define INT64_MAX 9223372036854775807LL
|
||||
# endif
|
||||
# if !defined (UINT32_MAX)
|
||||
# define UINT32_MAX 4294967295UL
|
||||
# endif
|
||||
# if !defined (INT32_MAX)
|
||||
# define INT32_MAX 2147483647L
|
||||
# endif
|
||||
# if !defined (INTMAX_MAX)
|
||||
# define INTMAX_MAX INT64_MAX
|
||||
# endif
|
||||
# if !defined (INTMAX_MIN)
|
||||
# define INTMAX_MIN INT64_MIN
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef _PSTDINT_H_INCLUDED
|
||||
#define _PSTDINT_H_INCLUDED
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX (~(size_t)0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Deduce the type assignments from limits.h under the assumption that
|
||||
* integer sizes in bits are powers of 2, and follow the ANSI
|
||||
* definitions.
|
||||
*/
|
||||
|
||||
#ifndef UINT8_MAX
|
||||
# define UINT8_MAX 0xff
|
||||
#endif
|
||||
#ifndef uint8_t
|
||||
# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S)
|
||||
typedef unsigned char uint8_t;
|
||||
# define UINT8_C(v) ((uint8_t) v)
|
||||
# else
|
||||
# error "Platform not supported"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef INT8_MAX
|
||||
# define INT8_MAX 0x7f
|
||||
#endif
|
||||
#ifndef INT8_MIN
|
||||
# define INT8_MIN INT8_C(0x80)
|
||||
#endif
|
||||
#ifndef int8_t
|
||||
# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S)
|
||||
typedef signed char int8_t;
|
||||
# define INT8_C(v) ((int8_t) v)
|
||||
# else
|
||||
# error "Platform not supported"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef UINT16_MAX
|
||||
# define UINT16_MAX 0xffff
|
||||
#endif
|
||||
#ifndef uint16_t
|
||||
#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S)
|
||||
typedef unsigned int uint16_t;
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER ""
|
||||
# endif
|
||||
# define UINT16_C(v) ((uint16_t) (v))
|
||||
#elif (USHRT_MAX == UINT16_MAX)
|
||||
typedef unsigned short uint16_t;
|
||||
# define UINT16_C(v) ((uint16_t) (v))
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER "h"
|
||||
# endif
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef INT16_MAX
|
||||
# define INT16_MAX 0x7fff
|
||||
#endif
|
||||
#ifndef INT16_MIN
|
||||
# define INT16_MIN INT16_C(0x8000)
|
||||
#endif
|
||||
#ifndef int16_t
|
||||
#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S)
|
||||
typedef signed int int16_t;
|
||||
# define INT16_C(v) ((int16_t) (v))
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER ""
|
||||
# endif
|
||||
#elif (SHRT_MAX == INT16_MAX)
|
||||
typedef signed short int16_t;
|
||||
# define INT16_C(v) ((int16_t) (v))
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER "h"
|
||||
# endif
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef UINT32_MAX
|
||||
# define UINT32_MAX (0xffffffffUL)
|
||||
#endif
|
||||
#ifndef uint32_t
|
||||
#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S)
|
||||
typedef unsigned long uint32_t;
|
||||
# define UINT32_C(v) v ## UL
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER "l"
|
||||
# endif
|
||||
#elif (UINT_MAX == UINT32_MAX)
|
||||
typedef unsigned int uint32_t;
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
# endif
|
||||
# define UINT32_C(v) v ## U
|
||||
#elif (USHRT_MAX == UINT32_MAX)
|
||||
typedef unsigned short uint32_t;
|
||||
# define UINT32_C(v) ((unsigned short) (v))
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
# endif
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef INT32_MAX
|
||||
# define INT32_MAX (0x7fffffffL)
|
||||
#endif
|
||||
#ifndef INT32_MIN
|
||||
# define INT32_MIN INT32_C(0x80000000)
|
||||
#endif
|
||||
#ifndef int32_t
|
||||
#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S)
|
||||
typedef signed long int32_t;
|
||||
# define INT32_C(v) v ## L
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER "l"
|
||||
# endif
|
||||
#elif (INT_MAX == INT32_MAX)
|
||||
typedef signed int int32_t;
|
||||
# define INT32_C(v) v
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
# endif
|
||||
#elif (SHRT_MAX == INT32_MAX)
|
||||
typedef signed short int32_t;
|
||||
# define INT32_C(v) ((short) (v))
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
# endif
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The macro stdint_int64_defined is temporarily used to record
|
||||
* whether or not 64 integer support is available. It must be
|
||||
* defined for any 64 integer extensions for new platforms that are
|
||||
* added.
|
||||
*/
|
||||
|
||||
#undef stdint_int64_defined
|
||||
#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S)
|
||||
# if (__STDC__ && __STDC_VERSION__ >= 199901L) || defined (S_SPLINT_S)
|
||||
# define stdint_int64_defined
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
# define UINT64_C(v) v ## ULL
|
||||
# define INT64_C(v) v ## LL
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "ll"
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined (stdint_int64_defined)
|
||||
# if defined(__GNUC__)
|
||||
# define stdint_int64_defined
|
||||
__extension__ typedef long long int64_t;
|
||||
__extension__ typedef unsigned long long uint64_t;
|
||||
# define UINT64_C(v) v ## ULL
|
||||
# define INT64_C(v) v ## LL
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "ll"
|
||||
# endif
|
||||
# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S)
|
||||
# define stdint_int64_defined
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
# define UINT64_C(v) v ## ULL
|
||||
# define INT64_C(v) v ## LL
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "ll"
|
||||
# endif
|
||||
# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC)
|
||||
# define stdint_int64_defined
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
# define UINT64_C(v) v ## UI64
|
||||
# define INT64_C(v) v ## I64
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "I64"
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined (LONG_LONG_MAX) && defined (INT64_C)
|
||||
# define LONG_LONG_MAX INT64_C (9223372036854775807)
|
||||
#endif
|
||||
#ifndef ULONG_LONG_MAX
|
||||
# define ULONG_LONG_MAX UINT64_C (18446744073709551615)
|
||||
#endif
|
||||
|
||||
#if !defined (INT64_MAX) && defined (INT64_C)
|
||||
# define INT64_MAX INT64_C (9223372036854775807)
|
||||
#endif
|
||||
#if !defined (INT64_MIN) && defined (INT64_C)
|
||||
# define INT64_MIN INT64_C (-9223372036854775808)
|
||||
#endif
|
||||
#if !defined (UINT64_MAX) && defined (INT64_C)
|
||||
# define UINT64_MAX UINT64_C (18446744073709551615)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Width of hexadecimal for number field.
|
||||
*/
|
||||
|
||||
#ifndef PRINTF_INT64_HEX_WIDTH
|
||||
# define PRINTF_INT64_HEX_WIDTH "16"
|
||||
#endif
|
||||
#ifndef PRINTF_INT32_HEX_WIDTH
|
||||
# define PRINTF_INT32_HEX_WIDTH "8"
|
||||
#endif
|
||||
#ifndef PRINTF_INT16_HEX_WIDTH
|
||||
# define PRINTF_INT16_HEX_WIDTH "4"
|
||||
#endif
|
||||
#ifndef PRINTF_INT8_HEX_WIDTH
|
||||
# define PRINTF_INT8_HEX_WIDTH "2"
|
||||
#endif
|
||||
|
||||
#ifndef PRINTF_INT64_DEC_WIDTH
|
||||
# define PRINTF_INT64_DEC_WIDTH "20"
|
||||
#endif
|
||||
#ifndef PRINTF_INT32_DEC_WIDTH
|
||||
# define PRINTF_INT32_DEC_WIDTH "10"
|
||||
#endif
|
||||
#ifndef PRINTF_INT16_DEC_WIDTH
|
||||
# define PRINTF_INT16_DEC_WIDTH "5"
|
||||
#endif
|
||||
#ifndef PRINTF_INT8_DEC_WIDTH
|
||||
# define PRINTF_INT8_DEC_WIDTH "3"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Ok, lets not worry about 128 bit integers for now. Moore's law says
|
||||
* we don't need to worry about that until about 2040 at which point
|
||||
* we'll have bigger things to worry about.
|
||||
*/
|
||||
|
||||
#ifdef stdint_int64_defined
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
# define INTMAX_MAX INT64_MAX
|
||||
# define INTMAX_MIN INT64_MIN
|
||||
# define UINTMAX_MAX UINT64_MAX
|
||||
# define UINTMAX_C(v) UINT64_C(v)
|
||||
# define INTMAX_C(v) INT64_C(v)
|
||||
# ifndef PRINTF_INTMAX_MODIFIER
|
||||
# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_HEX_WIDTH
|
||||
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_DEC_WIDTH
|
||||
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
|
||||
# endif
|
||||
#else
|
||||
typedef int32_t intmax_t;
|
||||
typedef uint32_t uintmax_t;
|
||||
# define INTMAX_MAX INT32_MAX
|
||||
# define UINTMAX_MAX UINT32_MAX
|
||||
# define UINTMAX_C(v) UINT32_C(v)
|
||||
# define INTMAX_C(v) INT32_C(v)
|
||||
# ifndef PRINTF_INTMAX_MODIFIER
|
||||
# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_HEX_WIDTH
|
||||
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_DEC_WIDTH
|
||||
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Because this file currently only supports platforms which have
|
||||
* precise powers of 2 as bit sizes for the default integers, the
|
||||
* least definitions are all trivial. Its possible that a future
|
||||
* version of this file could have different definitions.
|
||||
*/
|
||||
|
||||
#ifndef stdint_least_defined
|
||||
typedef int8_t int_least8_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER
|
||||
# define UINT_LEAST8_MAX UINT8_MAX
|
||||
# define INT_LEAST8_MAX INT8_MAX
|
||||
# define UINT_LEAST16_MAX UINT16_MAX
|
||||
# define INT_LEAST16_MAX INT16_MAX
|
||||
# define UINT_LEAST32_MAX UINT32_MAX
|
||||
# define INT_LEAST32_MAX INT32_MAX
|
||||
# define INT_LEAST8_MIN INT8_MIN
|
||||
# define INT_LEAST16_MIN INT16_MIN
|
||||
# define INT_LEAST32_MIN INT32_MIN
|
||||
# ifdef stdint_int64_defined
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER
|
||||
# define UINT_LEAST64_MAX UINT64_MAX
|
||||
# define INT_LEAST64_MAX INT64_MAX
|
||||
# define INT_LEAST64_MIN INT64_MIN
|
||||
# endif
|
||||
#endif
|
||||
#undef stdint_least_defined
|
||||
|
||||
/*
|
||||
* The ANSI C committee pretending to know or specify anything about
|
||||
* performance is the epitome of misguided arrogance. The mandate of
|
||||
* this file is to *ONLY* ever support that absolute minimum
|
||||
* definition of the fast integer types, for compatibility purposes.
|
||||
* No extensions, and no attempt to suggest what may or may not be a
|
||||
* faster integer type will ever be made in this file. Developers are
|
||||
* warned to stay away from these types when using this or any other
|
||||
* stdint.h.
|
||||
*/
|
||||
|
||||
typedef int_least8_t int_fast8_t;
|
||||
typedef uint_least8_t uint_fast8_t;
|
||||
typedef int_least16_t int_fast16_t;
|
||||
typedef uint_least16_t uint_fast16_t;
|
||||
typedef int_least32_t int_fast32_t;
|
||||
typedef uint_least32_t uint_fast32_t;
|
||||
#define UINT_FAST8_MAX UINT_LEAST8_MAX
|
||||
#define INT_FAST8_MAX INT_LEAST8_MAX
|
||||
#define UINT_FAST16_MAX UINT_LEAST16_MAX
|
||||
#define INT_FAST16_MAX INT_LEAST16_MAX
|
||||
#define UINT_FAST32_MAX UINT_LEAST32_MAX
|
||||
#define INT_FAST32_MAX INT_LEAST32_MAX
|
||||
#define INT_FAST8_MIN INT_LEAST8_MIN
|
||||
#define INT_FAST16_MIN INT_LEAST16_MIN
|
||||
#define INT_FAST32_MIN INT_LEAST32_MIN
|
||||
#ifdef stdint_int64_defined
|
||||
typedef int_least64_t int_fast64_t;
|
||||
typedef uint_least64_t uint_fast64_t;
|
||||
# define UINT_FAST64_MAX UINT_LEAST64_MAX
|
||||
# define INT_FAST64_MAX INT_LEAST64_MAX
|
||||
# define INT_FAST64_MIN INT_LEAST64_MIN
|
||||
#endif
|
||||
|
||||
#undef stdint_int64_defined
|
||||
|
||||
/*
|
||||
* Whatever piecemeal, per compiler thing we can do about the wchar_t
|
||||
* type limits.
|
||||
*/
|
||||
|
||||
#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__)
|
||||
# include <wchar.h>
|
||||
# ifndef WCHAR_MIN
|
||||
# define WCHAR_MIN 0
|
||||
# endif
|
||||
# ifndef WCHAR_MAX
|
||||
# define WCHAR_MAX ((wchar_t)-1)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Whatever piecemeal, per compiler/platform thing we can do about the
|
||||
* (u)intptr_t types and limits.
|
||||
*/
|
||||
|
||||
#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED)
|
||||
# define STDINT_H_UINTPTR_T_DEFINED
|
||||
#elif defined (_CVI_)
|
||||
# define STDINT_H_UINTPTR_T_DEFINED
|
||||
#endif
|
||||
|
||||
#ifndef STDINT_H_UINTPTR_T_DEFINED
|
||||
# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64)
|
||||
# define stdint_intptr_bits 64
|
||||
# elif defined (__WATCOMC__) || defined (__TURBOC__)
|
||||
# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)
|
||||
# define stdint_intptr_bits 16
|
||||
# else
|
||||
# define stdint_intptr_bits 32
|
||||
# endif
|
||||
# elif defined (__i386__) || defined (_WIN32) || defined (WIN32)
|
||||
# define stdint_intptr_bits 32
|
||||
# elif defined (__INTEL_COMPILER)
|
||||
/* TODO -- what did Intel do about x86-64? */
|
||||
# endif
|
||||
|
||||
# ifdef stdint_intptr_bits
|
||||
# define stdint_intptr_glue3_i(a,b,c) a##b##c
|
||||
# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c)
|
||||
# ifndef PRINTF_INTPTR_MODIFIER
|
||||
# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER)
|
||||
# endif
|
||||
# ifndef PTRDIFF_MAX
|
||||
# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
|
||||
# endif
|
||||
# ifndef PTRDIFF_MIN
|
||||
# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
|
||||
# endif
|
||||
# ifndef UINTPTR_MAX
|
||||
# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX)
|
||||
# endif
|
||||
# ifndef INTPTR_MAX
|
||||
# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
|
||||
# endif
|
||||
# ifndef INTPTR_MIN
|
||||
# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
|
||||
# endif
|
||||
# ifndef INTPTR_C
|
||||
# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x)
|
||||
# endif
|
||||
# ifndef UINTPTR_C
|
||||
# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x)
|
||||
# endif
|
||||
typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t;
|
||||
typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t;
|
||||
# else
|
||||
/* TODO -- This following is likely wrong for some platforms, and does
|
||||
nothing for the definition of uintptr_t. */
|
||||
typedef ptrdiff_t intptr_t;
|
||||
# endif
|
||||
# define STDINT_H_UINTPTR_T_DEFINED
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Assumes sig_atomic_t is signed and we have a 2s complement machine.
|
||||
*/
|
||||
|
||||
#ifndef SIG_ATOMIC_MAX
|
||||
# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (__TEST_PSTDINT_FOR_CORRECTNESS)
|
||||
|
||||
/*
|
||||
* Please compile with the maximum warning settings to make sure macros are not
|
||||
* defined more than once.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define glue3_aux(x,y,z) x ## y ## z
|
||||
#define glue3(x,y,z) glue3_aux(x,y,z)
|
||||
|
||||
#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,=) glue3(UINT,bits,_C) (0);
|
||||
#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,=) glue3(INT,bits,_C) (0);
|
||||
|
||||
#define DECL(us,bits) glue3(DECL,us,) (bits)
|
||||
|
||||
#define TESTUMAX(bits) glue3(u,bits,=) glue3(~,u,bits); if (glue3(UINT,bits,_MAX) glue3(!=,u,bits)) printf ("Something wrong with UINT%d_MAX\n", bits)
|
||||
|
||||
int main () {
|
||||
DECL(I,8)
|
||||
DECL(U,8)
|
||||
DECL(I,16)
|
||||
DECL(U,16)
|
||||
DECL(I,32)
|
||||
DECL(U,32)
|
||||
#ifdef INT64_MAX
|
||||
DECL(I,64)
|
||||
DECL(U,64)
|
||||
#endif
|
||||
intmax_t imax = INTMAX_C(0);
|
||||
uintmax_t umax = UINTMAX_C(0);
|
||||
char str0[256], str1[256];
|
||||
|
||||
sprintf (str0, "%d %x\n", 0, ~0);
|
||||
|
||||
sprintf (str1, "%d %x\n", i8, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with i8 : %s\n", str1);
|
||||
sprintf (str1, "%u %x\n", u8, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with u8 : %s\n", str1);
|
||||
sprintf (str1, "%d %x\n", i16, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with i16 : %s\n", str1);
|
||||
sprintf (str1, "%u %x\n", u16, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with u16 : %s\n", str1);
|
||||
sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with i32 : %s\n", str1);
|
||||
sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with u32 : %s\n", str1);
|
||||
#ifdef INT64_MAX
|
||||
sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with i64 : %s\n", str1);
|
||||
#endif
|
||||
sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with imax : %s\n", str1);
|
||||
sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with umax : %s\n", str1);
|
||||
|
||||
TESTUMAX(8);
|
||||
TESTUMAX(16);
|
||||
TESTUMAX(32);
|
||||
#ifdef INT64_MAX
|
||||
TESTUMAX(64);
|
||||
#endif
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
27
x502/osspec_cfg.h
Normal file
27
x502/osspec_cfg.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef OS_SPEC_CFG_H_
|
||||
#define OS_SPEC_CFG_H_
|
||||
|
||||
#include "x502api.h"
|
||||
|
||||
|
||||
//#define OSSPEC_USE_MUTEX
|
||||
//#define OSSPEC_USE_EVENTS
|
||||
//#define OSSPEC_USE_THREADS
|
||||
|
||||
|
||||
#define OSSPEC_ERR_MUTEX_INVALID_HANDLE X502_ERR_MUTEX_INVALID_HANDLE
|
||||
#define OSSPEC_ERR_MUTEX_LOCK_TOUT X502_ERR_MUTEX_LOCK_TOUT
|
||||
#define OSSPEC_ERR_MUTEX_RELEASE X502_ERR_MUTEX_RELEASE
|
||||
|
||||
|
||||
#define OSSPEC_ERR_EVENT_INVALID_HANDLE OSSPEC_ERR_MUTEX_INVALID_HANDLE
|
||||
#define OSSPEC_ERR_EVENT_WAIT_TOUT OSSPEC_ERR_MUTEX_LOCK_TOUT
|
||||
|
||||
|
||||
#define OSSPEC_ERR_THREAD_INVALID_HANDLE OSSPEC_ERR_MUTEX_INVALID_HANDLE
|
||||
#define OSSPEC_ERR_THREAD_WAIT_TOUT X502_ERR_THREAD_STOP
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
87
x502/x502_eeprom.h
Normal file
87
x502/x502_eeprom.h
Normal file
@ -0,0 +1,87 @@
|
||||
/***************************************************************************//**
|
||||
@file x502_eeprom.h
|
||||
@author Borisov Alexey <borisov@lcard.ru>
|
||||
@date 14.03.2011
|
||||
|
||||
Файл содержет описание констант и типов, для описание формата информации,
|
||||
записаной в EEPROM. Эти константы используются только внутри библиотеки и
|
||||
в специальном софте (для калибровки и обновлениия прошивки ПЛИС) и не
|
||||
доступны пользователю по-умолчанию
|
||||
******************************************************************************/
|
||||
#ifndef X502_EEPROM_H
|
||||
#define X502_EEPROM_H
|
||||
|
||||
|
||||
#define X502_EEPROM_CBR_SIGN 0x4C434352 //LCBR
|
||||
#define X502_EEPROM_CBR_FROMAT 2
|
||||
|
||||
#define X502_EEPROM_CBR_SRC_ADC 1
|
||||
#define X502_EEPROM_CBR_SRC_DAC 2
|
||||
|
||||
// TODO: это может быть проблемой для поддержки совместимости: E502-P1 флеш в 2 раза больше
|
||||
//#define X502_EEPROM_SIZE 0x400000UL
|
||||
// Устаревшая константа с размером внешней флеш памяти в байтах, надо использовать значения переменной из hnd->info.flash_size
|
||||
#define X502_EEPROM_SIZE 0x200000UL
|
||||
|
||||
#define X502_EEPROM_ADDR_DESCR 0x1F0000UL
|
||||
#define X502_DESCR_MAX_SIZE 0x010000UL
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define X502_EEPROM_FORMAT 1
|
||||
#define X502_DESCR_MIN_SIZE (sizeof(t_x502_eeprom_hdr)+4)
|
||||
#define X502_EEPROM_SIGN 0x4C524F4D
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t cbr_sign;
|
||||
uint32_t cbr_size;
|
||||
uint32_t format;
|
||||
uint32_t src;
|
||||
uint32_t flags;
|
||||
uint32_t reserv[3];
|
||||
uint64_t time;
|
||||
uint32_t channel_cnt;
|
||||
uint32_t range_cnt;
|
||||
} t_x502_eeprom_cbr_hdr;
|
||||
|
||||
typedef struct {
|
||||
t_x502_eeprom_cbr_hdr hdr;
|
||||
t_x502_cbr_coef coefs[X502_ADC_RANGE_CNT];
|
||||
} t_x502_eeprom_cbr_adc;
|
||||
|
||||
typedef struct {
|
||||
t_x502_eeprom_cbr_hdr hdr;
|
||||
t_x502_cbr_coef coefs[X502_DAC_CH_CNT];
|
||||
} t_x502_eeprom_cbr_dac;
|
||||
|
||||
typedef struct {
|
||||
uint32_t sign;
|
||||
uint32_t size;
|
||||
uint32_t format;
|
||||
char name[X502_DEVNAME_SIZE];
|
||||
char serial[X502_SERIAL_SIZE];
|
||||
uint8_t factory_mac[X502_MAC_ADDR_SIZE];
|
||||
char res[64-18];
|
||||
} t_x502_eeprom_hdr;
|
||||
|
||||
|
||||
typedef struct {
|
||||
t_x502_eeprom_hdr hdr;
|
||||
t_x502_eeprom_cbr_adc cbr_adc;
|
||||
t_x502_eeprom_cbr_dac cbr_dac;
|
||||
uint32_t crc;
|
||||
} t_x502_descr;
|
||||
|
||||
|
||||
typedef enum {
|
||||
X502_EEPROM_PROT_ALL = 0, /**< Защищена вся область памяти */
|
||||
X502_EEPROM_PROT_WR_USER = 1, /**< Разрешено изменение только пользовательской части */
|
||||
X502_EEPROM_PROT_WR_SETTINGS = 2, /**< Кроме пользовательской части, разрешено изменение
|
||||
области настроек, флага загрузки и второй копии прошивки ПЛИС */
|
||||
X502_EEPROM_PROT_WR_FPGA_FIRM = 3, /**< Разрешено изменение основной прошивки ПЛИС */
|
||||
X502_EEPROM_PROT_WR_ALL = 4, /**< Разрешена запись в любую область памяти */
|
||||
} t_x502_eeprom_prot_state;
|
||||
#endif // X502_EEPROM_H
|
||||
118
x502/x502_fpga_regs.h
Normal file
118
x502/x502_fpga_regs.h
Normal file
@ -0,0 +1,118 @@
|
||||
#ifndef X502_FPGA_REGS_H
|
||||
#define X502_FPGA_REGS_H
|
||||
|
||||
#define X502_BF_SDRAM_SIZE (32UL*1024*1024)
|
||||
|
||||
#define X502_BF_MEMADDR_CMD 0xFF800800
|
||||
|
||||
|
||||
#define X502_BF_CMD_READ 0x0001
|
||||
#define X502_BF_CMD_WRITE 0x0002
|
||||
#define X502_BF_CMD_HIRQ 0x0004
|
||||
#define X502_BF_CMD_HDMA_RST 0x0008
|
||||
|
||||
|
||||
|
||||
|
||||
/********************* Адреса регистров блока IOHARD **************************/
|
||||
#define X502_REGS_IOHARD_BLOCK 0x0200
|
||||
//Адрес Control Table
|
||||
#define X502_REGS_IOHARD_LTABLE (X502_REGS_IOHARD_BLOCK+0)
|
||||
#define X502_REGS_IOHARD_LTABLE_MAX_SIZE 0x100 // Максимальный размер Control Table
|
||||
|
||||
#define X502_REGS_IOHARD_LCH_CNT (X502_REGS_IOHARD_BLOCK+0x100)
|
||||
#define X502_REGS_IOHARD_ADC_FREQ_DIV (X502_REGS_IOHARD_BLOCK+0x102)
|
||||
#define X502_REGS_IOHARD_ADC_FRAME_DELAY (X502_REGS_IOHARD_BLOCK+0x104)
|
||||
#define X502_REGS_IOHARD_DIGIN_FREQ_DIV (X502_REGS_IOHARD_BLOCK+0x106)
|
||||
#define X502_REGS_IOHARD_IO_MODE (X502_REGS_IOHARD_BLOCK+0x108)
|
||||
#define X502_REGS_IOHARD_GO_SYNC_IO (X502_REGS_IOHARD_BLOCK+0x10A)
|
||||
#define X502_REGS_IOHARD_PRELOAD_ADC (X502_REGS_IOHARD_BLOCK+0x10C)
|
||||
#define X502_REGS_IOHARD_ASYNC_OUT (X502_REGS_IOHARD_BLOCK+0x112)
|
||||
#define X502_REGS_IOHARD_LED (X502_REGS_IOHARD_BLOCK+0x114)
|
||||
#define X502_REGS_IOHARD_DIGIN_PULLUP (X502_REGS_IOHARD_BLOCK+0x116)
|
||||
#define X502_REGS_IOHARD_OUTSWAP_BFCTL (X502_REGS_IOHARD_BLOCK+0x118)
|
||||
#define X502_REGS_IOHARD_OUTSWAP_ERROR (X502_REGS_IOHARD_BLOCK+0x120)
|
||||
|
||||
|
||||
|
||||
/********************* Адреса регистров блока IOARITH **************************/
|
||||
#define X502_REGS_IOARITH_BLOCK 0x0400
|
||||
#define X502_REGS_IOARITH_B10 X502_REGS_IOARITH_BLOCK
|
||||
#define X502_REGS_IOARITH_B5 (X502_REGS_IOARITH_BLOCK+0x01)
|
||||
#define X502_REGS_IOARITH_B2 (X502_REGS_IOARITH_BLOCK+0x02)
|
||||
#define X502_REGS_IOARITH_B1 (X502_REGS_IOARITH_BLOCK+0x03)
|
||||
#define X502_REGS_IOARITH_B05 (X502_REGS_IOARITH_BLOCK+0x04)
|
||||
#define X502_REGS_IOARITH_B02 (X502_REGS_IOARITH_BLOCK+0x05)
|
||||
#define X502_REGS_IOARITH_K10 (X502_REGS_IOARITH_BLOCK+0x08)
|
||||
#define X502_REGS_IOARITH_K5 (X502_REGS_IOARITH_BLOCK+0x09)
|
||||
#define X502_REGS_IOARITH_K2 (X502_REGS_IOARITH_BLOCK+0x0A)
|
||||
#define X502_REGS_IOARITH_K1 (X502_REGS_IOARITH_BLOCK+0x0B)
|
||||
#define X502_REGS_IOARITH_K05 (X502_REGS_IOARITH_BLOCK+0x0C)
|
||||
#define X502_REGS_IOARITH_K02 (X502_REGS_IOARITH_BLOCK+0x0D)
|
||||
#define X502_REGS_IOARITH_ADC_FREQ_DIV (X502_REGS_IOARITH_BLOCK+0x12)
|
||||
#define X502_REGS_IOARITH_THRESHOLD (X502_REGS_IOARITH_BLOCK+0x15)
|
||||
#define X502_REGS_IOARITH_N_CHAN_SYN (X502_REGS_IOARITH_BLOCK+0x16)
|
||||
#define X502_REGS_IOARITH_IN_STREAM_ENABLE (X502_REGS_IOARITH_BLOCK+0x19)
|
||||
#define X502_REGS_IOARITH_DIN_ASYNC (X502_REGS_IOARITH_BLOCK+0x1A)
|
||||
#define X502_REGS_IOARITH_SYNC_TYPE (X502_REGS_IOARITH_BLOCK+0x20)
|
||||
|
||||
|
||||
/********************* Адреса регистров блока управления BlackFin'ом **********/
|
||||
#define X502_REGS_BF_CTL_BLOCK 0
|
||||
#define X502_REGS_BF_CTL (X502_REGS_BF_CTL_BLOCK+0)
|
||||
#define X502_REGS_BF_CMD (X502_REGS_BF_CTL_BLOCK+1)
|
||||
#define X502_REGS_BF_STATUS (X502_REGS_BF_CTL_BLOCK+2)
|
||||
#define X502_REGS_BF_IRQ (X502_REGS_BF_CTL_BLOCK+3)
|
||||
#define X502_REGS_BF_IRQ_EN (X502_REGS_BF_CTL_BLOCK+4)
|
||||
#define X502_REGS_BF_REQ_ADDR (X502_REGS_BF_CTL_BLOCK+5)
|
||||
#define X502_REGS_BF_REQ_SIZE (X502_REGS_BF_CTL_BLOCK+6)
|
||||
#define X502_REGS_BF_REQ_DATA (X502_REGS_BF_CTL_BLOCK+128)
|
||||
|
||||
#define X502_BF_REQ_DATA_SIZE_MAX 128
|
||||
#define X502_BF_REQ_DATA_SIZE_MIN 8
|
||||
|
||||
|
||||
|
||||
|
||||
/* описание отдельных битов регистров */
|
||||
|
||||
#define X502_REGBIT_BF_STATUS_HWAIT_Pos 0
|
||||
#define X502_REGBIT_BF_STATUS_HWAIT_Msk (1UL << X502_REGBIT_BF_STATUS_HWAIT_Pos)
|
||||
|
||||
#define X502_REGBIT_BF_STATUS_BUSY_Pos 1
|
||||
#define X502_REGBIT_BF_STATUS_BUSY_Msk (1UL << X502_REGBIT_BF_STATUS_BUSY_Pos)
|
||||
|
||||
|
||||
|
||||
#define X502_REGBIT_BF_CTL_BF_RESET_Pos 1
|
||||
#define X502_REGBIT_BF_CTL_BF_RESET_Msk (0x1UL << X502_REGBIT_BF_CTL_BF_RESET_Pos)
|
||||
|
||||
|
||||
#define X502_REGBIT_BF_CTL_HOST_WAIT_Pos 3
|
||||
#define X502_REGBIT_BF_CTL_HOST_WAIT_Msk (0x1UL << X502_REGBIT_BF_CTL_HOST_WAIT_Pos)
|
||||
|
||||
#define X502_REGBIT_BF_CTL_DSP_MODE_Pos 4
|
||||
#define X502_REGBIT_BF_CTL_DSP_MODE_Msk (0x1UL << X502_REGBIT_BF_CTL_DSP_MODE_Pos)
|
||||
|
||||
#define X502_REGBIT_BF_CTL_DBG_MODE_Pos 5
|
||||
#define X502_REGBIT_BF_CTL_DBG_MODE_Msk (0x1UL << X502_REGBIT_BF_CTL_DBG_MODE_Pos)
|
||||
|
||||
#define X502_REGBIT_BF_CTL_CLK_DIV_Pos 8
|
||||
#define X502_REGBIT_BF_CTL_CLK_DIV_Msk (0xFUL << X502_REGBIT_BF_CTL_CLK_DIV_Pos)
|
||||
|
||||
#define X502_REGBIT_ADC_SLV_CLK_LOCK_Pos 31
|
||||
#define X502_REGBIT_ADC_SLV_CLK_LOCK_Msk (0x1UL << X502_REGBIT_ADC_SLV_CLK_LOCK_Pos)
|
||||
|
||||
#define X502_REGBIT_IOHARD_OUT_SWAP_Pos 0
|
||||
#define X502_REGBIT_IOHARD_OUT_SWAP_Msk (0x1UL << X502_REGBIT_IOHARD_OUT_SWAP_Pos)
|
||||
|
||||
#define X502_REGBIT_IOHARD_OUT_TFS_EN_Pos 1
|
||||
#define X502_REGBIT_IOHARD_OUT_TFS_EN_Msk (0x1UL << X502_REGBIT_IOHARD_OUT_TFS_EN_Pos)
|
||||
|
||||
#define X502_REGBIT_IOHARD_OUT_RING_Pos 2
|
||||
#define X502_REGBIT_IOHARD_OUT_RING_Msk (0x1UL << X502_REGBIT_IOHARD_OUT_RING_Pos)
|
||||
|
||||
#define X502_REGBIT_IOHARD_OUT_RFS_EN_Pos 3
|
||||
#define X502_REGBIT_IOHARD_OUT_RFS_EN_Msk (0x1UL << X502_REGBIT_IOHARD_OUT_RFS_EN_Pos)
|
||||
|
||||
#endif // E502_FPGA_REGS_H
|
||||
731
x502/x502api.c
Normal file
731
x502/x502api.c
Normal file
@ -0,0 +1,731 @@
|
||||
#include "x502api.h"
|
||||
#include "x502api_private.h"
|
||||
#include "x502_fpga_regs.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static const double f_x502_scales[] = {10., 5., 2., 1., 0.5, 0.2};
|
||||
// В E16 только 4 диапазона!
|
||||
static const double f_e16_scales[] = {10., 2.5, 0.625, 0.15625, 0., 0.};
|
||||
|
||||
|
||||
X502_EXPORT(double const*) E16_GetAdcRanges(uint32_t *ranges_len) {
|
||||
if (ranges_len) {
|
||||
*ranges_len = E16_ADC_RANGE_CNT;
|
||||
}
|
||||
return f_e16_scales;
|
||||
}
|
||||
|
||||
X502_EXPORT(double const*) E502_GetAdcRanges(uint32_t *ranges_len) {
|
||||
if (ranges_len) {
|
||||
*ranges_len = X502_ADC_RANGE_CNT;
|
||||
}
|
||||
return f_x502_scales;
|
||||
}
|
||||
|
||||
X502_EXPORT(double const*) X502_GetAdcRanges(t_x502_hnd hnd, uint32_t *ranges_len) {
|
||||
int32_t err = X502_CHECK_HND(hnd);
|
||||
if (err != X502_ERR_OK) {
|
||||
if (x502_is_E16(hnd)) {
|
||||
return E16_GetAdcRanges(ranges_len);
|
||||
} else {
|
||||
return E502_GetAdcRanges(ranges_len);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(t_x502_hnd) X502_Create(void) {
|
||||
t_x502_hnd hnd = calloc(sizeof(t_x502), 1);
|
||||
if (hnd != NULL) {
|
||||
hnd->sign = X502_SIGN;
|
||||
}
|
||||
|
||||
return hnd;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_Free(t_x502_hnd hnd) {
|
||||
int32_t err = X502_CHECK_HND(hnd);
|
||||
if (err == X502_ERR_OK) {
|
||||
if (hnd->flags & PRIV_FLAGS_OPENED)
|
||||
err = X502_Close(hnd);
|
||||
|
||||
hnd->sign = 0;
|
||||
free(hnd);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_Close(t_x502_hnd hnd) {
|
||||
int32_t err = X502_CHECK_HND(hnd);
|
||||
if ((err == X502_ERR_OK) && (hnd->flags & PRIV_FLAGS_OPENED)) {
|
||||
int32_t stop_err;
|
||||
if (hnd->flags & PRIV_FLAGS_STREAM_RUN) {
|
||||
/* остановка потока */
|
||||
err = X502_StreamsStop(hnd);
|
||||
}
|
||||
|
||||
hnd->flags &= ~PRIV_FLAGS_OPENED;
|
||||
|
||||
|
||||
stop_err = hnd->iface_hnd->close(hnd);
|
||||
if (err == X502_ERR_OK)
|
||||
err = stop_err;
|
||||
|
||||
if (hnd->mutex_cfg!=OSSPEC_INVALID_MUTEX) {
|
||||
stop_err = osspec_mutex_destroy(hnd->mutex_cfg);
|
||||
hnd->mutex_cfg = OSSPEC_INVALID_MUTEX;
|
||||
if (err == X502_ERR_OK)
|
||||
err = stop_err;
|
||||
}
|
||||
|
||||
if (hnd->mutex_bf!=OSSPEC_INVALID_MUTEX) {
|
||||
stop_err = osspec_mutex_destroy(hnd->mutex_bf);
|
||||
hnd->mutex_bf = OSSPEC_INVALID_MUTEX;
|
||||
if (err == X502_ERR_OK)
|
||||
err = stop_err;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_IsOpened(t_x502_hnd hnd) {
|
||||
int32_t err = X502_CHECK_HND(hnd);
|
||||
if ((err == X502_ERR_OK) && !(hnd->flags & PRIV_FLAGS_OPENED)) {
|
||||
err = X502_ERR_DEVICE_NOT_OPENED;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_OpenByDevRecord(t_x502* hnd, const t_x502_devrec *devrec) {
|
||||
int32_t err = X502_CHECK_HND(hnd);
|
||||
if ((err == X502_ERR_OK) && ((devrec==NULL) || (devrec->sign!=X502_DEVREC_SIGN)))
|
||||
err = X502_ERR_INVALID_DEVICE_RECORD;
|
||||
if (X502_IsOpened(hnd) == X502_ERR_OK) {
|
||||
X502_Close(hnd);
|
||||
}
|
||||
if (err == X502_ERR_OK) {
|
||||
hnd->iface_hnd = (const t_x502_dev_iface *)(devrec->internal->iface);
|
||||
memcpy(hnd->info.serial, devrec->serial, X502_SERIAL_SIZE);
|
||||
memcpy(hnd->info.name, devrec->devname, X502_DEVNAME_SIZE);
|
||||
hnd->iface = devrec->iface;
|
||||
hnd->info.devflags = devrec->flags;
|
||||
err = hnd->iface_hnd->open(hnd, devrec);
|
||||
if (err == X502_ERR_OK) {
|
||||
X502_SetLChannel(hnd, 0, 0, X502_LCH_MODE_COMM, X502_ADC_RANGE_10, 0);
|
||||
hnd->set.lch_cnt = 1;
|
||||
hnd->set.adc_frame_delay = 0;
|
||||
hnd->set.sync_mode = X502_SYNC_INTERNAL;
|
||||
hnd->set.sync_start_mode = X502_SYNC_INTERNAL;
|
||||
|
||||
|
||||
hnd->set.ext_ref_freq = 0;
|
||||
hnd->streams = 0;
|
||||
|
||||
if (x502_is_E16(hnd)) {
|
||||
hnd->set.ref_freq = E16_REF_FREQ_48000KHZ;
|
||||
hnd->set.dac_range = E16_DAC_RANGE;
|
||||
hnd->set.dac_code_max = E16_DAC_SCALE_CODE_MAX;
|
||||
hnd->set.adc_code_max = E16_ADC_SCALE_CODE_MAX;
|
||||
hnd->set.f_scales = f_e16_scales;
|
||||
|
||||
hnd->set.adc_freq_div = E16_REF_FREQ_48000KHZ / E16_ADC_FREQ_DEFAULT;
|
||||
hnd->set.din_freq_div = E16_REF_FREQ_48000KHZ / E16_DIN_FREQ_DEFAULT;
|
||||
hnd->set.out_freq_div = E16_REF_FREQ_48000KHZ / E16_OUT_FREQ_DEFAULT;
|
||||
} else {
|
||||
hnd->set.ref_freq = X502_REF_FREQ_2000KHZ;
|
||||
hnd->set.dac_range = X502_DAC_RANGE;
|
||||
hnd->set.dac_code_max = X502_DAC_SCALE_CODE_MAX;
|
||||
hnd->set.adc_code_max = X502_ADC_SCALE_CODE_MAX;
|
||||
hnd->set.f_scales = f_x502_scales;
|
||||
|
||||
hnd->set.adc_freq_div = 1;
|
||||
hnd->set.din_freq_div = 1;
|
||||
hnd->set.out_freq_div = 2;
|
||||
}
|
||||
|
||||
hnd->flags = PRIV_FLAGS_OPENED;
|
||||
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
hnd->mutex_bf = osspec_mutex_create();
|
||||
if (hnd->mutex_bf == OSSPEC_INVALID_MUTEX)
|
||||
err = X502_ERR_MUTEX_CREATE;
|
||||
} else {
|
||||
hnd->mutex_bf = OSSPEC_INVALID_MUTEX;
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
hnd->mutex_cfg = osspec_mutex_create();
|
||||
if (hnd->mutex_cfg == OSSPEC_INVALID_MUTEX)
|
||||
err = X502_ERR_MUTEX_CREATE;
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
if (!(hnd->info.devflags & X502_DEVFLAGS_FPGA_LOADED)) {
|
||||
err = X502_ERR_FPGA_NOT_LOADED;
|
||||
} else {
|
||||
|
||||
|
||||
/* определяем - в каком режиме работаем (BF или FPGA) */
|
||||
uint32_t bf_ctl;
|
||||
err = hnd->iface_hnd->fpga_reg_read(hnd, X502_REGS_BF_CTL, &bf_ctl);
|
||||
if (err == X502_ERR_OK) {
|
||||
uint32_t mode = bf_ctl;
|
||||
if (mode & X502_REGBIT_BF_CTL_DBG_MODE_Msk) {
|
||||
hnd->mode = X502_MODE_DEBUG;
|
||||
} else if (mode & X502_REGBIT_BF_CTL_DSP_MODE_Msk) {
|
||||
hnd->mode = X502_MODE_DSP;
|
||||
} else {
|
||||
hnd->mode = X502_MODE_FPGA;
|
||||
}
|
||||
|
||||
|
||||
if (hnd->mode==X502_MODE_DSP) {
|
||||
/* если blackfin находится в состоянии сброса, то возвращаемся в режим
|
||||
FPGA, т.к. все команды к HostDMA все равно не выполнятся */
|
||||
if (!(bf_ctl & X502_REGBIT_BF_CTL_BF_RESET_Msk)) {
|
||||
err = X502_SetMode(hnd, X502_MODE_FPGA);
|
||||
} else {
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_BF_CMD, X502_BF_CMD_HDMA_RST);
|
||||
/** @todo Для BlackFin проверить наличие прошивки */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* проверка захвата PLL (сейчас невозможна в режиме DSP) */
|
||||
if ((err == X502_ERR_OK) && (hnd->mode!=X502_MODE_DSP)) {
|
||||
uint32_t val;
|
||||
err = hnd->iface_hnd->fpga_reg_read(hnd, X502_REGS_IOHARD_IO_MODE, &val);
|
||||
if (err == X502_ERR_OK) {
|
||||
if (!(val & X502_REGBIT_ADC_SLV_CLK_LOCK_Msk)) {
|
||||
err = X502_ERR_REF_FREQ_NOT_LOCKED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* читаем информацию о версии прошивки ПЛИС'ов и наличии опций */
|
||||
if (err == X502_ERR_OK) {
|
||||
uint32_t hard_id=0;
|
||||
int32_t id_err = hnd->iface_hnd->fpga_reg_read(hnd, hnd->iface_hnd->id_reg_addr, &hard_id);
|
||||
if (id_err == X502_ERR_OK) {
|
||||
hnd->info.fpga_ver = (hard_id >> 16) & 0x7FFF;
|
||||
hnd->info.plda_ver = (hard_id >> 4) & 0xF;
|
||||
hnd->info.board_rev = (hard_id >> 8) & 0xF;
|
||||
FILL_HARD_ID_FLAGS(hnd->info.devflags, hard_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* если был запущен сбор - то останавливаем его */
|
||||
if ((err == X502_ERR_OK) && (hnd->mode==X502_MODE_FPGA)) {
|
||||
hnd->last_dout = 0;
|
||||
|
||||
if (hnd->iface_hnd->fpga_mode_init != NULL)
|
||||
err = hnd->iface_hnd->fpga_mode_init(hnd);
|
||||
|
||||
if (err == X502_ERR_OK)
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_GO_SYNC_IO, 0);
|
||||
|
||||
if (err == X502_ERR_OK)
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_OUTSWAP_BFCTL, 0);
|
||||
|
||||
if ((err == X502_ERR_OK) && (hnd->iface_hnd->stream_running != NULL)) {
|
||||
int32_t running;
|
||||
unsigned ch;
|
||||
for (ch=0; (ch < X502_STREAM_CH_CNT) && (err == X502_ERR_OK); ch++) {
|
||||
err = hnd->iface_hnd->stream_running(hnd, ch, &running);
|
||||
if ((err == X502_ERR_OK) && running) {
|
||||
err = hnd->iface_hnd->stream_stop(hnd, ch, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* читаем информацию из EEPROM (в первую очередь -
|
||||
калибровочные коэффициенты) */
|
||||
if (err == X502_ERR_OK || err == X502_ERR_FPGA_NOT_LOADED) {
|
||||
int i;
|
||||
|
||||
for (i=0; i < X502_ADC_RANGE_CNT; i++) {
|
||||
hnd->info.cbr.adc[i].offs = 0;
|
||||
hnd->info.cbr.adc[i].k = 1.;
|
||||
}
|
||||
|
||||
for (i=0; i < X502_DAC_CH_CNT; i++) {
|
||||
hnd->info.cbr.dac[i].offs = 0;
|
||||
hnd->info.cbr.dac[i].k = 1;
|
||||
}
|
||||
|
||||
x502_check_eeprom(hnd, 0);
|
||||
}
|
||||
|
||||
/* записываем конфигурацию по умолчанию, чтобы быть уверенным,
|
||||
что установлена нужная конфигурация */
|
||||
if ((err == X502_ERR_OK) && (hnd->mode==X502_MODE_FPGA))
|
||||
err = X502_Configure(hnd, 0);
|
||||
//if (!err)
|
||||
// err = _fpga_reg_write(hnd, L502_REGS_IOHARD_PRELOAD_ADC, 1);
|
||||
|
||||
if ((err != X502_ERR_OK) && (err != X502_ERR_FPGA_NOT_LOADED) && (err != X502_ERR_REF_FREQ_NOT_LOCKED))
|
||||
X502_Close(hnd);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_Open(t_x502_hnd hnd, const char* serial,
|
||||
const char *devname, t_x502_get_devinfo_list_cb get_list) {
|
||||
int32_t err = X502_CHECK_HND(hnd);
|
||||
int32_t get_info_res = 0;
|
||||
uint32_t fnd_cnt;
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
get_info_res = get_list(NULL, 0, 0, &fnd_cnt);
|
||||
if (get_info_res < 0) {
|
||||
err = get_info_res;
|
||||
} else if (!fnd_cnt) {
|
||||
err = X502_ERR_DEVICE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
t_x502_devrec *info_list = malloc(sizeof(t_x502_devrec)*fnd_cnt);
|
||||
if (info_list==NULL) {
|
||||
err = X502_ERR_MEMORY_ALLOC;
|
||||
} else {
|
||||
/* получаем информацию по всем устройствам драйвера lpcie */
|
||||
get_info_res = get_list(info_list, fnd_cnt, 0, NULL);
|
||||
if (get_info_res < 0) {
|
||||
err = get_info_res;
|
||||
} else {
|
||||
int32_t i, ser_size=0, fnd=0, open_err = 0;
|
||||
|
||||
if (serial!=NULL) {
|
||||
/* если серийный задан - смотрим его размер, отсекая
|
||||
* все что начинается с признака кноца строки */
|
||||
for (ser_size=0; (ser_size < X502_SERIAL_SIZE) &&
|
||||
!((serial[ser_size]=='\0') ||
|
||||
(serial[ser_size]=='\n') ||
|
||||
(serial[ser_size]=='\r')); ser_size++)
|
||||
{}
|
||||
}
|
||||
|
||||
for (i=0; !fnd && (i < get_info_res); i++) {
|
||||
/* ищем устройство L502 с совпадающим серийным */
|
||||
if (((devname==NULL) || !strcmp(info_list[i].devname, devname)) &&
|
||||
((ser_size==0) || !strncmp(serial, info_list[i].serial,
|
||||
ser_size))) {
|
||||
/* пробуем открыть устройство */
|
||||
err = X502_OpenByDevRecord(hnd, &info_list[i]);
|
||||
|
||||
/* если серийный номер не был указан, то сохраняем
|
||||
код ошибки и идем дальше, пробовать открыть
|
||||
следующее устройство */
|
||||
if (err && (ser_size==0)) {
|
||||
open_err = err;
|
||||
err = 0;
|
||||
} else {
|
||||
/* иначе заканчиваем поиск */
|
||||
fnd = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* если не нашли устройство - устанавливаем соотвествующий код
|
||||
ошибки */
|
||||
if (!fnd) {
|
||||
err = open_err ? open_err : X502_ERR_DEVICE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
X502_FreeDevRecordList(info_list, fnd_cnt);
|
||||
free(info_list);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_GetSerialList(char serials[][X502_SERIAL_SIZE], uint32_t size,
|
||||
uint32_t flags, uint32_t *devcnt, const char *devname,
|
||||
t_x502_get_devinfo_list_cb get_list) {
|
||||
uint32_t fnd_cnt=0, put_cnt=0;
|
||||
/* получаем количество устройств, поддерживаемых драйвером lpcie */
|
||||
int32_t res = get_list(NULL, 0, flags, &fnd_cnt);
|
||||
if ((res>=0) && fnd_cnt) {
|
||||
t_x502_devrec *info_list = malloc(sizeof(t_x502_devrec)*fnd_cnt);
|
||||
if (info_list==NULL) {
|
||||
res = X502_ERR_MEMORY_ALLOC;
|
||||
} else {
|
||||
/* получаем информацию по всем устройствам драйвера lpcie */
|
||||
res = get_list(info_list, fnd_cnt, flags, NULL);
|
||||
if (res>0) {
|
||||
int32_t i;
|
||||
for (i=0; i < res; i++) {
|
||||
/* проверяем, что это устройство - E502 */
|
||||
if (!strcmp(info_list[i].devname, devname)) {
|
||||
/* если есть место в списке, то сохраняем серийный номер
|
||||
устройства */
|
||||
if (put_cnt < size) {
|
||||
memcpy(serials[put_cnt], info_list[i].serial,
|
||||
X502_SERIAL_SIZE);
|
||||
}
|
||||
put_cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
X502_FreeDevRecordList(info_list, fnd_cnt);
|
||||
free(info_list);
|
||||
}
|
||||
}
|
||||
|
||||
if (devcnt != NULL)
|
||||
*devcnt = put_cnt;
|
||||
|
||||
return res < 0 ? res : put_cnt > size ? (int32_t)size : (int32_t)put_cnt;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_FreeDevRecordList(t_x502_devrec *list, uint32_t size) {
|
||||
uint32_t i;
|
||||
int32_t err = X502_ERR_OK;
|
||||
if (list!=NULL) {
|
||||
for (i=0; (i < size) && (err==X502_ERR_OK); i++) {
|
||||
if (list[i].sign!=X502_DEVREC_SIGN) {
|
||||
err = X502_ERR_INVALID_DEVICE_RECORD;
|
||||
} else {
|
||||
t_x502_devrec_inptr *devinfo_ptr = (t_x502_devrec_inptr*)list[i].internal;
|
||||
if (devinfo_ptr != NULL) {
|
||||
const t_x502_dev_iface *iface = (const t_x502_dev_iface *)devinfo_ptr->iface;
|
||||
if (iface!=NULL)
|
||||
iface->free_devinfo_ptr(devinfo_ptr);
|
||||
|
||||
}
|
||||
list[i].internal = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_GetDevInfo(t_x502_hnd hnd, t_x502_info* info) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if ((err == X502_ERR_OK) && (info==NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
|
||||
if (err == X502_ERR_OK)
|
||||
*info = hnd->info;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_GetNextExpectedLchNum(t_x502_hnd hnd, uint32_t *lch) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if ((err == X502_ERR_OK) && (lch==NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
if (err == X502_ERR_OK)
|
||||
*lch = hnd->proc_adc_ch;
|
||||
return err;
|
||||
}
|
||||
|
||||
#define STREAM_IN_WRD_TYPE(wrd) wrd & 0x80000000 ? STREAM_IN_WRD_ADC : \
|
||||
(wrd & 0xFF000000) == 0x0 ? STREAM_IN_WRD_DIN : \
|
||||
((wrd & 0xFF000000)>>24) == 0x01 ? STREAM_IN_WRD_MSG : STREAM_IN_WRD_USR
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_ProcessAdcData(t_x502_hnd hnd, const uint32_t* src, double *dest,
|
||||
uint32_t *size, uint32_t flags) {
|
||||
if (size == NULL)
|
||||
return X502_ERR_INVALID_POINTER;
|
||||
return X502_ProcessDataWithUserExt(hnd, src, *size, flags, dest, size,
|
||||
NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_ProcessData(t_x502_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) {
|
||||
return X502_ProcessDataWithUserExt(hnd, src, size, flags, adc_data, adc_data_size,
|
||||
din_data, din_data_size, NULL, NULL);
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_ProcessDataWithUserExt(t_x502_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) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if ((err == X502_ERR_OK) && (adc_data_size==NULL) && (adc_data!=NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
if ((err == X502_ERR_OK) && (din_data_size==NULL) && (din_data!=NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
if ((err == X502_ERR_OK) && (usr_data_size==NULL) && (usr_data!=NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
if (err == X502_ERR_OK) {
|
||||
uint32_t adc_cnt = 0, din_cnt=0, usr_cnt = 0;
|
||||
uint32_t i;
|
||||
|
||||
for (i=0; (i<size) && (err == X502_ERR_OK); i++) {
|
||||
register uint32_t wrd = src[i];
|
||||
t_stream_in_wrd_type type = STREAM_IN_WRD_TYPE(wrd);
|
||||
/* проверяем - это данные от АЦП или цифровых входов */
|
||||
switch (type) {
|
||||
case STREAM_IN_WRD_ADC: {
|
||||
uint32_t ch_num = (wrd >> 24) & 0xF;
|
||||
uint32_t ch_mode = (wrd >> 28) & 0x3;
|
||||
int32_t val;
|
||||
uint32_t range;
|
||||
|
||||
/* проверяем совпадение каналов */
|
||||
switch (ch_mode) {
|
||||
case 0:
|
||||
ch_mode = X502_LCH_MODE_DIFF;
|
||||
break;
|
||||
case 1:
|
||||
ch_mode = X502_LCH_MODE_COMM;
|
||||
break;
|
||||
case 2:
|
||||
ch_mode = X502_LCH_MODE_COMM;
|
||||
ch_num+=16;
|
||||
break;
|
||||
case 3:
|
||||
ch_mode = X502_LCH_MODE_ZERO;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(flags & X502_PROC_FLAGS_DONT_CHECK_CH) &&
|
||||
((hnd->set.lch[hnd->proc_adc_ch].mode != ch_mode) ||
|
||||
(hnd->set.lch[hnd->proc_adc_ch].ch != ch_num))) {
|
||||
err = X502_ERR_PROC_INVALID_CH_NUM;
|
||||
} else {
|
||||
/* проверяем формат - пришло откалиброванное 24-битное слово,
|
||||
или неоткалиброванное 16-битное */
|
||||
if (wrd & 0x40000000) {
|
||||
val = wrd & 0xFFFFFF;
|
||||
if (wrd & 0x800000)
|
||||
val |= 0xFF000000;
|
||||
|
||||
range = hnd->set.lch[hnd->proc_adc_ch].range;
|
||||
} else {
|
||||
range = (wrd >> 16) & 0x7;
|
||||
if (!(flags & X502_PROC_FLAGS_DONT_CHECK_CH) &&
|
||||
(range != hnd->set.lch[hnd->proc_adc_ch].range)) {
|
||||
err = X502_ERR_PROC_INVALID_CH_RANGE;
|
||||
} else {
|
||||
val = wrd & 0xFFFF;
|
||||
if (wrd & 0x8000)
|
||||
val |= 0xFFFF0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
double res_val = val;
|
||||
if (flags & X502_PROC_FLAGS_VOLT) {
|
||||
res_val = hnd->set.f_scales[range]*res_val/hnd->set.adc_code_max;
|
||||
}
|
||||
|
||||
|
||||
if ((adc_data!=NULL) && (adc_cnt<*adc_data_size)) {
|
||||
*adc_data++ = res_val;
|
||||
adc_cnt++;
|
||||
} else if (adc_data==NULL) {
|
||||
adc_cnt++;
|
||||
}
|
||||
|
||||
if (++hnd->proc_adc_ch ==hnd->set.lch_cnt)
|
||||
hnd->proc_adc_ch = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STREAM_IN_WRD_DIN:
|
||||
if ((din_data!=NULL) && (din_cnt<*din_data_size)) {
|
||||
*din_data++ = wrd & 0x3FFFF;
|
||||
din_cnt++;
|
||||
} else if (din_data==NULL) {
|
||||
din_cnt++;
|
||||
}
|
||||
break;
|
||||
case STREAM_IN_WRD_MSG:
|
||||
err = wrd==X502_STREAM_IN_MSG_OVERFLOW ? X502_ERR_STREAM_OVERFLOW :
|
||||
X502_ERR_UNSUP_STREAM_MSG;
|
||||
break;
|
||||
case STREAM_IN_WRD_USR:
|
||||
if ((usr_data!=NULL) && (usr_cnt<*usr_data_size)) {
|
||||
*usr_data++ = wrd;
|
||||
usr_cnt++;
|
||||
} else if (usr_data==NULL) {
|
||||
usr_cnt++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (adc_data_size!=NULL)
|
||||
*adc_data_size = adc_cnt;
|
||||
if (din_data_size!=NULL)
|
||||
*din_data_size = din_cnt;
|
||||
if (usr_data_size!=NULL)
|
||||
*usr_data_size = usr_cnt;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
uint32_t prepare_dac_wrd(t_x502_hnd hnd, double val, uint32_t flags, const t_x502_cbr_coef* coef) {
|
||||
uint16_t wrd = 0;
|
||||
if (flags & X502_DAC_FLAGS_VOLT) {
|
||||
val = (val / hnd->set.dac_range) * hnd->set.dac_code_max;
|
||||
}
|
||||
if (flags & X502_DAC_FLAGS_CALIBR) {
|
||||
val = (val + coef->offs) * coef->k;
|
||||
}
|
||||
if (val > SHRT_MAX) {
|
||||
wrd = SHRT_MAX;
|
||||
} else
|
||||
if (val < SHRT_MIN) {
|
||||
wrd = SHRT_MIN;
|
||||
} else {
|
||||
wrd = val;
|
||||
}
|
||||
return wrd;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_PrepareData(t_x502_hnd hnd, const double* dac1, const double* dac2,
|
||||
const uint32_t* digout, uint32_t size, int32_t flags,
|
||||
uint32_t* out_buf) {
|
||||
int err = X502_CHECK_HND_OPENED(hnd);
|
||||
if ((err == X502_ERR_OK) && (out_buf==NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
if ((err == X502_ERR_OK) && ((dac1==NULL) && (dac2==NULL) && (digout==NULL)))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
uint32_t i;
|
||||
for (i = 0; (i < size) && (err == X502_ERR_OK); i++) {
|
||||
if ((dac1 != NULL) && (hnd->streams & X502_STREAM_DAC1)) {
|
||||
uint32_t wrd = prepare_dac_wrd(hnd, *dac1++, flags, &hnd->info.cbr.dac[0]);
|
||||
*out_buf++ = wrd | X502_STREAM_OUT_WORD_TYPE_DAC1;
|
||||
}
|
||||
if ((dac2 != NULL) && (hnd->streams & X502_STREAM_DAC2)) {
|
||||
uint32_t wrd = prepare_dac_wrd(hnd, *dac2++, flags, &hnd->info.cbr.dac[1]);
|
||||
*out_buf++ = wrd | X502_STREAM_OUT_WORD_TYPE_DAC2;
|
||||
}
|
||||
if ((digout != NULL) && (hnd->streams & X502_STREAM_DOUT)) {
|
||||
uint32_t wrd = *digout++;
|
||||
*out_buf++ = (wrd &0x3FFFF)
|
||||
| X502_STREAM_OUT_WORD_TYPE_DOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_FpgaRegWrite(t_x502_hnd hnd, uint32_t reg, uint32_t val) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK) {
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, reg & 0xFFFF, val);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_FpgaRegRead(t_x502_hnd hnd, uint32_t reg, uint32_t *val) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK) {
|
||||
err = hnd->iface_hnd->fpga_reg_read(hnd, reg, val);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(uint32_t) X502_GetLibraryVersion(void) {
|
||||
return (X502API_VER_MAJOR << 24) | (X502API_VER_MINOR<<16) |
|
||||
(X502API_VER_PATCH << 8);
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_DevRecordInit(t_x502_devrec *rec) {
|
||||
if (rec!=NULL) {
|
||||
memset(rec, 0, sizeof(t_x502_devrec));
|
||||
rec->sign = X502_DEVREC_SIGN;
|
||||
}
|
||||
return X502_ERR_OK;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_LedBlink(t_x502_hnd hnd) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK) {
|
||||
int32_t err2;
|
||||
err = hnd->mode == X502_MODE_DSP ? bf_fpga_reg_wr(hnd, X502_REGS_IOHARD_LED, 0) :
|
||||
X502_FpgaRegWrite(hnd, X502_REGS_IOHARD_LED, 0);
|
||||
SLEEP_MS(200);
|
||||
err2 = hnd->mode == X502_MODE_DSP ? bf_fpga_reg_wr(hnd, X502_REGS_IOHARD_LED, 1) :
|
||||
X502_FpgaRegWrite(hnd, X502_REGS_IOHARD_LED, 1);
|
||||
if (err == X502_ERR_OK)
|
||||
err = err2;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetDigInPullup(t_x502_hnd hnd, uint32_t pullups) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK) {
|
||||
uint32_t val = 0;
|
||||
if (pullups & X502_PULLUPS_DI_L)
|
||||
val |= 0x1;
|
||||
if (pullups & X502_PULLUPS_DI_H)
|
||||
val |= 0x2;
|
||||
if (pullups & X502_PULLUPS_DI_SYN1)
|
||||
val |= 0x4;
|
||||
if (pullups & X502_PULLUPS_DI_SYN2)
|
||||
val |= 0x8;
|
||||
if (pullups & X502_PULLDOWN_CONV_IN)
|
||||
val |= 0x10;
|
||||
if (pullups & X502_PULLDOWN_START_IN)
|
||||
val |= 0x20;
|
||||
if (pullups & E16_MODE_RELAY_ON)
|
||||
val |= 0x40;
|
||||
|
||||
err = hnd->mode == X502_MODE_DSP ? bf_fpga_reg_wr(hnd, X502_REGS_IOHARD_DIGIN_PULLUP, val) :
|
||||
X502_FpgaRegWrite(hnd, X502_REGS_IOHARD_DIGIN_PULLUP, val);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_CheckFeature(t_x502_hnd hnd, uint32_t feature) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK) {
|
||||
err = hnd->iface_hnd->check_feature(hnd, feature);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
BOOL WINAPI DllMain(HINSTANCE hmod, DWORD reason, LPVOID resvd) {
|
||||
switch (reason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
2700
x502/x502api.h
Normal file
2700
x502/x502api.h
Normal file
File diff suppressed because it is too large
Load Diff
143
x502/x502api_async.c
Normal file
143
x502/x502api_async.c
Normal file
@ -0,0 +1,143 @@
|
||||
#include "x502api_private.h"
|
||||
#include "ltimer.h"
|
||||
|
||||
uint32_t prepare_dac_wrd(t_x502_hnd hnd, double val, uint32_t flags, const t_x502_cbr_coef* coef);
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_AsyncOutDac(t_x502_hnd hnd, uint32_t ch, double data, uint32_t flags) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (ch!=X502_DAC_CH1) && (ch!=X502_DAC_CH2))
|
||||
err = X502_ERR_INVALID_DAC_CHANNEL;
|
||||
if (!err && !(hnd->info.devflags & X502_DEVFLAGS_DAC_PRESENT))
|
||||
err = X502_ERR_DAC_NOT_PRESENT;
|
||||
if (!err) {
|
||||
uint32_t wr_val = prepare_dac_wrd(hnd, data, flags, &hnd->info.cbr.dac[ch]);
|
||||
|
||||
if (ch==X502_DAC_CH1) {
|
||||
wr_val |= X502_STREAM_OUT_WORD_TYPE_DAC1;
|
||||
} else {
|
||||
wr_val |= X502_STREAM_OUT_WORD_TYPE_DAC2;
|
||||
}
|
||||
|
||||
if (hnd->mode == X502_MODE_FPGA) {
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_ASYNC_OUT, wr_val);
|
||||
} else if (hnd->mode == X502_MODE_DSP) {
|
||||
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_ASYNC_OUT, ch==X502_DAC_CH1 ?
|
||||
L502_BF_CMD_ASYNC_TYPE_DAC1 : L502_BF_CMD_ASYNC_TYPE_DAC2,
|
||||
(uint32_t*)&wr_val, 1, NULL, 0, X502_BF_CMD_DEFAULT_TOUT, NULL);
|
||||
} else {
|
||||
err = X502_ERR_INVALID_MODE;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_AsyncOutDig(t_x502_hnd hnd, uint32_t val, uint32_t msk) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err) {
|
||||
if(hnd->mode == X502_MODE_FPGA) {
|
||||
err = osspec_mutex_lock(hnd->mutex_cfg, X502_MUTEX_CFG_LOCK_TOUT);
|
||||
if (!err) {
|
||||
int32_t release_err;
|
||||
/* маскированные биты берем из последнего выведенного значения */
|
||||
if (msk) {
|
||||
val = val & ~msk;
|
||||
val |= hnd->last_dout & msk;
|
||||
}
|
||||
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_ASYNC_OUT,
|
||||
val | X502_STREAM_OUT_WORD_TYPE_DOUT);
|
||||
/* сохраняем выведенное значения, для последующего использования
|
||||
в маске */
|
||||
if (!err)
|
||||
hnd->last_dout = val;
|
||||
|
||||
release_err = osspec_mutex_release(hnd->mutex_cfg);
|
||||
if (!err)
|
||||
err = release_err;
|
||||
}
|
||||
} else if (hnd->mode == X502_MODE_DSP) {
|
||||
uint32_t wrds[2] = {val, msk};
|
||||
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_ASYNC_OUT, L502_BF_CMD_ASYNC_TYPE_DOUT,
|
||||
wrds, 2, NULL, 0, X502_BF_CMD_DEFAULT_TOUT, NULL);
|
||||
} else {
|
||||
err = X502_ERR_INVALID_MODE;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int32_t f_read_digin(t_x502_hnd hnd, uint32_t* din) {
|
||||
int32_t err = 0;
|
||||
uint32_t val;
|
||||
int rdy=0;
|
||||
t_ltimer tmr;
|
||||
|
||||
/* читаем состояние входов, чтобы сбросить флаг готовности */
|
||||
if (!x502_is_E16(hnd)) {
|
||||
err = hnd->iface_hnd->fpga_reg_read(hnd, X502_REGS_IOARITH_DIN_ASYNC, &val);
|
||||
}
|
||||
|
||||
/* читаем синхронный ввод до готовности данных или пока не
|
||||
выйдем по таймауту*/
|
||||
ltimer_set(&tmr, LTIMER_MS_TO_CLOCK_TICKS(500));
|
||||
while (!rdy && !ltimer_expired(&tmr) && (err == X502_ERR_OK)) {
|
||||
err = hnd->iface_hnd->fpga_reg_read(hnd, X502_REGS_IOARITH_DIN_ASYNC, &val);
|
||||
if (!err && (val & 0x80000000)) {
|
||||
rdy = 1;
|
||||
*din = (val & 0x3FFFF);
|
||||
}
|
||||
}
|
||||
|
||||
if (!err && !rdy)
|
||||
err = X502_ERR_DIG_IN_NOT_RDY;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_AsyncInDig(t_x502_hnd hnd, uint32_t* din) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err & (din==NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
if (!err)
|
||||
err = osspec_mutex_lock(hnd->mutex_cfg, X502_MUTEX_CFG_LOCK_TOUT);
|
||||
if (!err) {
|
||||
if (x502_is_E16(hnd)) {
|
||||
err = f_read_digin(hnd, din);
|
||||
} else if (hnd->mode == X502_MODE_FPGA) {
|
||||
if (hnd->flags & PRIV_FLAGS_STREAM_RUN) {
|
||||
err = f_read_digin(hnd, din);
|
||||
} else {
|
||||
/* запрещаем прием данных */
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOARITH_IN_STREAM_ENABLE, 0);
|
||||
if (!err) {
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_PRELOAD_ADC, 1);
|
||||
if (!err) {
|
||||
/* запускаем чтение цифровых входов */
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_GO_SYNC_IO, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
int32_t stop_err;
|
||||
err = f_read_digin(hnd, din);
|
||||
|
||||
/* останавливаем сбор данных */
|
||||
stop_err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_GO_SYNC_IO, 0);
|
||||
if (!err)
|
||||
err = stop_err;
|
||||
}
|
||||
}
|
||||
} else if (hnd->mode == X502_MODE_DSP) {
|
||||
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_ASYNC_DIG_IN,
|
||||
0, NULL, 0, din, 1, X502_BF_CMD_DEFAULT_TOUT, NULL);
|
||||
} else {
|
||||
err = X502_ERR_INVALID_MODE;
|
||||
}
|
||||
osspec_mutex_release(hnd->mutex_cfg);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
391
x502/x502api_bf.c
Normal file
391
x502/x502api_bf.c
Normal file
@ -0,0 +1,391 @@
|
||||
#include "x502api_private.h"
|
||||
#include "ltimer.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BF_LDR_HDR_SIZE (16)
|
||||
#define BF_LDR_HDRSGN (0xAD)
|
||||
|
||||
#define BF_LDR_HDRPOS_SGN (3)
|
||||
|
||||
#define BF_LDR_FLAG_SAVE (0x0010) //не используется
|
||||
#define BF_LDR_FLAG_AUX (0x0020) //не используется
|
||||
#define BF_LDR_FLAG_FILL (0x0100)
|
||||
#define BF_LDR_FLAG_QUICKBOOT (0x0200) //не используется
|
||||
#define BF_LDR_FLAG_CALLBACK (0x0400) //не используется
|
||||
#define BF_LDR_FLAG_INIT (0x0800) //не используется
|
||||
#define BF_LDR_FLAG_IGNORE (0x1000)
|
||||
#define BF_LDR_FLAG_INDIRECT (0x2000) //не используется
|
||||
#define BF_LDR_FLAG_FIRST (0x4000)
|
||||
#define BF_LDR_FLAG_FINAL (0x8000)
|
||||
|
||||
#define BF_WAIT_LOAD_RDY_TOUT 500
|
||||
#define BF_MUTEX_LOCK_TOUT 1000
|
||||
|
||||
#define LDR_BUFF_SIZE 4096
|
||||
|
||||
|
||||
|
||||
#define BF_CHECK_ADDR(addr) (((addr) < 0xFFA0C000) && ((addr)>= 0xFFA0000)) || \
|
||||
(((addr) < 0xFF908000) && ((addr) >=0xFF900000)) || \
|
||||
(((addr) < 0xFF808000) && ((addr) >=0xFF800000)) || \
|
||||
(((addr) < 0x2000000)) ? 0 : X502_ERR_BF_INVALID_ADDR
|
||||
|
||||
#define BF_CHECK_ADDR_SIZE(addr, size) BF_CHECK_ADDR(addr) ? X502_ERR_BF_INVALID_ADDR : \
|
||||
BF_CHECK_ADDR(addr+size*4-1) ? X502_ERR_BF_INVALID_ADDR : 0
|
||||
|
||||
|
||||
#define BF_CMD_FIRST_DATA_BLOCK_SIZE ((X502_BF_REQ_DATA_SIZE_MAX-offsetof(t_l502_bf_cmd, data))/4)
|
||||
|
||||
typedef struct st_bf_ldr_pkt {
|
||||
uint8_t res;
|
||||
uint8_t dma_mode;
|
||||
uint16_t flags;
|
||||
uint32_t addr;
|
||||
uint32_t size;
|
||||
uint32_t arg;
|
||||
} t_bf_ldr_pkt;
|
||||
|
||||
/* Разбираем заголовок блока LDR-формата из буфера размером BF_LDR_HDR_SIZE
|
||||
и сохраняем параметры в структуре pkt */
|
||||
int f_parse_ldr_hdr(const uint8_t* hdr, t_bf_ldr_pkt* pkt) {
|
||||
int err = 0;
|
||||
uint32_t* pdw_buff = (uint32_t*)hdr;
|
||||
uint8_t xor_ch = 0;
|
||||
int i;
|
||||
for (i=0; i < BF_LDR_HDR_SIZE; i++) {
|
||||
xor_ch ^= hdr[i];
|
||||
}
|
||||
|
||||
if ((xor_ch!=0) || (hdr[BF_LDR_HDRPOS_SGN] != BF_LDR_HDRSGN)) {
|
||||
err = X502_ERR_LDR_FILE_FORMAT;
|
||||
} else {
|
||||
pkt->res = 0;
|
||||
pkt->dma_mode = pdw_buff[0]&0xF;
|
||||
pkt->flags = pdw_buff[0]&0xFFF0;
|
||||
pkt->addr = pdw_buff[1];
|
||||
pkt->size = pdw_buff[2];
|
||||
pkt->arg = pdw_buff[3];
|
||||
|
||||
if ((pkt->flags & BF_LDR_FLAG_INIT) && (pkt->flags & BF_LDR_FLAG_FILL))
|
||||
err = X502_ERR_LDR_FILE_FORMAT;
|
||||
else if (pkt->flags & (BF_LDR_FLAG_CALLBACK | BF_LDR_FLAG_INDIRECT | BF_LDR_FLAG_INIT))
|
||||
err = X502_ERR_LDR_FILE_UNSUP_FEATURE;
|
||||
else if ((pkt->flags & BF_LDR_FLAG_INIT) && (pkt->addr != 0xFFA00000))
|
||||
err = X502_ERR_LDR_FILE_UNSUP_STARTUP_ADDR;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int32_t f_bf_mem_wr(t_x502_hnd hnd, uint32_t addr, const uint32_t* regs, uint32_t size) {
|
||||
int32_t err = 0;
|
||||
|
||||
/* данные записываем блоками по L502_BF_REQ_DATA_SIZE */
|
||||
while (!err && size) {
|
||||
int put_size = (size < hnd->iface_hnd->bf_mem_block_size) ? size :
|
||||
hnd->iface_hnd->bf_mem_block_size;
|
||||
err = hnd->iface_hnd->bf_mem_block_wr(hnd, addr, regs, put_size);
|
||||
if (!err) {
|
||||
size -= put_size;
|
||||
regs += put_size;
|
||||
addr += put_size*4;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int32_t f_bf_mem_rd(t_x502_hnd hnd, uint32_t addr, uint32_t* regs, uint32_t size) {
|
||||
int err = 0;
|
||||
while (!err && size) {
|
||||
int get_size = (size < hnd->iface_hnd->bf_mem_block_size) ? size :
|
||||
hnd->iface_hnd->bf_mem_block_size;
|
||||
|
||||
err = hnd->iface_hnd->bf_mem_block_rd(hnd, addr, regs, get_size);
|
||||
|
||||
if (!err) {
|
||||
size -= get_size;
|
||||
regs += get_size;
|
||||
addr += get_size*4;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t bf_fpga_reg_wr(t_x502_hnd hnd, uint32_t addr, uint32_t val) {
|
||||
int32_t err = hnd->mode != X502_MODE_DSP ? X502_ERR_INVALID_MODE :
|
||||
(hnd->bf_features & L502_BF_FEATURE_FPGA_REG_ACCESS) ?
|
||||
X502_ERR_OK : X502_ERR_NOT_IMPLEMENTED;
|
||||
if (err == X502_ERR_OK) {
|
||||
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_FPGA_REG_WR, addr, &val, 1, NULL, 0,
|
||||
X502_BF_CMD_DEFAULT_TOUT, NULL);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t bf_fpga_reg_rd(t_x502_hnd hnd, uint32_t addr, uint32_t* val) {
|
||||
int32_t err = hnd->mode != X502_MODE_DSP ? X502_ERR_INVALID_MODE :
|
||||
(hnd->bf_features & L502_BF_FEATURE_FPGA_REG_ACCESS) ?
|
||||
X502_ERR_OK : X502_ERR_NOT_IMPLEMENTED;
|
||||
if (err == X502_ERR_OK) {
|
||||
uint32_t recvd;
|
||||
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_FPGA_REG_RD, addr, NULL, 0, val, 1,
|
||||
X502_BF_CMD_DEFAULT_TOUT, &recvd);
|
||||
if ((err == X502_ERR_OK) && (recvd < 1)) {
|
||||
err = X502_ERR_BF_CMD_RETURN_INSUF_DATA;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int32_t f_check_bf_firm(t_x502_hnd hnd) {
|
||||
int32_t err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_BF_CMD, X502_BF_CMD_HDMA_RST);
|
||||
if (!err) {
|
||||
uint32_t rcv_wrds[2], recvd;
|
||||
|
||||
/* Проверяем версию прошивки BlackFin */
|
||||
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_GET_PARAM, L502_BF_PARAM_FIRM_VERSION,
|
||||
NULL, 0, rcv_wrds, 2, X502_BF_CMD_DEFAULT_TOUT, &recvd);
|
||||
if (!err) {
|
||||
if (recvd >= 1) {
|
||||
hnd->bf_ver = rcv_wrds[0];
|
||||
|
||||
} else {
|
||||
err = X502_ERR_BF_CMD_RETURN_INSUF_DATA;
|
||||
}
|
||||
hnd->bf_features = recvd >= 2 ? rcv_wrds[1] : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Проверка состояния прошивки (запущен поток сбора или нет) */
|
||||
if (!err) {
|
||||
uint32_t mode, streams;
|
||||
|
||||
err = x502_bf_get_par(hnd, L502_BF_PARAM_STREAM_MODE, &mode, 1);
|
||||
if (!err)
|
||||
err = x502_bf_get_par(hnd, L502_BF_PARAM_ENABLED_STREAMS, &streams, 1);
|
||||
if (!err) {
|
||||
err = osspec_mutex_lock(hnd->mutex_cfg, BF_MUTEX_LOCK_TOUT);
|
||||
if (!err) {
|
||||
if (mode==L502_BF_MODE_IDLE) {
|
||||
hnd->flags &= ~PRIV_FLAGS_STREAM_RUN;
|
||||
} else {
|
||||
hnd->flags |= PRIV_FLAGS_STREAM_RUN;
|
||||
}
|
||||
hnd->streams = streams;
|
||||
osspec_mutex_release(hnd->mutex_cfg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* передаем информацию о модуле */
|
||||
if (!err && !(hnd->flags & PRIV_FLAGS_STREAM_RUN)) {
|
||||
uint32_t put_wrds[3];
|
||||
uint32_t ch;
|
||||
put_wrds[0] = hnd->info.devflags;
|
||||
put_wrds[1] = hnd->info.fpga_ver | ((uint32_t)hnd->info.plda_ver<<16);
|
||||
err = x502_bf_set_par(hnd, L502_BF_PARAM_MODULE_INFO, put_wrds, 2);
|
||||
|
||||
for (ch=0; !err && (ch < X502_DAC_CH_CNT); ch++) {
|
||||
float* pk = (float*)&put_wrds[1];
|
||||
float* po = (float*)&put_wrds[2];
|
||||
put_wrds[0] = ch;
|
||||
*pk = (float)hnd->info.cbr.dac[ch].k;
|
||||
*po = (float)hnd->info.cbr.dac[ch].offs;
|
||||
err = x502_bf_set_par(hnd, L502_BF_PARAM_DAC_COEF, put_wrds, 3);
|
||||
}
|
||||
}
|
||||
|
||||
if (!err && (hnd->mode!=X502_MODE_DSP))
|
||||
err = X502_SetMode(hnd, X502_MODE_DSP);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_BfCheckFirmwareIsLoaded(t_x502_hnd hnd, uint32_t *version) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err) {
|
||||
err = f_check_bf_firm(hnd);
|
||||
if (!err && version)
|
||||
*version = hnd->bf_ver;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_BfLoadFirmware(t_x502_hnd hnd, const char* filename) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
|
||||
|
||||
if (!err && !(hnd->info.devflags & X502_DEVFLAGS_BF_PRESENT))
|
||||
err = X502_ERR_BF_NOT_PRESENT;
|
||||
|
||||
|
||||
|
||||
if (!err) {
|
||||
err = osspec_mutex_lock(hnd->mutex_bf, BF_MUTEX_LOCK_TOUT);
|
||||
if (!err) {
|
||||
err = hnd->iface_hnd->bf_firm_load(hnd, filename);
|
||||
osspec_mutex_release(hnd->mutex_bf);
|
||||
}
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
SLEEP_MS(100);
|
||||
err = f_check_bf_firm(hnd);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_BfMemWrite(t_x502_hnd hnd, uint32_t addr,
|
||||
const uint32_t* regs, uint32_t size) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && !(hnd->info.devflags & X502_DEVFLAGS_BF_PRESENT))
|
||||
err = X502_ERR_BF_NOT_PRESENT;;
|
||||
if (!err)
|
||||
err = BF_CHECK_ADDR_SIZE(addr, size);
|
||||
if (!err)
|
||||
err = osspec_mutex_lock(hnd->mutex_bf, BF_MUTEX_LOCK_TOUT);
|
||||
|
||||
if (!err) {
|
||||
int32_t release_err;
|
||||
err = f_bf_mem_wr(hnd, addr, regs, size);
|
||||
release_err = osspec_mutex_release(hnd->mutex_bf);
|
||||
if (!err)
|
||||
err = release_err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_BfMemRead(t_x502_hnd hnd, uint32_t addr,
|
||||
uint32_t* regs, uint32_t size) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && !(hnd->info.devflags & X502_DEVFLAGS_BF_PRESENT))
|
||||
err = X502_ERR_BF_NOT_PRESENT;
|
||||
if (!err)
|
||||
err = BF_CHECK_ADDR_SIZE(addr,size);
|
||||
if (!err)
|
||||
err = osspec_mutex_lock(hnd->mutex_bf, BF_MUTEX_LOCK_TOUT);
|
||||
if (!err) {
|
||||
int32_t release_err;
|
||||
err = f_bf_mem_rd(hnd, addr, regs, size);
|
||||
release_err = osspec_mutex_release(hnd->mutex_bf);
|
||||
if (!err)
|
||||
err = release_err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int f_bf_start_cmd(t_x502_hnd hnd, uint16_t cmd_code, uint32_t par,
|
||||
const uint32_t* data, uint32_t size) {
|
||||
int err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && !(hnd->info.devflags & X502_DEVFLAGS_BF_PRESENT))
|
||||
err = X502_ERR_BF_NOT_PRESENT;
|
||||
if (size > L502_BF_CMD_DATA_SIZE_MAX)
|
||||
err = X502_ERR_BF_INVALID_CMD_DATA_SIZE;
|
||||
if (!err)
|
||||
err = osspec_mutex_lock(hnd->mutex_bf, BF_MUTEX_LOCK_TOUT);
|
||||
|
||||
if (!err) {
|
||||
t_l502_bf_cmd cmd;
|
||||
cmd.code = cmd_code;
|
||||
cmd.data_size = size;
|
||||
cmd.param = par;
|
||||
cmd.result = 0;
|
||||
cmd.status = L502_BF_CMD_STATUS_REQ;
|
||||
|
||||
|
||||
|
||||
if (size!=0) {
|
||||
memcpy(cmd.data, data, size*sizeof(data[0]));
|
||||
}
|
||||
|
||||
/* если размер больше, чем можем записать за раз, то сперва записываем
|
||||
* хвост, чтобы не получилось, что информация о команде будет записана
|
||||
* раньше данных */
|
||||
if (size > BF_CMD_FIRST_DATA_BLOCK_SIZE) {
|
||||
err = f_bf_mem_wr(hnd, X502_BF_MEMADDR_CMD+X502_BF_REQ_DATA_SIZE_MAX*4,
|
||||
&cmd.data[BF_CMD_FIRST_DATA_BLOCK_SIZE],
|
||||
size - BF_CMD_FIRST_DATA_BLOCK_SIZE);
|
||||
size = BF_CMD_FIRST_DATA_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
err = f_bf_mem_wr(hnd, X502_BF_MEMADDR_CMD, (const uint32_t*)&cmd,
|
||||
(offsetof(t_l502_bf_cmd, data))/4 + size);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
osspec_mutex_release(hnd->mutex_bf);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int f_bf_cmd_check(t_x502_hnd hnd, int32_t *res) {
|
||||
t_l502_bf_cmd cmd;
|
||||
int err = f_bf_mem_rd(hnd, X502_BF_MEMADDR_CMD, (uint32_t*)&cmd,
|
||||
X502_BF_REQ_DATA_SIZE_MIN);
|
||||
if (!err) {
|
||||
if (cmd.status != L502_BF_CMD_STATUS_DONE) {
|
||||
err = X502_ERR_BF_CMD_IN_PROGRESS;
|
||||
} else if (res) {
|
||||
*res = cmd.result;
|
||||
}
|
||||
}
|
||||
|
||||
if (err != X502_ERR_BF_CMD_IN_PROGRESS)
|
||||
osspec_mutex_release(hnd->mutex_bf);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_BfExecCmd(t_x502_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) {
|
||||
t_l502_bf_cmd cmd;
|
||||
int done = 0;
|
||||
t_ltimer tmr;
|
||||
int err;
|
||||
|
||||
ltimer_set(&tmr, LTIMER_MS_TO_CLOCK_TICKS(tout));
|
||||
err = f_bf_start_cmd(hnd, cmd_code, par, snd_data, snd_size);
|
||||
while (!err && !done) {
|
||||
err = f_bf_cmd_check(hnd, &cmd.result);
|
||||
if (!err) {
|
||||
done = 1;
|
||||
if (rcv_size != 0) {
|
||||
err = X502_BfMemRead(hnd, X502_BF_MEMADDR_CMD, (uint32_t*)&cmd,
|
||||
(offsetof(t_l502_bf_cmd, data))/4 + rcv_size);
|
||||
memcpy(rcv_data, cmd.data, rcv_size*sizeof(rcv_data[0]));
|
||||
if (recvd_size!=NULL)
|
||||
*recvd_size = cmd.data_size;
|
||||
}
|
||||
if (!err)
|
||||
err = cmd.result;
|
||||
} else if (err==X502_ERR_BF_CMD_IN_PROGRESS) {
|
||||
if (ltimer_expired(&tmr)) {
|
||||
err = X502_ERR_BF_CMD_TIMEOUT;
|
||||
osspec_mutex_release(hnd->mutex_bf);
|
||||
} else {
|
||||
err = 0;
|
||||
SLEEP_MS(20);
|
||||
}
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
795
x502/x502api_config.c
Normal file
795
x502/x502api_config.c
Normal file
@ -0,0 +1,795 @@
|
||||
#include "x502api_private.h"
|
||||
#include "x502_fpga_regs.h"
|
||||
|
||||
#define SYNC_FREQ_CODE(mode) ((mode == X502_SYNC_DI_SYN2_RISE) ? X502_SYNC_DI_SYN1_FALL : \
|
||||
(mode == X502_SYNC_DI_SYN1_FALL) ? X502_SYNC_DI_SYN2_RISE : mode)
|
||||
|
||||
#define CHECK_SYNC_MODE(mode) (((mode)) != X502_SYNC_INTERNAL) \
|
||||
&& ((mode)!=X502_SYNC_EXTERNAL_MASTER) \
|
||||
&& ((mode)!=X502_SYNC_DI_SYN1_RISE) \
|
||||
&& ((mode)!=X502_SYNC_DI_SYN2_RISE) \
|
||||
&& ((mode)!=X502_SYNC_DI_SYN1_FALL) \
|
||||
&& ((mode)!=X502_SYNC_DI_SYN2_FALL) \
|
||||
? X502_ERR_INVALID_SYNC_MODE : X502_ERR_OK
|
||||
|
||||
/** Максимальное значения частоты АЦП для варианта E16*/
|
||||
#define E16_ADC_FREQ_MAX 1000000
|
||||
/** Максимальное значения частоты DIN для варианта E16*/
|
||||
#define E16_DIN_FREQ_MAX 1000000
|
||||
/** Максимальное значения частоты OUT для варианта E16*/
|
||||
#define E16_OUT_FREQ_MAX 1000000
|
||||
|
||||
static const uint16_t f_regadd_k[X502_ADC_RANGE_CNT] = {X502_REGS_IOARITH_K10,
|
||||
X502_REGS_IOARITH_K5,
|
||||
X502_REGS_IOARITH_K2,
|
||||
X502_REGS_IOARITH_K1,
|
||||
X502_REGS_IOARITH_K05,
|
||||
X502_REGS_IOARITH_K02};
|
||||
|
||||
static const uint16_t f_regadd_offs[X502_ADC_RANGE_CNT] = {X502_REGS_IOARITH_B10,
|
||||
X502_REGS_IOARITH_B5,
|
||||
X502_REGS_IOARITH_B2,
|
||||
X502_REGS_IOARITH_B1,
|
||||
X502_REGS_IOARITH_B05,
|
||||
X502_REGS_IOARITH_B02};
|
||||
|
||||
|
||||
static uint32_t f_get_out_freq_div_min(double ref_freq) {
|
||||
return ref_freq > X502_OUT_FREQ_REF_LF_VAL ? X502_OUT_FREQ_DIV_MIN : X502_OUT_FREQ_DIV_MIN_REF_LF;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetLChannel(t_x502_hnd hnd, uint32_t lch, uint32_t phy_ch,
|
||||
uint32_t mode, uint32_t range, uint32_t avg) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
|
||||
if (!err) {
|
||||
/* Для измерения собственного нуля номер канала не имеет значения */
|
||||
if (mode == X502_LCH_MODE_ZERO)
|
||||
phy_ch = 0;
|
||||
|
||||
if ((mode != X502_LCH_MODE_COMM) && (mode != X502_LCH_MODE_DIFF) &&
|
||||
(mode != X502_LCH_MODE_ZERO)) {
|
||||
err = X502_ERR_INVALID_LCH_MODE;
|
||||
} else if ((phy_ch >= X502_ADC_COMM_CH_CNT) ||
|
||||
((mode == X502_LCH_MODE_DIFF) && (phy_ch >= X502_ADC_DIFF_CH_CNT))) {
|
||||
err = X502_ERR_INVALID_LCH_PHY_NUMBER;
|
||||
} else if (range >= X502_ADC_RANGE_CNT) {
|
||||
err = X502_ERR_INVALID_LCH_RANGE;
|
||||
} else if (avg > X502_LCH_AVG_SIZE_MAX) {
|
||||
err = X502_ERR_INVALID_LCH_AVG_SIZE;
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
hnd->set.lch[lch].ch = phy_ch;
|
||||
hnd->set.lch[lch].range = range;
|
||||
hnd->set.lch[lch].mode = mode;
|
||||
hnd->set.lch[lch].avg = avg;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetLChannelCount(t_x502_hnd hnd, uint32_t lch_cnt) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
|
||||
if (!err) {
|
||||
if (lch_cnt > X502_LTABLE_MAX_CH_CNT) {
|
||||
err = X502_ERR_INVALID_LTABLE_SIZE;
|
||||
} else if (x502_is_E16(hnd) && lch_cnt > E16_LTABLE_MAX_CH_CNT) {
|
||||
err = X502_ERR_INVALID_LTABLE_SIZE;
|
||||
} else {
|
||||
hnd->set.lch_cnt = lch_cnt;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_GetLChannelCount(t_x502_hnd hnd, uint32_t* lch_cnt) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (lch_cnt==NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
|
||||
if (!err)
|
||||
*lch_cnt = hnd->set.lch_cnt;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetAdcFreqDivider(t_x502_hnd hnd, uint32_t adc_freq_div) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
|
||||
if (!err) {
|
||||
if ((adc_freq_div==0) ||
|
||||
(x502_is_E16(hnd) && adc_freq_div > E16_ADC_FREQ_DIV_MAX) ||
|
||||
(!x502_is_E16(hnd) && adc_freq_div > X502_ADC_FREQ_DIV_MAX)) {
|
||||
err = X502_ERR_INVALID_ADC_FREQ_DIV;
|
||||
} else {
|
||||
hnd->set.adc_freq_div = adc_freq_div;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetAdcInterframeDelay(t_x502_hnd hnd, uint32_t delay) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
|
||||
if (!err && (delay > X502_ADC_INTERFRAME_DELAY_MAX))
|
||||
err = X502_ERR_INVALID_INTERFRAME_DELAY;
|
||||
|
||||
if (!err) {
|
||||
hnd->set.adc_frame_delay = delay;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetDinFreqDivider(t_x502_hnd hnd, uint32_t din_freq_div) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
|
||||
if (!err) {
|
||||
if ((din_freq_div==0) ||
|
||||
(x502_is_E16(hnd) && din_freq_div > E16_DIN_FREQ_DIV_MAX) ||
|
||||
(!x502_is_E16(hnd) && din_freq_div > X502_DIN_FREQ_DIV_MAX)) {
|
||||
err = X502_ERR_INVALID_ADC_FREQ_DIV;
|
||||
} else {
|
||||
hnd->set.din_freq_div = din_freq_div;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetOutFreqDivider(t_x502_hnd hnd, uint32_t out_freq_div) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
|
||||
if (!err) {
|
||||
/* Проверяем, поддерживается ли возможность установить значение, отличное от стандартного */
|
||||
if (out_freq_div != X502_OUT_FREQ_DIV_DEFAULT) {
|
||||
err = X502_CheckFeature(hnd, X502_FEATURE_OUT_FREQ_DIV);
|
||||
}
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
double ref_freq;
|
||||
X502_GetRefFreqValue(hnd, &ref_freq);
|
||||
if ((out_freq_div < f_get_out_freq_div_min(ref_freq)) ||
|
||||
(x502_is_E16(hnd) && out_freq_div > E16_OUT_FREQ_DIV_MAX) ||
|
||||
(!x502_is_E16(hnd) && out_freq_div > X502_OUT_FREQ_DIV_MAX)) {
|
||||
err = X502_ERR_INVALID_OUT_FREQ_DIV;
|
||||
} else {
|
||||
hnd->set.out_freq_div = out_freq_div;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetMode(t_x502_hnd hnd, uint32_t mode) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
|
||||
if (!err && (mode==X502_MODE_DSP) &&
|
||||
!(hnd->info.devflags & X502_DEVFLAGS_BF_PRESENT)) {
|
||||
err = X502_ERR_BF_NOT_PRESENT;
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
uint32_t val;
|
||||
err = hnd->iface_hnd->fpga_reg_read(hnd, X502_REGS_BF_CTL, &val);
|
||||
if (!err) {
|
||||
val &= ~(X502_REGBIT_BF_CTL_CLK_DIV_Msk | X502_REGBIT_BF_CTL_DBG_MODE_Msk | X502_REGBIT_BF_CTL_DSP_MODE_Msk);
|
||||
if (mode==X502_MODE_DSP) {
|
||||
/* в DSP режиме сброс должен быть снят с blackfin, иначе не будут работать
|
||||
команды по HostDMA */
|
||||
val |= X502_REGBIT_BF_CTL_DSP_MODE_Msk | X502_REGBIT_BF_CTL_BF_RESET_Msk;
|
||||
} else if (mode==X502_MODE_DEBUG) {
|
||||
val |= X502_REGBIT_BF_CTL_DBG_MODE_Msk;
|
||||
} else if (mode!=X502_MODE_FPGA) {
|
||||
err = X502_ERR_INVALID_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!err)
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_BF_CTL, val);
|
||||
|
||||
/* при переходе в режим DSP сбрасываем автомат HDMA */
|
||||
if (!err && (mode==X502_MODE_DSP))
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_BF_CMD, X502_BF_CMD_HDMA_RST);
|
||||
|
||||
if (!err)
|
||||
hnd->mode = mode;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_GetMode(t_x502_hnd hnd, uint32_t* mode) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (mode==NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
|
||||
if (!err) {
|
||||
*mode = hnd->mode;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
#define IS_E16_FREQ(hnd, ref_freq) ((hnd && x502_is_E16(hnd)) || (uint32_t)ref_freq == E16_REF_FREQ_48000KHZ)
|
||||
|
||||
X502_EXPORT(int32_t) X502_CalcAdcFreq2(t_x502_hnd hnd, double ref_freq, uint32_t lch_cnt, double *f_acq,
|
||||
double *f_frame, uint32_t *adc_freq_div, uint32_t *adc_frame_delay) {
|
||||
int32_t err = (f_acq==NULL) ? X502_ERR_INVALID_POINTER : X502_ERR_OK;
|
||||
if (err == X502_ERR_OK) {
|
||||
uint32_t cur_adc_freq_div, cur_frame_delay = 0;
|
||||
uint32_t div_max = X502_ADC_FREQ_DIV_MAX;
|
||||
|
||||
double set_freq = *f_acq;
|
||||
if (set_freq <= 0) {
|
||||
if (IS_E16_FREQ(hnd, ref_freq)) {
|
||||
set_freq = E16_ADC_FREQ_DEFAULT;
|
||||
} else {
|
||||
set_freq = ref_freq;
|
||||
}
|
||||
}
|
||||
if (IS_E16_FREQ(hnd, ref_freq)) {
|
||||
div_max = E16_ADC_FREQ_DIV_MAX;
|
||||
if (set_freq > E16_ADC_FREQ_MAX) {
|
||||
set_freq = E16_ADC_FREQ_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
cur_adc_freq_div = (uint32_t)(ref_freq/set_freq+0.49);
|
||||
if (cur_adc_freq_div == 0)
|
||||
cur_adc_freq_div = 1;
|
||||
if (cur_adc_freq_div > div_max)
|
||||
cur_adc_freq_div = div_max;
|
||||
set_freq = ref_freq/cur_adc_freq_div;
|
||||
|
||||
*f_acq = set_freq;
|
||||
|
||||
if (f_frame==NULL) {
|
||||
cur_frame_delay = 0;
|
||||
} else {
|
||||
if (lch_cnt == 0)
|
||||
lch_cnt = 1;
|
||||
|
||||
if (*f_frame <= 0) {
|
||||
cur_frame_delay = 0;
|
||||
} else {
|
||||
int32_t frame_div = (int32_t)((ref_freq/(*f_frame)
|
||||
- lch_cnt*ref_freq/set_freq)+0.49);
|
||||
|
||||
cur_frame_delay = frame_div <=0 ? 0 :
|
||||
frame_div > X502_ADC_INTERFRAME_DELAY_MAX ?
|
||||
X502_ADC_INTERFRAME_DELAY_MAX : frame_div;
|
||||
}
|
||||
*f_frame = 1./(lch_cnt/set_freq +
|
||||
cur_frame_delay/ref_freq);
|
||||
}
|
||||
|
||||
if (adc_freq_div != NULL)
|
||||
*adc_freq_div = cur_adc_freq_div;
|
||||
if (adc_frame_delay != NULL)
|
||||
*adc_frame_delay = cur_frame_delay;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_CalcAdcFreq(double ref_freq, uint32_t lch_cnt, double *f_acq,
|
||||
double *f_frame, uint32_t *adc_freq_div, uint32_t *adc_frame_delay) {
|
||||
return X502_CalcAdcFreq2(NULL, ref_freq, lch_cnt, f_acq, f_frame, adc_freq_div, adc_frame_delay);
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetAdcFreq(t_x502_hnd hnd, double *f_acq, double *f_frame) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
|
||||
if (!err) {
|
||||
double ref_freq;
|
||||
X502_GetRefFreqValue(hnd, &ref_freq);
|
||||
err = X502_CalcAdcFreq2(hnd, ref_freq, hnd->set.lch_cnt, f_acq, f_frame,
|
||||
&hnd->set.adc_freq_div, &hnd->set.adc_frame_delay);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_GetAdcFreq(t_x502_hnd hnd, double *f_acq, double *f_frame) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (f_acq == NULL) && (f_frame==NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
|
||||
if (!err) {
|
||||
double ref_freq, set_freq;
|
||||
|
||||
X502_GetRefFreqValue(hnd, &ref_freq);
|
||||
|
||||
set_freq = ref_freq/hnd->set.adc_freq_div;
|
||||
if (f_acq!=NULL) {
|
||||
*f_acq = set_freq;
|
||||
}
|
||||
|
||||
if (f_frame!=NULL) {
|
||||
*f_frame = 1./(hnd->set.lch_cnt/set_freq +
|
||||
hnd->set.adc_frame_delay/ref_freq);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_CalcDinFreq2(t_x502_hnd hnd, double ref_freq, double *f_din, uint32_t *result_freq_div) {
|
||||
int32_t err = f_din==NULL ? X502_ERR_INVALID_POINTER : X502_ERR_OK;
|
||||
if (err == X502_ERR_OK) {
|
||||
uint32_t freq_div;
|
||||
double set_freq = *f_din;
|
||||
uint32_t div_max = X502_DIN_FREQ_DIV_MAX;
|
||||
|
||||
if (set_freq<=0) {
|
||||
if (IS_E16_FREQ(hnd, ref_freq)) {
|
||||
set_freq = E16_DIN_FREQ_DEFAULT;
|
||||
} else {
|
||||
set_freq = ref_freq;
|
||||
}
|
||||
}
|
||||
if (IS_E16_FREQ(hnd, ref_freq)) {
|
||||
div_max = E16_DIN_FREQ_DIV_MAX;
|
||||
if (set_freq > E16_DIN_FREQ_MAX) {
|
||||
set_freq = E16_DIN_FREQ_MAX;
|
||||
}
|
||||
}
|
||||
freq_div = (uint32_t)(ref_freq/set_freq+0.49);
|
||||
if (freq_div == 0)
|
||||
freq_div = 1;
|
||||
if (freq_div > div_max)
|
||||
freq_div = div_max;
|
||||
set_freq = ref_freq/freq_div;
|
||||
*f_din = set_freq;
|
||||
|
||||
if (result_freq_div != NULL)
|
||||
*result_freq_div = freq_div;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_CalcDinFreq(double ref_freq, double *f_din, uint32_t *result_freq_div) {
|
||||
return X502_CalcDinFreq2(NULL, ref_freq, f_din, result_freq_div);
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetDinFreq(t_x502_hnd hnd, double *f_din) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
if (!err) {
|
||||
double ref_freq;
|
||||
X502_GetRefFreqValue(hnd, &ref_freq);
|
||||
err = X502_CalcDinFreq2(hnd, ref_freq, f_din, &hnd->set.din_freq_div);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_CalcOutFreq2(t_x502_hnd hnd, double ref_freq, double *f_dout, uint32_t *result_freq_div) {
|
||||
int32_t err = f_dout==NULL ? X502_ERR_INVALID_POINTER : X502_ERR_OK;
|
||||
if (err == X502_ERR_OK) {
|
||||
const uint32_t out_div_min = f_get_out_freq_div_min(ref_freq);
|
||||
uint32_t out_freq_div;
|
||||
uint32_t div_max = X502_OUT_FREQ_DIV_MAX;
|
||||
|
||||
|
||||
double set_freq = *f_dout;
|
||||
if (set_freq <= 0) {
|
||||
if (IS_E16_FREQ(hnd, ref_freq)) {
|
||||
set_freq = E16_OUT_FREQ_DEFAULT;
|
||||
} else {
|
||||
set_freq = ref_freq;
|
||||
}
|
||||
}
|
||||
if (IS_E16_FREQ(hnd, ref_freq)) {
|
||||
div_max = E16_OUT_FREQ_DIV_MAX;
|
||||
if (set_freq > E16_OUT_FREQ_MAX) {
|
||||
set_freq = E16_OUT_FREQ_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
out_freq_div = (uint32_t)(ref_freq/set_freq+0.49);
|
||||
if (out_freq_div < out_div_min)
|
||||
out_freq_div = out_div_min;
|
||||
if (out_freq_div > div_max)
|
||||
out_freq_div = div_max;
|
||||
|
||||
set_freq = ref_freq/out_freq_div;
|
||||
*f_dout = set_freq;
|
||||
|
||||
if (result_freq_div != NULL)
|
||||
*result_freq_div = out_freq_div;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_CalcOutFreq(double ref_freq, double *f_dout, uint32_t *result_freq_div) {
|
||||
return X502_CalcOutFreq2(NULL, ref_freq, f_dout, result_freq_div);
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetOutFreq(t_x502_hnd hnd, double *f_dout) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
if (!err && (f_dout==NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
|
||||
if (!err) {
|
||||
double ref_freq;
|
||||
|
||||
X502_GetRefFreqValue(hnd, &ref_freq);
|
||||
/* Если не поддерживается возможность установки нестандартного делителя, то
|
||||
всегда устанавливаем стандартный */
|
||||
if (X502_CheckFeature(hnd, X502_FEATURE_OUT_FREQ_DIV) != X502_ERR_OK) {
|
||||
hnd->set.out_freq_div = X502_OUT_FREQ_DIV_DEFAULT;
|
||||
*f_dout = ref_freq/hnd->set.out_freq_div;
|
||||
} else {
|
||||
err = X502_CalcOutFreq2(hnd, ref_freq, f_dout, &hnd->set.out_freq_div);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetRefFreq(t_x502_hnd hnd, uint32_t freq) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
|
||||
if (!err) {
|
||||
if (x502_is_E16(hnd)) {
|
||||
// для E16 ref freq всегда 48 МГц
|
||||
hnd->set.ref_freq = E16_REF_FREQ_48000KHZ;
|
||||
} else {
|
||||
hnd->set.ref_freq = freq;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetExtRefFreqValue(t_x502_hnd hnd, double freq) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
if (!err)
|
||||
hnd->set.ext_ref_freq = freq;
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetAdcSyncStartValue(t_x502_hnd hnd, uint32_t phy_ch, uint32_t mode, uint32_t range, double value) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
if (!err) {
|
||||
hnd->set.adc_sync_ch = phy_ch;
|
||||
hnd->set.adc_sync_range = range;
|
||||
hnd->set.adc_sync_mode = mode;
|
||||
hnd->set.adc_sync_val = value;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_GetRefFreqValue(t_x502_hnd hnd, double *freq) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
|
||||
if (!err) {
|
||||
if ((hnd->set.sync_mode == X502_SYNC_INTERNAL) ||
|
||||
!(hnd->set.ext_ref_freq > 0)) {
|
||||
*freq = hnd->set.ref_freq;
|
||||
} else {
|
||||
*freq = hnd->set.ext_ref_freq;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetSyncMode(t_x502_hnd hnd, uint32_t sync_mode) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
|
||||
if (!err) {
|
||||
err = CHECK_SYNC_MODE(sync_mode);
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
hnd->set.sync_mode = sync_mode;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetSyncStartMode(t_x502_hnd hnd, uint32_t sync_start_mode) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
|
||||
if (!err) {
|
||||
if (sync_start_mode==E16_SYNC_ADC_EDGE_RISE ||
|
||||
sync_start_mode==E16_SYNC_ADC_EDGE_FALL ||
|
||||
sync_start_mode==E16_SYNC_ADC_ABOVE_LEVEL ||
|
||||
sync_start_mode==E16_SYNC_ADC_BELOW_LEVEL) {
|
||||
if (x502_is_E16(hnd) == false) {
|
||||
// реализовано только в E16
|
||||
return X502_ERR_INVALID_SYNC_MODE;
|
||||
}
|
||||
} else {
|
||||
err = CHECK_SYNC_MODE(sync_start_mode);
|
||||
}
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
hnd->set.sync_start_mode = sync_start_mode;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
uint32_t get_ltable_val(t_x502_hnd hnd, uint32_t phy_ch, uint32_t mode, uint32_t range, uint32_t avg) {
|
||||
uint32_t wrd = ((phy_ch & 0xF) << 3) | (range & 0x7);
|
||||
|
||||
if (mode == X502_LCH_MODE_ZERO) {
|
||||
wrd |= (3 << 7);
|
||||
} else if (mode == X502_LCH_MODE_COMM) {
|
||||
wrd |= (phy_ch & 0x10 ? 2 : 1) << 7;
|
||||
}
|
||||
|
||||
if (avg) {
|
||||
uint32_t avg_val = avg;
|
||||
if (avg_val > hnd->set.adc_freq_div)
|
||||
avg_val = hnd->set.adc_freq_div;
|
||||
wrd |= ((avg_val-1) & 0x7F) << 9;
|
||||
}
|
||||
return wrd;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_Configure(t_x502_hnd hnd, uint32_t flags) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
|
||||
if (!err) {
|
||||
/* Проверяем правильность установленной опорной частоты.
|
||||
Для внутренней может быть только одно из двух значений,
|
||||
для внешней главное, чтобы не принимало требуемой */
|
||||
if ((hnd->set.sync_mode==X502_SYNC_INTERNAL)
|
||||
&& (hnd->set.ref_freq!=E16_REF_FREQ_48000KHZ)
|
||||
&& (hnd->set.ref_freq!=X502_REF_FREQ_2000KHZ)
|
||||
&&(hnd->set.ref_freq!=X502_REF_FREQ_1500KHZ)) {
|
||||
err = X502_ERR_INVALID_REF_FREQ;
|
||||
} else if (hnd->set.ext_ref_freq > 2000000) {
|
||||
err = X502_ERR_INVALID_REF_FREQ;
|
||||
}
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
if (hnd->mode == X502_MODE_FPGA) {
|
||||
uint32_t ch;
|
||||
/* записываем логическую таблицу */
|
||||
for (ch=0; (ch < hnd->set.lch_cnt) && !err; ch++) {
|
||||
uint32_t wrd = get_ltable_val(hnd, hnd->set.lch[ch].ch, hnd->set.lch[ch].mode, hnd->set.lch[ch].range, hnd->set.lch[ch].avg);
|
||||
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, (X502_REGS_IOHARD_LTABLE +
|
||||
hnd->set.lch_cnt - 1 - ch) & 0xFFFF, wrd);
|
||||
}
|
||||
if (!err) {
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_LCH_CNT,
|
||||
hnd->set.lch_cnt-1);
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_ADC_FREQ_DIV,
|
||||
hnd->set.adc_freq_div-1);
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOARITH_ADC_FREQ_DIV,
|
||||
hnd->set.adc_freq_div-1);
|
||||
}
|
||||
|
||||
|
||||
if (!err) {
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_ADC_FRAME_DELAY,
|
||||
hnd->set.adc_frame_delay);
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
// для варианта E16 ref_freq будет всегда 48000000
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_IO_MODE,
|
||||
(SYNC_FREQ_CODE(hnd->set.sync_mode) & 0x7)
|
||||
| ((hnd->set.sync_start_mode&0xF)<<3)
|
||||
| ((hnd->set.ref_freq==X502_REF_FREQ_2000KHZ ? X502_MODE_REF_FREQ_2000 :
|
||||
(hnd->set.ref_freq==X502_REF_FREQ_1500KHZ ? X502_MODE_REF_FREQ_1500: E16_MODE_REF_FREQ_48000)) << 7)
|
||||
| (((hnd->set.out_freq_div-1) & (x502_is_E16(hnd) ? 0x7FFF : 0x3FF))<<9));
|
||||
}
|
||||
|
||||
if (x502_is_E16(hnd)) {
|
||||
// старт по аналоговому сигналу реализован только в E16
|
||||
if (!err) {
|
||||
uint32_t wrd = get_ltable_val(hnd, hnd->set.adc_sync_ch, hnd->set.adc_sync_mode, hnd->set.adc_sync_range, 0);
|
||||
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOARITH_N_CHAN_SYN, wrd);
|
||||
}
|
||||
if (!err) {
|
||||
uint32_t threshold;
|
||||
threshold = hnd->set.adc_sync_val / hnd->set.f_scales[hnd->set.adc_sync_range] * E16_ADC_SCALE_CODE_MAX;
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOARITH_THRESHOLD, threshold);
|
||||
}
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_DIGIN_FREQ_DIV,
|
||||
hnd->set.din_freq_div-1);
|
||||
}
|
||||
} else if (hnd->mode == X502_MODE_DSP) {
|
||||
uint32_t ch;
|
||||
err = x502_bf_set_par(hnd, L502_BF_PARAM_LCH_CNT, &hnd->set.lch_cnt, 1);
|
||||
for (ch=0; !err && (ch < hnd->set.lch_cnt); ch++) {
|
||||
uint32_t ch_par[] = {ch, hnd->set.lch[ch].ch,
|
||||
hnd->set.lch[ch].mode,
|
||||
hnd->set.lch[ch].range,
|
||||
hnd->set.lch[ch].avg > hnd->set.adc_freq_div ?
|
||||
hnd->set.adc_freq_div : hnd->set.lch[ch].avg} ;
|
||||
err = x502_bf_set_par(hnd, L502_BF_PARAM_LCH, ch_par,
|
||||
sizeof(ch_par)/sizeof(ch_par[0]));
|
||||
}
|
||||
if (!err) {
|
||||
err = x502_bf_set_par(hnd, L502_BF_PARAM_ADC_FREQ_DIV,
|
||||
&hnd->set.adc_freq_div, 1);
|
||||
}
|
||||
if (!err) {
|
||||
err = x502_bf_set_par(hnd, L502_BF_PARAM_ADC_FRAME_DELAY,
|
||||
&hnd->set.adc_frame_delay, 1);
|
||||
}
|
||||
if (!err) {
|
||||
err = x502_bf_set_par(hnd, L502_BF_PARAM_REF_FREQ_SRC,
|
||||
&hnd->set.ref_freq, 1);
|
||||
}
|
||||
if (!err) {
|
||||
uint32_t sync_code = SYNC_FREQ_CODE(hnd->set.sync_mode);
|
||||
err = x502_bf_set_par(hnd, L502_BF_PARAM_SYNC_MODE,
|
||||
&sync_code, 1);
|
||||
}
|
||||
if (!err) {
|
||||
err = x502_bf_set_par(hnd, L502_BF_PARAM_SYNC_START_MODE,
|
||||
&hnd->set.sync_start_mode, 1);
|
||||
}
|
||||
if (!err) {
|
||||
err = x502_bf_set_par(hnd, L502_BF_PARAM_DAC_FREQ_DIV,
|
||||
&hnd->set.out_freq_div, 1);
|
||||
}
|
||||
if (!err)
|
||||
{
|
||||
err = x502_bf_set_par(hnd, L502_BF_PARAM_DIN_FREQ_DIV,
|
||||
&hnd->set.din_freq_div, 1);
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_CONFIGURE, 0, NULL,
|
||||
0, NULL, 0, X502_BF_CMD_DEFAULT_TOUT, NULL);
|
||||
}
|
||||
} else {
|
||||
err = X502_ERR_INVALID_MODE;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetAdcCoef(t_x502_hnd hnd, uint32_t range, double k, double offs) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
|
||||
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
|
||||
if (!err) {
|
||||
if (x502_is_E16(hnd)) {
|
||||
if (range >= E16_ADC_RANGE_CNT) {
|
||||
err = X502_ERR_INVALID_LCH_RANGE;
|
||||
}
|
||||
} else {
|
||||
if (range >= X502_ADC_RANGE_CNT) {
|
||||
err = X502_ERR_INVALID_LCH_RANGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
uint32_t kval = (uint32_t)(k*0x400000);
|
||||
uint32_t offs_val = (uint32_t)(-offs);
|
||||
|
||||
if (hnd->mode == X502_MODE_FPGA) {
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, f_regadd_k[range], kval);
|
||||
if (!err)
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, f_regadd_offs[range], offs_val);
|
||||
} else if (hnd->mode == X502_MODE_DSP) {
|
||||
uint32_t wrds[3] = {range, kval, offs_val};
|
||||
err = x502_bf_set_par(hnd, L502_BF_PARAM_ADC_COEF, wrds, 3);
|
||||
} else {
|
||||
err = X502_ERR_INVALID_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
hnd->info.cbr.adc[range].k = k;
|
||||
hnd->info.cbr.adc[range].offs = offs;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_GetAdcCoef(t_x502_hnd hnd, uint32_t range, double* k, double* offs) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err) {
|
||||
if (range >= X502_ADC_RANGE_CNT) {
|
||||
err = X502_ERR_INVALID_LCH_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
*k = hnd->info.cbr.adc[range].k;
|
||||
*offs = hnd->info.cbr.adc[range].offs;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetDacCoef(t_x502_hnd hnd, uint32_t ch, double k, double offs) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
|
||||
if (!err && (ch!=X502_DAC_CH1) && (ch!=X502_DAC_CH2)) {
|
||||
err = X502_ERR_INVALID_DAC_CHANNEL;
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
hnd->info.cbr.dac[ch].offs = offs;
|
||||
hnd->info.cbr.dac[ch].k = k;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_GetDacCoef(t_x502_hnd hnd, uint32_t ch, double* k, double* offs) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (!err && (ch!=X502_DAC_CH1) && (ch!=X502_DAC_CH2)) {
|
||||
err = X502_ERR_INVALID_DAC_CHANNEL;
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
if (offs!=NULL)
|
||||
*offs = hnd->info.cbr.dac[ch].offs;
|
||||
|
||||
if (k!=NULL)
|
||||
*k = hnd->info.cbr.dac[ch].k;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
213
x502/x502api_eeprom.c
Normal file
213
x502/x502api_eeprom.c
Normal file
@ -0,0 +1,213 @@
|
||||
#include "x502api_private.h"
|
||||
#include "x502_eeprom.h"
|
||||
#include "fast_crc.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "../devs/e502/e502_fpga_regs.h"
|
||||
|
||||
#define X502_CHECK_ADDR(hnd, addr, size) ((addr+size)>hnd->info.flash_size ? \
|
||||
X502_ERR_FLASH_INVALID_ADDR : (size==0) ? X502_ERR_FLASH_INVALID_SIZE : X502_ERR_OK)
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_FlashRead(t_x502_hnd hnd, uint32_t addr, uint8_t* data,
|
||||
uint32_t size) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err==X502_ERR_OK) {
|
||||
err = X502_CHECK_ADDR(hnd, addr, size);
|
||||
}
|
||||
if (err==X502_ERR_OK) {
|
||||
|
||||
for ( ; (size!=0) && (err==X502_ERR_OK); ) {
|
||||
uint32_t rd_size = size;
|
||||
if (rd_size > hnd->iface_hnd->flash_rd_size)
|
||||
rd_size = hnd->iface_hnd->flash_rd_size;
|
||||
|
||||
err = hnd->iface_hnd->flash_rd(hnd, addr, data, rd_size);
|
||||
if (err==X502_ERR_OK) {
|
||||
data+=rd_size;
|
||||
addr+=rd_size;
|
||||
size-=rd_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_FlashWrite(t_x502_hnd hnd, uint32_t addr,
|
||||
const uint8_t* data, uint32_t size) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err==X502_ERR_OK) {
|
||||
err = X502_CHECK_ADDR(hnd, addr, size);
|
||||
}
|
||||
if (err==X502_ERR_OK) {
|
||||
for ( ; (size!=0) && (err==X502_ERR_OK); ) {
|
||||
uint32_t wr_size = size;
|
||||
if (wr_size > hnd->iface_hnd->flash_wr_size)
|
||||
wr_size = hnd->iface_hnd->flash_wr_size;
|
||||
|
||||
err = hnd->iface_hnd->flash_wr(hnd, addr, data, wr_size);
|
||||
if (err==X502_ERR_OK) {
|
||||
data+=wr_size;
|
||||
addr+=wr_size;
|
||||
size-=wr_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_FlashErase(t_x502_hnd hnd, uint32_t addr, uint32_t size) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err==X502_ERR_OK) {
|
||||
err = X502_CHECK_ADDR(hnd, addr, size);
|
||||
}
|
||||
if (err==X502_ERR_OK) {
|
||||
err = hnd->iface_hnd->flash_erase(hnd, addr, size);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_FlashWriteEnable(t_x502_hnd hnd) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err==X502_ERR_OK) {
|
||||
err = hnd->iface_hnd->flash_set_prot(hnd, X502_EEPROM_PROT_WR_USER, NULL, 0);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_FlashWriteDisable(t_x502_hnd hnd) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err==X502_ERR_OK) {
|
||||
err = hnd->iface_hnd->flash_set_prot(hnd, X502_EEPROM_PROT_ALL, NULL, 0);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_FlashSetProtection(t_x502_hnd hnd, uint32_t prot, uint8_t *prot_data, uint32_t prot_data_size) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err==X502_ERR_OK) {
|
||||
err = hnd->iface_hnd->flash_set_prot(hnd, prot, prot_data, prot_data_size);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
bool x502_is_E16(t_x502_hnd hnd) {
|
||||
if (strcmp(hnd->info.name, E16_DEVICE_NAME) == 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Функция проверяет правильность информации о устройстве, записанной в EEPROM.
|
||||
При наличии верной инофрмации, из EEPROM считывается название устройства и
|
||||
серийный номер, а так же, при наличии, калибровочные коэффициенты */
|
||||
int x502_check_eeprom(t_x502_hnd hnd, uint32_t flags) {
|
||||
int err;
|
||||
uint32_t sign, size;
|
||||
|
||||
if (x502_is_E16(hnd)) {
|
||||
// в E16 добавился новый регистр и мы можем узнать размер flash-памяти
|
||||
uint32_t flash_size;
|
||||
err = hnd->iface_hnd->fpga_reg_read(hnd, E502_REGS_ARM_FLASHSIZE, &flash_size);
|
||||
if (err != X502_ERR_OK) {
|
||||
hnd->info.flash_size = 0;
|
||||
return err;
|
||||
}
|
||||
hnd->info.flash_size = flash_size;
|
||||
} else {
|
||||
hnd->info.flash_size = X502_EEPROM_SIZE;
|
||||
}
|
||||
|
||||
hnd->info.devflags &= ~(X502_DEVFLAGS_FLASH_DATA_VALID |
|
||||
((flags & X502_RELOAD_FLAGS_NO_ADC) ? 0 : X502_DEVFLAGS_FLASH_ADC_CALIBR_VALID) |
|
||||
((flags & X502_RELOAD_FLAGS_NO_DAC) ? 0 : X502_DEVFLAGS_FLASH_DAC_CALIBR_VALID));
|
||||
|
||||
/* проверяем признак правильного описателя в EEPROM и его размер */
|
||||
err = X502_FlashRead(hnd, X502_EEPROM_ADDR_DESCR, (uint8_t*)&sign, (uint32_t)sizeof(sign));
|
||||
if (err == X502_ERR_OK)
|
||||
err = X502_FlashRead(hnd, X502_EEPROM_ADDR_DESCR+sizeof(sign), (uint8_t*)&size, (uint32_t)sizeof(size));
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
if ((sign == X502_EEPROM_SIGN) && (size >= X502_DESCR_MIN_SIZE) && (size <= X502_DESCR_MAX_SIZE)) {
|
||||
t_x502_descr* pdescr = (t_x502_descr*)malloc(size);
|
||||
/* читаем весь описатель */
|
||||
if (pdescr!=NULL) {
|
||||
err = X502_FlashRead(hnd, X502_EEPROM_ADDR_DESCR, (uint8_t*)pdescr, size);
|
||||
} else {
|
||||
err = X502_ERR_MEMORY_ALLOC;
|
||||
}
|
||||
|
||||
/* сверяем crc */
|
||||
if (err == X502_ERR_OK) {
|
||||
uint32_t crc, crc2;
|
||||
crc = CRC32_Block8(0, (uint8_t*)pdescr, (uint32_t)(size-sizeof(crc)));
|
||||
memcpy(&crc2, &((uint8_t*)pdescr)[size-4], 4);
|
||||
if (crc == crc2) {
|
||||
|
||||
hnd->info.devflags |= X502_DEVFLAGS_FLASH_DATA_VALID;
|
||||
memcpy(hnd->info.serial, pdescr->hdr.serial, sizeof(pdescr->hdr.serial));
|
||||
memcpy(hnd->info.name, pdescr->hdr.name, sizeof(pdescr->hdr.name));
|
||||
memcpy(hnd->info.factory_mac, pdescr->hdr.factory_mac, sizeof(pdescr->hdr.factory_mac));
|
||||
|
||||
if (!(flags & X502_RELOAD_FLAGS_NO_ADC)) {
|
||||
if ((pdescr->cbr_adc.hdr.cbr_sign == X502_EEPROM_CBR_SIGN) &&
|
||||
(pdescr->cbr_adc.hdr.format == X502_EEPROM_CBR_FROMAT) &&
|
||||
(pdescr->cbr_adc.hdr.src == X502_EEPROM_CBR_SRC_ADC) &&
|
||||
(pdescr->cbr_adc.hdr.range_cnt == X502_ADC_RANGE_CNT || pdescr->cbr_adc.hdr.range_cnt == E16_ADC_RANGE_CNT) &&
|
||||
(pdescr->cbr_adc.hdr.channel_cnt == 1)) {
|
||||
unsigned int i;
|
||||
|
||||
hnd->info.devflags |= X502_DEVFLAGS_FLASH_ADC_CALIBR_VALID;
|
||||
for (i=0; (i < pdescr->cbr_adc.hdr.range_cnt) && (err == X502_ERR_OK); i++) {
|
||||
if (x502_is_E16(hnd)) {
|
||||
if (i > E16_ADC_RANGE_CNT) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (i > X502_ADC_RANGE_CNT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
err = X502_SetAdcCoef(hnd, i, pdescr->cbr_adc.coefs[i].k,
|
||||
pdescr->cbr_adc.coefs[i].offs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(flags & X502_RELOAD_FLAGS_NO_DAC)) {
|
||||
if ((pdescr->cbr_dac.hdr.cbr_sign == X502_EEPROM_CBR_SIGN) &&
|
||||
(pdescr->cbr_dac.hdr.format == X502_EEPROM_CBR_FROMAT) &&
|
||||
(pdescr->cbr_dac.hdr.src == X502_EEPROM_CBR_SRC_DAC) &&
|
||||
(pdescr->cbr_dac.hdr.range_cnt == 1) &&
|
||||
(pdescr->cbr_dac.hdr.channel_cnt == X502_DAC_CH_CNT)) {
|
||||
unsigned int i;
|
||||
|
||||
hnd->info.devflags |= X502_DEVFLAGS_FLASH_DAC_CALIBR_VALID;
|
||||
for (i=0; (i < pdescr->cbr_dac.hdr.channel_cnt) &&
|
||||
(i < X502_ADC_RANGE_CNT) && (err == X502_ERR_OK); i++) {
|
||||
err = X502_SetDacCoef(hnd, i, pdescr->cbr_dac.coefs[i].k,
|
||||
pdescr->cbr_dac.coefs[i].offs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(pdescr);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_ReloadDevInfo(t_x502_hnd hnd, uint32_t flags) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if ((err==X502_ERR_OK) && (hnd->iface_hnd->reload_dev_info!=NULL))
|
||||
err = hnd->iface_hnd->reload_dev_info(hnd);
|
||||
if (err==X502_ERR_OK)
|
||||
err = x502_check_eeprom(hnd, flags);
|
||||
return err;
|
||||
}
|
||||
186
x502/x502api_errs.c
Normal file
186
x502/x502api_errs.c
Normal file
@ -0,0 +1,186 @@
|
||||
//---------------------------------------------------------------------------
|
||||
#include "x502api.h"
|
||||
#include "l502_bf_cmd_defs.h"
|
||||
|
||||
#include "../devs/e502/e502_cm4_defs.h"
|
||||
|
||||
static const char* f_unknow_err = "Неизвестная ошибка";
|
||||
|
||||
typedef struct {
|
||||
int32_t err;
|
||||
const char* str;
|
||||
}t_err_table;
|
||||
|
||||
static const t_err_table f_err_tbl[] = {
|
||||
{ X502_ERR_OK, "Выполнено без ошибок" },
|
||||
{ X502_ERR_INVALID_HANDLE, "Недействительный описатель модуля"},
|
||||
{ X502_ERR_MEMORY_ALLOC, "Ошибка выделения памяти"},
|
||||
{ X502_ERR_ALREADY_OPENED, "Попытка открыть уже открытое устройство"},
|
||||
{ X502_ERR_DEVICE_NOT_FOUND, "Устройство с заданными параметрами не найдено в системе"},
|
||||
{ X502_ERR_DEVICE_ACCESS_DENIED, "Доступ к устройству запрещен"},
|
||||
{ X502_ERR_DEVICE_OPEN, "Ошибка открытия устройства"},
|
||||
{ X502_ERR_INVALID_POINTER, "В функцию передан недействительный указатель"},
|
||||
{ X502_ERR_STREAM_IS_RUNNING, "Функция не может быть выполнена при запущенном потоке сбора данных"},
|
||||
{ X502_ERR_RECV, "Ошибка чтения данных синхронного ввода"},
|
||||
{ X502_ERR_SEND, "Ошибка записи данных для синхронного вывода"},
|
||||
{ X502_ERR_STREAM_OVERFLOW, "Произошло переполнение внутреннего буфера для потока синхронного ввода"},
|
||||
{ X502_ERR_UNSUP_STREAM_MSG, "Неизвестное сообщение в потоке синхронного ввода"},
|
||||
{ X502_ERR_MUTEX_CREATE, "Ошибка создания системного мьютекса"},
|
||||
{ X502_ERR_MUTEX_INVALID_HANDLE, "Неверный описатель мьютекса"},
|
||||
{ X502_ERR_MUTEX_LOCK_TOUT, "Истекло время ожидания освобождния мьютекса"},
|
||||
{ X502_ERR_MUTEX_RELEASE, "Ошибка освобождения мьютекса"},
|
||||
{ X502_ERR_INSUFFICIENT_SYSTEM_RESOURCES, "Недостаточно системных ресурсов"},
|
||||
{ X502_ERR_NOT_IMPLEMENTED, "Данная возможность еще не реализована"},
|
||||
{ X502_ERR_INSUFFICIENT_ARRAY_SIZE, "Недостаточный размер массива"},
|
||||
{ X502_ERR_FPGA_REG_READ, "Ошибка чтения регистра FPGA"},
|
||||
{ X502_ERR_FPGA_REG_WRITE, "Ошибка записи регистра FPGA"},
|
||||
{ X502_ERR_STREAM_IS_NOT_RUNNING, "Синхронный сбор уже остановлен"},
|
||||
{ X502_ERR_INTERFACE_RELEASE, "Ошибка освобождения интерфейса"},
|
||||
{ X502_ERR_THREAD_START, "Ошибка запуска потока"},
|
||||
{ X502_ERR_THREAD_STOP, "Ошибка останова потока"},
|
||||
{ X502_ERR_DEVICE_DISCONNECTED, "Устройство было отключено"},
|
||||
{ X502_ERR_IOCTL_INVALID_RESP_SIZE, "Неверный размер ответа на управляющий запрос"},
|
||||
{ X502_ERR_INVALID_DEVICE, "Неверный тип устройства"},
|
||||
{ X502_ERR_INVALID_DEVICE_RECORD, "Недействительная запись о устройстве"},
|
||||
{ X502_ERR_INVALID_CONFIG_HANDLE, "Неверный описатель конфигурации модуля"},
|
||||
{ X502_ERR_DEVICE_NOT_OPENED, "Связь с устройством закрыта или не была установлена"},
|
||||
{ X502_ERR_INVALID_OP_FOR_IFACE, "Данная операция не доступна для текущего интерфейса связи с устройством"},
|
||||
{ X502_ERR_FPGA_NOT_LOADED, "Не загружен ПЛИС модуля"},
|
||||
{ X502_ERR_INVALID_USB_CONFIGURATION,"Неверная конфигурация USB-устройства"},
|
||||
{ X502_ERR_INVALID_SVC_BROWSE_HANDLE, "Неверный описатель контекста поиска сервисов"},
|
||||
{ X502_ERR_INVALID_SVC_RECORD_HANDLE,"Неверный описатель записи о сервисе"},
|
||||
#ifdef _WIN32
|
||||
{ X502_ERR_DNSSD_NOT_RUNNING, "Не запущена программа обнаружения устройств в локальной сети (Bonjour Service)"},
|
||||
#else
|
||||
{ X502_ERR_DNSSD_NOT_RUNNING, "Не запущена программа обнаружения устройств в локальной сети (AVAHI)"},
|
||||
#endif
|
||||
{ X502_ERR_DNSSD_COMMUNICATION, "Ошибка при обращении к программе обнаружения устройств в локальной сети"},
|
||||
{ X502_ERR_INVALID_SVC_BROWSE_HANDLE, "Неверный описатель контекста поиска устройств в сети"},
|
||||
{ X502_ERR_INVALID_SVC_RECORD_HANDLE, "Неверный описатель записи о сервисе"},
|
||||
{ X502_ERR_DNSSD_NOT_RUNNING, "Не запущена программа обнаружения устройств в локальной сети"},
|
||||
{ X502_ERR_DNSSD_COMMUNICATION, "Ошибка при обращении к программе обнаружения устройств в локальной сети"},
|
||||
{ X502_ERR_SVC_RESOLVE_TIMEOUT, "Превышен таймаут запроса параметров автообнаруженного сетевого устройства"},
|
||||
{ X502_ERR_INSTANCE_NAME_ENCODING, "Ошибка в кодировке имени экземляра устройства"},
|
||||
{ X502_ERR_INSTANCE_MISMATCH, "Экземпляры модулей не совпадают"},
|
||||
{ X502_ERR_NOT_SUP_BY_FIRMWARE, "Возможность не поддерживается текущей версией прошивки устройства"},
|
||||
{ X502_ERR_NOT_SUP_BY_DRIVER, "Возможность не поддерживается текущей версией драйвера устройства"},
|
||||
{ X502_ERR_OUT_CYCLE_SETUP_TOUT, "Превышено время ожидания установления цикличиского сигнала на вывод"},
|
||||
|
||||
{ X502_ERR_INVALID_LTABLE_SIZE, "Задан неверный размер логической таблицы"},
|
||||
{ X502_ERR_INVALID_LCH_NUMBER, "Задан неверный номер логического канала"},
|
||||
{ X502_ERR_INVALID_LCH_RANGE, "Неверно задано значение диапазона АЦП"},
|
||||
{ X502_ERR_INVALID_LCH_MODE, "Неверно задан режим измерения для логического канала"},
|
||||
{ X502_ERR_INVALID_LCH_PHY_NUMBER, "Неверно задан номер физического канала при настройке логического"},
|
||||
{ X502_ERR_INVALID_LCH_AVG_SIZE, "Неверно задан размер усреднения для логического канала"},
|
||||
{ X502_ERR_INVALID_ADC_FREQ_DIV, "Неверно задан делитель частоты сбора данных АЦП"},
|
||||
{ X502_ERR_INVALID_DIN_FREQ_DIV, "Неверно задан делитель частоты синхронного ввода цифровых линий"},
|
||||
{ X502_ERR_INVALID_MODE, "Неверно задан режим работы платы"},
|
||||
{ X502_ERR_INVALID_DAC_CHANNEL, "Неверный номер канала ЦАП"},
|
||||
{ X502_ERR_INVALID_REF_FREQ, "Неверный код выбора опорной частоты синхронизации"},
|
||||
{ X502_ERR_INVALID_INTERFRAME_DELAY,"Неверно задано значение межкадровой задержки"},
|
||||
{ X502_ERR_INVALID_SYNC_MODE, "Неверно задан режим синхронизации"},
|
||||
{ X502_ERR_INVALID_STREAM_CH, "Неверно задан номер потока данных"},
|
||||
{ X502_ERR_INVALID_OUT_FREQ_DIV, "Неверно задан делитель частоты синхронного вывода"},
|
||||
{ X502_ERR_REF_FREQ_NOT_LOCKED, "Ошибка захвата опорной частоты синхронизации"},
|
||||
{ X502_ERR_IOCTL_FAILD, "Управляющий запрос к драйверу завершен с ошибкой"},
|
||||
{ X502_ERR_IOCTL_TIMEOUT, "Истек таймаут ожидания завершения выполнения управляющего запроса к драйверу"},
|
||||
{ X502_ERR_GET_INFO, "Ошибка получения информации о устройстве от драйвера"},
|
||||
{ X502_ERR_DIG_IN_NOT_RDY, "За время ожидания не было считано новое слово с цифровых линий"},
|
||||
{ X502_ERR_RECV_INSUFFICIENT_WORDS, "Принято недостаточно слов от модуля"},
|
||||
{ X502_ERR_DAC_NOT_PRESENT, "Попытка выполнить операцию, требующую наличие ЦАП, при его отсутствии"},
|
||||
{ X502_ERR_SEND_INSUFFICIENT_WORDS, "Передано недостаточно слов в модуль"},
|
||||
{ X502_ERR_NO_CMD_RESPONSE, "Не пришло ответа на переданную команду"},
|
||||
{ X502_ERR_PROC_INVALID_CH_NUM, "Неверный номер канала в обрабатываемом потоке синхронного ввода"},
|
||||
{ X502_ERR_PROC_INVALID_CH_RANGE, "Неверный код диапазона в обрабатываемом потоке синхронного ввода"},
|
||||
{ X502_ERR_FLASH_INVALID_ADDR, "Задан неверный адрес во Flash-памяти"},
|
||||
{ X502_ERR_FLASH_INVALID_SIZE, "Задан неверный размер блока данных при работе с Flash-памятью"},
|
||||
{ X502_ERR_FLASH_WRITE_TOUT, "Истек таймаут ожидания завершения записи во Flash-память"},
|
||||
{ X502_ERR_FLASH_ERASE_TOUT, "Истек таймаут ожидания завершения стирания блока Flash-памяти"},
|
||||
{ X502_ERR_FLASH_SECTOR_BOUNDARY, "Заданная область для стирания Flash-памяти нарушает границу блока в 4 Кбайт"},
|
||||
|
||||
{ X502_ERR_SOCKET_OPEN, "Не удалось открыть сокет для соединения"},
|
||||
{ X502_ERR_CONNECTION_TOUT, "Превышено время подключения"},
|
||||
{ X502_ERR_CONNECTION_CLOSED_BY_DEV,"Соединение закрыто устройством"},
|
||||
{ X502_ERR_SOCKET_SET_BUF_SIZE, "Не удалось установить заданный размер буфера сокета"},
|
||||
{ X502_ERR_NO_DATA_CONNECTION, "Соединение для передачи данных не установлено"},
|
||||
{ X502_ERR_NO_STREAM_END_MSG, "Не удалось дождаться сообщения о завершении потока"},
|
||||
{ X502_ERR_CONNECTION_RESET, "Соединение было сброшено другой стороной"},
|
||||
{ X502_ERR_HOST_UNREACHABLE, "Не удалось найти хост с указанным адресом"},
|
||||
{ X502_ERR_TCP_CONNECTION_ERROR, "Ошибка установления TCP-соединения"},
|
||||
|
||||
{ X502_ERR_LDR_FILE_OPEN, "Не удалось открыть файл прошивки BlackFin"},
|
||||
{ X502_ERR_LDR_FILE_READ, "Ошибка чтения из фала прошивки BlackFin"},
|
||||
{ X502_ERR_LDR_FILE_FORMAT, "Неверный формат файла прошивки BlackFin"},
|
||||
{ X502_ERR_LDR_FILE_UNSUP_FEATURE, "Используются возможность LDR-файла, недоступные при записи прошивки BlackFin по HDMA"},
|
||||
{ X502_ERR_LDR_FILE_UNSUP_STARTUP_ADDR, "Неверный стартовый адрес программы в прошивке BlackFin"},
|
||||
{ X502_ERR_BF_REQ_TIMEOUT, "Истек таймаут выполнения запроса на чтения/запись памяти BlackFin"},
|
||||
{ X502_ERR_BF_CMD_IN_PROGRESS, "Команда для BlackFin все еще находится в процессе обработки"},
|
||||
{ X502_ERR_BF_CMD_TIMEOUT, "Истекло время выполнения управляющей команды процессором BlackFin"},
|
||||
{ X502_ERR_BF_CMD_RETURN_INSUF_DATA,"Возвращено недостаточно данных в ответ на команду к BlackFin"},
|
||||
{ X502_ERR_BF_LOAD_RDY_TOUT, "Истек таймаут ожидания готовности процессора BlackFin к записи прошивки"},
|
||||
{ X502_ERR_BF_NOT_PRESENT, "Процессор BlackFin не присутствует на плате"},
|
||||
{ X502_ERR_BF_INVALID_ADDR, "Неверный адрес памяти BlackFin при записи или чтении по HDMA"},
|
||||
{ X502_ERR_BF_INVALID_CMD_DATA_SIZE,"Неверный размер данных, передаваемых с управляющей командой в BlackFin"},
|
||||
|
||||
{ L502_BF_ERR_UNSUP_CMD, "Ошибка BlackFin: неподдерживаемый код команды"},
|
||||
{ L502_BF_ERR_CMD_OVERRUN, "Ошибка BlackFin: запрос на выполнение команды опережает завершение предыдущей"},
|
||||
{ L502_BF_ERR_INVALID_CMD_PARAMS, "Ошибка BlackFin: неверное значение параметров команды"},
|
||||
{ L502_BF_ERR_INSUF_CMD_DATA, "Ошибка BlackFin: недостаточное данных передано с командой"},
|
||||
{ L502_BF_ERR_STREAM_RUNNING, "Ошибка BlackFin: команда не допустима при запущеном сборе"},
|
||||
{ L502_BF_ERR_STREAM_STOPPED, "Ошибка BlackFin: команда допустима только при запущеном сборе"},
|
||||
{ L502_BF_ERR_NO_TEST_IN_PROGR, "Ошибка BlackFin: не выполняется ни одного теста"},
|
||||
{ L502_BF_ERR_TEST_VALUE, "Ошибка BlackFin: неверное значение при выполнении теста"},
|
||||
|
||||
{ E502_CM4_ERR_FPGA_NSTATUS_TOUT, "Ошибка Cortex-M4: При загрузке ПЛИС не удалось дождаться сигнала перехода в режим загрузки"},
|
||||
{ E502_CM4_ERR_FPGA_CONF_DONE_TOUT, "Ошибка Cortex-M4: При загрузке ПЛИС не удалось дождаться сигнала завершения загрузки"},
|
||||
{ E502_CM4_ERR_FPGA_FW_NOT_PRESENT, "Ошибка Cortex-M4: Не обнаружена прошивка ПЛИС во flash-памяти модуля"},
|
||||
{ E502_CM4_ERR_FPGA_REG_NACK, "Ошибка Cortex-M4: Обращение к регистру ПЛИС вернуло ответ NACK"},
|
||||
{ E502_CM4_ERR_FPGA_REG_ERROR, "Ошибка Cortex-M4: Обращение к регистру ПЛИС вернуло ответ ERROR"},
|
||||
{ E502_CM4_ERR_FPGA_REG_WT_TOUT, "Ошибка Cortex-M4: Не удалось дожлаться ответ на обращение к регистру ПЛИС"},
|
||||
{ E502_CM4_ERR_TEST_INVALID_NUM, "Ошибка Cortex-M4: Неподдерживаемый номер теста"},
|
||||
{ E502_CM4_ERR_TEST_VALUE_MISMATH, "Ошибка Cortex-M4: Несовпадение ожидаемых значений при проходе теста"},
|
||||
{ E502_CM4_ERR_TEST_NOT_RUNNING, "Ошибка Cortex-M4: Тест не запущен"},
|
||||
{ E502_CM4_ERR_TEST_ALREADY_RUNNING,"Ошибка Cortex-M4: Tест уже запщен"},
|
||||
{ E502_CM4_ERR_BF_LDR_FILE_SIZE, "Ошибка Cortex-M4: Не удалось найти конец файла прошивки BlackFin"},
|
||||
{ E502_CM4_ERR_LDR_FILE_FORMAT, "Ошибка Cortex-M4: Неверный формат файла прошивки BlackFin"},
|
||||
{ E502_CM4_ERR_LDR_FILE_UNSUP_FEATURE, "Ошибка Cortex-M4: Используются возможность LDR-файла, недоступные при записи прошивки BlackFin по HDMA"},
|
||||
{ E502_CM4_ERR_LDR_FILE_UNSUP_STARTUP_ADDR, "Ошибка Cortex-M4: Неверный стартовый адрес программы в прошивке BlackFin"},
|
||||
{ E502_CM4_ERR_BF_REQ_TIMEOUT, "Ошибка Cortex-M4: Истек таймаут выполнения запроса на чтения/запись памяти BlackFin"},
|
||||
{ E502_CM4_ERR_BF_CMD_IN_PROGRESS, "Ошибка Cortex-M4: Команда для BlackFin все еще находится в процессе обработки"},
|
||||
{ E502_CM4_ERR_BF_CMD_TIMEOUT, "Ошибка Cortex-M4: Истекло время выполнения управляющей команды процессором BlackFin"},
|
||||
{ E502_CM4_ERR_BF_CMD_RETURN_INSUF_DATA, "Ошибка Cortex-M4: Возвращено недостаточно данных в ответ на команду к BlackFin"},
|
||||
{ E502_CM4_ERR_BF_LOAD_RDY_TOUT, "Ошибка Cortex-M4: Истек таймаут ожидания готовности процессора BlackFin к записи прошивки"},
|
||||
{ E502_CM4_ERR_BF_NOT_PRESENT, "Ошибка Cortex-M4: Попытка выполнить операцию для которой нужен сигнальный процессор при отсутствии сигнального процессора в модуле"},
|
||||
{ E502_CM4_ERR_BF_INVALID_ADDR, "Ошибка Cortex-M4: Неверный адрес памяти BlackFin при записи или чтении по HDMA"},
|
||||
{ E502_CM4_ERR_BF_INVALID_CMD_DATA_SIZE, "Ошибка Cortex-M4: Неверный размер данных, передаваемых с управляющей командой в BlackFin"},
|
||||
{ E502_CM4_ERR_UNKNOWN_CMD, "Ошибка Cortex-M4: Неподдерживаемый код команды"},
|
||||
{ E502_CM4_ERR_INVALID_CMD_PARAMS, "Ошибка Cortex-M4: Неверные параметры переданной команды"},
|
||||
{ E502_CM4_ERR_FIRM_BUF_OVERFLOW, "Ошибка Cortex-M4: Переполнение буфера для приема прошивки"},
|
||||
{ E502_CM4_ERR_CMD_SIGNATURE, "Ошибка Cortex-M4: Неверный признак начала команды"},
|
||||
{ E502_CM4_ERR_INVALID_CMD_DATA_SIZE, "Ошибка Cortex-M4: Неверное количество данных в команде"},
|
||||
{ E502_CM4_ERR_FLASH_PROT_CODE, "Ошибка Cortex-M4: Неверный код настройки защиты Flash-памяти"},
|
||||
{ E502_CM4_ERR_FLASH_OP, "Ошибка Cortex-M4: Ошибка выполнения операции с Flash-памятью"},
|
||||
{ E502_CM4_ERR_FLASH_DATA_COMPARE, "Ошибка Cortex-M4: Ошибка сравнения записанных данных во Flash-память"},
|
||||
{ E502_CM4_ERR_INVALID_PASSWORD, "Ошибка Cortex-M4: Неверный пароль для изменения сетевых настроек"},
|
||||
{ E502_CM4_ERR_FPGA_NOT_LOADED, "Ошибка Cortex-M4: ПЛИС не был загружен"},
|
||||
{ E502_CM4_ERR_FLASH_SET_PROT_BITS, "Ошибка Cortex-M4: Не удалось изменить занчения битов защиты Flash-памяти"},
|
||||
{ E502_CM4_ERR_FPGA_FW_INVALID_TEMP_RANGE, "Ошибка Cortex-M4: Загруженная прошивка ПЛИС предназначена для другого темп. исполнения"},
|
||||
{ E502_CM4_ERR_M0_STREAM_START_REQ, "Ошибка Cortex-M4: Нет ответа на запрос запуска потока от ядра Cortex-M0"},
|
||||
{ E502_CM4_ERR_M0_STREAM_STOP_REQ, "Ошибка Cortex-M4: Нет ответа на запрос останова потока от ядра Cortex-M0"},
|
||||
{ E502_CM4_ERR_OUT_STREAM_RUNNING, "Ошибка Cortex-M4: Уже запущен вывод в потоковом режиме"},
|
||||
{ E502_CM4_ERR_OUT_NO_CYCLE_BUF, "Ошибка Cortex-M4: Нет свободного буфера для циклического режима. Не произошла смена страниц"},
|
||||
{ E502_CM4_ERR_OUT_CYCLE_BUF_SIZE, "Ошибка Cortex-M4: Задан слишком большой размер циклического буфера"},
|
||||
{ E502_CM4_ERR_OUT_CYCLE_NOT_LOADED, "Ошибка Cortex-M4: Не был полностью загружен циклический буфер перед сменой"}
|
||||
};
|
||||
|
||||
|
||||
X502_EXPORT(const char*) X502_GetErrorString(int32_t err) {
|
||||
size_t i;
|
||||
const char *str = f_unknow_err;
|
||||
|
||||
for (i=0; (i < sizeof(f_err_tbl)/sizeof(f_err_tbl[0])) && (str==f_unknow_err); i++) {
|
||||
if (f_err_tbl[i].err == err)
|
||||
str = f_err_tbl[i].str;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
310
x502/x502api_private.h
Normal file
310
x502/x502api_private.h
Normal file
@ -0,0 +1,310 @@
|
||||
#ifndef X502API_PRIVATE_H
|
||||
#define X502API_PRIVATE_H
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "x502api.h"
|
||||
#include "osspec.h"
|
||||
#include "l502_bf_cmd_defs.h"
|
||||
#include "x502_fpga_regs.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct st_x502_devrec_inptr {
|
||||
const void *iface;
|
||||
void *iface_data;
|
||||
};
|
||||
|
||||
#define E16_DEVICE_NAME "E16"
|
||||
|
||||
#define X502_SIGN 0xA55A0502
|
||||
|
||||
|
||||
#define X502_CHECK_HND(hnd) ((hnd!=NULL) ? (hnd)->sign == X502_SIGN ? X502_ERR_OK \
|
||||
: X502_ERR_INVALID_HANDLE : X502_ERR_INVALID_HANDLE)
|
||||
|
||||
#define X502_CHECK_HND_OPENED(hnd) ((hnd!=NULL) ? (hnd)->sign == X502_SIGN ? \
|
||||
(((hnd)->flags & PRIV_FLAGS_OPENED) ? X502_ERR_OK : X502_ERR_DEVICE_NOT_OPENED) \
|
||||
: X502_ERR_INVALID_HANDLE : X502_ERR_INVALID_HANDLE)
|
||||
|
||||
|
||||
|
||||
|
||||
/* на сколько секунд данных будет рассчитан внутренний буфер */
|
||||
#define X502_DMA_IN_BUF_FOR_SEC 4
|
||||
/* максимальное кол-во прерываний в секунду */
|
||||
#define X502_DMA_IN_MAX_IRQ_PER_SEC 20
|
||||
|
||||
#define X502_DMA_OUT_BUF_SIZE (3*3*1024*1024)
|
||||
#define X502_DMA_OUT_IRQ_STEP (3*1024*1024/32)
|
||||
|
||||
|
||||
|
||||
#define X502_MUTEX_CFG_LOCK_TOUT 1000
|
||||
|
||||
#define X502_OUT_CYCLE_WAIT_TOUT 20000
|
||||
|
||||
|
||||
#define X502_STREAM_CH_CNT 2
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define SLEEP_MS(ms) Sleep(ms)
|
||||
#else
|
||||
#define SLEEP_MS(ms) usleep(ms*1000)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/** параметры канала потока данных */
|
||||
typedef struct {
|
||||
uint32_t buf_size; /** размер временного буфера */
|
||||
uint32_t step; /** через сколько переданных отсчетов будет генерироваться прерывание */
|
||||
} t_x502_stream_ch_params;
|
||||
|
||||
|
||||
|
||||
typedef int32_t (*t_x502_iface_free_devinfo_ptr)(t_x502_devrec_inptr *devinfo_ptr);
|
||||
|
||||
typedef int32_t (*t_x502_iface_open)(t_x502_hnd hnd, const t_x502_devrec *devinfo);
|
||||
typedef int32_t (*t_x502_iface_close)(t_x502_hnd hnd);
|
||||
typedef int32_t (*t_x502_iface_fpga_reg_read)(t_x502_hnd hnd, uint32_t addr, uint32_t *val);
|
||||
typedef int32_t (*t_x502_iface_fpga_reg_write)(t_x502_hnd hnd, uint32_t addr, uint32_t val);
|
||||
|
||||
typedef int32_t (*t_x502_iface_stream_cfg)(t_x502_hnd hnd, uint32_t ch, t_x502_stream_ch_params *pars);
|
||||
typedef int32_t (*t_x502_iface_stream_start)(t_x502_hnd hnd, uint32_t ch, uint32_t flags);
|
||||
typedef int32_t (*t_x502_iface_stream_stop)(t_x502_hnd hnd, uint32_t ch, uint32_t flags);
|
||||
typedef int32_t (*t_x502_iface_stream_free)(t_x502_hnd hnd, uint32_t ch, uint32_t flags);
|
||||
typedef int32_t (*t_x502_iface_stream_running)(t_x502_hnd hnd, uint32_t ch, int32_t* running);
|
||||
typedef int32_t (*t_x502_iface_stream_read)(t_x502_hnd hnd, uint32_t *buf, uint32_t size, uint32_t tout);
|
||||
typedef int32_t (*t_x502_iface_stream_write)(t_x502_hnd hnd, const uint32_t *buf, uint32_t size, uint32_t tout);
|
||||
typedef int32_t (*t_x502_iface_stream_get_rdy_cnt)(t_x502_hnd hnd, uint32_t ch, uint32_t *rdy_cnt);
|
||||
|
||||
typedef int32_t (*t_x502_iface_bf_mem_block_rd)(t_x502_hnd hnd, uint32_t addr, uint32_t *block, uint32_t size);
|
||||
typedef int32_t (*t_x502_iface_bf_mem_block_wr)(t_x502_hnd hnd, uint32_t addr, const uint32_t *block, uint32_t size);
|
||||
typedef int32_t (*t_x502_iface_bf_firm_load)(t_x502_hnd hnd, const char* filename);
|
||||
|
||||
typedef int32_t (*t_x502_iface_flash_rd)(t_x502_hnd hnd, uint32_t addr, uint8_t* data, uint32_t size);
|
||||
typedef int32_t (*t_x502_iface_flash_wr)(t_x502_hnd hnd, uint32_t addr, const uint8_t* data, uint32_t size);
|
||||
typedef int32_t (*t_x502_iface_flash_erase)(t_x502_hnd hnd, uint32_t addr, uint32_t size);
|
||||
typedef int32_t (*t_x502_iface_flash_set_prot)(t_x502_hnd hnd, uint32_t flags,
|
||||
const uint8_t* prot_data, uint32_t size);
|
||||
|
||||
|
||||
typedef int32_t (*t_x502_iface_reload_devinfo)(t_x502_hnd hnd);
|
||||
|
||||
typedef int32_t (*t_x502_iface_cycle_load_start)(t_x502_hnd hnd, uint32_t size);
|
||||
typedef int32_t (*t_x502_iface_cycle_setup)(t_x502_hnd hnd, uint32_t flags);
|
||||
typedef int32_t (*t_x502_iface_cycle_stop)(t_x502_hnd hnd, uint32_t flags);
|
||||
typedef int32_t (*t_x502_iface_cycle_check_setup)(t_x502_hnd hnd, uint32_t *done);
|
||||
|
||||
|
||||
typedef int32_t (*t_x502_iface_gen_ioctl)(t_x502_hnd hnd, uint32_t cmd_code, uint32_t param,
|
||||
const void* snd_data, uint32_t snd_size,
|
||||
void* rcv_data, uint32_t recv_size,
|
||||
uint32_t* recvd_size, uint32_t tout);
|
||||
|
||||
typedef int32_t (*t_x502_iface_check_feature)(t_x502_hnd hnd, uint32_t feature);
|
||||
|
||||
typedef int32_t (*t_x502_iface_fpga_mode_init)(t_x502_hnd hnd);
|
||||
|
||||
typedef enum {
|
||||
X502_STREAM_FLAG_SINGLE = 0x01,
|
||||
X502_STREAM_FLAG_NO_REQUEST = 0x02
|
||||
} t_x502_streams_flags;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16_t id_reg_addr;
|
||||
uint16_t in_stream_buf_min;
|
||||
uint16_t ioctl_max_data_size;
|
||||
uint16_t bf_mem_block_size;
|
||||
uint16_t flash_rd_size; /**< Максимальный размер чтения из flash-памяти за один запрос */
|
||||
uint16_t flash_wr_size; /**< Максимальный размер записи во flash-память за один запрос */
|
||||
t_x502_iface_free_devinfo_ptr free_devinfo_ptr;
|
||||
t_x502_iface_open open;
|
||||
t_x502_iface_close close;
|
||||
t_x502_iface_fpga_reg_read fpga_reg_read;
|
||||
t_x502_iface_fpga_reg_write fpga_reg_write;
|
||||
t_x502_iface_stream_cfg stream_cfg;
|
||||
t_x502_iface_stream_start stream_start;
|
||||
t_x502_iface_stream_stop stream_stop;
|
||||
t_x502_iface_stream_free stream_free;
|
||||
t_x502_iface_stream_running stream_running;
|
||||
t_x502_iface_stream_read stream_read;
|
||||
t_x502_iface_stream_write stream_write;
|
||||
t_x502_iface_stream_get_rdy_cnt stream_get_rdy_cnt;
|
||||
t_x502_iface_bf_mem_block_rd bf_mem_block_rd;
|
||||
t_x502_iface_bf_mem_block_wr bf_mem_block_wr;
|
||||
t_x502_iface_bf_firm_load bf_firm_load;
|
||||
t_x502_iface_flash_rd flash_rd;
|
||||
t_x502_iface_flash_wr flash_wr;
|
||||
t_x502_iface_flash_erase flash_erase;
|
||||
t_x502_iface_flash_set_prot flash_set_prot;
|
||||
t_x502_iface_reload_devinfo reload_dev_info;
|
||||
t_x502_iface_cycle_load_start cycle_load_start;
|
||||
t_x502_iface_cycle_setup cycle_setup;
|
||||
t_x502_iface_cycle_stop cycle_stop;
|
||||
t_x502_iface_cycle_check_setup cycle_check_setup;
|
||||
t_x502_iface_fpga_mode_init fpga_mode_init;
|
||||
t_x502_iface_gen_ioctl gen_ioctl;
|
||||
t_x502_iface_check_feature check_feature;
|
||||
} t_x502_dev_iface;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef enum {
|
||||
STREAM_IN_WRD_ADC = 0,
|
||||
STREAM_IN_WRD_DIN = 1,
|
||||
STREAM_IN_WRD_MSG = 2,
|
||||
STREAM_IN_WRD_USR = 3,
|
||||
STREAM_IN_WRD_TSP = 4,
|
||||
} t_stream_in_wrd_type;
|
||||
|
||||
|
||||
|
||||
typedef enum {
|
||||
PRIV_FLAGS_OPENED = 0x0001,
|
||||
PRIV_FLAGS_PRELOAD_DONE = 0x0002,
|
||||
PRIV_FLAGS_CYCLE_MODE = 0x0004,
|
||||
PRIV_FLAGS_STREAM_RUN = 0x0080
|
||||
} t_x502_state_flags;
|
||||
|
||||
typedef enum {
|
||||
X502_RELOAD_FLAGS_NO_DAC = 0x0001,
|
||||
X502_RELOAD_FLAGS_NO_ADC = 0x0002
|
||||
} t_x502_reload_flags;
|
||||
|
||||
/** структура, описывающая параметры логического канала */
|
||||
typedef struct {
|
||||
uint32_t ch; /** физический номер канала */
|
||||
uint32_t mode; /** режим работы канала из #t_l502_ch_mode */
|
||||
uint32_t range; /** диапазон измерения */
|
||||
uint32_t avg; /** коэффициент усреднения */
|
||||
} t_x502_lch;
|
||||
|
||||
typedef struct {
|
||||
t_x502_lch lch[X502_LTABLE_MAX_CH_CNT];
|
||||
uint32_t lch_cnt;
|
||||
uint32_t adc_freq_div;
|
||||
uint32_t adc_frame_delay;
|
||||
uint32_t din_freq_div;
|
||||
uint32_t sync_mode;
|
||||
uint32_t sync_start_mode;
|
||||
uint32_t ref_freq;
|
||||
double ext_ref_freq;
|
||||
uint32_t out_freq_div;
|
||||
uint32_t adc_sync_ch;
|
||||
uint32_t adc_sync_range;
|
||||
uint32_t adc_sync_mode;
|
||||
double adc_sync_val;
|
||||
double dac_range;
|
||||
uint32_t dac_code_max;
|
||||
uint32_t adc_code_max;
|
||||
const double *f_scales;
|
||||
} t_x502_settings;
|
||||
|
||||
|
||||
|
||||
typedef struct st_x502 {
|
||||
uint32_t sign; /* признак описателя L502/E502 */
|
||||
t_x502_iface iface;
|
||||
const t_x502_dev_iface *iface_hnd;
|
||||
void *iface_data;
|
||||
t_x502_state_flags flags; /* флаги состояния платы */
|
||||
t_x502_streams streams; /* какие синхронные потоки разрешены */
|
||||
t_x502_mode mode; /* режим работы (через ПЛИС или DSP) */
|
||||
t_x502_info info;
|
||||
t_x502_settings set; /* настройки платы */
|
||||
|
||||
t_x502_stream_ch_params stream_pars[X502_STREAM_CH_CNT];
|
||||
|
||||
uint32_t last_dout; /* последнее выданное значение на DIGOUT */
|
||||
uint32_t proc_adc_ch; /* ожидаемый логический канал для следующей ProcessData() */
|
||||
|
||||
|
||||
t_mutex mutex_cfg; /* мьютекс для доступа к полям параметров и состояния модуля */
|
||||
t_mutex mutex_bf; /* мьютекс для доступа к памяти сигнального процессора */
|
||||
|
||||
uint32_t bf_ver; /* версия прошивки BlackFin, если есть */
|
||||
uint32_t bf_features; /* дополниельные возможности, поддерживаемые прошивкой */
|
||||
} t_x502;
|
||||
|
||||
|
||||
typedef int32_t (APIENTRY *t_x502_get_devinfo_list_cb)(t_x502_devrec* list, uint32_t size,
|
||||
uint32_t flags, uint32_t* devcnt);
|
||||
|
||||
|
||||
|
||||
bool x502_is_E16(t_x502_hnd hnd);
|
||||
|
||||
int x502_check_eeprom(t_x502_hnd hnd, uint32_t flags);
|
||||
|
||||
X502_EXPORT(int32_t) X502_DevRecordInit(t_x502_devrec *info);
|
||||
X502_EXPORT(int32_t) X502_Open(t_x502_hnd hnd, const char* serial,
|
||||
const char *devname, t_x502_get_devinfo_list_cb get_list);
|
||||
X502_EXPORT(int32_t) X502_GetSerialList(char serials[][X502_SERIAL_SIZE], uint32_t size,
|
||||
uint32_t flags, uint32_t *devcnt, const char *devname,
|
||||
t_x502_get_devinfo_list_cb get_list);
|
||||
|
||||
X502_EXPORT(int32_t) X502_FpgaRegWrite(t_x502_hnd hnd, uint32_t reg, uint32_t val);
|
||||
X502_EXPORT(int32_t) X502_FpgaRegRead(t_x502_hnd hnd, uint32_t reg, uint32_t *val);
|
||||
X502_EXPORT(int32_t) X502_ReloadDevInfo(t_x502_hnd hnd, uint32_t flags);
|
||||
|
||||
int32_t bf_fpga_reg_rd(t_x502_hnd hnd, uint32_t addr, uint32_t* val);
|
||||
int32_t bf_fpga_reg_wr(t_x502_hnd hnd, uint32_t addr, uint32_t val);
|
||||
|
||||
#define x502_bf_set_par(hnd, par, data, size) X502_BfExecCmd(hnd, L502_BF_CMD_CODE_SET_PARAM, \
|
||||
par, data, size, NULL, 0, X502_BF_CMD_DEFAULT_TOUT, NULL)
|
||||
|
||||
#define x502_bf_get_par(hnd, par, data, size) X502_BfExecCmd(hnd, L502_BF_CMD_CODE_GET_PARAM, \
|
||||
par, NULL, 0, data, size, X502_BF_CMD_DEFAULT_TOUT, NULL)
|
||||
|
||||
|
||||
|
||||
|
||||
#define FILL_HARD_ID_FLAGS(devflags, hard_id) do { \
|
||||
if (hard_id & 0x01) { \
|
||||
devflags |= X502_DEVFLAGS_DAC_PRESENT; \
|
||||
} else { \
|
||||
devflags &= ~X502_DEVFLAGS_DAC_PRESENT; \
|
||||
} \
|
||||
if (hard_id & 0x02) { \
|
||||
devflags |= X502_DEVFLAGS_GAL_PRESENT; \
|
||||
} else { \
|
||||
devflags &= ~X502_DEVFLAGS_GAL_PRESENT; \
|
||||
} \
|
||||
if (hard_id & 0x04) {\
|
||||
devflags |= X502_DEVFLAGS_BF_PRESENT; \
|
||||
} else { \
|
||||
devflags &= ~X502_DEVFLAGS_BF_PRESENT; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define STREAM_OUT_IRQ_STEP(hnd) (hnd->stream_pars[X502_STREAM_CH_OUT].step ? \
|
||||
hnd->stream_pars[X502_STREAM_CH_OUT].step : \
|
||||
X502_DMA_OUT_IRQ_STEP/hnd->set.out_freq_div)
|
||||
|
||||
#define STREAM_OUT_CFG(hnd, err) do { \
|
||||
t_x502_stream_ch_params params; \
|
||||
memset(¶ms, 0, sizeof(params)); \
|
||||
params.buf_size = hnd->stream_pars[X502_STREAM_CH_OUT].buf_size ? \
|
||||
hnd->stream_pars[X502_STREAM_CH_OUT].buf_size : \
|
||||
X502_DMA_OUT_BUF_SIZE; \
|
||||
params.step = STREAM_OUT_IRQ_STEP(hnd); \
|
||||
err = hnd->iface_hnd->stream_cfg(hnd, X502_STREAM_CH_OUT, ¶ms); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#endif // X502API_PRIVATE_H
|
||||
717
x502/x502api_streams.c
Normal file
717
x502/x502api_streams.c
Normal file
@ -0,0 +1,717 @@
|
||||
#include "x502api_private.h"
|
||||
#include "x502_fpga_regs.h"
|
||||
#include "l502_bf_cmd_defs.h"
|
||||
#include "ltimer.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
/* разрешение/запрещение потоков ввода вывода в соответствии с полем hnd->streams */
|
||||
static int32_t f_set_streams(t_x502_hnd hnd, uint32_t streams) {
|
||||
int32_t err = X502_ERR_OK;
|
||||
if (hnd->mode == X502_MODE_FPGA) {
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOARITH_IN_STREAM_ENABLE,
|
||||
(streams & X502_STREAM_ADC ? 0x01 : 0) |
|
||||
(streams & X502_STREAM_DIN ? 0x02 : 0));
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
hnd->streams = streams;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Функция автоматического рассчета параметов DMA для входного потока
|
||||
на основе частоты сбора данных */
|
||||
static int32_t f_stream_in_cfg(t_x502 *hnd) {
|
||||
int32_t err = X502_ERR_OK;
|
||||
|
||||
|
||||
t_x502_stream_ch_params params;
|
||||
double din_freq = 0;
|
||||
uint32_t total_size = 0;
|
||||
double ref_freq;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
||||
X502_GetRefFreqValue(hnd, &ref_freq);
|
||||
|
||||
/* рассчитываем частоту сбора для потоков АЦП и DIN */
|
||||
if (hnd->streams & X502_STREAM_ADC) {
|
||||
double f_frame;
|
||||
X502_GetAdcFreq(hnd, NULL, &f_frame);
|
||||
din_freq = f_frame*hnd->set.lch_cnt;
|
||||
}
|
||||
|
||||
if (hnd->streams & X502_STREAM_DIN) {
|
||||
din_freq+=ref_freq/hnd->set.din_freq_div;
|
||||
}
|
||||
|
||||
/* размер полного буфера определяем таким, чтобы его хватило на
|
||||
L502_DMA_IN_BUF_FOR_SEC секунд постоянного сбора, но не меньше минимального
|
||||
размера */
|
||||
total_size = (uint32_t)(X502_DMA_IN_BUF_FOR_SEC*din_freq);
|
||||
if (total_size < hnd->iface_hnd->in_stream_buf_min)
|
||||
total_size = hnd->iface_hnd->in_stream_buf_min;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* рассчитываем IRQ_STEP, чтобы он был L502_DMA_IN_MAX_IRQ_PER_SEC
|
||||
в секунду */
|
||||
|
||||
params.step = hnd->stream_pars[X502_STREAM_CH_IN].step ?
|
||||
hnd->stream_pars[X502_STREAM_CH_IN].step :
|
||||
(din_freq>X502_DMA_IN_MAX_IRQ_PER_SEC) ?
|
||||
(uint32_t)(din_freq/X502_DMA_IN_MAX_IRQ_PER_SEC) : 1;
|
||||
|
||||
/* для эффиктивности делаем размер буфера кратным irq_step */
|
||||
total_size = ((total_size+params.step-1)/params.step)*params.step;
|
||||
|
||||
params.buf_size = hnd->stream_pars[X502_STREAM_CH_IN].buf_size ?
|
||||
hnd->stream_pars[X502_STREAM_CH_IN].buf_size : total_size;
|
||||
|
||||
err = hnd->iface_hnd->stream_cfg(hnd, X502_STREAM_CH_IN, ¶ms);
|
||||
|
||||
if ((err == X502_ERR_OK) && (hnd->mode == X502_MODE_DSP)) {
|
||||
/* для BlackFin нужно так же установить еще шаг прерываний для
|
||||
приема данных от SPORT'а */
|
||||
uint32_t size;
|
||||
err = x502_bf_get_par(hnd, L502_BF_PARAM_IN_BUF_SIZE, &size, 1);
|
||||
if (err == X502_ERR_OK) {
|
||||
uint32_t instep = params.step;
|
||||
if (instep>size/4) {
|
||||
instep=size/4;
|
||||
}
|
||||
if (instep > 0x8000)
|
||||
instep = 0x8000;
|
||||
err = x502_bf_set_par(hnd, L502_BF_PARAM_IN_STEP_SIZE, &instep, 1);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int32_t f_out_stream_preload(t_x502 *hnd) {
|
||||
int32_t err;
|
||||
STREAM_OUT_CFG(hnd, err);
|
||||
if (err == X502_ERR_OK)
|
||||
err = hnd->iface_hnd->stream_start(hnd, X502_STREAM_CH_OUT, 0);
|
||||
|
||||
if ((err == X502_ERR_OK) && (hnd->mode == X502_MODE_DSP)) {
|
||||
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_PRELOAD, 0, NULL, 0,
|
||||
NULL, 0, X502_BF_REQ_TOUT, NULL);
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
hnd->flags |= PRIV_FLAGS_PRELOAD_DONE;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_StreamsEnable(t_x502_hnd hnd, uint32_t streams) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK)
|
||||
err = osspec_mutex_lock(hnd->mutex_cfg, X502_MUTEX_CFG_LOCK_TOUT);
|
||||
if (err == X502_ERR_OK) {
|
||||
if (hnd->mode == X502_MODE_DSP) {
|
||||
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_STREAM_EN, streams,
|
||||
NULL, 0, NULL, 0, X502_BF_REQ_TOUT, NULL);
|
||||
if (err == X502_ERR_OK)
|
||||
hnd->streams |= streams;
|
||||
} else {
|
||||
if (hnd->flags & PRIV_FLAGS_STREAM_RUN) {
|
||||
uint32_t old_streams = hnd->streams;
|
||||
hnd->streams |= streams;
|
||||
|
||||
/* если не было разрешено потока на ввод до этого,
|
||||
а при вызове стал разрешен => инициализируем его */
|
||||
if ((err == X502_ERR_OK) && !(old_streams & X502_STREAM_ALL_IN) &&
|
||||
(streams & X502_STREAM_ALL_IN)) {
|
||||
err = f_stream_in_cfg(hnd);
|
||||
if (err == X502_ERR_OK)
|
||||
err = hnd->iface_hnd->stream_start(hnd, X502_STREAM_CH_IN, 0);
|
||||
} else if ((err == X502_ERR_OK) && ((old_streams & X502_STREAM_ALL_IN) !=
|
||||
(streams & X502_STREAM_ALL_IN))) {
|
||||
err =f_stream_in_cfg(hnd);
|
||||
}
|
||||
|
||||
|
||||
/* Запись в регистры плиса имеет смысл делать только перед запуском
|
||||
или во время запуска синхронного сбора, т.к. пока сбор не запущен
|
||||
- не вляют. но в старых версиях ПЛИС могли приводит к сдвигу по
|
||||
времени первого отсчета АЦП.
|
||||
Разрешение потока в ПЛИС следует делать уже после stream_start,
|
||||
чтобы ПК был готов принимать данные */
|
||||
err = f_set_streams(hnd, hnd->streams | streams);
|
||||
} else {
|
||||
hnd->streams |= streams;
|
||||
}
|
||||
}
|
||||
osspec_mutex_release(hnd->mutex_cfg);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_StreamsDisable(t_x502_hnd hnd, uint32_t streams) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK)
|
||||
err = osspec_mutex_lock(hnd->mutex_cfg, X502_MUTEX_CFG_LOCK_TOUT);
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
if (hnd->mode == X502_MODE_DSP) {
|
||||
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_STREAM_DIS, streams,
|
||||
NULL, 0, NULL, 0, X502_BF_REQ_TOUT, NULL);
|
||||
if (err == X502_ERR_OK)
|
||||
hnd->streams &= ~streams;
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
if (hnd->flags & PRIV_FLAGS_STREAM_RUN) {
|
||||
uint32_t old_streams = hnd->streams;
|
||||
err = f_set_streams(hnd, hnd->streams & ~streams);
|
||||
/* если все потоки на ввод были запрещены, то
|
||||
останавливаем их */
|
||||
if ((err == X502_ERR_OK) && (old_streams & X502_STREAM_ALL_IN) &&
|
||||
!(hnd->streams & X502_STREAM_ALL_IN)) {
|
||||
err = hnd->iface_hnd->stream_stop(hnd, X502_STREAM_CH_IN, 0);
|
||||
}
|
||||
|
||||
if ((err == X502_ERR_OK) && (old_streams & X502_STREAM_ALL_OUT) &&
|
||||
!(hnd->streams & X502_STREAM_ALL_OUT)) {
|
||||
err = hnd->iface_hnd->stream_stop(hnd, X502_STREAM_CH_OUT, 0);
|
||||
if (err == X502_ERR_OK) {
|
||||
hnd->flags &= ~PRIV_FLAGS_PRELOAD_DONE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hnd->streams &= ~streams;
|
||||
}
|
||||
}
|
||||
|
||||
osspec_mutex_release(hnd->mutex_cfg);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_GetEnabledStreams(t_x502_hnd hnd, uint32_t* streams) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if ((err == X502_ERR_OK) && (streams == NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
if (err == X502_ERR_OK)
|
||||
*streams = hnd->streams;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_StreamsStart(t_x502_hnd hnd) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if ((err == X502_ERR_OK) && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
|
||||
if ((err == X502_ERR_OK) && (hnd->mode==X502_MODE_FPGA)) {
|
||||
uint32_t reg;
|
||||
err = hnd->iface_hnd->fpga_reg_read(hnd, X502_REGS_IOHARD_IO_MODE, ®);
|
||||
if ((err == X502_ERR_OK) && !(reg & X502_REGBIT_ADC_SLV_CLK_LOCK_Msk))
|
||||
err = X502_ERR_REF_FREQ_NOT_LOCKED;
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK)
|
||||
err = osspec_mutex_lock(hnd->mutex_cfg, X502_MUTEX_CFG_LOCK_TOUT);
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
int in_started = 0;
|
||||
f_set_streams(hnd, hnd->streams);
|
||||
|
||||
/** @todo корректные действия, если сбор в Bf не остановлен */
|
||||
|
||||
/* выполняем предзагрузку первого слова выходного потока и
|
||||
коммутатора АЦП (при наличии DSP это делает DSP) */
|
||||
if ((err == X502_ERR_OK) && (hnd->mode==X502_MODE_FPGA)) {
|
||||
/* предзагрузку значения на вывод делаем только если реально данные уже были
|
||||
* предзагружены в буфер платы */
|
||||
if ((hnd->streams & X502_STREAM_ALL_OUT) &&
|
||||
(hnd->flags & (PRIV_FLAGS_PRELOAD_DONE | PRIV_FLAGS_CYCLE_MODE))) {
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_OUTSWAP_BFCTL, 1);
|
||||
}
|
||||
|
||||
|
||||
/* Предзагрузку АЦП должны делать всегда, так как по этой функции
|
||||
выполняется часть инициализации параметров синхронного сбора!
|
||||
|
||||
Так как конвейер автомата управления входной коммутации АЦП состоит
|
||||
из 2-х стадий, для корректного синхронного старта необходимо в
|
||||
ыполнить два раза предзагрузку. В противном случае,
|
||||
время момента первого отсчета может не совпадать с моментом
|
||||
запуска синхронизации
|
||||
*/
|
||||
if (err == X502_ERR_OK)
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_PRELOAD_ADC, 1);
|
||||
if (err == X502_ERR_OK)
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_PRELOAD_ADC, 1);
|
||||
SLEEP_MS(20);
|
||||
}
|
||||
|
||||
|
||||
/* запуск потока на ввод выполняем при запуске синхронного ввода-вывода */
|
||||
if ((err == X502_ERR_OK) && (hnd->streams & X502_STREAM_ALL_IN)) {
|
||||
err = f_stream_in_cfg(hnd);
|
||||
if (err == X502_ERR_OK)
|
||||
err = hnd->iface_hnd->stream_start(hnd, X502_STREAM_CH_IN, 0);
|
||||
if (err == X502_ERR_OK)
|
||||
in_started = 1;
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
if (hnd->mode == X502_MODE_FPGA) {
|
||||
/* взводим сигнал GO, указывающий что запущен синхронных ввод-вывод */
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_GO_SYNC_IO, 1);
|
||||
} else if (hnd->mode == X502_MODE_DSP) {
|
||||
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_STREAM_START, 0,
|
||||
NULL, 0, NULL, 0, X502_BF_CMD_DEFAULT_TOUT, NULL);
|
||||
} else {
|
||||
err = X502_ERR_INVALID_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
if (err && in_started) {
|
||||
hnd->iface_hnd->stream_free(hnd, X502_STREAM_CH_IN, 0);
|
||||
}
|
||||
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
hnd->flags |= PRIV_FLAGS_STREAM_RUN;
|
||||
hnd->proc_adc_ch = 0;
|
||||
}
|
||||
|
||||
osspec_mutex_release(hnd->mutex_cfg);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_StreamsStop(t_x502_hnd hnd) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK)
|
||||
err = osspec_mutex_lock(hnd->mutex_cfg, X502_MUTEX_CFG_LOCK_TOUT);
|
||||
if (err == X502_ERR_OK) {
|
||||
int32_t stop_err1, stop_err2;
|
||||
|
||||
if (hnd->mode==X502_MODE_FPGA) {
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_GO_SYNC_IO, 0);
|
||||
} else if (hnd->mode == X502_MODE_DSP) {
|
||||
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_STREAM_STOP, 0,
|
||||
NULL, 0, NULL, 0, X502_BF_CMD_DEFAULT_TOUT, NULL);
|
||||
}
|
||||
|
||||
stop_err1 = hnd->iface_hnd->stream_free(hnd, X502_STREAM_CH_IN, 0);
|
||||
stop_err2 = hnd->iface_hnd->stream_free(hnd, X502_STREAM_CH_OUT, 0);
|
||||
if (err == X502_ERR_OK)
|
||||
err = stop_err1;
|
||||
if (err == X502_ERR_OK)
|
||||
err = stop_err2;
|
||||
|
||||
hnd->flags &= ~(PRIV_FLAGS_STREAM_RUN | PRIV_FLAGS_PRELOAD_DONE | PRIV_FLAGS_CYCLE_MODE);
|
||||
|
||||
osspec_mutex_release(hnd->mutex_cfg);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_IsRunning(t_x502_hnd hnd) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
uint32_t bf_mode=0;
|
||||
if ((err == X502_ERR_OK) && (hnd->mode==X502_MODE_DSP)) {
|
||||
err = x502_bf_get_par(hnd, L502_BF_PARAM_STREAM_MODE, &bf_mode, 1);
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK)
|
||||
err = osspec_mutex_lock(hnd->mutex_cfg, X502_MUTEX_CFG_LOCK_TOUT);
|
||||
if (err == X502_ERR_OK) {
|
||||
if (hnd->mode==X502_MODE_DSP) {
|
||||
if (bf_mode==L502_BF_MODE_IDLE) {
|
||||
hnd->flags &= ~PRIV_FLAGS_STREAM_RUN;
|
||||
} else {
|
||||
hnd->flags |= PRIV_FLAGS_STREAM_RUN;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(hnd->flags & PRIV_FLAGS_STREAM_RUN))
|
||||
err = X502_ERR_STREAM_IS_NOT_RUNNING;
|
||||
|
||||
osspec_mutex_release(hnd->mutex_cfg);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_Recv(t_x502_hnd hnd, uint32_t* buf, uint32_t size, uint32_t tout) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if ((err == X502_ERR_OK) && (buf==NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
if (err == X502_ERR_OK) {
|
||||
err = hnd->iface_hnd->stream_read(hnd, buf, size, tout);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_Send(t_x502_hnd hnd, const uint32_t* buf, uint32_t size, uint32_t tout) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if ((err == X502_ERR_OK) && (buf==NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
|
||||
/* если разрешен синхронный вывод, но не было
|
||||
* вызова X502_PreloadStart() или не был установлен синхронных режим, то
|
||||
* делаем запуск потока вывода при первой записи */
|
||||
if ((err == X502_ERR_OK) && (hnd->streams & X502_STREAM_ALL_OUT)) {
|
||||
if (err == X502_ERR_OK)
|
||||
err = osspec_mutex_lock(hnd->mutex_cfg, X502_MUTEX_CFG_LOCK_TOUT);
|
||||
if (err == X502_ERR_OK) {
|
||||
if (!(hnd->flags & (PRIV_FLAGS_PRELOAD_DONE | PRIV_FLAGS_CYCLE_MODE))) {
|
||||
err = f_out_stream_preload(hnd);
|
||||
}
|
||||
osspec_mutex_release(hnd->mutex_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
err = hnd->iface_hnd->stream_write(hnd, buf, size, tout);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t)X502_PreloadStart(t_x502_hnd hnd) {
|
||||
int err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK)
|
||||
err = osspec_mutex_lock(hnd->mutex_cfg, X502_MUTEX_CFG_LOCK_TOUT);
|
||||
if (err == X502_ERR_OK) {
|
||||
err = f_out_stream_preload(hnd);
|
||||
osspec_mutex_release(hnd->mutex_cfg);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_GetRecvReadyCount(t_x502_hnd hnd, uint32_t *rdy_cnt) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if ((err == X502_ERR_OK) && (rdy_cnt==NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
if (err == X502_ERR_OK)
|
||||
err = hnd->iface_hnd->stream_get_rdy_cnt(hnd, X502_STREAM_CH_IN, rdy_cnt);
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_GetSendReadyCount(t_x502_hnd hnd, uint32_t *rdy_cnt) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if ((err == X502_ERR_OK) && (rdy_cnt==NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
if (err == X502_ERR_OK)
|
||||
err = hnd->iface_hnd->stream_get_rdy_cnt(hnd, X502_STREAM_CH_OUT, rdy_cnt);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int32_t f_check_stream_ch_par_en(t_x502_hnd hnd, uint32_t stream_ch) {
|
||||
int32_t err = 0;
|
||||
if (stream_ch == X502_STREAM_CH_IN) {
|
||||
if ((hnd->flags & PRIV_FLAGS_STREAM_RUN)
|
||||
&& (hnd->streams & X502_STREAM_ALL_IN)) {
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
}
|
||||
} else if (stream_ch == X502_STREAM_CH_OUT) {
|
||||
if ((hnd->flags & (PRIV_FLAGS_PRELOAD_DONE | PRIV_FLAGS_STREAM_RUN))
|
||||
&& (hnd->streams & X502_STREAM_ALL_OUT)) {
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
}
|
||||
} else {
|
||||
err = X502_ERR_INVALID_STREAM_CH;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetStreamBufSize(t_x502_hnd hnd, uint32_t ch, uint32_t size) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK)
|
||||
err = f_check_stream_ch_par_en(hnd, ch);
|
||||
if (err == X502_ERR_OK)
|
||||
hnd->stream_pars[ch].buf_size = size;
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetStreamStep(t_x502_hnd hnd, uint32_t ch, uint32_t step) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK)
|
||||
err = f_check_stream_ch_par_en(hnd, ch);
|
||||
if (err == X502_ERR_OK)
|
||||
hnd->stream_pars[ch].step = step;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_OutCycleLoadStart(t_x502_hnd hnd, uint32_t size) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK) {
|
||||
err = osspec_mutex_lock(hnd->mutex_cfg, X502_MUTEX_CFG_LOCK_TOUT);
|
||||
if (err == X502_ERR_OK) {
|
||||
/** @todo проверить правильность момента вызова */
|
||||
err = hnd->iface_hnd->cycle_load_start(hnd, size);
|
||||
|
||||
/* если еще не была выполнена предзагрузка сигнала, то посылаем DSP
|
||||
команду, чтобы успел подгрузить данные до старта выдачи */
|
||||
if ((err == X502_ERR_OK) && !(hnd->flags & (PRIV_FLAGS_CYCLE_MODE | PRIV_FLAGS_PRELOAD_DONE))) {
|
||||
if (hnd->mode == X502_MODE_DSP) {
|
||||
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_PRELOAD, 0, NULL, 0,
|
||||
NULL, 0, X502_BF_REQ_TOUT, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK)
|
||||
hnd->flags |= PRIV_FLAGS_CYCLE_MODE;
|
||||
|
||||
osspec_mutex_release(hnd->mutex_cfg);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int32_t f_cycle_setup_wait(t_x502_hnd hnd, uint32_t tout) {
|
||||
int32_t err = X502_ERR_OK;
|
||||
t_ltimer tmr;
|
||||
uint32_t done = 0;
|
||||
int first = 1;
|
||||
ltimer_set(&tmr, LTIMER_MS_TO_CLOCK_TICKS(tout));
|
||||
|
||||
do {
|
||||
if (!first) {
|
||||
SLEEP_MS(5);
|
||||
} else {
|
||||
first = 0;
|
||||
}
|
||||
|
||||
err = X502_OutCycleCheckSetupDone(hnd, &done);
|
||||
} while (!done && !ltimer_expired(&tmr) && (err == X502_ERR_OK));
|
||||
|
||||
if ((err == X502_ERR_NOT_SUP_BY_DRIVER) || (err == X502_ERR_NOT_SUP_BY_FIRMWARE)) {
|
||||
done = 1;
|
||||
err = X502_ERR_OK;
|
||||
}
|
||||
|
||||
if ((err == X502_ERR_OK) && !done) {
|
||||
err = X502_ERR_OUT_CYCLE_SETUP_TOUT;
|
||||
}
|
||||
|
||||
return err;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_OutCycleSetup(t_x502_hnd hnd, uint32_t flags) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK)
|
||||
err = hnd->iface_hnd->cycle_setup(hnd, flags);
|
||||
if ((err == X502_ERR_OK) && (flags & X502_OUT_CYCLE_FLAGS_WAIT_DONE))
|
||||
err = f_cycle_setup_wait(hnd, X502_OUT_CYCLE_WAIT_TOUT);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_OutCycleStop(t_x502_hnd hnd, uint32_t flags) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK)
|
||||
err = hnd->iface_hnd->cycle_stop(hnd, flags);
|
||||
if (err == X502_ERR_OK) {
|
||||
err = osspec_mutex_lock(hnd->mutex_cfg, X502_MUTEX_CFG_LOCK_TOUT);
|
||||
if (err == X502_ERR_OK) {
|
||||
hnd->flags &= ~PRIV_FLAGS_CYCLE_MODE;
|
||||
osspec_mutex_release(hnd->mutex_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
if ((err == X502_ERR_OK) && (flags & X502_OUT_CYCLE_FLAGS_WAIT_DONE))
|
||||
err = f_cycle_setup_wait(hnd, X502_OUT_CYCLE_WAIT_TOUT);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_OutCycleCheckSetupDone(t_x502_hnd hnd, uint32_t *done) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK) {
|
||||
err = hnd->iface_hnd->cycle_check_setup(hnd, done);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_OutGetStatusFlags(t_x502_hnd hnd, uint32_t *status) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK) {
|
||||
err = hnd->iface_hnd->check_feature(hnd, X502_FEATURE_OUT_STATUS_FLAGS);
|
||||
}
|
||||
if (err == X502_ERR_OK) {
|
||||
if (hnd->mode == X502_MODE_DSP) {
|
||||
if (hnd->bf_features & L502_BF_FEATURE_OUT_STATUS_FLAGS) {
|
||||
uint32_t recvd;
|
||||
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_GET_OUT_STATUS,
|
||||
0, NULL, 0, status, 1, X502_BF_CMD_DEFAULT_TOUT,
|
||||
&recvd);
|
||||
if ((err == X502_ERR_OK) && (recvd < 1)) {
|
||||
err = X502_ERR_BF_CMD_RETURN_INSUF_DATA;
|
||||
}
|
||||
} else {
|
||||
err = X502_ERR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
} else {
|
||||
err = X502_FpgaRegRead(hnd, X502_REGS_IOHARD_OUTSWAP_ERROR, status);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_AsyncGetAdcFrame(t_x502_hnd hnd, uint32_t flags,
|
||||
uint32_t tout, double* data) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if ((err == X502_ERR_OK) && (data==NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
if (err == X502_ERR_OK)
|
||||
err = osspec_mutex_lock(hnd->mutex_cfg, X502_MUTEX_CFG_LOCK_TOUT);
|
||||
if (err == X502_ERR_OK) {
|
||||
if (hnd->mode == X502_MODE_FPGA) {
|
||||
/* если запущен хоть один поток на ввод синхронно, то ввод кадра
|
||||
* не возможне */
|
||||
if ((hnd->flags & PRIV_FLAGS_STREAM_RUN) && (hnd->streams & X502_STREAM_ALL_IN)) {
|
||||
err = X502_ERR_STREAM_IS_RUNNING;
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
int need_stop = 0;
|
||||
int old_streams = hnd->streams;
|
||||
uint32_t *wrds = NULL;
|
||||
int32_t rcv_size = hnd->set.lch_cnt;
|
||||
|
||||
/* разрешаем поток для АЦП */
|
||||
err = f_set_streams(hnd, (hnd->streams & ~X502_STREAM_ALL_IN)
|
||||
| X502_STREAM_ADC);
|
||||
|
||||
hnd->proc_adc_ch = 0;
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
/* инициализируем буфер для приема - достаточно всего на один кадр */
|
||||
t_x502_stream_ch_params par = hnd->stream_pars[X502_STREAM_CH_IN];
|
||||
hnd->stream_pars[X502_STREAM_CH_IN].buf_size = hnd->iface_hnd->in_stream_buf_min;
|
||||
hnd->stream_pars[X502_STREAM_CH_IN].step = hnd->set.lch_cnt;
|
||||
err = f_stream_in_cfg(hnd);
|
||||
|
||||
/* восстанавливаем параметры в структуре, что были заданы
|
||||
до этой функции */
|
||||
hnd->stream_pars[X502_STREAM_CH_IN] = par;
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
/* выделяем массив для необработанных отсчетов */
|
||||
wrds = malloc(sizeof(wrds[0])*rcv_size);
|
||||
if (wrds==NULL)
|
||||
err = X502_ERR_MEMORY_ALLOC;
|
||||
}
|
||||
|
||||
/* предзагрузка логической таблицы для АЦП */
|
||||
if (err == X502_ERR_OK)
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_PRELOAD_ADC, 1);
|
||||
|
||||
/* запуск канала DMA на прием данных */
|
||||
if (err == X502_ERR_OK) {
|
||||
err = hnd->iface_hnd->stream_start(hnd, X502_STREAM_CH_IN,
|
||||
X502_STREAM_FLAG_SINGLE);
|
||||
}
|
||||
|
||||
/* если общий синхронный ввод не был запущен - разрешаем его */
|
||||
if (err == X502_ERR_OK) {
|
||||
if (!(hnd->flags & PRIV_FLAGS_STREAM_RUN)) {
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_GO_SYNC_IO, 1);
|
||||
if (err == X502_ERR_OK)
|
||||
need_stop = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
/* принимаем отсчеты от одного кадра */
|
||||
int32_t rcv = X502_Recv(hnd, wrds, rcv_size, tout);
|
||||
if (rcv < 0) {
|
||||
err = rcv;
|
||||
} else if (rcv!=rcv_size) {
|
||||
err = X502_ERR_RECV_INSUFFICIENT_WORDS;
|
||||
} else {
|
||||
err = X502_ProcessAdcData(hnd, wrds, data, (uint32_t*)&rcv_size, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/* если в этой функции запустили синхронный сбор, то останвливаем его */
|
||||
if (need_stop)
|
||||
hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_GO_SYNC_IO, 0);
|
||||
|
||||
hnd->proc_adc_ch = 0;
|
||||
hnd->iface_hnd->stream_free(hnd, X502_STREAM_CH_IN, 0);
|
||||
/* восстанавливаем те потоки, которые были разрешены */
|
||||
f_set_streams(hnd, old_streams);
|
||||
free(wrds);
|
||||
}
|
||||
} else if (hnd->mode == X502_MODE_DSP) {
|
||||
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_ADC_GET_FRAME,
|
||||
0, NULL, 0, (uint32_t*)data, 2*hnd->set.lch_cnt,
|
||||
X502_BF_CMD_DEFAULT_TOUT, NULL);
|
||||
} else {
|
||||
err = X502_ERR_INVALID_MODE;
|
||||
}
|
||||
osspec_mutex_release(hnd->mutex_cfg);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_ManualStreamStart(t_x502_hnd hnd, uint32_t stream_ch, uint32_t flags) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK)
|
||||
err = X502_StreamsEnable(hnd, stream_ch == X502_STREAM_CH_IN ? X502_STREAM_ALL_IN : X502_STREAM_ALL_OUT );
|
||||
if (err == X502_ERR_OK) {
|
||||
if (stream_ch == X502_STREAM_CH_IN) {
|
||||
err = f_stream_in_cfg(hnd);
|
||||
} else {
|
||||
STREAM_OUT_CFG(hnd, err);
|
||||
}
|
||||
}
|
||||
if (err == X502_ERR_OK)
|
||||
err = hnd->iface_hnd->stream_start(hnd, stream_ch, flags);
|
||||
if ((err == X502_ERR_OK) && (stream_ch == X502_STREAM_CH_OUT)) {
|
||||
err = osspec_mutex_lock(hnd->mutex_cfg, X502_MUTEX_CFG_LOCK_TOUT);
|
||||
if (err==X502_ERR_OK) {
|
||||
hnd->flags |= PRIV_FLAGS_PRELOAD_DONE;
|
||||
osspec_mutex_release(hnd->mutex_cfg);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_ManualStreamStop(t_x502_hnd hnd, uint32_t stream_ch) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK)
|
||||
err = X502_StreamsDisable(hnd, stream_ch == X502_STREAM_CH_IN ? X502_STREAM_ALL_IN : X502_STREAM_ALL_OUT );
|
||||
if (err == X502_ERR_OK)
|
||||
err = hnd->iface_hnd->stream_free(hnd, stream_ch, 0);
|
||||
return err;
|
||||
}
|
||||
137
x502/x502tstp.c
Normal file
137
x502/x502tstp.c
Normal file
@ -0,0 +1,137 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "x502tstp.h"
|
||||
|
||||
typedef enum {
|
||||
STREAM_IN_WRD_ADC = 0,
|
||||
STREAM_IN_WRD_DIN = 1,
|
||||
STREAM_IN_WRD_MSG = 2,
|
||||
STREAM_IN_WRD_USR = 3,
|
||||
STREAM_IN_WRD_TSP = 4,
|
||||
} t_stream_in_wrd_type;
|
||||
|
||||
#define STREAM_IN_WRD_TYPE(wrd) wrd & 0x80000000 ? STREAM_IN_WRD_ADC : \
|
||||
(wrd & 0xFF000000) == 0x0 ? STREAM_IN_WRD_DIN : \
|
||||
(wrd & 0xF0000000) == 0x40000000 ? STREAM_IN_WRD_TSP : \
|
||||
((wrd & 0xFF000000)>>24) == 0x01 ? STREAM_IN_WRD_MSG : STREAM_IN_WRD_USR
|
||||
|
||||
static uint64_t get_secssec(uint32_t wrd1, uint32_t wrd2, uint32_t wrd3) {
|
||||
uint64_t wrd1_sec = TSP_WRD1_GET_SSEC(wrd1);
|
||||
uint64_t wrd2_sec = TSP_WRD2_GET_SECSSEC(wrd2);
|
||||
uint64_t wrd3_sec = TSP_WRD3_GET_SEC(wrd3);
|
||||
uint64_t ret;
|
||||
|
||||
ret = wrd1_sec | wrd2_sec | wrd3_sec;
|
||||
return ret;
|
||||
//return TSP_WRD3_GET_SEC(wrd3) | TSP_WRD2_GET_SECSSEC(wrd2) | TSP_WRD1_GET_SSEC(wrd1);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int32_t get_ssec(uint32_t wrd1, uint32_t wrd2, uint32_t wrd3) {
|
||||
int32_t ret;
|
||||
ret = (TSP_WRD2_GET_SSEC(wrd2) << TSP_WRD1_SSEC_LEN) | TSP_WRD1_GET_SSEC(wrd1);
|
||||
if(ret < 0) {
|
||||
fprintf(stderr, "unexpected get_ssec ret=%d\n", ret);
|
||||
while(1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t get_sec(uint32_t wrd2) {
|
||||
return ((wrd2 & TSP_WRD2_SEC_MASK) >> TSP_WRD2_SSEC_LEN);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
X502_EXPORT(bool) X502_tstp_get_lock(t_x502_tstp_state *tstp_state) {
|
||||
if (TSP_WRD1_IS_LOCK(tstp_state->wrd[1])) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
X502_EXPORT(void) X502_tstp_process_wrd(t_x502_tstp_state *tstp_state, uint32_t wrd) {
|
||||
t_stream_in_wrd_type type = STREAM_IN_WRD_TYPE(wrd);
|
||||
if (type == STREAM_IN_WRD_TSP) {
|
||||
if (TSP_WRD_NUM(wrd) == 3) {
|
||||
uint64_t cur_tspt_time;
|
||||
|
||||
tstp_state->wrd[3] = wrd;
|
||||
|
||||
cur_tspt_time = get_secssec(tstp_state->wrd[1], tstp_state->wrd[2], tstp_state->wrd[3]);
|
||||
|
||||
if (TSP_WRD1_IS_FMARK(tstp_state->wrd[1])) {
|
||||
tstp_state->tstp_start_time = cur_tspt_time;
|
||||
#ifdef DEBUG
|
||||
if (tstp_state->tstp_mark_rcvd) {
|
||||
fprintf(stderr, "fmark && tstp_mark_rcv unexpected!\n");
|
||||
}
|
||||
#endif
|
||||
tstp_state->tstp_mark_rcvd = true;
|
||||
}
|
||||
tstp_state->adcwrds_after_tstp = 0;
|
||||
tstp_state->dinwrds_after_tstp = 0;
|
||||
tstp_state->wrds_after_tstp = 0;
|
||||
|
||||
if (cur_tspt_time < tstp_state->last_tstp_time) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "cur = %" PRIu64 " last = %" PRIu64 "\n", cur_tspt_time, tstp_state->last_tstp_time);
|
||||
fprintf(stderr, "cur_tstp < last_tstp unexpected!\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
//printf("tstp time = %d.%09d\n", TSTP_SECSSEC_TO_SEC(cur_tspt_time), TSTP_SSEC_TO_NSEC(cur_tspt_time));
|
||||
|
||||
tstp_state->last_tstp_time = cur_tspt_time;
|
||||
} else {
|
||||
if (TSP_WRD_NUM(wrd) == 0) {
|
||||
tstp_state->wrd[0] = wrd;
|
||||
} else
|
||||
if (TSP_WRD_NUM(wrd) == 1) {
|
||||
tstp_state->wrd[1] = wrd;
|
||||
} else
|
||||
if (TSP_WRD_NUM(wrd) == 2) {
|
||||
tstp_state->wrd[2] = wrd;
|
||||
}
|
||||
tstp_state->wrds_after_tstp++;
|
||||
}
|
||||
} else {
|
||||
if (type == STREAM_IN_WRD_DIN) {
|
||||
tstp_state->dinwrds_after_tstp++;
|
||||
} else
|
||||
if (type == STREAM_IN_WRD_ADC) {
|
||||
tstp_state->adcwrds_after_tstp++;
|
||||
}
|
||||
tstp_state->wrds_after_tstp++;
|
||||
}
|
||||
tstp_state->processed_wrds++;
|
||||
tstp_state->cur_wrd = wrd;
|
||||
}
|
||||
|
||||
X502_EXPORT(void) X502_tstp_init(t_x502_tstp_state *tstp_state, uint32_t adc_freq, uint32_t din_freq) {
|
||||
memset(tstp_state, 0, sizeof(*tstp_state));
|
||||
|
||||
tstp_state->adc_freq = adc_freq;
|
||||
tstp_state->din_freq = din_freq;
|
||||
}
|
||||
|
||||
X502_EXPORT(void) X502_tstp_get_curwrd_time(t_x502_tstp_state *tstp_state, t_x502_tstptime *ret) {
|
||||
t_x502_tstptime wrd_time;
|
||||
t_stream_in_wrd_type type = STREAM_IN_WRD_TYPE(tstp_state->cur_wrd);
|
||||
|
||||
if (type == STREAM_IN_WRD_DIN) {
|
||||
wrd_time = tstp_state->last_tstp_time + ((double)(tstp_state->dinwrds_after_tstp - 1) / tstp_state->din_freq) * (1U << 31);
|
||||
} else
|
||||
if (type == STREAM_IN_WRD_ADC) {
|
||||
wrd_time = tstp_state->last_tstp_time + ((double)(tstp_state->adcwrds_after_tstp - 1)/ tstp_state->adc_freq) * (1U << 31);
|
||||
} else {
|
||||
// чтобы посчитать время слова отличного от АЦП и DIN нужно знать частоту их появления
|
||||
wrd_time = tstp_state->last_tstp_time + ((double)(tstp_state->adcwrds_after_tstp - 1)/ tstp_state->adc_freq) * (1U << 31);
|
||||
wrd_time += tstp_state->last_tstp_time + ((double)(tstp_state->dinwrds_after_tstp - 1) / tstp_state->din_freq) * (1U << 31);
|
||||
}
|
||||
if (ret) {
|
||||
*ret = wrd_time;
|
||||
}
|
||||
}
|
||||
140
x502/x502tstp.h
Normal file
140
x502/x502tstp.h
Normal file
@ -0,0 +1,140 @@
|
||||
#ifndef E502TSTP_H
|
||||
#define E502TSTP_H
|
||||
|
||||
#include "x502api.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @addtogroup tstpfunc_list Функции для работы с метками времени
|
||||
@{ **/
|
||||
|
||||
/***************************************************************************//**
|
||||
@addtogroup tstptype_list Константы и перечисления
|
||||
@{
|
||||
*****************************************************************************/
|
||||
|
||||
#define TSP_NSEC_PER_SEC (1000000000)
|
||||
|
||||
#define TSP_WRD1_SSEC_LEN (24)
|
||||
#define TSP_WRD2_SSEC_LEN (7)
|
||||
#define TSP_WRD2_SEC_LEN (19)
|
||||
#define TSP_WRD3_SEC_LEN (13)
|
||||
#define TSP_SSEC_WIDTH (31)
|
||||
|
||||
|
||||
#define TSP_WRD_NUM(wrd) (((wrd) >> 26) & 3)
|
||||
#define TSP_WRD0_ADC_CLK_NUM_MASK (0x3ffffff)
|
||||
#define TSP_WRD1_LOCK_MASK (1 << 25)
|
||||
#define TSP_WRD1_FMARK_MASK (1 << 24)
|
||||
#define TSP_WRD1_SSEC_MASK ((1 << TSP_WRD1_SSEC_LEN) - 1)
|
||||
#define TSP_WRD2_SEC_MASK (0x3ffff80)
|
||||
#define TSP_WRD2_SSEC_MASK ((1 << TSP_WRD2_SSEC_LEN) - 1)
|
||||
#define TSP_WRD2_SECSSEC_MASK ((1 << (TSP_WRD2_SEC_LEN + TSP_WRD2_SSEC_LEN)) - 1)
|
||||
#define TSP_WRD3_SEC_MASK ((1 << TSP_WRD3_SEC_LEN) - 1)
|
||||
|
||||
#define TSP_WRD1_IS_FMARK(wrd) (!!((wrd) & TSP_WRD1_FMARK_MASK))
|
||||
#define TSP_WRD1_IS_LOCK(wrd) (!!((wrd) & TSP_WRD1_LOCK_MASK))
|
||||
#define TSP_WRD1_GET_SSEC(wrd) ((wrd) & TSP_WRD1_SSEC_MASK)
|
||||
#define TSP_WRD2_GET_SECSSEC(wrd) ((uint64_t)((wrd) & TSP_WRD2_SECSSEC_MASK) << TSP_WRD1_SSEC_LEN)
|
||||
#define TSP_WRD2_GET_SSEC(wrd) ((wrd) & TSP_WRD2_SSEC_MASK)
|
||||
#define TSP_WRD3_GET_SEC(wrd) ((uint64_t)((wrd) & TSP_WRD3_SEC_MASK) << (TSP_WRD1_SSEC_LEN + TSP_WRD2_SSEC_LEN + TSP_WRD2_SEC_LEN))
|
||||
#define SSEC_MAX (0x7fffffff)
|
||||
#define TSTP_SSEC_TO_NSEC(time) (time > 0 ? ((uint32_t)((((double)((time) & SSEC_MAX)) / (1U << TSP_SSEC_WIDTH)) * TSP_NSEC_PER_SEC)) : ((uint32_t)((((double)((time*(-1)) & SSEC_MAX)) / (1U << TSP_SSEC_WIDTH)) * TSP_NSEC_PER_SEC)))
|
||||
#define TSTP_SECSSEC_TO_SEC(time) (time > 0 ? (uint32_t)((time) >> TSP_SSEC_WIDTH) : (uint32_t)((time * -1) >> TSP_SSEC_WIDTH))
|
||||
#define TSTP_SECSSEC_TO_SEC_DOUBLE(time) (((double)(time)) / (1U << TSP_SSEC_WIDTH))
|
||||
#define TSTP_SEC_TO_SSEC(time) (((uint64_t)(time)) << TSP_SSEC_WIDTH)
|
||||
|
||||
/** Тип данных для хранения времени
|
||||
* Время хранится в секундах прошедшее с начала этой эпохи (00:00:00 UTC, 1 Января 1970 года)
|
||||
* Дробный формат хранения 32.31: 32 целых бит, 31 дробных бит,
|
||||
* старшие 32 бита - секунды, младшие 31 бит сабсекунды = 1 / (1<<31) секунд
|
||||
+ сабсекунды,
|
||||
*/
|
||||
typedef uint64_t t_x502_tstptime;
|
||||
|
||||
/** Структура для хранения контекста при обработке потока слов "на ввод" с включенными метками времени */
|
||||
typedef struct {
|
||||
/** значение слов последней метки времени */
|
||||
uint32_t wrd[4];
|
||||
/** частота АЦП */
|
||||
uint32_t adc_freq;
|
||||
/** частота DIN */
|
||||
uint32_t din_freq;
|
||||
/** время первой метки времени */
|
||||
t_x502_tstptime tstp_start_time;
|
||||
/** признак, что первая метка времени получена */
|
||||
bool tstp_mark_rcvd;
|
||||
/** значение текущего обрабатываемого слова */
|
||||
uint32_t cur_wrd;
|
||||
/** кол-во обработанных слов из потока */
|
||||
uint32_t processed_wrds;
|
||||
/** кол-во слов АЦП после последней метки времени */
|
||||
uint32_t adcwrds_after_tstp;
|
||||
/** кол-во слов DIN после последней метки времени */
|
||||
uint32_t dinwrds_after_tstp;
|
||||
/** общее кол-во слов после последней метки времени */
|
||||
uint32_t wrds_after_tstp;
|
||||
/** время последней метки времени */
|
||||
t_x502_tstptime last_tstp_time;
|
||||
} t_x502_tstp_state;
|
||||
|
||||
/** @} */
|
||||
|
||||
/***************************************************************************//**
|
||||
@addtogroup func_tstp Функции для работы с метками времени
|
||||
@{
|
||||
*******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
@brief Инициализация tstp_state, в нем хранится текущий контекст для операций с метками времени из потока "на ввод"
|
||||
|
||||
Данная функция инициализирует структуру в которой хранится контекст для работы с метками времени
|
||||
Необходимо указывать на частоту АЦП и DIN т.к. время для слов между двумя метками
|
||||
будет считаться в зависимости от частоты.
|
||||
|
||||
@param[in] tstp_state Указатель на существующую струтуру t_x502_tstp_state
|
||||
@param[in] adc_freq Частота АЦП
|
||||
@param[in] din_freq Частота DIN
|
||||
*******************************************************************************/
|
||||
X502_EXPORT(void) X502_tstp_init(t_x502_tstp_state *tstp_state, uint32_t adc_freq, uint32_t din_freq);
|
||||
|
||||
/** @brief Обработать очередное слово wrd из потока "на ввод"
|
||||
*
|
||||
* Функция должна быть вызвана только один раз и последовательно для каждого слова полученного из X502_Recv
|
||||
*
|
||||
* @param[in] tstp_state Указатель на струтуру t_x502_tstp_state предварительно инициализированную через tstp_init()
|
||||
* @param[in] wrd Слово из потока "на ввод"
|
||||
*/
|
||||
X502_EXPORT(void) X502_tstp_process_wrd(t_x502_tstp_state *tstp_state, uint32_t wrd);
|
||||
|
||||
/** @brief Узнать время текущего обработанного слова
|
||||
*
|
||||
* Узнать время текущего слова которое до этого было обработано функцией tstp_process_wrd()
|
||||
* Формат времени: 32бита - секунды, 31 бит сабсекунды = 1 / (1<<31) секунд
|
||||
*
|
||||
* @param[in] tstp_state Указатель на струтуру t_x502_tstp_state предварительно инициализированную через tstp_init()
|
||||
* @param[in] ret Указатель на t_x502_tstptime по которому будет сохранено расчитанное значение времени для текущего слова
|
||||
*/
|
||||
X502_EXPORT(void) X502_tstp_get_curwrd_time(t_x502_tstp_state *tstp_state, t_x502_tstptime *ret);
|
||||
|
||||
/** @brief Возвращает признак того что часы синхронизированы
|
||||
*
|
||||
* Возвращает признак "захват PTP" для текущего обработанного слова
|
||||
*
|
||||
* @param[in] tstp_state Указатель на струтуру t_x502_tstp_state предварительно инициализированную через tstp_init()
|
||||
*
|
||||
* @return true: присутствует признак "захват PTP" для текущего обработанного слова, false: признак "захват PTP" отсутствует
|
||||
*/
|
||||
X502_EXPORT(bool) X502_tstp_get_lock(t_x502_tstp_state *tstp_state);
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //E502TSTP_H
|
||||
Reference in New Issue
Block a user